mirror of
https://github.com/c-cube/tiny_httpd.git
synced 2025-12-06 11:15:35 -05:00
feat: allow socket activation
This enables passing in an existing socket e.g. from systemd,[1] instead of creating a new socket when running the server. [1] https://github.com/juergenhoetzel/ocaml-systemd
This commit is contained in:
parent
9961bd1b29
commit
ce61ac2afd
2 changed files with 22 additions and 8 deletions
|
|
@ -809,6 +809,8 @@ type t = {
|
||||||
|
|
||||||
port: int;
|
port: int;
|
||||||
|
|
||||||
|
sock: Unix.file_descr option;
|
||||||
|
|
||||||
sem_max_connections: Sem_.t;
|
sem_max_connections: Sem_.t;
|
||||||
(* semaphore to restrict the number of active concurrent connections *)
|
(* semaphore to restrict the number of active concurrent connections *)
|
||||||
|
|
||||||
|
|
@ -947,10 +949,10 @@ let create
|
||||||
?(masksigpipe=true)
|
?(masksigpipe=true)
|
||||||
?(max_connections=32)
|
?(max_connections=32)
|
||||||
?(new_thread=(fun f -> ignore (Thread.create f () : Thread.t)))
|
?(new_thread=(fun f -> ignore (Thread.create f () : Thread.t)))
|
||||||
?(addr="127.0.0.1") ?(port=8080) () : t =
|
?(addr="127.0.0.1") ?(port=8080) ?sock () : t =
|
||||||
let handler _req = Response.fail ~code:404 "no top handler" in
|
let handler _req = Response.fail ~code:404 "no top handler" in
|
||||||
let max_connections = max 4 max_connections in
|
let max_connections = max 4 max_connections in
|
||||||
{ new_thread; addr; port; masksigpipe; handler;
|
{ new_thread; addr; port; sock; masksigpipe; handler;
|
||||||
running= true; sem_max_connections=Sem_.create max_connections;
|
running= true; sem_max_connections=Sem_.create max_connections;
|
||||||
path_handlers=[];
|
path_handlers=[];
|
||||||
cb_encode_resp=[]; cb_decode_req=[];
|
cb_encode_resp=[]; cb_decode_req=[];
|
||||||
|
|
@ -1065,16 +1067,24 @@ let run (self:t) : (unit,_) result =
|
||||||
if self.masksigpipe then (
|
if self.masksigpipe then (
|
||||||
ignore (Unix.sigprocmask Unix.SIG_BLOCK [Sys.sigpipe] : _ list);
|
ignore (Unix.sigprocmask Unix.SIG_BLOCK [Sys.sigpipe] : _ list);
|
||||||
);
|
);
|
||||||
let sock =
|
let sock, should_bind = match self.sock with
|
||||||
Unix.socket (if is_ipv6 self then Unix.PF_INET6 else Unix.PF_INET)
|
| Some s ->
|
||||||
Unix.SOCK_STREAM 0
|
s, false (* Because we're getting a socket from systemd *)
|
||||||
|
| None ->
|
||||||
|
Unix.socket
|
||||||
|
(if is_ipv6 self then Unix.PF_INET6 else Unix.PF_INET)
|
||||||
|
Unix.SOCK_STREAM
|
||||||
|
0,
|
||||||
|
true (* Because we're creating the socket ourselves *)
|
||||||
in
|
in
|
||||||
Unix.clear_nonblock sock;
|
Unix.clear_nonblock sock;
|
||||||
Unix.setsockopt sock Unix.SO_REUSEADDR true;
|
Unix.setsockopt sock Unix.SO_REUSEADDR true;
|
||||||
Unix.setsockopt_optint sock Unix.SO_LINGER None;
|
Unix.setsockopt_optint sock Unix.SO_LINGER None;
|
||||||
let inet_addr = Unix.inet_addr_of_string self.addr in
|
let inet_addr = Unix.inet_addr_of_string self.addr in
|
||||||
Unix.bind sock (Unix.ADDR_INET (inet_addr, self.port));
|
begin if should_bind then
|
||||||
Unix.listen sock (2 * self.sem_max_connections.Sem_.n);
|
Unix.bind sock (Unix.ADDR_INET (inet_addr, self.port));
|
||||||
|
Unix.listen sock (2 * self.sem_max_connections.Sem_.n)
|
||||||
|
end;
|
||||||
while self.running do
|
while self.running do
|
||||||
(* limit concurrency *)
|
(* limit concurrency *)
|
||||||
Sem_.acquire 1 self.sem_max_connections;
|
Sem_.acquire 1 self.sem_max_connections;
|
||||||
|
|
|
||||||
|
|
@ -437,6 +437,7 @@ val create :
|
||||||
?new_thread:((unit -> unit) -> unit) ->
|
?new_thread:((unit -> unit) -> unit) ->
|
||||||
?addr:string ->
|
?addr:string ->
|
||||||
?port:int ->
|
?port:int ->
|
||||||
|
?sock:Unix.file_descr ->
|
||||||
unit ->
|
unit ->
|
||||||
t
|
t
|
||||||
(** Create a new webserver.
|
(** Create a new webserver.
|
||||||
|
|
@ -455,7 +456,10 @@ val create :
|
||||||
@param max_connections maximum number of simultaneous connections.
|
@param max_connections maximum number of simultaneous connections.
|
||||||
@param addr address (IPv4 or IPv6) to listen on. Default ["127.0.0.1"].
|
@param addr address (IPv4 or IPv6) to listen on. Default ["127.0.0.1"].
|
||||||
@param port to listen on. Default [8080].
|
@param port to listen on. Default [8080].
|
||||||
*)
|
@param sock an existing socket given to the server to listen on, e.g. by
|
||||||
|
systemd on Linux (or launchd on macOS). If passed in, this socket will be
|
||||||
|
used instead of the [addr] and [port]. If not passed in, those will be
|
||||||
|
used. *)
|
||||||
|
|
||||||
val addr : t -> string
|
val addr : t -> string
|
||||||
(** Address on which the server listens. *)
|
(** Address on which the server listens. *)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue