(in-package :smsg-network) (defun command-loop (in out route) (loop (let ((command (read-sexp in))) (when (not (handle-inbound-command command in out route)) (return))))) (defun handle-inbound-command (command in out route) (ematch-sexp command (("subscribe" filter sink name reply-sink reply-name) (if (rebind-node filter nil route) (when (plusp (length reply-sink)) (post reply-sink reply-name (sexp-build ("subscribe-ok" (= filter))))) (report! `(rebind-failed ,command)))) (("unsubscribe" id) (when (not (rebind-node id route nil)) (report! `(rebind-failed ,command)))) (("post" name body token) (send name body)))) (defun relay (in out localname servermode) (flet ((route (message) (write-sexp message out) (write-byte 13 out) (write-byte 10 out))) (if servermode (route (sexp-quote ("hop" "0"))) (ematch-sexp (read-sexp in) (("hop" "0") t))) (force-output out) (route (sexp-build ("subscribe" (= localname) "" "" "" ""))) (command-loop in out #'route))) (defun handle-connection (stream) (relay stream stream (sexp-quote "smsg") t)) (defun serve-on-port (port) (usocket:socket-server "localhost" port 'handle-connection '() :in-new-thread t :multi-threading t :reuse-address t :element-type '(unsigned-byte 8))) (defun client (localname hostname portnumber) (let ((s (usocket:socket-stream (usocket:socket-connect hostname portnumber :element-type '(unsigned-byte 8))))) (relay s s localname nil)))