fake-nmea.fnl (2150B)
1 (local { : sleep : close } (require :posix.unistd)) 2 (local sock (require :posix.sys.socket)) 3 (local poll (require :posix.poll)) 4 (local { : view } (require :fennel)) 5 6 (fn handle-client [fd event] 7 (case event 8 {:HUP true} 9 (do 10 (print fd " disconnected") 11 (close fd) 12 (values fd nil)) 13 {:IN true} 14 (do 15 (sock.recv fd 1024) ; discard input and carry on 16 nil))) 17 18 (fn accept-new-connection [server-sock event] 19 (case event 20 {:IN true} 21 (do 22 (print "new connection") 23 (let [connected (sock.accept server-sock)] 24 (print connected) 25 (values connected handle-client))) 26 {:HUP true} 27 (do 28 (print "HUP on server socket") 29 (os.exit 1)) 30 _ 31 (values nil nil))) 32 33 (fn server-socket [path] 34 (let [s (assert (sock.socket sock.AF_UNIX sock.SOCK_STREAM 0)) 35 sa { :family sock.AF_UNIX 36 :path path 37 }] 38 (assert (sock.bind s sa)) 39 (assert (sock.listen s 10)) 40 s)) 41 42 (fn read-with-rewind [handle] 43 (let [(s err) (handle:read "L")] 44 (if s 45 s 46 (if (and (not err) (handle:seek "set" 0)) ; eof 47 (read-with-rewind handle) 48 (error err))))) 49 50 (fn write-sentences [handle outputs] 51 (var done false) 52 (while (not done) 53 (let [l (read-with-rewind handle)] 54 (if (string.match l "GNS") (set done true)) 55 (each [fd action (pairs outputs)] 56 (when (= action handle-client) 57 (print :sending l) 58 (sock.send fd l)))))) 59 60 (let [[filename socketname] arg 61 server (server-socket socketname) 62 fd-actions { server accept-new-connection }] 63 (with-open [handle (io.open filename :r)] 64 (while true 65 (let [poll-fds (collect [fd _ (pairs fd-actions)] 66 (values fd {:events { :IN true } }))] 67 (if (> (poll.poll poll-fds (* 1 1000)) 0) 68 (each [fd v (pairs poll-fds)] 69 (when (. v :revents) 70 (print :polled fd (view v.revents)) 71 (let [(k v) ((. fd-actions fd) fd v.revents)] 72 (and k (tset fd-actions k v))))) 73 (write-sentences handle fd-actions))))))