···11+open Printf
22+33+let () =
44+ let queue_depth = 128 in
55+ let t = Uring.create ~queue_depth () in
66+77+ (* Create server socket - Unix.socket is necessary as io_uring doesn't have socket creation *)
88+ let server_sock = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
99+ Unix.set_nonblock server_sock;
1010+ printf "Server socket created\n";
1111+1212+ (* Create an address to bind to *)
1313+ let addr = Unix.ADDR_INET (Unix.inet_addr_loopback, 0) in
1414+1515+ (* Use io_uring for bind operation *)
1616+ let bind_result =
1717+ match Uring.bind t server_sock addr () with
1818+ | None -> failwith "Failed to submit bind operation"
1919+ | Some _job ->
2020+ let _submitted = Uring.submit t in
2121+ match Uring.wait t with
2222+ | Uring.None -> failwith "No completion for bind"
2323+ | Uring.Some { result; data = _ } ->
2424+ if result < 0 then begin
2525+ Uring.close t server_sock () |> ignore;
2626+ Uring.submit t |> ignore;
2727+ Uring.exit t;
2828+ let err = Uring.error_of_errno (-result) in
2929+ failwith (sprintf "Bind failed: %s" (Unix.error_message err))
3030+ end else
3131+ result
3232+ in
3333+ printf "Bind completed with result: %d\n" bind_result;
3434+3535+ (* Use io_uring for listen operation *)
3636+ let backlog = 10 in
3737+ let listen_result =
3838+ match Uring.listen t server_sock backlog () with
3939+ | None -> failwith "Failed to submit listen operation"
4040+ | Some _job ->
4141+ let _submitted = Uring.submit t in
4242+ match Uring.wait t with
4343+ | Uring.None -> failwith "No completion for listen"
4444+ | Uring.Some { result; data = _ } ->
4545+ if result < 0 then begin
4646+ Uring.close t server_sock () |> ignore;
4747+ Uring.submit t |> ignore;
4848+ Uring.exit t;
4949+ let err = Uring.error_of_errno (-result) in
5050+ failwith (sprintf "Listen failed: %s" (Unix.error_message err))
5151+ end else
5252+ result
5353+ in
5454+ printf "Listen completed with result: %d\n" listen_result;
5555+5656+ (* Get the actual bound port - Unix.getsockname is necessary for socket introspection *)
5757+ let actual_addr = Unix.getsockname server_sock in
5858+ let port = match actual_addr with
5959+ | Unix.ADDR_INET (_, p) -> p
6060+ | _ -> failwith "Unexpected address type"
6161+ in
6262+ printf "Socket bound and listening on port: %d\n" port;
6363+6464+ (* Test connecting to the bound socket *)
6565+ printf "Testing connection to the bound socket...\n";
6666+6767+ (* Create client socket - Unix.socket is necessary as io_uring doesn't have socket creation *)
6868+ let client_sock = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
6969+ Unix.set_nonblock client_sock;
7070+ printf "Client socket created\n";
7171+7272+ (* Use io_uring for connect operation *)
7373+ let connect_addr = Unix.ADDR_INET (Unix.inet_addr_loopback, port) in
7474+ let connect_result =
7575+ match Uring.connect t client_sock connect_addr () with
7676+ | None -> failwith "Failed to submit connect operation"
7777+ | Some _job ->
7878+ let _submitted = Uring.submit t in
7979+ match Uring.wait t with
8080+ | Uring.None -> failwith "No completion for connect"
8181+ | Uring.Some { result; data = _ } ->
8282+ (* Connect may return -EINPROGRESS for non-blocking sockets, which is normal *)
8383+ if result < 0 && result <> (-115) (* -EINPROGRESS *) then begin
8484+ Uring.close t client_sock () |> ignore;
8585+ Uring.close t server_sock () |> ignore;
8686+ Uring.submit t |> ignore;
8787+ Uring.exit t;
8888+ let err = Uring.error_of_errno (-result) in
8989+ failwith (sprintf "Connect failed: %s (errno: %d)" (Unix.error_message err) (-result))
9090+ end else
9191+ result
9292+ in
9393+9494+ if connect_result = 0 || connect_result = (-115) then
9595+ printf "Connect initiated successfully (result: %d)\n" connect_result
9696+ else
9797+ printf "Connect completed with result: %d\n" connect_result;
9898+9999+ (* Get the client socket's local port - Unix.getsockname is necessary for socket introspection *)
100100+ let client_addr = Unix.getsockname client_sock in
101101+ let client_port = match client_addr with
102102+ | Unix.ADDR_INET (_, p) -> p
103103+ | _ -> failwith "Unexpected address type"
104104+ in
105105+ printf "Client socket connected from port: %d to port: %d\n" client_port port;
106106+107107+ (* Clean up using io_uring close operations *)
108108+ begin match Uring.close t client_sock () with
109109+ | None -> failwith "Failed to submit close for client socket"
110110+ | Some _ -> ()
111111+ end;
112112+113113+ begin match Uring.close t server_sock () with
114114+ | None -> failwith "Failed to submit close for server socket"
115115+ | Some _ -> ()
116116+ end;
117117+118118+ let _submitted = Uring.submit t in
119119+120120+ (* Wait for both close operations to complete *)
121121+ let rec wait_closes pending =
122122+ if pending > 0 then
123123+ match Uring.wait t with
124124+ | Uring.None -> failwith "No completion for close"
125125+ | Uring.Some { result; data = _ } ->
126126+ if result < 0 then
127127+ printf "Close warning: %s\n" (Unix.error_message (Uring.error_of_errno (-result)));
128128+ wait_closes (pending - 1)
129129+ in
130130+ wait_closes 2;
131131+132132+ Uring.exit t;
133133+ printf "Test completed successfully!\n"