about summary refs log tree commit diff stats
path: root/src/io
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2023-12-14 20:38:30 +0100
committerbptato <nincsnevem662@gmail.com>2023-12-14 20:38:30 +0100
commit600058a19e58aee247ca90b9eb2a8271b458b2d4 (patch)
tree5f9d07d7236ff7bb67555c04cb65a12b4d1d32fa /src/io
parent2f902aeaee8ffa6ceb54876af8f73f56f7840004 (diff)
downloadchawan-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.c14
-rw-r--r--src/io/connect_unix.c14
-rw-r--r--src/io/serversocket.nim25
-rw-r--r--src/io/socketstream.nim7
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 =