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
This commit is contained in:
parent
c37fdbf843
commit
71e9fff364
3 changed files with 66 additions and 7 deletions
|
|
@ -622,6 +622,61 @@ proc bindAddr*(socket: AsyncSocket, port = Port(0), address = "") {.
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
freeAddrInfo(aiList)
|
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) =
|
proc close*(socket: AsyncSocket) =
|
||||||
## Closes the socket.
|
## Closes the socket.
|
||||||
defer:
|
defer:
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,7 @@ else:
|
||||||
osInvalidSocket* = posix.INVALID_SOCKET
|
osInvalidSocket* = posix.INVALID_SOCKET
|
||||||
nativeAfInet = posix.AF_INET
|
nativeAfInet = posix.AF_INET
|
||||||
nativeAfInet6 = posix.AF_INET6
|
nativeAfInet6 = posix.AF_INET6
|
||||||
|
nativeAfUnix = posix.AF_UNIX
|
||||||
|
|
||||||
proc `==`*(a, b: Port): bool {.borrow.}
|
proc `==`*(a, b: Port): bool {.borrow.}
|
||||||
## ``==`` for ports.
|
## ``==`` for ports.
|
||||||
|
|
@ -482,8 +483,18 @@ proc getAddrString*(sockAddr: ptr SockAddr): string =
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
setLen(result, len(cstring(result)))
|
setLen(result, len(cstring(result)))
|
||||||
else:
|
else:
|
||||||
|
when defined(posix) and not defined(nimdoc):
|
||||||
|
if sockAddr.sa_family.cint == nativeAfUnix:
|
||||||
|
return "unix"
|
||||||
raise newException(IOError, "Unknown socket family in getAddrString")
|
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 =
|
proc getSockName*(socket: SocketHandle): Port =
|
||||||
## returns the socket's associated port number.
|
## returns the socket's associated port number.
|
||||||
var name: Sockaddr_in
|
var name: Sockaddr_in
|
||||||
|
|
|
||||||
|
|
@ -947,13 +947,6 @@ proc setSockOpt*(socket: Socket, opt: SOBool, value: bool, level = SOL_SOCKET) {
|
||||||
var valuei = cint(if value: 1 else: 0)
|
var valuei = cint(if value: 1 else: 0)
|
||||||
setSockOptInt(socket.fd, cint(level), toCInt(opt), valuei)
|
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):
|
when defined(posix) or defined(nimdoc):
|
||||||
proc connectUnix*(socket: Socket, path: string) =
|
proc connectUnix*(socket: Socket, path: string) =
|
||||||
## Connects to Unix socket on `path`.
|
## Connects to Unix socket on `path`.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue