SpaceOS wire protocol codecs for host-guest communication
at main 64 lines 1.8 kB view raw
1open Wire 2 3let max_value_len = 240 4 5type t = { 6 param_id : int; 7 len : int; 8 generation : int; 9 value : string; 10 crc32 : int; 11} 12 13let codec = 14 let open Codec in 15 record "ParamEntry" (fun param_id len generation value crc32 -> 16 { param_id; len; generation; value; crc32 }) 17 |+ field "param_id" uint32be (fun t -> t.param_id) 18 |+ field "len" uint16be (fun t -> t.len) 19 |+ field "generation" uint16be (fun t -> t.generation) 20 |+ field "value" (byte_array ~size:(int max_value_len)) (fun t -> t.value) 21 |+ field "crc32" uint32be (fun t -> t.crc32) 22 |> seal 23 24let crc32c data = 25 Optint.to_unsigned_int 26 (Checkseum.Crc32c.digest_string data 0 (String.length data) 27 Checkseum.Crc32c.default) 28 29let compute_crc t = 30 let wire_size = Codec.wire_size codec in 31 let buf = Bytes.create wire_size in 32 Codec.encode codec t buf 0; 33 (* CRC covers everything before the CRC field *) 34 crc32c (Bytes.sub_string buf 0 (wire_size - 4)) 35 36let pad_to n s = 37 let slen = String.length s in 38 if slen >= n then String.sub s 0 n 39 else 40 let b = Bytes.make n '\x00' in 41 Bytes.blit_string s 0 b 0 slen; 42 Bytes.unsafe_to_string b 43 44let v ~param_id ~generation value = 45 let len = min max_value_len (String.length value) in 46 let value = pad_to max_value_len value in 47 let t = { param_id; len; generation; value; crc32 = 0 } in 48 { t with crc32 = compute_crc t } 49 50let value_bytes t = String.sub t.value 0 (min t.len (String.length t.value)) 51 52let check_crc t = 53 let expected = compute_crc { t with crc32 = 0 } in 54 t.crc32 = expected 55 56let pp ppf t = 57 Fmt.pf ppf "@[<h>param(id=%d gen=%d len=%d crc=0x%08x)@]" t.param_id 58 t.generation t.len t.crc32 59 60let equal a b = 61 a.param_id = b.param_id && a.len = b.len 62 && a.generation = b.generation 63 && String.equal a.value b.value 64 && a.crc32 = b.crc32