From 904759f6eb77e5f4170486bb8398c5db46d23f93 Mon Sep 17 00:00:00 2001 From: Romain Beauxis Date: Tue, 2 Jan 2024 15:01:11 -0600 Subject: [PATCH] Remove. --- examples/dune | 7 - examples/http_domain.ml | 302 ---------------------------------------- 2 files changed, 309 deletions(-) delete mode 100644 examples/http_domain.ml diff --git a/examples/dune b/examples/dune index 99609cf..887559f 100644 --- a/examples/dune +++ b/examples/dune @@ -3,13 +3,6 @@ (modules http) (libraries duppy)) -(executable - (name http_domain) - (modules http_domain) - (enabled_if - (<= 5.0.0 %{ocaml_version})) - (libraries duppy)) - (executable (name telnet) (modules telnet) diff --git a/examples/http_domain.ml b/examples/http_domain.ml deleted file mode 100644 index 603bcc9..0000000 --- a/examples/http_domain.ml +++ /dev/null @@ -1,302 +0,0 @@ -let queue_mode = ref `Thread -let queues = ref 3 -let port = ref 8080 -let usage = "usage: http_domain [options]" -let ( let* ) = Duppy.Monad.bind - -let () = - let () = - match Domain.recommended_domain_count () with - | 1 -> queue_mode := `Thread - | n -> - queues := n - 1; - queue_mode := `Domain - in - let arg _ = - Printf.eprintf "Error: too many arguments\n"; - exit 1 - in - Arg.parse - [ - ( "--queues", - Arg.Int (fun i -> queues := i), - Printf.sprintf "Number of non-blocking queues. (default: %d)" !queues ); - ( "--mode", - Arg.String - (fun m -> - match m with - | "thread" -> queue_mode := `Thread - | "domain" -> queue_mode := `Thread - | v -> failwith ("Invalid queue mode: " ^ v)), - Printf.sprintf "Queue mode. (default: %s)" - (match !queue_mode with `Thread -> "thread" | `Domain -> "domain") ); - ( "--port", - Arg.Int (fun i -> port := i), - Printf.sprintf "Port used to bind the server. (default: %d)" !port ); - ] - arg usage - -type priority = Non_blocking - -let scheduler = Duppy.create () - -type http_method = Post | Get -type http_protocol = Http_11 | Http_10 - -let string_of_protocol = function - | Http_11 -> "HTTP/1.1" - | Http_10 -> "HTTP/1.0" - -let protocol_of_string = function - | "HTTP/1.1" -> Http_11 - | "HTTP/1.0" -> Http_10 - | _ -> assert false - -let string_of_method = function Post -> "POST" | Get -> "GET" - -let method_of_string = function - | "POST" -> Post - | "GET" -> Get - | _ -> assert false - -type data = None | String of string - -type request = { - request_protocol : http_protocol; - request_method : http_method; - request_uri : string; - request_headers : (string * string) list; - request_data : data; -} - -type reply = { - reply_protocol : http_protocol; - reply_status : int * string; - reply_headers : (string * string) list; - reply_data : data; -} - -exception Assoc of string - -let assoc_uppercase x y = - try - List.iter - (fun (l, v) -> - if String.uppercase_ascii l = x then raise (Assoc v) else ()) - y; - raise Not_found - with Assoc s -> s - -let server = "dhttpd" - -let html_template = - Printf.sprintf - "\r\n\ - \r\n\ - %s" - -let server_error status protocol = - let _, explanation = status in - let data = - String - (html_template - (Printf.sprintf "%s\r\n%s !" - explanation explanation)) - in - { - reply_protocol = protocol; - reply_status = status; - reply_headers = - [("Content-Type", "text/html; charset=UTF-8"); ("Server", server)]; - reply_data = data; - } - -let error_404 = server_error (404, "File Not Found") -let error_500 = server_error (500, "Bad Request") Http_10 -let error_403 = server_error (403, "Forbidden") - -let http_302 protocol uri = - { - reply_protocol = protocol; - reply_status = (302, "Found"); - reply_headers = [("Location", uri)]; - reply_data = String ""; - } - -let send_reply h reply = - let write s = - Duppy.Monad.Io.write ?timeout:None ~priority:Non_blocking h - (Bytes.unsafe_of_string s) - in - let code, status = reply.reply_status in - let http_header = - Printf.sprintf "%s %d %s\r\n%s\r\n\r\n" - (string_of_protocol reply.reply_protocol) - code status - (String.concat "\r\n" - (List.map - (fun (x, y) -> Printf.sprintf "%s: %s" x y) - reply.reply_headers)) - in - let* () = write http_header in - match reply.reply_data with - | String s -> write s - | None -> Duppy.Monad.return () - -let parse_headers headers = - let split_header l h = - try - let rex = Pcre.regexp "([^:\\r\\n]+):\\s*([^\\r\\n]+)" in - let sub = Pcre.exec ~rex h in - Duppy.Monad.return - ((Pcre.get_substring sub 1, Pcre.get_substring sub 2) :: l) - with Not_found -> Duppy.Monad.raise error_500 - in - Duppy.Monad.fold_left split_header [] headers - -let payload = String.init 4096 (fun i -> Char.chr (i mod 100)) - -let handle_request request = - if request.request_uri = "/" then ( - let headers = - [ - ("Server", server); - ("Content-Length", string_of_int (String.length payload)); - ("Content-Type", "application/octet-stream"); - ] - in - Duppy.Monad.raise - { - reply_protocol = request.request_protocol; - reply_status = (200, "OK"); - reply_headers = headers; - reply_data = String payload; - }) - else Duppy.Monad.return (error_404 request.request_protocol) - -let parse_request h r = - try - let headers = Pcre.split ~pat:"\r\n" r in - let* request, headers = - match headers with - | e :: l -> - let* headers = parse_headers l in - Duppy.Monad.return (e, headers) - | _ -> Duppy.Monad.raise error_500 - in - let rex = Pcre.regexp "([\\w]+)\\s([^\\s]+)\\s(HTTP/1.[01])" in - let* http_method, uri, protocol = - try - let sub = Pcre.exec ~rex request in - let http_method, uri, protocol = - ( Pcre.get_substring sub 1, - Pcre.get_substring sub 2, - Pcre.get_substring sub 3 ) - in - Duppy.Monad.return - (method_of_string http_method, uri, protocol_of_string protocol) - with _ -> Duppy.Monad.raise error_500 - in - let* data = - match http_method with - | Get -> Duppy.Monad.return None - | Post -> ( - let* len = - try - let length = assoc_uppercase "CONTENT-LENGTH" headers in - Duppy.Monad.return (int_of_string length) - with - | Not_found -> Duppy.Monad.return 0 - | _ -> Duppy.Monad.raise error_500 - in - match len with - | 0 -> Duppy.Monad.return None - | d -> - let* data = - Duppy.Monad.Io.read ?timeout:None ~priority:Non_blocking - ~marker:(Duppy.Io.Length d) h - in - Duppy.Monad.return (String data)) - in - Duppy.Monad.return - { - request_method = http_method; - request_protocol = protocol; - request_uri = uri; - request_headers = headers; - request_data = data; - } - with _ -> Duppy.Monad.raise error_500 - -let handle_client socket = - (* Read and process lines *) - let on_error _ = error_500 in - let h = { Duppy.Monad.Io.scheduler; socket; data = ""; on_error } in - let exec = - let* reply = - Duppy.Monad.catch - (let* data = - Duppy.Monad.Io.read ?timeout:None ~priority:Non_blocking - ~marker:(Duppy.Io.Split "\r\n\r\n") h - in - let* request = parse_request h data in - handle_request request) - (fun reply -> Duppy.Monad.return reply) - in - send_reply h reply - in - let finish _ = try Unix.close socket with _ -> () in - Duppy.Monad.run ~return:finish ~raise:finish exec - -let new_queue ~priority ~name () = - let priorities p = p = priority in - let queue () = Duppy.queue scheduler ~log:(fun _ -> ()) ~priorities name in - match !queue_mode with - | `Thread -> `Thread (Thread.create queue ()) - | `Domain -> `Domain (Domain.spawn queue) - -let bind_addr_inet = Unix.inet_addr_of_string "0.0.0.0" -let bind_addr = Unix.ADDR_INET (bind_addr_inet, !port) -let max_conn = 100 -let sock = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 - -let () = - (* See http://caml.inria.fr/mantis/print_bug_page.php?bug_id=4640 - * for this: we want Unix EPIPE error and not SIGPIPE, which - * crashes the program.. *) - Sys.set_signal Sys.sigpipe Sys.Signal_ignore; - ignore (Unix.sigprocmask Unix.SIG_BLOCK [Sys.sigpipe]); - Unix.setsockopt sock Unix.SO_REUSEADDR true; - let rec incoming _ = - (try - let s, _ = Unix.accept sock in - handle_client s - with e -> - Printf.printf "Failed to accept new client: %S\n" (Printexc.to_string e)); - [ - { - Duppy.Task.priority = Non_blocking; - events = [`Read sock]; - handler = incoming; - }; - ] - in - (try Unix.bind sock bind_addr - with Unix.Unix_error (Unix.EADDRINUSE, "bind", "") -> - failwith (Printf.sprintf "port %d already taken" !port)); - Unix.listen sock max_conn; - Duppy.Task.add scheduler - { - Duppy.Task.priority = Non_blocking; - events = [`Read sock]; - handler = incoming; - }; - for i = 1 to !queues do - Printf.printf "Initiating queue %d\n%!" i; - ignore - (new_queue ~priority:Non_blocking - ~name:(Printf.sprintf "Non blocking queue #%d" i) - ()) - done; - Duppy.queue scheduler ~log:(fun _ -> ()) "root"