open Swim.Types external env_cast : 'a -> 'b = "%identity" let hex_of_cstruct cs = let len = Cstruct.length cs in let buf = Buffer.create (len * 2) in for i = 0 to len - 1 do Buffer.add_string buf (Printf.sprintf "%02x" (Cstruct.get_uint8 cs i)) done; Buffer.contents buf let () = Eio_main.run @@ fun env -> let env = env_cast env in Eio.Switch.run @@ fun sw -> let net = env#net in let sock = Swim.Transport.create_udp_socket net ~sw ~addr:"\127\000\000\001" ~port:7947 in Printf.printf "Bound to 127.0.0.1:7947\n%!"; (* Create and send a ping to Go memberlist *) let self = make_node_info ~id:(node_id_of_string "ocaml-node") ~addr:(`Udp (Eio.Net.Ipaddr.of_raw "\127\000\000\001", 7947)) ~meta:"" in let target_id = node_id_of_string "go-node" in let ping = Ping { seq = 1; target = target_id; sender = self } in let packet = { cluster = ""; primary = ping; piggyback = [] } in let send_buf = Cstruct.create 1500 in match Swim.Codec.encode_packet packet ~buf:send_buf with | Error _ -> Printf.eprintf "Encode failed\n" | Ok len -> let encoded = Cstruct.sub send_buf 0 len in Printf.printf "Sending ping (%d bytes): %s\n%!" len (hex_of_cstruct encoded); let dst = `Udp (Eio.Net.Ipaddr.of_raw "\127\000\000\001", 7946) in Eio.Net.send sock ~dst [ encoded ]; Printf.printf "Sent! Waiting for ack...\n%!"; (* Wait for response *) let recv_buf = Cstruct.create 1500 in for i = 1 to 5 do Printf.printf "Waiting for packet %d (with 2s timeout)...\n%!" i; Eio.Fiber.fork ~sw (fun () -> let src, n = Eio.Net.recv sock recv_buf in let received = Cstruct.sub recv_buf 0 n in Printf.printf "Received %d bytes from %s\n%!" n (match src with | `Udp (ip, port) -> Printf.sprintf "%s:%d" (Fmt.to_to_string Eio.Net.Ipaddr.pp ip) port | _ -> "unknown"); Printf.printf "Hex: %s\n%!" (hex_of_cstruct received); Printf.printf "First byte (msg type): %d\n%!" (Cstruct.get_uint8 received 0)); Eio.Time.sleep env#clock 2.0 done