From 64789d1fe98bee96f69e0d9a4df56aa8c6b1ab45 Mon Sep 17 00:00:00 2001 From: Daniel Barlow Date: Mon, 30 Jun 2025 18:17:13 +0100 Subject: [PATCH] rewrite fake-nmea to not need socat --- pkgs/maps/fake-nmea.fnl | 76 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/pkgs/maps/fake-nmea.fnl b/pkgs/maps/fake-nmea.fnl index f30631f..a361cc3 100644 --- a/pkgs/maps/fake-nmea.fnl +++ b/pkgs/maps/fake-nmea.fnl @@ -1,10 +1,72 @@ -(local { : sleep } (require :posix.unistd)) +(local { : sleep : close } (require :posix.unistd)) +(local sock (require :posix.sys.socket)) +(local poll (require :posix.poll)) +(local { : view } (require :fennel)) + +(fn handle-client [fd event] + (case event + {:HUP true} + (do + (print fd " disconnected") + (close fd) + (values fd nil)) + {:IN true} + (do + (sock.recv fd 1024) ; discard input and carry on + nil))) + +(fn accept-new-connection [server-sock event] + (case event + {:IN true} + (do + (print "new connection") + (let [connected (sock.accept server-sock)] + (print connected) + (values connected handle-client))) + {:HUP true} + (do + (print "HUP on server socket") + (os.exit 1)) + _ + (values nil nil))) + +(fn server-socket [path] + (let [s (assert (sock.socket sock.AF_UNIX sock.SOCK_STREAM 0)) + sa { :family sock.AF_UNIX + :path path + }] + (assert (sock.bind s sa)) + (assert (sock.listen s 10)) + s)) + +(fn read-with-rewind [handle] + (let [(s err) (handle:read "L")] + (if s + s + (if (and (not err) (handle:seek "set" 0)) ; eof + (read-with-rewind handle) + (error err))))) + +(fn write-sentences [handle outputs] + (var done false) + (while (not done) + (let [l (read-with-rewind handle)] + (if (string.match l "GNS") (set done true)) + (each [fd action (pairs outputs)] + (when (sock.getpeername fd) ; cheeky + (sock.send fd l)))))) (let [[filename socketname] arg - socket (io.popen (.. "socat - unix-listen:" socketname) :w)] + server (server-socket socketname) + fd-actions { server accept-new-connection }] (with-open [handle (io.open filename :r)] - (each [l (handle:lines "L")] - (if (string.match l "GNS") (sleep 1)) - (socket:write l) - (socket:flush) - ))) + (while true + (let [poll-fds (collect [fd _ (pairs fd-actions)] + (values fd {:events { :IN true } }))] + (if (> (poll.poll poll-fds (* 1 1000)) 0) + (each [fd v (pairs poll-fds)] + (when (. v :revents) + (print :polled fd (view v.revents)) + (let [(k v) ((. fd-actions fd) fd v.revents)] + (and k (tset fd-actions k v))))) + (write-sentences handle fd-actions))))))