package tiny_libs
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
From-scratch libraries for teaching: graphics, audio, compression, crypto, networking and more
Install
dune-project
Dependency
Authors
Maintainers
Sources
0.3.6.tar.gz
md5=7c636383d146d30ac6f2fa234a6253c8
sha512=c79f3823c5f8f57e5038eb640d487c61168b84aa07c61999d6622ef9fd0c890e2b03b4c6a7cdbbe9352a49e25dda00ac7bb14693cee8e3d7beeed251351a2af0
doc/src/tiny_libs.networking_netcode/Sim_net.ml.html
Source file Sim_net.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 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100(* Claude Code * * Copyright (C) 2026 Yoann Padioleau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * (LGPL) as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. *) (* See Sim_net.mli *) type config = { latency : float; jitter : float; loss : float; duplication : float } let perfect = { latency = 0.; jitter = 0.; loss = 0.; duplication = 0. } type packet = { src : int; dst : int; bytes : string; arrival : float; (* the order it was sent in, between its two peers: to count the * packets overtaken *) number : int; } type stats = { sent : int; lost : int; duplicated : int; delivered : int; reordered : int } type t = { mutable config : config; mutable seed : Lehmer.t; (* in flight, sorted by arrival (ties: in the order sent) *) mutable in_flight : packet list; (* per (src, dst): packets sent so far, and the highest number * delivered *) sent_between : (int * int, int) Hashtbl.t; last_delivered : (int * int, int) Hashtbl.t; mutable stats : stats; } let create ~(seed : int) (config : config) : t = { config; seed = Lehmer.scramble seed; in_flight = []; sent_between = Hashtbl.create 8; last_delivered = Hashtbl.create 8; stats = { sent = 0; lost = 0; duplicated = 0; delivered = 0; reordered = 0 }; } let config (net : t) : config = net.config let set_config (net : t) (config : config) : unit = net.config <- config (* a number in [0, 1), from the network's own seed *) let draw (net : t) : float = net.seed <- Lehmer.next net.seed; Lehmer.to_unit net.seed (* after the packets arriving at the same time or before: a stable * insertion keeps the sending order among equals *) let rec insert (p : packet) (ps : packet list) : packet list = match ps with | q :: rest when q.arrival <= p.arrival -> q :: insert p rest | _ -> p :: ps let send (net : t) ~(now : float) ~(src : int) ~(dst : int) (bytes : string) : unit = let c = net.config in let number = 1 + Option.value (Hashtbl.find_opt net.sent_between (src, dst)) ~default:0 in Hashtbl.replace net.sent_between (src, dst) number; net.stats <- { net.stats with sent = net.stats.sent + 1 }; (* the draws, always in the same order, so that a seed is a network *) let lost = draw net < c.loss in let delay () = c.latency +. (c.jitter *. draw net) in let first = delay () in let twice = draw net < c.duplication in let second = delay () in if lost then net.stats <- { net.stats with lost = net.stats.lost + 1 } else begin let put arrival = net.in_flight <- insert { src; dst; bytes; arrival; number } net.in_flight in put (now +. first); if twice then begin put (now +. second); net.stats <- { net.stats with duplicated = net.stats.duplicated + 1 } end end let receive (net : t) ~(now : float) (dst : int) : (int * string) list = let arrived, rest = List.partition (fun p -> p.dst = dst && p.arrival <= now) net.in_flight in net.in_flight <- rest; List.iter (fun p -> let last = Option.value (Hashtbl.find_opt net.last_delivered (p.src, p.dst)) ~default:0 in let reordered = if p.number < last then 1 else 0 in Hashtbl.replace net.last_delivered (p.src, p.dst) (max last p.number); net.stats <- { net.stats with delivered = net.stats.delivered + 1; reordered = net.stats.reordered + reordered }) arrived; List.map (fun p -> (p.src, p.bytes)) arrived let stats (net : t) : stats = net.stats
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>