From da308be2d7b25683a3073187f699f95f81ac149e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zieli=C5=84ski?= Date: Wed, 28 Oct 2015 19:55:04 +0100 Subject: [PATCH 1/2] net.nim: add support for Unix sockets --- examples/unix_socket/client.nim | 6 ++++++ examples/unix_socket/server.nim | 14 ++++++++++++++ lib/posix/posix.nim | 13 +++++++++++++ lib/pure/nativesockets.nim | 2 +- lib/pure/net.nim | 24 +++++++++++++++++++++++- 5 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 examples/unix_socket/client.nim create mode 100644 examples/unix_socket/server.nim diff --git a/examples/unix_socket/client.nim b/examples/unix_socket/client.nim new file mode 100644 index 0000000000..f4283d64dd --- /dev/null +++ b/examples/unix_socket/client.nim @@ -0,0 +1,6 @@ +import net + +let sock = newSocket(AF_UNIX, SOCK_STREAM, IPPROTO_IP) + +sock.connectUnix("sock") +sock.send("hello\n") diff --git a/examples/unix_socket/server.nim b/examples/unix_socket/server.nim new file mode 100644 index 0000000000..e798bbb48e --- /dev/null +++ b/examples/unix_socket/server.nim @@ -0,0 +1,14 @@ +import net + +let sock = newSocket(AF_UNIX, SOCK_STREAM, IPPROTO_IP) +sock.bindUnix("sock") +sock.listen() + +while true: + var client = new(Socket) + sock.accept(client) + var output = "" + output.setLen 32 + client.readLine(output) + echo "got ", output + client.close() diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim index 5f1dfcfcd5..cae469fe87 100644 --- a/lib/posix/posix.nim +++ b/lib/posix/posix.nim @@ -439,6 +439,14 @@ when hasSpawnH: Tposix_spawn_file_actions* {.importc: "posix_spawn_file_actions_t", header: "", final, pure.} = object +when defined(linux): + # from sys/un.h + const Sockaddr_un_path_length* = 108 +else: + # according to http://pubs.opengroup.org/onlinepubs/009604499/basedefs/sys/un.h.html + # this is >=92 + const Sockaddr_un_path_length* = 92 + type Socklen* {.importc: "socklen_t", header: "".} = cuint TSa_Family* {.importc: "sa_family_t", header: "".} = cint @@ -448,6 +456,11 @@ type sa_family*: TSa_Family ## Address family. sa_data*: array [0..255, char] ## Socket address (variable-length data). + Sockaddr_un* {.importc: "struct sockaddr_un", header: "", + pure, final.} = object ## struct sockaddr_un + sun_family*: TSa_Family ## Address family. + sun_path*: array [0..Sockaddr_un_path_length-1, char] ## Socket path + Sockaddr_storage* {.importc: "struct sockaddr_storage", header: "", pure, final.} = object ## struct sockaddr_storage diff --git a/lib/pure/nativesockets.nim b/lib/pure/nativesockets.nim index c9e067a3e7..e75555115f 100644 --- a/lib/pure/nativesockets.nim +++ b/lib/pure/nativesockets.nim @@ -27,7 +27,7 @@ else: import posix export fcntl, F_GETFL, O_NONBLOCK, F_SETFL, EAGAIN, EWOULDBLOCK, MSG_NOSIGNAL, EINTR, EINPROGRESS, ECONNRESET, EPIPE, ENETRESET - export Sockaddr_storage + export Sockaddr_storage, Sockaddr_un, Sockaddr_un_path_length export SocketHandle, Sockaddr_in, Addrinfo, INADDR_ANY, SockAddr, SockLen, Sockaddr_in6, diff --git a/lib/pure/net.nim b/lib/pure/net.nim index d1016011e4..8bc08c4335 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -10,8 +10,9 @@ ## This module implements a high-level cross-platform sockets interface. {.deadCodeElim: on.} -import nativesockets, os, strutils, unsigned, parseutils, times +import nativesockets, os, strutils, parseutils, times export Port, `$`, `==` +export Domain, SockType, Protocol const useWinVersion = defined(Windows) or defined(nimdoc) @@ -582,6 +583,27 @@ proc connect*(socket: Socket, address: string, let ret = SSLConnect(socket.sslHandle) socketError(socket, ret) +when defined(posix): + proc makeUnixAddr(path: string): Sockaddr_un = + result.sun_family = AF_UNIX.toInt + if path.len >= Sockaddr_un_path_length: + raise newException(ValueError, "socket path too long") + copyMem(addr result.sun_path, path.cstring, path.len + 1) + + proc connectUnix*(socket: Socket, path: string) = + ## Connects to Unix socket on `path`. + var socketAddr = makeUnixAddr(path) + if socket.fd.connect(cast[ptr SockAddr](addr socketAddr), + sizeof(socketAddr).Socklen) != 0'i32: + raiseOSError(osLastError()) + + proc bindUnix*(socket: Socket, path: string) = + ## Binds Unix socket to `path`. + var socketAddr = makeUnixAddr(path) + if socket.fd.bindAddr(cast[ptr SockAddr](addr socketAddr), + sizeof(socketAddr).Socklen) != 0'i32: + raiseOSError(osLastError()) + when defined(ssl): proc handshake*(socket: Socket): bool {.tags: [ReadIOEffect, WriteIOEffect].} = ## This proc needs to be called on a socket after it connects. This is From b662d22ad181fae7fb0e9efc44fe3563406b236e Mon Sep 17 00:00:00 2001 From: Josh Girvin Date: Mon, 30 May 2016 16:29:38 +1000 Subject: [PATCH 2/2] Adding nimdoc comments as per PR comments As per @dom96 code review comments in PR #3488 --- lib/pure/net.nim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 8bc08c4335..4483230364 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -583,7 +583,7 @@ proc connect*(socket: Socket, address: string, let ret = SSLConnect(socket.sslHandle) socketError(socket, ret) -when defined(posix): +when defined(posix) or defined(nimdoc): proc makeUnixAddr(path: string): Sockaddr_un = result.sun_family = AF_UNIX.toInt if path.len >= Sockaddr_un_path_length: @@ -592,6 +592,7 @@ when defined(posix): proc connectUnix*(socket: Socket, path: string) = ## Connects to Unix socket on `path`. + ## This only works on Unix-style systems: Mac OS X, BSD and Linux var socketAddr = makeUnixAddr(path) if socket.fd.connect(cast[ptr SockAddr](addr socketAddr), sizeof(socketAddr).Socklen) != 0'i32: @@ -599,6 +600,7 @@ when defined(posix): proc bindUnix*(socket: Socket, path: string) = ## Binds Unix socket to `path`. + ## This only works on Unix-style systems: Mac OS X, BSD and Linux var socketAddr = makeUnixAddr(path) if socket.fd.bindAddr(cast[ptr SockAddr](addr socketAddr), sizeof(socketAddr).Socklen) != 0'i32: