33 This sub-library ([tiny_httpd.ws]) exports a small implementation for a
44 websocket server. It has no additional dependencies. *)
55
6+ (* * Synchronization primitive used to allow both the reader to reply to "ping",
7+ and the handler to send messages, without stepping on each other's toes.
8+
9+ @since NEXT_RELEASE *)
10+ module With_lock : sig
11+ type t = { with_lock : 'a . (unit -> 'a ) -> 'a }
12+ (* * A primitive to run the callback in a critical section where others cannot
13+ run at the same time.
14+
15+ The default is a mutex, but that works poorly with thread pools so it's
16+ possible to use a semaphore or a cooperative mutex instead. *)
17+
18+ type builder = unit -> t
19+
20+ val default_builder : builder
21+ (* * Lock using [Mutex]. *)
22+ end
23+
624type handler = unit Request .t -> IO.Input .t -> IO.Output .t -> unit
725(* * Websocket handler *)
826
9- val upgrade : IO.Input .t -> IO.Output .t -> IO.Input .t * IO.Output .t
10- (* * Upgrade a byte stream to the websocket framing protocol. *)
27+ val upgrade :
28+ ?with_lock : With_lock .t ->
29+ IO.Input .t ->
30+ IO.Output .t ->
31+ IO.Input .t * IO.Output .t
32+ (* * Upgrade a byte stream to the websocket framing protocol.
33+ @param with_lock
34+ if provided, use this to prevent reader and writer to compete on sending
35+ frames. since NEXT_RELEASE. *)
1136
1237exception Close_connection
1338(* * Exception that can be raised from IOs inside the handler, when the
@@ -17,14 +42,19 @@ val add_route_handler :
1742 ?accept : (unit Request .t -> (unit , int * string ) result ) ->
1843 ?accept_ws_protocol : (string -> bool ) ->
1944 ?middlewares : Server.Head_middleware .t list ->
45+ ?with_lock : With_lock .builder ->
2046 Server .t ->
2147 (Server .upgrade_handler , Server .upgrade_handler ) Route .t ->
2248 handler ->
2349 unit
2450(* * Add a route handler for a websocket endpoint.
2551 @param accept_ws_protocol
2652 decides whether this endpoint accepts the websocket protocol sent by the
27- client. Default accepts everything. *)
53+ client. Default accepts everything.
54+ @param with_lock
55+ if provided, use this to synchronize writes between the frame reader
56+ (replies "pong" to "ping") and the handler emitting writes. since
57+ NEXT_RELEASE. *)
2858
2959(* */**)
3060
@@ -33,15 +63,4 @@ module Private_ : sig
3363 mask_key :bytes -> mask_offset :int -> bytes -> int -> int -> unit
3464end
3565
36- (* * @since NEXT_RELEASE *)
37- module With_lock : sig
38- type t = { with_lock : 'a . (unit -> 'a ) -> 'a }
39- type builder = unit -> t
40-
41- val default_builder : builder
42- (* * Lock using [Mutex]. *)
43-
44- val builder : builder ref
45- end
46-
4766(* */**)
0 commit comments