Rewrite syndev to uevent_dump
This commit is contained in:
parent
4512b33fa9
commit
f51f92c30d
|
@ -1,3 +1,3 @@
|
|||
include_rules
|
||||
: syndev.nim | $(SYNDICATE_PROTOCOL) |> !nim_bin |> {bin}
|
||||
: foreach *.nim | $(SYNDICATE_PROTOCOL) |> !nim_bin |> {bin}
|
||||
: {bin} |> !assert_built |>
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
# SPDX-FileCopyrightText: ☭ Emery Hemingway
|
||||
# SPDX-License-Identifier: Unlicense
|
||||
|
||||
# *Do not misinterpret any of this as documentation for handling Linux uevents.*
|
||||
|
||||
import std/[asyncdispatch, nativesockets, asyncnet, os, parseutils, posix]
|
||||
import preserves, syndicate
|
||||
|
||||
var
|
||||
AF_NETLINK {.importc, header: "sys/socket.h", nodecl.}: uint16
|
||||
NETLINK_KOBJECT_UEVENT {.importc, header: "linux/netlink.h", nodecl.}: cint
|
||||
|
||||
type
|
||||
Sockaddr_nl {.importc: "struct sockaddr_nl", header: "linux/netlink.h".} = object
|
||||
nl_family: uint16
|
||||
nl_pad: uint16
|
||||
nl_pid: uint32
|
||||
nl_groups: uint32
|
||||
|
||||
proc initSockaddr(family = AF_NETLINK; pid, groups = 0'u32): Sockaddr_nl =
|
||||
Sockaddr_nl(nl_family: family, nl_pid: pid, nl_groups: groups)
|
||||
|
||||
proc saddr(sa_nl: var Sockaddr_nl): ptr Sockaddr =
|
||||
cast[ptr Sockaddr](addr sa_nl)
|
||||
|
||||
proc openUeventSocket: AsyncSocket =
|
||||
result = newAsyncSocket(
|
||||
cint AF_NETLINK,
|
||||
posix.SOCK_DGRAM,
|
||||
NETLINK_KOBJECT_UEVENT,
|
||||
buffered = false
|
||||
)
|
||||
var sa = initSockaddr(pid = uint32 getPid(), groups = 1)
|
||||
if bindAddr(result.getFd, saddr sa, SockLen sizeof(sa)) != 0:
|
||||
close(result)
|
||||
raiseOSError(osLastError(), "failed to bind Netlink socket")
|
||||
if sa.nl_family != AF_NETLINK:
|
||||
close(result)
|
||||
raise newException(IOError, "Netlink not supported")
|
||||
|
||||
proc main(facet: Facet; ds: Ref; sock: AsyncSocket) =
|
||||
var
|
||||
buf = newString(1 shl 14)
|
||||
msg = initRecord("uevent", "".toPreserve, "".toPreserve, "".toSymbol, initDictionary(), 0.toPreserve)
|
||||
key, val: string
|
||||
proc recvUevent {.gcsafe.} =
|
||||
let fut = recvInto(sock, buf[0].addr, buf.len)
|
||||
addCallback(fut, facet) do (turn: var Turn):
|
||||
let n = read fut
|
||||
if n < 1:
|
||||
close(sock)
|
||||
else:
|
||||
var i = 0
|
||||
while i < n:
|
||||
inc i, skipWhile(buf, {'\0'}, i)
|
||||
inc i, parseUntil(buf, key, {'=', '@'}, i)
|
||||
if i < n:
|
||||
let sep = buf[i]
|
||||
inc i, parseUntil(buf, val, '\0', i+1)+1
|
||||
case sep
|
||||
of '@':
|
||||
if msg.record[3].dict.len > 0:
|
||||
cannonicalize(msg.record[3])
|
||||
message(turn, ds, msg)
|
||||
msg.record[3].dict.setLen(0)
|
||||
of '=':
|
||||
if key == "SUBSYSTEM":
|
||||
msg.record[0].string = val
|
||||
elif key == "DEVPATH":
|
||||
msg.record[1].string = val
|
||||
elif key == "ACTION":
|
||||
msg.record[2].symbol = Symbol val
|
||||
elif key == "SEQNUM":
|
||||
discard parseBiggestInt(val, msg.record[4].int)
|
||||
else:
|
||||
# TODO: check if val can be an integer
|
||||
var num: BiggestInt
|
||||
if parseBiggestInt(val, num) == val.len:
|
||||
add(msg.record[3].dict, (key.toSymbol, num.toPreserve,))
|
||||
else:
|
||||
add(msg.record[3].dict, (key.toSymbol, val.toPreserve,))
|
||||
val.setLen(0)
|
||||
else:
|
||||
stderr.writeLine "uevent parser synchronization lost"
|
||||
break
|
||||
recvUevent()
|
||||
recvUevent()
|
||||
|
||||
type Args {.preservesDictionary.} = object
|
||||
machine: Ref
|
||||
|
||||
runActor("syndev") do (root: Ref; turn: var Turn):
|
||||
connectStdio(root, turn)
|
||||
during(turn, root, ?Args) do (machine: Ref):
|
||||
let sock = openUeventSocket()
|
||||
main(turn.facet, machine, sock)
|
||||
do:
|
||||
close(sock)
|
|
@ -0,0 +1,106 @@
|
|||
# SPDX-FileCopyrightText: ☭ Emery Hemingway
|
||||
# SPDX-License-Identifier: Unlicense
|
||||
|
||||
# *Do not misinterpret any of this as documentation for handling Linux uevents.*
|
||||
|
||||
import std/[nativesockets, os, parseutils, posix]
|
||||
import pkg/sys/[handles, ioqueue, sockets]
|
||||
import preserves, syndicate, syndicate/relays
|
||||
|
||||
var
|
||||
AF_NETLINK {.importc, header: "sys/socket.h", nodecl.}: uint16
|
||||
NETLINK_KOBJECT_UEVENT {.importc, header: "linux/netlink.h", nodecl.}: cint
|
||||
|
||||
type
|
||||
Sockaddr_nl {.importc: "struct sockaddr_nl", header: "linux/netlink.h".} = object
|
||||
nl_family: uint16
|
||||
nl_pad: uint16
|
||||
nl_pid: uint32
|
||||
nl_groups: uint32
|
||||
|
||||
proc initSockaddr(family = AF_NETLINK; pid, groups: uint32): Sockaddr_nl =
|
||||
Sockaddr_nl(nl_family: family, nl_pid: pid, nl_groups: groups)
|
||||
|
||||
proc saddr(sa_nl: var Sockaddr_nl): ptr Sockaddr =
|
||||
cast[ptr Sockaddr](addr sa_nl)
|
||||
|
||||
proc openUeventSocket: SocketHandle =
|
||||
result = createNativeSocket(
|
||||
cint AF_NETLINK,
|
||||
cint posix.SOCK_DGRAM,
|
||||
NETLINK_KOBJECT_UEVENT,
|
||||
)
|
||||
var sa = initSockaddr(pid = uint32 getPid(), groups = 1)
|
||||
if bindAddr(result, saddr sa, SockLen sizeof(sa)) != 0:
|
||||
close(result)
|
||||
raiseOSError(osLastError(), "failed to bind Netlink socket")
|
||||
if sa.nl_family != AF_NETLINK:
|
||||
close(result)
|
||||
raise newException(IOError, "Netlink not supported")
|
||||
|
||||
proc openUeventSocketAsync: AsyncConn[sockets.Protocol.Unix] =
|
||||
let fd = openUeventSocket()
|
||||
var flags = fcntl(fd.cint, F_GETFL)
|
||||
if flags < 0:
|
||||
raiseOSError(osLastError())
|
||||
flags = flags or O_NONBLOCK
|
||||
if fcntl(fd.cint, F_SETFL, flags) < 0:
|
||||
raiseOSError(osLastError())
|
||||
AsyncConn[sockets.Protocol.Unix] fd.SocketFD.initHandle.newAsyncSocket
|
||||
|
||||
proc sendMessage(turn: var Turn; ds: Cap; buf: string; n: int) =
|
||||
var
|
||||
msg = initRecord("uevent", toPreserves"", toPreserves"", toSymbol"", initDictionary(), 0.toPreserves)
|
||||
key, val: string
|
||||
i = 0
|
||||
while i < n:
|
||||
inc i, skipWhile(buf, {'\0'}, i)
|
||||
inc i, parseUntil(buf, key, {'=', '@'}, i)
|
||||
if i < n:
|
||||
let sep = buf[i]
|
||||
inc i, parseUntil(buf, val, '\0', i+1)+1
|
||||
case sep
|
||||
of '@': discard
|
||||
of '=':
|
||||
if key == "SUBSYSTEM":
|
||||
msg.record[0].string = val
|
||||
elif key == "DEVPATH":
|
||||
msg.record[1].string = val
|
||||
elif key == "ACTION":
|
||||
msg.record[2].symbol = Symbol val
|
||||
elif key == "SEQNUM":
|
||||
msg.record[4] = parsePreserves(val)
|
||||
else:
|
||||
# TODO: check if val can be an integer
|
||||
var num: BiggestInt
|
||||
if parseBiggestInt(val, num) == val.len:
|
||||
add(msg.record[3].dict, (key.toSymbol, num.toPreserve,))
|
||||
else:
|
||||
add(msg.record[3].dict, (key.toSymbol, val.toPreserve,))
|
||||
val.setLen(0)
|
||||
else:
|
||||
stderr.writeLine "uevent parser failure"
|
||||
return
|
||||
if msg.record[3].dict.len > 0:
|
||||
cannonicalize(msg.record[3])
|
||||
message(turn, ds, msg)
|
||||
msg.record[3].dict.setLen(0)
|
||||
|
||||
proc loop(facet: Facet; ds: Cap; sock: AsyncConn[sockets.Protocol.Unix]) {.asyncio.} =
|
||||
let buf = new string
|
||||
buf[].setLen(16 shl 10)
|
||||
while true:
|
||||
let n = read(sock, buf)
|
||||
if n < 1: stopActor(facet)
|
||||
else:
|
||||
proc act(turn: var Turn) =
|
||||
sendMessage(turn, ds, buf[], n)
|
||||
run(facet, act)
|
||||
|
||||
runActor("uevent_dump") do (turn: var Turn):
|
||||
let sock = openUeventSocketAsync()
|
||||
onStop(turn) do (turn: var Turn):
|
||||
close(sock)
|
||||
resolveEnvironment(turn) do (turn: var Turn; ds: Cap):
|
||||
discard trampoline:
|
||||
whelp loop(turn.facet, ds, sock)
|
|
@ -1,13 +1,13 @@
|
|||
# Package
|
||||
|
||||
version = "20230704"
|
||||
version = "20240315"
|
||||
author = "Emery Hemingway"
|
||||
description = "Syndicated actor for publishing Linux device events"
|
||||
description = "Syndicate utilties for Linux."
|
||||
license = "Unlicense"
|
||||
srcDir = "src"
|
||||
bin = @["syndev"]
|
||||
bin = @["uevent_dump"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.12", "syndicate >= 20230701"
|
||||
requires "nim >= 1.6.12", "syndicate >= 20240208", "https://github.com/ehmry/nim-sys.git#b974e1a4ca6ae7d89fc9e7b3714b1e7daf6f33e5", "https://github.com/nim-works/cps"
|
||||
|
|
Loading…
Reference in New Issue