]> matita.cs.unibo.it Git - helm.git/blob - helm/DEVEL/ocaml-http/http_tcp_server.ml
- split threaded and non threaded implementations
[helm.git] / helm / DEVEL / ocaml-http / http_tcp_server.ml
1
2   (** raised when a client timeouts *)
3 exception Timeout;;
4
5 let backlog = 10;;
6
7   (** if timeout is given (Some _) @return a new callback which establish
8   timeout_callback as callback for signal Sys.sigalrm and register an alarm
9   (expiring after timeout seconds) before invoking the real callback given. If
10   timeout is None, callback is returned unchanged. *)
11 let wrap_callback_w_timeout ~callback ~timeout ~timeout_callback =
12   match timeout with
13   | None -> callback
14   | Some timeout -> (* wrap callback setting an handler for ALRM signal and an
15                     alarm that ring after timeout seconds *)
16       (fun inchan outchan ->
17         ignore (Sys.signal Sys.sigalrm (Sys.Signal_handle ~timeout_callback));
18         ignore (Unix.alarm timeout);
19         callback inchan outchan)
20
21 let init_socket_and_callback sockaddr callback timeout =
22   let suck = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
23   Unix.setsockopt suck Unix.SO_REUSEADDR true;
24   Unix.bind suck sockaddr;
25   Unix.listen suck backlog;
26   let timeout_callback signo =
27     if signo = Sys.sigalrm then
28       raise Timeout
29   in
30   let callback = wrap_callback_w_timeout ~callback ~timeout ~timeout_callback in
31   (suck, callback)
32
33   (** tcp_server which use Unix.establish_server which in turn forks a child for
34   each request *)
35 let ocaml_builtin ~sockaddr ~timeout callback =
36   let timeout_callback signo =
37     if signo = Sys.sigalrm then
38       exit 2
39   in
40   Unix.establish_server
41     (wrap_callback_w_timeout ~callback ~timeout ~timeout_callback)
42     sockaddr
43
44   (** tcp_server which doesn't fork, requests are server sequentially and in the
45   same address space of the calling process *)
46 let simple ~sockaddr ~timeout callback =
47   let (suck, callback) = init_socket_and_callback sockaddr callback timeout in
48   while true do
49     let (client, _) = Unix.accept suck in
50       (* client is now connected *)
51     let (inchan, outchan) =
52       (Unix.in_channel_of_descr client, Unix.out_channel_of_descr client)
53     in
54     (try
55       callback inchan outchan;
56       ignore (Unix.alarm 0) (* reset alarm *)
57     with Timeout -> ());
58     close_out outchan (* this close also inchan, because socket is the same *)
59   done
60
61   (** tcp_server which creates a new thread for each request to be served *)
62 let thread ~sockaddr ~timeout callback =
63   let (suck, callback) = init_socket_and_callback sockaddr callback timeout in
64   let callback (i, o) =
65     try
66       callback i o;
67       close_out o
68     with
69     | Timeout -> close_out o
70     | e ->
71         close_out o;
72         raise e
73   in
74   while true do
75     let (client, _) = Unix.accept suck in
76       (* client is now connected *)
77     let (inchan, outchan) =
78       (Unix.in_channel_of_descr client, Unix.out_channel_of_descr client)
79     in
80     Http_threaded_tcp_server.serve callback (inchan, outchan)
81   done
82