diff options
author | Ico Doornekamp <ico@pruts.nl> | 2018-12-05 09:52:57 +0100 |
---|---|---|
committer | Ico Doornekamp <ico@pruts.nl> | 2018-12-09 20:53:05 +0100 |
commit | 71e9fff364e4e2063b3c24d62dc57128f4a766fd (patch) | |
tree | 923fb693b7f055ab026f37428f96225a9f226fc8 /lib | |
parent | c37fdbf843124406ad70185105ab0396867a06d2 (diff) | |
download | Nim-71e9fff364e4e2063b3c24d62dc57128f4a766fd.tar.gz |
Added basic AF_UNIX support to asyncnet.
Unfortunately this required some code duplication because the doConnect() from asynccommon.nim only works with addrInfo which does not make sense for AF_UNIX. makeUnixAddr() was moved to nativesocket.nim and exported
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pure/asyncnet.nim | 55 | ||||
-rw-r--r-- | lib/pure/nativesockets.nim | 11 | ||||
-rw-r--r-- | lib/pure/net.nim | 7 |
3 files changed, 66 insertions, 7 deletions
diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim index 71a1600dc..5cc8d69d6 100644 --- a/lib/pure/asyncnet.nim +++ b/lib/pure/asyncnet.nim @@ -622,6 +622,61 @@ proc bindAddr*(socket: AsyncSocket, port = Port(0), address = "") {. raiseOSError(osLastError()) freeAddrInfo(aiList) +when defined(posix): + + proc connectUnix*(socket: AsyncSocket, path: string): Future[void] = + ## Binds Unix socket to `path`. + ## This only works on Unix-style systems: Mac OS X, BSD and Linux + when not defined(nimdoc): + let retFuture = newFuture[void]("connectUnix") + result = retFuture + + proc cb(fd: AsyncFD): bool = + let ret = SocketHandle(fd).getSockOptInt(cint(SOL_SOCKET), cint(SO_ERROR)) + if ret == 0: + retFuture.complete() + return true + elif ret == EINTR: + return false + else: + retFuture.fail(newException(OSError, osErrorMsg(OSErrorCode(ret)))) + return true + + var socketAddr = makeUnixAddr(path) + let ret = socket.fd.connect(cast[ptr SockAddr](addr socketAddr), + (sizeof(socketAddr.sun_family) + path.len).Socklen) + if ret == 0: + # Request to connect completed immediately. + retFuture.complete() + else: + let lastError = osLastError() + if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS: + addWrite(AsyncFD(socket.fd), cb) + else: + retFuture.fail(newException(OSError, osErrorMsg(lastError))) + + proc bindUnix*(socket: AsyncSocket, path: string) {. + tags: [ReadIOEffect].} = + ## Binds Unix socket to `path`. + ## This only works on Unix-style systems: Mac OS X, BSD and Linux + when not defined(nimdoc): + var socketAddr = makeUnixAddr(path) + if socket.fd.bindAddr(cast[ptr SockAddr](addr socketAddr), + (sizeof(socketAddr.sun_family) + path.len).Socklen) != 0'i32: + raiseOSError(osLastError()) + +elif defined(nimdoc): + + proc connectUnix*(socket: AsyncSocket, path: string): Future[void] = + ## Binds Unix socket to `path`. + ## This only works on Unix-style systems: Mac OS X, BSD and Linux + discard + + proc bindUnix*(socket: AsyncSocket, path: string) = + ## Binds Unix socket to `path`. + ## This only works on Unix-style systems: Mac OS X, BSD and Linux + discard + proc close*(socket: AsyncSocket) = ## Closes the socket. defer: diff --git a/lib/pure/nativesockets.nim b/lib/pure/nativesockets.nim index 514b8d66a..49185b96a 100644 --- a/lib/pure/nativesockets.nim +++ b/lib/pure/nativesockets.nim @@ -105,6 +105,7 @@ else: osInvalidSocket* = posix.INVALID_SOCKET nativeAfInet = posix.AF_INET nativeAfInet6 = posix.AF_INET6 + nativeAfUnix = posix.AF_UNIX proc `==`*(a, b: Port): bool {.borrow.} ## ``==`` for ports. @@ -482,8 +483,18 @@ proc getAddrString*(sockAddr: ptr SockAddr): string = raiseOSError(osLastError()) setLen(result, len(cstring(result))) else: + when defined(posix) and not defined(nimdoc): + if sockAddr.sa_family.cint == nativeAfUnix: + return "unix" raise newException(IOError, "Unknown socket family in getAddrString") +when defined(posix) and not defined(nimdoc): + proc makeUnixAddr*(path: string): Sockaddr_un = + result.sun_family = AF_UNIX.uint16 + 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 getSockName*(socket: SocketHandle): Port = ## returns the socket's associated port number. var name: Sockaddr_in diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 179fccaa3..e73a80cd2 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -947,13 +947,6 @@ proc setSockOpt*(socket: Socket, opt: SOBool, value: bool, level = SOL_SOCKET) { var valuei = cint(if value: 1 else: 0) setSockOptInt(socket.fd, cint(level), toCInt(opt), valuei) -when defined(posix) and not defined(nimdoc): - proc makeUnixAddr(path: string): Sockaddr_un = - result.sun_family = AF_UNIX.uint16 - if path.len >= Sockaddr_un_path_length: - raise newException(ValueError, "socket path too long") - copyMem(addr result.sun_path, path.cstring, path.len + 1) - when defined(posix) or defined(nimdoc): proc connectUnix*(socket: Socket, path: string) = ## Connects to Unix socket on `path`. |