Compare commits
4 Commits
90d9d0e811
...
032d0f8aca
Author | SHA1 | Date |
---|---|---|
Daniel Barlow | 032d0f8aca | |
Daniel Barlow | b8ac9e5279 | |
Daniel Barlow | ff2604ca5d | |
Daniel Barlow | 72789984ce |
54
THOUGHTS.txt
54
THOUGHTS.txt
|
@ -4676,3 +4676,57 @@ needs to filter, but the client will anyway have to do some message
|
||||||
parsing so they can distinguish add from remove
|
parsing so they can distinguish add from remove
|
||||||
|
|
||||||
* where do we start?
|
* where do we start?
|
||||||
|
|
||||||
|
Sun Apr 21 13:31:48 BST 2024
|
||||||
|
|
||||||
|
We have the mechanics of it working (albeit implemented in the
|
||||||
|
simplest possible terms), we need to glue it to some I/O
|
||||||
|
|
||||||
|
1) open a netlink socket and read the events from it
|
||||||
|
|
||||||
|
2) "create a PF_UNIX socket of type SOCK_STREAM, and accept connections on it, then each time you accept a connection, you get a new fd"
|
||||||
|
|
||||||
|
- accept connection
|
||||||
|
- read terms from it
|
||||||
|
- register callback that writes event to connected socket
|
||||||
|
|
||||||
|
minisock has no support for "test if fd is ready" or "wait for [fds]
|
||||||
|
to become ready", either we need poll() or we could add a call for "is
|
||||||
|
this fd ready to read" and use coroutines. Fork minisock or add as
|
||||||
|
another library?
|
||||||
|
|
||||||
|
[ if we fork minisock we could expose the protocol param to Lua
|
||||||
|
so we could use it for netlink ]
|
||||||
|
|
||||||
|
Tue Apr 23 19:13:45 BST 2024
|
||||||
|
|
||||||
|
we could convert from minisock to lualinux. if we can also use that to
|
||||||
|
get rid of nellie and/or lfs, the size tradeoff is minimal
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Is there some way we could test the devout event loop?
|
||||||
|
|
||||||
|
I can register a fd with a callback
|
||||||
|
when the fd is ready, my callback is called
|
||||||
|
when the callback return true it remains registered
|
||||||
|
when the callback return true it is unregistered and the fd is closed
|
||||||
|
|
||||||
|
loop.register
|
||||||
|
loop.registered?
|
||||||
|
loop.feed
|
||||||
|
|
||||||
|
Tue Apr 23 20:34:03 BST 2024
|
||||||
|
|
||||||
|
I think we could make the event loop abstraction leak less?
|
||||||
|
It's not actually a _loop_, all the actual GOTO 10 happens
|
||||||
|
outside of it
|
||||||
|
|
||||||
|
1) see if we can do netlink in lualinux
|
||||||
|
2) if so, convert it to lualinux
|
||||||
|
3) add netlink socket to event loop
|
||||||
|
4) make it send messages to subscribers
|
||||||
|
5) package it
|
||||||
|
6) make inout test use it instead of uevent-watcher
|
||||||
|
7) write an inout test variant that has the stick inserted
|
||||||
|
at boot time already
|
||||||
|
|
|
@ -71,6 +71,7 @@ in {
|
||||||
levitate = callPackage ./levitate {};
|
levitate = callPackage ./levitate {};
|
||||||
libubootenv = callPackage ./libubootenv {};
|
libubootenv = callPackage ./libubootenv {};
|
||||||
linotify = callPackage ./linotify {};
|
linotify = callPackage ./linotify {};
|
||||||
|
lualinux = callPackage ./lualinux {};
|
||||||
|
|
||||||
# we need to build real lzma instead of using xz, because the lzma
|
# we need to build real lzma instead of using xz, because the lzma
|
||||||
# decoder in u-boot doesn't understand streaming lzma archives
|
# decoder in u-boot doesn't understand streaming lzma archives
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
, fennel
|
, fennel
|
||||||
, stdenv
|
, stdenv
|
||||||
, fennelrepl
|
, fennelrepl
|
||||||
, minisock
|
, lualinux
|
||||||
}:
|
}:
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
name = "devout";
|
name = "devout";
|
||||||
|
@ -15,12 +15,12 @@ stdenv.mkDerivation {
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
mkdir -p $out/bin
|
mkdir -p $out/bin
|
||||||
cp -p ${writeFennel "devout" {
|
cp -p ${writeFennel "devout" {
|
||||||
packages = [fennel anoia nellie lua.pkgs.luafilesystem minisock];
|
packages = [fennel anoia nellie lua.pkgs.luafilesystem lualinux];
|
||||||
mainFunction = "run";
|
mainFunction = "run";
|
||||||
} ./devout.fnl} $out/bin/devout
|
} ./devout.fnl} $out/bin/devout
|
||||||
'';
|
'';
|
||||||
checkPhase = ''
|
checkPhase = ''
|
||||||
LUA_CPATH=${minisock}/lib/lua/5.3/?.so\;$LUA_CPATH \
|
LUA_CPATH=${lualinux}/lib/lua/5.3/?.so\;$LUA_CPATH \
|
||||||
fennelrepl ./test.fnl
|
fennelrepl ./test.fnl
|
||||||
'';
|
'';
|
||||||
doCheck = true;
|
doCheck = true;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
(local sock (require :minisock))
|
(local ll (require :lualinux))
|
||||||
(local { : view } (require :fennel))
|
(local { : view } (require :fennel))
|
||||||
|
|
||||||
(fn trace [expr]
|
(fn trace [expr]
|
||||||
(doto expr (print :TRACE (view expr))))
|
(do (print :TRACE (view expr)) expr))
|
||||||
|
|
||||||
(fn parse-uevent [s]
|
(fn parse-uevent [s]
|
||||||
(let [at (string.find s "@" 1 true)
|
(let [at (string.find s "@" 1 true)
|
||||||
|
@ -50,29 +50,39 @@
|
||||||
:unsubscribe (fn [_ id] (tset subscribers id nil))
|
:unsubscribe (fn [_ id] (tset subscribers id nil))
|
||||||
}))
|
}))
|
||||||
|
|
||||||
;; #define POLLIN 0x0001
|
;; grepped from kernel headers
|
||||||
;; #define POLLPRI 0x0002
|
|
||||||
;; #define POLLOUT 0x0004
|
(local POLLIN 0x0001)
|
||||||
;; #define POLLERR 0x0008
|
(local POLLPRI 0x0002)
|
||||||
;; #define POLLHUP 0x0010
|
(local POLLOUT 0x0004)
|
||||||
;; #define POLLNVAL 0x0020
|
(local POLLERR 0x0008)
|
||||||
|
(local POLLHUP 0x0010)
|
||||||
|
(local POLLNVAL 0x0020)
|
||||||
|
|
||||||
|
(local AF_LOCAL 1)
|
||||||
|
(local AF_NETLINK 16)
|
||||||
|
(local SOCK_STREAM 1)
|
||||||
|
(local SOCK_DGRAM 2)
|
||||||
|
(local SOCK_RAW 3)
|
||||||
|
(local NETLINK_KOBJECT_UEVENT 15)
|
||||||
|
|
||||||
(fn unix-socket [name]
|
(fn unix-socket [name]
|
||||||
(let [addr (.. "\1\0" name "\0\0\0\0\0")
|
(let [addr (.. "\1\0" name "\0\0\0\0\0")]
|
||||||
(sock err) (sock.bind addr)]
|
(match (ll.socket AF_LOCAL SOCK_STREAM 0)
|
||||||
(assert sock err)))
|
fd (match (ll.bind fd addr)
|
||||||
|
0 (doto fd (ll.listen 32))
|
||||||
|
(nil err) (values nil err))
|
||||||
|
(nil err) (values nil err))))
|
||||||
|
|
||||||
(fn pollfds-for [fds]
|
(fn pollfds-for [fds]
|
||||||
(table.concat (icollect [_ v (ipairs fds)] (string.pack "iHH" v 1 0))))
|
(icollect [_ v (ipairs fds)]
|
||||||
|
(bor (lshift v 32) (lshift 1 16))))
|
||||||
|
|
||||||
(fn unpack-pollfds [pollfds]
|
(fn unpack-pollfds [pollfds]
|
||||||
(var i 1)
|
(collect [_ v (ipairs pollfds)]
|
||||||
(let [fds {}]
|
(let [fd (band (rshift v 32) 0xffffffff)
|
||||||
(while (< i (# pollfds))
|
revent (band v 0xffff)]
|
||||||
(let [(fd _ revents i_) (string.unpack "iHH" pollfds i)]
|
(values fd revent))))
|
||||||
(if (> revents 0) (tset fds fd revents))
|
|
||||||
(set i i_)))
|
|
||||||
fds))
|
|
||||||
|
|
||||||
(fn parse-terms [str]
|
(fn parse-terms [str]
|
||||||
(print :terms str)
|
(print :terms str)
|
||||||
|
@ -80,7 +90,7 @@
|
||||||
(string.match n "(.-)=(.+)")))
|
(string.match n "(.-)=(.+)")))
|
||||||
|
|
||||||
(fn handle-client [db client]
|
(fn handle-client [db client]
|
||||||
(match (trace (sock.read client))
|
(match (ll.read client)
|
||||||
"" (do
|
"" (do
|
||||||
(db:unsubscribe client)
|
(db:unsubscribe client)
|
||||||
false)
|
false)
|
||||||
|
@ -88,11 +98,18 @@
|
||||||
(db:subscribe
|
(db:subscribe
|
||||||
client
|
client
|
||||||
(fn [e]
|
(fn [e]
|
||||||
(sock.write client (view e)))
|
(ll.write client (view e)))
|
||||||
(parse-terms s))
|
(parse-terms s))
|
||||||
true)
|
true)
|
||||||
(nil err) (do (print err) false)))
|
(nil err) (do (print err) false)))
|
||||||
|
|
||||||
|
(fn open-netlink [groups]
|
||||||
|
(match (ll.socket AF_NETLINK SOCK_RAW NETLINK_KOBJECT_UEVENT)
|
||||||
|
fd (doto fd (ll.bind (string.pack "I2I2I4I4" ; family pad pid groups
|
||||||
|
AF_NETLINK 0 0 groups)))
|
||||||
|
(nil errno) (values nil errno)))
|
||||||
|
|
||||||
|
|
||||||
(fn event-loop []
|
(fn event-loop []
|
||||||
(let [fds {}]
|
(let [fds {}]
|
||||||
{
|
{
|
||||||
|
@ -101,27 +118,30 @@
|
||||||
(each [fd revent (pairs revents)]
|
(each [fd revent (pairs revents)]
|
||||||
(when (not ((. fds fd) fd))
|
(when (not ((. fds fd) fd))
|
||||||
(tset fds fd nil)
|
(tset fds fd nil)
|
||||||
(sock.close fd))))
|
(ll.close fd))))
|
||||||
:fds #(icollect [fd _ (pairs fds)] fd)
|
:fds #(icollect [fd _ (pairs fds)] fd)
|
||||||
:_tbl #(do fds) ;exposed for tests
|
:_tbl #(do fds) ;exposed for tests
|
||||||
}))
|
}))
|
||||||
|
|
||||||
(fn run []
|
(fn run []
|
||||||
(let [[sockname] arg
|
(let [[sockname nl-groups] arg
|
||||||
s (unix-socket sockname)
|
s (unix-socket sockname)
|
||||||
db (database)
|
db (database)
|
||||||
|
nl (open-netlink nl-groups)
|
||||||
loop (event-loop)]
|
loop (event-loop)]
|
||||||
(loop:register
|
(loop:register
|
||||||
s
|
s
|
||||||
#(match (sock.accept s)
|
#(match (ll.accept s)
|
||||||
(client addr)
|
(client addr)
|
||||||
(do
|
(do
|
||||||
(loop:register client (partial handle-client db))
|
(loop:register client (partial handle-client db))
|
||||||
true)))
|
true)))
|
||||||
|
(loop:register
|
||||||
|
nl
|
||||||
|
#(do (print :netlink (ll.read nl)) true))
|
||||||
(while true
|
(while true
|
||||||
(let [pollfds (pollfds-for (loop:fds))
|
(let [pollfds (pollfds-for (loop:fds))]
|
||||||
(rpollfds numfds) (sock.poll pollfds 1000)]
|
(ll.poll pollfds 5000)
|
||||||
(when (> numfds 0)
|
(loop:feed (unpack-pollfds pollfds))))))
|
||||||
(loop:feed (unpack-pollfds rpollfds)))))))
|
|
||||||
|
|
||||||
{ : database : run : event-loop }
|
{ : database : run : event-loop }
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
{ lua, lib, fetchFromGitHub }:
|
||||||
|
let
|
||||||
|
pname = "lualinux";
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
repo = "lualinux";
|
||||||
|
owner = "philanc";
|
||||||
|
rev = "1d4c962aad9cbe01c05df741b91e8b39c356362c";
|
||||||
|
hash = "sha256-+Ys4sERG+TI8nRzG38UP+KqbH0efspaX0j4IHCt56RI=";
|
||||||
|
};
|
||||||
|
in lua.pkgs.buildLuaPackage {
|
||||||
|
inherit pname;
|
||||||
|
version = "0.1"; # :shrug:
|
||||||
|
|
||||||
|
inherit src;
|
||||||
|
makeFlags = [ "LUADIR=." "lualinux.so" ];
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p "$out/lib/lua/${lua.luaversion}"
|
||||||
|
cp ${pname}.so "$out/lib/lua/${lua.luaversion}/"
|
||||||
|
'';
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue