mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-12 05:59:10 +00:00
Add unix domain socket support to redbean
This commit is contained in:
parent
4b23985b7f
commit
fc097ac275
25 changed files with 594 additions and 172 deletions
89
tool/net/demo/unix-unix.lua
Normal file
89
tool/net/demo/unix-unix.lua
Normal file
|
@ -0,0 +1,89 @@
|
|||
-- UNIX Domain Sockets Example
|
||||
|
||||
-- So we can detect that child died.
|
||||
died = false
|
||||
function OnSigchld(sig)
|
||||
died = true
|
||||
unix.wait() -- Prevent it from becoming a zombie
|
||||
end
|
||||
assert(unix.sigaction(unix.SIGCHLD, OnSigchld))
|
||||
|
||||
-- So keyboard interurpts only go to subprocess.
|
||||
oldint = assert(unix.sigaction(unix.SIGINT, unix.SIG_IGN))
|
||||
oldquit = assert(unix.sigaction(unix.SIGQUIT, unix.SIG_IGN))
|
||||
|
||||
-- UNIX domain sockets need a file
|
||||
tmpdir = os.getenv('TMPDIR') or '/tmp'
|
||||
unixpath = '%s/redbean-unix.sock.%d' % {tmpdir, unix.getpid()}
|
||||
|
||||
-- Create child process which is the server.
|
||||
child = assert(unix.fork())
|
||||
if child == 0 then
|
||||
server = assert(unix.socket(unix.AF_UNIX, unix.SOCK_STREAM))
|
||||
assert(unix.setsockopt(server, unix.SOL_SOCKET, unix.SO_RCVTIMEO, 2))
|
||||
assert(unix.bind(server, unixpath))
|
||||
assert(unix.listen(server))
|
||||
client = assert(unix.accept(server))
|
||||
data = assert(unix.read(client))
|
||||
assert(data == 'ping!')
|
||||
assert(assert(unix.write(client, 'pong!')) == 5)
|
||||
assert(unix.close(client))
|
||||
unix.exit(0)
|
||||
end
|
||||
|
||||
-- Wait for the child to create the the socket file.
|
||||
function FileExists(path)
|
||||
st, err = unix.stat(path)
|
||||
return not err
|
||||
end
|
||||
expobackoff = 1
|
||||
while not died do
|
||||
if FileExists(unixpath) then
|
||||
break
|
||||
else
|
||||
expobackoff = expobackoff << 1
|
||||
unix.nanosleep(expobackoff // 1000000000,
|
||||
expobackoff % 1000000000)
|
||||
end
|
||||
end
|
||||
|
||||
-- Now connect to the socket.
|
||||
if not died then
|
||||
client = assert(unix.socket(unix.AF_UNIX, unix.SOCK_STREAM))
|
||||
assert(unix.connect(client, unixpath))
|
||||
assert(assert(unix.write(client, 'ping!')) == 5)
|
||||
data = assert(unix.read(client))
|
||||
assert(data == 'pong!')
|
||||
itworked = true
|
||||
else
|
||||
itworked = false
|
||||
end
|
||||
|
||||
-- Wait for client to terminate. We don't check error here because if
|
||||
-- the child already died and the signal handler reaped it, then this
|
||||
-- returns a ECHILD error which is fine.
|
||||
unix.wait()
|
||||
assert(itworked)
|
||||
|
||||
-- Now clean up the socket file.
|
||||
unix.unlink(unixpath)
|
||||
|
||||
SetStatus(200)
|
||||
SetHeader('Connection', 'close') -- be lazy and let _Exit() clean up signal handlers
|
||||
SetHeader('Content-Type', 'text/html; charset=utf-8')
|
||||
Write('<!doctype html>\r\n')
|
||||
Write('<title>redbean unix domain sockets example</title>\r\n')
|
||||
Write('<h1>\r\n')
|
||||
Write('<img style="vertical-align:middle" src="data:image/png;base64,\r\n')
|
||||
Write(EncodeBase64(LoadAsset('/redbean.png')))
|
||||
Write('">\r\n')
|
||||
Write('redbean unix domain sockets example\r\n')
|
||||
Write('</h1>\r\n')
|
||||
Write([[
|
||||
<p>
|
||||
<strong>It worked!</strong> We successfully sent a ping
|
||||
pong via UNIX local sockets. Please check out the source
|
||||
code to this example inside your redbean at unix-unix.lua.
|
||||
</p>
|
||||
]])
|
||||
Write('</h1>\r\n')
|
|
@ -2546,8 +2546,10 @@ UNIX MODULE
|
|||
|
||||
`family` defaults to `AF_INET` and can be:
|
||||
|
||||
- `AF_UNIX`
|
||||
- `AF_INET`
|
||||
- `AF_INET`: Creates Internet Protocol Version 4 (IPv4) socket.
|
||||
|
||||
- `AF_UNIX`: Creates local UNIX domain socket. On the New Technology
|
||||
this requires Windows 10 and only works with `SOCK_STREAM`.
|
||||
|
||||
`type` defaults to `SOCK_STREAM` and can be:
|
||||
|
||||
|
@ -2562,7 +2564,8 @@ UNIX MODULE
|
|||
- `SOCK_CLOEXEC`
|
||||
- `SOCK_NONBLOCK`
|
||||
|
||||
`protocol` defaults to `IPPROTO_TCP` and can be:
|
||||
`protocol` defaults to `IPPROTO_TCP` for AF_INET` and `0` for
|
||||
`AF_UNIX`. It can also be:
|
||||
|
||||
- `IPPROTO_IP`
|
||||
- `IPPROTO_ICMP`
|
||||
|
@ -2592,6 +2595,7 @@ UNIX MODULE
|
|||
`protocol` defaults to `0`.
|
||||
|
||||
unix.bind(fd:int[, ip:uint32, port:uint16])
|
||||
unix.bind(fd:int[, unixpath:str])
|
||||
├─→ true
|
||||
└─→ nil, unix.Errno
|
||||
|
||||
|
@ -2743,6 +2747,7 @@ UNIX MODULE
|
|||
|
||||
unix.accept(serverfd:int[, flags:int])
|
||||
├─→ clientfd:int, ip:uint32, port:uint16
|
||||
├─→ clientfd:int, unixpath:str
|
||||
└─→ nil, unix.Errno
|
||||
|
||||
Accepts new client socket descriptor for a listening tcp socket.
|
||||
|
@ -2753,6 +2758,7 @@ UNIX MODULE
|
|||
- `SOCK_NONBLOCK`
|
||||
|
||||
unix.connect(fd:int, ip:uint32, port:uint16)
|
||||
unix.connect(fd:int, unixpath:str)
|
||||
├─→ true
|
||||
└─→ nil, unix.Errno
|
||||
|
||||
|
@ -2764,16 +2770,21 @@ UNIX MODULE
|
|||
|
||||
unix.getsockname(fd:int)
|
||||
├─→ ip:uint32, port:uint16
|
||||
├─→ unixpath:str
|
||||
└─→ nil, unix.Errno
|
||||
|
||||
Retrieves the local address of a socket.
|
||||
|
||||
unix.getpeername(fd:int)
|
||||
├─→ ip:uint32, port:uint16
|
||||
├─→ unixpath:str
|
||||
└─→ nil, unix.Errno
|
||||
|
||||
Retrieves the remote address of a socket.
|
||||
|
||||
This operation will either fail on `AF_UNIX` sockets or return an
|
||||
empty string.
|
||||
|
||||
unix.recv(fd:int[, bufsiz:int[, flags:int]])
|
||||
├─→ data:str
|
||||
└─→ nil, unix.Errno
|
||||
|
@ -2787,6 +2798,7 @@ UNIX MODULE
|
|||
|
||||
unix.recvfrom(fd:int[, bufsiz:int[, flags:int]])
|
||||
├─→ data:str, ip:uint32, port:uint16
|
||||
├─→ data:str, unixpath:str
|
||||
└─→ nil, unix.Errno
|
||||
|
||||
`flags` may have any combination (using bitwise OR) of:
|
||||
|
@ -2810,6 +2822,7 @@ UNIX MODULE
|
|||
- `MSG_NOSIGNAL`
|
||||
|
||||
unix.sendto(fd:int, data:str, ip:uint32, port:uint16[, flags:int])
|
||||
unix.sendto(fd:int, data:str, unixpath:str[, flags:int])
|
||||
├─→ sent:int
|
||||
└─→ nil, unix.Errno
|
||||
|
||||
|
|
|
@ -167,6 +167,7 @@ o/tinylinux/tool/net/redbean.com: \
|
|||
o/$(MODE)/tool/net/demo/.init.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/.reload.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/sql.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/unix-unix.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/unix-rawsocket.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/unix-subprocess.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/unix-webserver.lua.zip.o \
|
||||
|
@ -215,6 +216,7 @@ o/$(MODE)/tool/net/redbean-demo.com.dbg: \
|
|||
o/$(MODE)/tool/net/largon2.o \
|
||||
o/$(MODE)/tool/net/net.pkg \
|
||||
o/$(MODE)/tool/net/demo/sql.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/unix-unix.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/unix-rawsocket.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/unix-subprocess.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/unix-webserver.lua.zip.o \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue