package mnet
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
An implementation of TCP (Transmission Control Protocol) in OCaml for Miou & Solo5
Install
dune-project
Dependency
Authors
Maintainers
Sources
mnet-0.0.2.tbz
sha256=92b1cfec8487423090ed7abedee824ca20db86f1a7af7e308b4118bc0f774e03
sha512=ce7685c363581121c7d8ae0c33d7dff30ee2dd9dcd29d56f451ac3261b84a91d35a2fa65b31f1f321ddc4b5984e21840459c63614e81ee814f47ac24376bf018
doc/src/mnet.fragments/fragments.ml.html
Source file fragments.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85let src = Logs.Src.create "mnet.fragments" module Log = (val Logs.src_log src : Logs.LOG) module SBstr = Slice_bstr type payload = Slice of SBstr.t | String of string module Make (Key : Hashtbl.HashedType) = struct module Value = struct type t = { to_expire: int; fragment: Fragment.t; count: int } let weight { fragment; _ } = Fragment.weight fragment end module Cache = Lru.M.Make (Key) (Value) type t = { cache: Cache.t; to_expire: int } let max_expiration = Int64.to_int (Duration.of_sec 10) let create ?(to_expire = max_expiration) () = { cache= Cache.create (1024 * 256); to_expire } let catch ~on_exn fn = try fn () with exn -> on_exn exn let insert ~now t key ?(last = false) ~off ~len slice = match (off, last, Cache.find key t.cache) with | 0, true, None -> Log.debug (fun m -> m "receive unfragmented packet"); Some (key, Slice (SBstr.sub slice ~off:0 ~len)) (* unfragmented packet *) | _, _, None -> Log.debug (fun m -> m "receive new fragment"); (* NOTE(dinosaure): we have an new fragment which is not recorded into our cache. We [add] this new fragment and [trim] our cache to avoid an OOM. *) let fragment = Fragment.singleton ~off ~len ~limit:last slice in let to_expire = now + t.to_expire in let value = { Value.to_expire; count= 1; fragment } in Cache.add key value t.cache; Cache.trim t.cache; None | _, _, Some { count; _ } when count > 16 -> Log.debug (fun m -> m "Too many fragments received"); (* NOTE(dinosaure): from @hannesm, if we have more than 16 fragments, we just delete our entry from our cache. *) Cache.remove key t.cache; None | _, _, Some { to_expire; _ } when to_expire < now -> Log.debug (fun m -> m "Too old fragment"); (* NOTE(dinosaure): from @hannesm, if we found an entry and get a new fragment [max_expiration]ns (10secs), we delete the old entry and create a new one. *) let fragment = Fragment.singleton ~off ~len ~limit:last slice in let to_expire = now + t.to_expire in let value = { Value.to_expire; count= 1; fragment } in Cache.add key value t.cache; None | _, _, Some { fragment; count; to_expire } -> Log.debug (fun m -> m "receive a fragment which completes an existing packet"); (* NOTE(dinosaure): the basic execution path. If the fragment does not fit into our entry, we remove it. Otherwise, we insert the new incoming fragment. If the resulted entry is fullfilled, we returns the result. Otherwise, we update our cache with our new entry and [trim] our cache to avoid an OOM. NOTE(dinosaure): [Cache.add] does a promotion of our entry into our cache also. *) let on_exn _exn = Cache.remove key t.cache; None in catch ~on_exn @@ fun () -> let str = SBstr.sub_string ~off:0 ~len slice in let fragment = Fragment.insert fragment ~off ~limit:last str in if Fragment.is_complete fragment then begin let str = Fragment.reassemble_exn fragment in Cache.remove key t.cache; Some (key, String str) end else begin let value = { Value.fragment; count= count + 1; to_expire } in Cache.add key value t.cache; Cache.trim t.cache; None end end
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>