Preserve client address down to Request.t

Note that the argument is optional because of the Internal_ use case.
This commit is contained in:
Stéphane Lavergne 2023-08-07 16:52:32 -04:00
parent b3b99af7ae
commit 53182375c0
3 changed files with 11 additions and 8 deletions

View file

@ -187,7 +187,7 @@ end
(** A TCP server abstraction. *) (** A TCP server abstraction. *)
module TCP_server = struct module TCP_server = struct
type conn_handler = { type conn_handler = {
handle: In_channel.t -> Out_channel.t -> unit; handle: ?client_addr:Unix.sockaddr -> In_channel.t -> Out_channel.t -> unit;
(** Handle client connection *) (** Handle client connection *)
} }

View file

@ -164,6 +164,7 @@ module Request = struct
type 'body t = { type 'body t = {
meth: Meth.t; meth: Meth.t;
host: string; host: string;
client_addr: Unix.sockaddr option;
headers: Headers.t; headers: Headers.t;
http_version: int * int; http_version: int * int;
path: string; path: string;
@ -245,7 +246,7 @@ module Request = struct
bad_reqf 400 "body is too short by %d bytes" size) bad_reqf 400 "body is too short by %d bytes" size)
(* parse request, but not body (yet) *) (* parse request, but not body (yet) *)
let parse_req_start ~get_time_s ~buf (bs : byte_stream) : let parse_req_start ?client_addr ~get_time_s ~buf (bs : byte_stream) :
unit t option resp_result = unit t option resp_result =
try try
let line = Byte_stream.read_line ~buf bs in let line = Byte_stream.read_line ~buf bs in
@ -281,6 +282,7 @@ module Request = struct
meth; meth;
query; query;
host; host;
client_addr;
path; path;
path_components; path_components;
headers; headers;
@ -934,7 +936,7 @@ module Unix_tcp_server_ = struct
after_init tcp_server; after_init tcp_server;
(* how to handle a single client *) (* how to handle a single client *)
let handle_client_unix_ (client_sock : Unix.file_descr) : unit = let handle_client_unix_ (client_sock : Unix.file_descr) (client_addr : Unix.sockaddr) : unit =
Unix.(setsockopt_float client_sock SO_RCVTIMEO self.timeout); Unix.(setsockopt_float client_sock SO_RCVTIMEO self.timeout);
Unix.(setsockopt_float client_sock SO_SNDTIMEO self.timeout); Unix.(setsockopt_float client_sock SO_SNDTIMEO self.timeout);
let oc = let oc =
@ -942,7 +944,7 @@ module Unix_tcp_server_ = struct
@@ Unix.out_channel_of_descr client_sock @@ Unix.out_channel_of_descr client_sock
in in
let ic = IO.In_channel.of_unix_fd client_sock in let ic = IO.In_channel.of_unix_fd client_sock in
handle.handle ic oc; handle.handle ~client_addr ic oc;
_debug (fun k -> k "done with client, exiting"); _debug (fun k -> k "done with client, exiting");
(try Unix.close client_sock (try Unix.close client_sock
with e -> with e ->
@ -955,11 +957,11 @@ module Unix_tcp_server_ = struct
(* limit concurrency *) (* limit concurrency *)
Sem_.acquire 1 self.sem_max_connections; Sem_.acquire 1 self.sem_max_connections;
try try
let client_sock, _ = Unix.accept sock in let client_sock, client_addr = Unix.accept sock in
Unix.setsockopt client_sock Unix.TCP_NODELAY true; Unix.setsockopt client_sock Unix.TCP_NODELAY true;
self.new_thread (fun () -> self.new_thread (fun () ->
try try
handle_client_unix_ client_sock; handle_client_unix_ client_sock client_addr;
Sem_.release 1 self.sem_max_connections Sem_.release 1 self.sem_max_connections
with e -> with e ->
(try Unix.close client_sock with _ -> ()); (try Unix.close client_sock with _ -> ());
@ -1024,7 +1026,7 @@ let find_map f l =
aux f l aux f l
(* handle client on [ic] and [oc] *) (* handle client on [ic] and [oc] *)
let client_handle_for (self : t) ic oc : unit = let client_handle_for (self : t) ?client_addr ic oc : unit =
Pool.with_resource self.buf_pool @@ fun buf -> Pool.with_resource self.buf_pool @@ fun buf ->
Pool.with_resource self.buf_pool @@ fun buf_res -> Pool.with_resource self.buf_pool @@ fun buf_res ->
let is = Byte_stream.of_input ~buf_size:self.buf_size ic in let is = Byte_stream.of_input ~buf_size:self.buf_size ic in
@ -1032,7 +1034,7 @@ let client_handle_for (self : t) ic oc : unit =
while !continue && running self do while !continue && running self do
_debug (fun k -> k "read next request"); _debug (fun k -> k "read next request");
let (module B) = self.backend in let (module B) = self.backend in
match Request.parse_req_start ~get_time_s:B.get_time_s ~buf is with match Request.parse_req_start ?client_addr ~get_time_s:B.get_time_s ~buf is with
| Ok None -> continue := false (* client is done *) | Ok None -> continue := false (* client is done *)
| Error (c, s) -> | Error (c, s) ->
(* connection error, close *) (* connection error, close *)

View file

@ -67,6 +67,7 @@ module Request : sig
meth: Meth.t; (** HTTP method for this request. *) meth: Meth.t; (** HTTP method for this request. *)
host: string; host: string;
(** Host header, mandatory. It can also be found in {!headers}. *) (** Host header, mandatory. It can also be found in {!headers}. *)
client_addr : Unix.sockaddr option; (** Client address. *)
headers: Headers.t; (** List of headers. *) headers: Headers.t; (** List of headers. *)
http_version: int * int; http_version: int * int;
(** HTTP version. This should be either [1, 0] or [1, 1]. *) (** HTTP version. This should be either [1, 0] or [1, 1]. *)