From 98642811bc4f9635d4d312d4cb6a092df42d1e95 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Tue, 26 Nov 2019 18:09:46 -0600 Subject: [PATCH] feat: autodetect ipv6 address --- src/Tiny_httpd.ml | 11 ++++++----- src/Tiny_httpd.mli | 7 +++++-- src/bin/http_of_dir.ml | 8 +++----- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/Tiny_httpd.ml b/src/Tiny_httpd.ml index 2d353627..6232bd6c 100644 --- a/src/Tiny_httpd.ml +++ b/src/Tiny_httpd.ml @@ -518,7 +518,6 @@ type cb_path_handler = string Request.t -> Response.t type t = { addr: string; port: int; - ipv6: bool; sem_max_connections: Sem_.t; new_thread: (unit -> unit) -> unit; masksigpipe: bool; @@ -558,14 +557,13 @@ let add_path_handler self.path_handlers <- ph :: self.path_handlers let create - ?(ipv6=false) ?(masksigpipe=true) ?(max_connections=32) ?(new_thread=(fun f -> ignore (Thread.create f () : Thread.t))) ?(addr="127.0.0.1") ?(port=8080) () : 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; ipv6; + { new_thread; addr; port; masksigpipe; handler; running= true; sem_max_connections=Sem_.create max_connections; path_handlers=[]; cb_encode_resp=[]; cb_decode_req=[]; @@ -656,14 +654,17 @@ let handle_client_ (self:t) (client_sock:Unix.file_descr) : unit = (try Unix.close client_sock with _ -> ()); () +let is_ipv6 self = String.contains self.addr ':' + let run (self:t) : (unit,_) result = try if self.masksigpipe then ( ignore (Unix.sigprocmask Unix.SIG_BLOCK [Sys.sigpipe] : _ list); ); let sock = - Unix.socket (if self.ipv6 then Unix.PF_INET6 else Unix.PF_INET) - Unix.SOCK_STREAM 0 in + Unix.socket (if is_ipv6 self then Unix.PF_INET6 else Unix.PF_INET) + Unix.SOCK_STREAM 0 + in Unix.clear_nonblock sock; Unix.setsockopt sock Unix.SO_REUSEADDR true; Unix.setsockopt_optint sock Unix.SO_LINGER None; diff --git a/src/Tiny_httpd.mli b/src/Tiny_httpd.mli index 4adbbdcd..52a0a798 100644 --- a/src/Tiny_httpd.mli +++ b/src/Tiny_httpd.mli @@ -322,7 +322,6 @@ type t (** A HTTP server. See {!create} for more details. *) val create : - ?ipv6:bool -> ?masksigpipe:bool -> ?max_connections:int -> ?new_thread:((unit -> unit) -> unit) -> @@ -344,13 +343,17 @@ val create : could use a thread pool instead. @param max_connections maximum number of simultaneous connections. - @param addr the address (IPv4) 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]. *) val addr : t -> string (** Address on which the server listens. *) +val is_ipv6 : t -> bool +(** [is_ipv6 server] returns [true] iff the address of the server is an IPv6 address. + @since 0.3 *) + val port : t -> int (** Port on which the server listens. *) diff --git a/src/bin/http_of_dir.ml b/src/bin/http_of_dir.ml index 8eb84380..d541369a 100644 --- a/src/bin/http_of_dir.ml +++ b/src/bin/http_of_dir.ml @@ -9,7 +9,6 @@ type config = { mutable max_upload_size: int; mutable delete: bool; mutable j: int; - mutable ipv6: bool; } let default_config () : config = { @@ -19,7 +18,6 @@ let default_config () : config = { upload=true; max_upload_size = 10 * 1024 * 1024; j=32; - ipv6=false; } let contains_dot_dot s = @@ -101,8 +99,9 @@ let date_of_time (f:float) : string = *) let serve ~config (dir:string) : _ result = - Printf.printf "serve directory %s on http://%s:%d\n%!" dir config.addr config.port; - let server = S.create ~ipv6:config.ipv6 ~max_connections:config.j ~addr:config.addr ~port:config.port () in + let server = S.create ~max_connections:config.j ~addr:config.addr ~port:config.port () in + Printf.printf "serve directory %s on http://%(%s%):%d\n%!" + dir (if S.is_ipv6 server then "[%s]" else "%s") config.addr config.port; if config.delete then ( S.add_path_handler server ~meth:`DELETE "/%s" (fun path _req -> @@ -211,7 +210,6 @@ let main () = "--delete", Unit (fun () -> config.delete <- true), " enable `delete` on files"; "--no-delete", Unit (fun () -> config.delete <- false), " disable `delete` on files"; "-j", Int (fun j->config.j <- j), " maximum number of simultaneous connections"; - "-6", Unit (fun () -> config.ipv6 <- true), " allow ipv6"; ]) (fun s -> dir_ := s) "http_of_dir [options] [dir]"; match serve ~config !dir_ with | Ok () -> ()