mirror of
https://github.com/c-cube/tiny_httpd.git
synced 2025-12-06 03:05:29 -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;
|
||||
|
||||
sock: Unix.file_descr option;
|
||||
|
||||
sem_max_connections: Sem_.t;
|
||||
(* semaphore to restrict the number of active concurrent connections *)
|
||||
|
||||
|
|
@ -947,10 +949,10 @@ let create
|
|||
?(masksigpipe=true)
|
||||
?(max_connections=32)
|
||||
?(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 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;
|
||||
path_handlers=[];
|
||||
cb_encode_resp=[]; cb_decode_req=[];
|
||||
|
|
@ -1065,16 +1067,24 @@ let run (self:t) : (unit,_) result =
|
|||
if self.masksigpipe then (
|
||||
ignore (Unix.sigprocmask Unix.SIG_BLOCK [Sys.sigpipe] : _ list);
|
||||
);
|
||||
let sock =
|
||||
Unix.socket (if is_ipv6 self then Unix.PF_INET6 else Unix.PF_INET)
|
||||
Unix.SOCK_STREAM 0
|
||||
let sock, should_bind = match self.sock with
|
||||
| Some s ->
|
||||
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
|
||||
Unix.clear_nonblock sock;
|
||||
Unix.setsockopt sock Unix.SO_REUSEADDR true;
|
||||
Unix.setsockopt_optint sock Unix.SO_LINGER None;
|
||||
let inet_addr = Unix.inet_addr_of_string self.addr in
|
||||
begin if should_bind then
|
||||
Unix.bind sock (Unix.ADDR_INET (inet_addr, self.port));
|
||||
Unix.listen sock (2 * self.sem_max_connections.Sem_.n);
|
||||
Unix.listen sock (2 * self.sem_max_connections.Sem_.n)
|
||||
end;
|
||||
while self.running do
|
||||
(* limit concurrency *)
|
||||
Sem_.acquire 1 self.sem_max_connections;
|
||||
|
|
|
|||
|
|
@ -437,6 +437,7 @@ val create :
|
|||
?new_thread:((unit -> unit) -> unit) ->
|
||||
?addr:string ->
|
||||
?port:int ->
|
||||
?sock:Unix.file_descr ->
|
||||
unit ->
|
||||
t
|
||||
(** Create a new webserver.
|
||||
|
|
@ -455,7 +456,10 @@ val create :
|
|||
@param max_connections maximum number of simultaneous connections.
|
||||
@param addr address (IPv4 or IPv6) to listen on. Default ["127.0.0.1"].
|
||||
@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
|
||||
(** Address on which the server listens. *)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue