(* Copyright 2012 Tony Garnock-Jones . *) (* This file is part of Hop. *) (* Hop is free software: you can redistribute it and/or modify it *) (* under the terms of the GNU General Public License as published by the *) (* Free Software Foundation, either version 3 of the License, or (at your *) (* option) any later version. *) (* Hop is distributed in the hope that it will be useful, but *) (* WITHOUT ANY WARRANTY; without even the implied warranty of *) (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *) (* General Public License for more details. *) (* You should have received a copy of the GNU General Public License *) (* along with Hop. If not, see . *) open Lwt open Unix open Printf open Sexp let send_error ch message details = let m = Message.error (Str message, details) in ignore (Log.warn "Sending error" [m]); ch m let send_sexp_syntax_error ch explanation = send_error ch explanation (Str "http://people.csail.mit.edu/rivest/Sexp.txt") let dispatch_message n ch m = match m with | Message.Post (Str name, body, token) -> Node.send_ignore' name body | Message.Subscribe (Str filter, sink, name, Str reply_sink, Str reply_name) -> (match_lwt Node.bind (Node.name_of_string filter, n) with | true -> Node.post_ignore' reply_sink (Str reply_name) (Message.subscribe_ok (Str filter)) (Str "") | false -> Log.warn "Bind failed" [Str filter]) | Message.Unsubscribe (Str token) -> (match_lwt Node.unbind (Node.name_of_string token) with | true -> return () | false -> Log.warn "Unbind failed" [Str token]) | _ -> send_error ch "Message not understood" (Message.sexp_of_message m) let issue_banner cin cout = lwt () = output_sexp cout (Arr [Str "hop"; Str ""]) in lwt () = Lwt_io.flush cout in lwt () = output_sexp cout (Message.subscribe (Str (Node.local_container_name()), Str "", Str "", Str "", Str "")) in lwt () = Lwt_io.flush cout in return true let relay_boot (peername, cin, cout) = return (peername, Lwt_mutex.create (), cin, cout) let relay_handler (_, mtx, _, cout) _ m = Lwt_mutex.with_lock mtx (fun () -> output_sexp cout m) let relay_mainloop (peername, mtx, cin, cout) n = let write_sexp sexp = Lwt_mutex.with_lock mtx (fun () -> output_sexp cout sexp) in (try_lwt while_lwt true do lwt message_sexp = Sexp.input_sexp cin in dispatch_message n write_sexp (Message.message_of_sexp message_sexp) done with | Sexp.Syntax_error explanation -> lwt () = send_sexp_syntax_error write_sexp explanation in Log.info "Disconnected relay for syntax error" [Str (Connections.endpoint_name peername); Str explanation]) let start (s, peername) = Connections.start_connection "relay" issue_banner relay_boot relay_handler relay_mainloop (s, peername) let init () = Util.create_daemon_thread "Hop listener" None (Net.start_net "Hop" 5671) start