diff options
author | bptato <nincsnevem662@gmail.com> | 2023-12-14 20:38:30 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2023-12-14 20:38:30 +0100 |
commit | 600058a19e58aee247ca90b9eb2a8271b458b2d4 (patch) | |
tree | 5f9d07d7236ff7bb67555c04cb65a12b4d1d32fa /src/io | |
parent | 2f902aeaee8ffa6ceb54876af8f73f56f7840004 (diff) | |
download | chawan-600058a19e58aee247ca90b9eb2a8271b458b2d4.tar.gz |
socketstream, serversocket: portable bindUnix
reimplementing it portably in Nim seems incredibly annoying, so we just use C
Diffstat (limited to 'src/io')
-rw-r--r-- | src/io/bind_unix.c | 14 | ||||
-rw-r--r-- | src/io/connect_unix.c | 14 | ||||
-rw-r--r-- | src/io/serversocket.nim | 25 | ||||
-rw-r--r-- | src/io/socketstream.nim | 7 |
4 files changed, 50 insertions, 10 deletions
diff --git a/src/io/bind_unix.c b/src/io/bind_unix.c new file mode 100644 index 00000000..02e86eed --- /dev/null +++ b/src/io/bind_unix.c @@ -0,0 +1,14 @@ +#include <stddef.h> +#include <sys/socket.h> +#include <sys/un.h> + +int bind_unix_from_c(int socket, const char *path, int pathlen) +{ + struct sockaddr_un sa = { + .sun_family = AF_UNIX + }; + int len = offsetof(struct sockaddr_un, sun_path) + pathlen + 1; + + memcpy(sa.sun_path, path, pathlen + 1); + return bind(socket, (struct sockaddr *)&sa, len); +} diff --git a/src/io/connect_unix.c b/src/io/connect_unix.c new file mode 100644 index 00000000..26b3d6db --- /dev/null +++ b/src/io/connect_unix.c @@ -0,0 +1,14 @@ +#include <stddef.h> +#include <sys/socket.h> +#include <sys/un.h> + +int connect_unix_from_c(int socket, const char *path, int pathlen) +{ + struct sockaddr_un sa = { + .sun_family = AF_UNIX + }; + int len = offsetof(struct sockaddr_un, sun_path) + pathlen + 1; + + memcpy(sa.sun_path, path, pathlen + 1); + return connect(socket, (struct sockaddr *)&sa, len); +} diff --git a/src/io/serversocket.nim b/src/io/serversocket.nim index 61b633a9..c83af974 100644 --- a/src/io/serversocket.nim +++ b/src/io/serversocket.nim @@ -1,6 +1,6 @@ -import nativesockets -import net -import os +import std/nativesockets +import std/net +import std/os when defined(posix): import posix @@ -13,15 +13,22 @@ const SocketPathPrefix = "cha_sock_" proc getSocketPath*(pid: Pid): string = SocketDirectory / SocketPathPrefix & $pid +# The way stdlib does bindUnix is utterly broken at least on FreeBSD. +# It seems that just writing it in C is the easiest solution. +{.compile: "bind_unix.c".} +proc bind_unix_from_c(fd: cint, path: cstring, pathlen: cint): cint {.importc.} + proc initServerSocket*(buffered = true, blocking = true): ServerSocket = createDir(SocketDirectory) - result.sock = newSocket(Domain.AF_UNIX, SockType.SOCK_STREAM, Protocol.IPPROTO_IP, buffered) + let sock = newSocket(Domain.AF_UNIX, SockType.SOCK_STREAM, Protocol.IPPROTO_IP, buffered) if not blocking: - result.sock.getFd().setBlocking(false) - result.path = getSocketPath(getpid()) - discard unlink(cstring(result.path)) - bindUnix(result.sock, result.path) - listen(result.sock) + sock.getFd().setBlocking(false) + let path = getSocketPath(getpid()) + discard unlink(cstring(path)) + if bind_unix_from_c(cint(sock.getFd()), cstring(path), cint(path.len)) != 0: + raiseOSError(osLastError()) + listen(sock) + return ServerSocket(sock: sock, path: path) proc close*(ssock: ServerSocket) = close(ssock.sock) diff --git a/src/io/socketstream.nim b/src/io/socketstream.nim index 29337a16..28b15c11 100644 --- a/src/io/socketstream.nim +++ b/src/io/socketstream.nim @@ -127,13 +127,18 @@ func newSocketStream*(): SocketStream = proc setBlocking*(ss: SocketStream, blocking: bool) = ss.source.getFd().setBlocking(blocking) +# see serversocket.nim for an explanation +{.compile: "connect_unix.c".} +proc connect_unix_from_c(fd: cint, path: cstring, pathlen: cint): cint {.importc.} + proc connectSocketStream*(path: string, buffered = true, blocking = true): SocketStream = result = newSocketStream() result.blk = blocking let sock = newSocket(Domain.AF_UNIX, SockType.SOCK_STREAM, Protocol.IPPROTO_IP, buffered) if not blocking: sock.getFd().setBlocking(false) - connectUnix(sock, path) + if connect_unix_from_c(cint(sock.getFd()), cstring(path), cint(path.len)) != 0: + raiseOSError(osLastError()) result.source = sock proc connectSocketStream*(pid: Pid, buffered = true, blocking = true): SocketStream = |