Skip to content

Commit 70dcf82

Browse files
authored
Merge pull request #19 from yawaramin/master
feat: allow socket activation
2 parents 9961bd1 + 0e05b8c commit 70dcf82

File tree

2 files changed

+24
-10
lines changed

2 files changed

+24
-10
lines changed

src/Tiny_httpd.ml

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,8 @@ type t = {
809809

810810
port: int;
811811

812+
sock: Unix.file_descr option;
813+
812814
sem_max_connections: Sem_.t;
813815
(* semaphore to restrict the number of active concurrent connections *)
814816

@@ -947,10 +949,10 @@ let create
947949
?(masksigpipe=true)
948950
?(max_connections=32)
949951
?(new_thread=(fun f -> ignore (Thread.create f () : Thread.t)))
950-
?(addr="127.0.0.1") ?(port=8080) () : t =
952+
?(addr="127.0.0.1") ?(port=8080) ?sock () : t =
951953
let handler _req = Response.fail ~code:404 "no top handler" in
952954
let max_connections = max 4 max_connections in
953-
{ new_thread; addr; port; masksigpipe; handler;
955+
{ new_thread; addr; port; sock; masksigpipe; handler;
954956
running= true; sem_max_connections=Sem_.create max_connections;
955957
path_handlers=[];
956958
cb_encode_resp=[]; cb_decode_req=[];
@@ -1065,16 +1067,24 @@ let run (self:t) : (unit,_) result =
10651067
if self.masksigpipe then (
10661068
ignore (Unix.sigprocmask Unix.SIG_BLOCK [Sys.sigpipe] : _ list);
10671069
);
1068-
let sock =
1069-
Unix.socket (if is_ipv6 self then Unix.PF_INET6 else Unix.PF_INET)
1070-
Unix.SOCK_STREAM 0
1070+
let sock, should_bind = match self.sock with
1071+
| Some s ->
1072+
s, false (* Because we're getting a socket from the caller (e.g. systemd) *)
1073+
| None ->
1074+
Unix.socket
1075+
(if is_ipv6 self then Unix.PF_INET6 else Unix.PF_INET)
1076+
Unix.SOCK_STREAM
1077+
0,
1078+
true (* Because we're creating the socket ourselves *)
10711079
in
10721080
Unix.clear_nonblock sock;
1073-
Unix.setsockopt sock Unix.SO_REUSEADDR true;
10741081
Unix.setsockopt_optint sock Unix.SO_LINGER None;
1075-
let inet_addr = Unix.inet_addr_of_string self.addr in
1076-
Unix.bind sock (Unix.ADDR_INET (inet_addr, self.port));
1077-
Unix.listen sock (2 * self.sem_max_connections.Sem_.n);
1082+
begin if should_bind then
1083+
let inet_addr = Unix.inet_addr_of_string self.addr in
1084+
Unix.setsockopt sock Unix.SO_REUSEADDR true;
1085+
Unix.bind sock (Unix.ADDR_INET (inet_addr, self.port));
1086+
Unix.listen sock (2 * self.sem_max_connections.Sem_.n)
1087+
end;
10781088
while self.running do
10791089
(* limit concurrency *)
10801090
Sem_.acquire 1 self.sem_max_connections;

src/Tiny_httpd.mli

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ val create :
437437
?new_thread:((unit -> unit) -> unit) ->
438438
?addr:string ->
439439
?port:int ->
440+
?sock:Unix.file_descr ->
440441
unit ->
441442
t
442443
(** Create a new webserver.
@@ -455,7 +456,10 @@ val create :
455456
@param max_connections maximum number of simultaneous connections.
456457
@param addr address (IPv4 or IPv6) to listen on. Default ["127.0.0.1"].
457458
@param port to listen on. Default [8080].
458-
*)
459+
@param sock an existing socket given to the server to listen on, e.g. by
460+
systemd on Linux (or launchd on macOS). If passed in, this socket will be
461+
used instead of the [addr] and [port]. If not passed in, those will be
462+
used. *)
459463

460464
val addr : t -> string
461465
(** Address on which the server listens. *)

0 commit comments

Comments
 (0)