#! /home/tak/bin/mytop (************************************************************ proxy.ml Created : Fri Feb 15 22:18:25 2002 Last modified: Sun Feb 09 13:33:12 2003 FTP Directory: sources/ocaml # mytopの作り方 > ocamlmktop unix.cma -custom -o mytop 並列度がなく、ブロックばかりするので、遅いプロキシ ************************************************************) #use "url.ml" module Unix = UnixLabels;; let port = 80 let connect host port = let addr = Unix.gethostbyname host in let s = Unix.socket ~domain:Unix.PF_INET ~kind:Unix.SOCK_STREAM ~protocol:0 in Unix.connect s (Unix.ADDR_INET(addr.Unix.h_addr_list.(0), port)); s let request_split_regexp = Str.regexp "\\(\r\n\\)+" let line_split_regexp = Str.regexp " +" let receive_request s = let c = ref "" in let buf = String.make 1 '\000' in let lf = ref false in try while true do let num = Unix.recv s buf 0 1 [] in if num = 0 then raise End_of_file else let ch = String.sub buf 0 num in begin c := !c^(String.sub buf 0 num); let size = String.length !c in if size >= 4 then let last = Str.last_chars !c 4 in if last = "\r\n\r\n" then raise End_of_file end done; "hoge" with End_of_file -> !c let receive_message_from_connected_socket s = let c = ref "" in let buf = String.make 1 '\000' in try while true do let num = Unix.recv s buf 0 1 [] in if num = 0 then raise End_of_file else c := !c^(String.sub buf 0 num) done; "hoge" with End_of_file -> !c let interpret_request request = let hd::tl = Str.split request_split_regexp request in let m::url::remain = Str.split line_split_regexp hd in let u = of_string url in let host = u.hostname in let path = u.path in (host, path) let session (serv_sock, addr) = let request = receive_request serv_sock in let _ = print_endline ("PROXY request =====>\n" ^ request) in let (host, path) = interpret_request request in let sock = connect host port in let size = String.length request in let _ = Unix.send sock request 0 size [] in let reply = receive_message_from_connected_socket sock in let _ = print_endline ("PROXY reply <=====\n" ^ reply); flush stdout in let reply_size = String.length reply in begin ignore (Unix.send serv_sock reply 0 reply_size []); Unix.shutdown serv_sock Unix.SHUTDOWN_SEND; end let listen_as_server ~host ~port = let s = Unix.socket ~domain:Unix.PF_INET ~kind:Unix.SOCK_STREAM ~protocol:0 in begin Unix.bind s ~addr:(Unix.ADDR_INET(((Unix.gethostbyname host).Unix.h_addr_list).(0), port)); Unix.listen s ~max:5; (* maxは受け付ける接続数 *) while true do session (Unix.accept s) done end;; (************************************************************ * メイン * * *) if (Array.length Sys.argv) != 3 then print_string "listen [hostname] [port]\n" else listen_as_server Sys.argv.(1) (int_of_string Sys.argv.(2));