Skip to content

Commit f32c43d

Browse files
committed
Add a hello server example using cohttp
1 parent e0ba28b commit f32c43d

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed

example/dune

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
(executable
2+
(name hello_cohttp)
3+
(modules hello_cohttp)
4+
(enabled_if
5+
(>= %{ocaml_version} 5.0.0))
6+
(libraries
7+
cohttp
8+
picos_io
9+
picos_io_cohttp
10+
picos_mux.fifo
11+
picos_mux.multififo
12+
picos_mux.random
13+
picos_mux.thread
14+
picos_std.finally
15+
picos_std.structured))

example/hello_cohttp.ml

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
open Picos_io
2+
open Picos_io_cohttp
3+
open Picos_std_finally
4+
open Picos_std_structured
5+
6+
module String_ext = struct
7+
let drop_prefix_opt ~prefix s =
8+
if String.starts_with ~prefix s then
9+
let i = String.length prefix in
10+
Some (String.sub s i (String.length s - i))
11+
else None
12+
end
13+
14+
module Option_ext = struct
15+
let ( >>= ) = Option.bind
16+
let ( >>- ) xO xy = Option.map xy xO
17+
18+
let ( <|> ) xyO1 xyO2 x =
19+
match xyO1 x with Some _ as some -> some | None -> xyO2 x
20+
21+
let filter p x = if p x then Some x else None
22+
end
23+
24+
module Scheduler = struct
25+
open Option_ext
26+
27+
let parse =
28+
let parse_0 name con s =
29+
String_ext.drop_prefix_opt ~prefix:name s
30+
>>- String.trim
31+
>>= filter (( = ) "")
32+
>>- fun _ -> con
33+
and parse_1 name con s =
34+
String_ext.drop_prefix_opt ~prefix:name s
35+
>>- String.trim >>= int_of_string_opt
36+
>>= filter (fun n -> 1 <= n && n <= Domain.recommended_domain_count ())
37+
>>- con
38+
in
39+
fun s ->
40+
match
41+
String.trim s
42+
|> (parse_0 "fifo" `Fifo <|> parse_0 "thread" `Thread
43+
<|> parse_1 "multififo" (fun n -> `Multififo n)
44+
<|> parse_1 "random" (fun n -> `Random n))
45+
with
46+
| None -> failwith "Unknown or unacceptable scheduler"
47+
| Some s -> s
48+
end
49+
50+
let main ~port ~n_connections ~n_servers () =
51+
let@ server_socket =
52+
finally Unix.close @@ fun () ->
53+
Unix.socket ~cloexec:true PF_INET SOCK_STREAM 0
54+
in
55+
Unix.set_nonblock server_socket;
56+
Unix.bind server_socket Unix.(ADDR_INET (inet_addr_loopback, port));
57+
Unix.listen server_socket n_connections;
58+
let callback _conn _req _req_body =
59+
let res_body = "Hello world!\n" in
60+
Server.respond_string ~status:`OK ~body:res_body ()
61+
in
62+
Flock.join_after @@ fun () ->
63+
for _ = 1 to n_servers do
64+
Flock.fork @@ fun () -> Server.run (Server.make ~callback ()) server_socket
65+
done
66+
67+
let () =
68+
let port = ref 8082
69+
and n_connections = ref 300
70+
and scheduler = ref `Fifo
71+
and n_servers = ref 1 in
72+
let specs =
73+
[
74+
("-port", Arg.Set_int port, "\t Port");
75+
("-conns", Arg.Set_int n_connections, "\t Connections");
76+
("-servers", Arg.Set_int n_servers, "\t Server fibers");
77+
( "-scheduler",
78+
Arg.String (fun s -> scheduler := Scheduler.parse s),
79+
"\t Scheduler ('fifo' | 'thread' | 'multififo n' | 'random n')" );
80+
]
81+
in
82+
Arg.parse specs ignore "";
83+
let main =
84+
main ~port:!port ~n_connections:!n_connections ~n_servers:!n_servers
85+
in
86+
match !scheduler with
87+
| `Fifo ->
88+
Printf.printf "Fifo\n%!";
89+
Picos_mux_fifo.run main
90+
| `Thread ->
91+
Printf.printf "Thread\n%!";
92+
Picos_mux_thread.run main
93+
| `Multififo n_domains ->
94+
Printf.printf "Multififo %d\n%!" n_domains;
95+
Picos_mux_multififo.run_on ~n_domains main
96+
| `Random n_domains ->
97+
Printf.printf "Random %d\n%!" n_domains;
98+
Picos_mux_random.run_on ~n_domains main

0 commit comments

Comments
 (0)