implement asyncRecvMsg

This commit is contained in:
Christian Ulrich 2020-06-11 16:18:56 +02:00
parent 742c047480
commit 2f49216e15
No known key found for this signature in database
GPG Key ID: 8241BE099775A097
1 changed files with 54 additions and 1 deletions

View File

@ -16,7 +16,8 @@ from posix import
CMSG_FIRSTHDR,
CMSG_LEN,
CMSG_DATA,
sendmsg
sendmsg,
recvmsg
## asyncReadline as discussed at https://github.com/nim-lang/Nim/issues/11564
proc asyncReadline*(): Future[string] =
@ -90,3 +91,55 @@ proc asyncSendMsg*(fd: AsyncFD,
addWrite(fd, cb)
return retFuture
proc asyncRecvMsg*(fd: AsyncFD,
size: int): Future[tuple[data: string, ancillaryFd: Option[AsyncFD]]] =
var retFuture = newFuture[
tuple[data: string, ancillaryFd: Option[AsyncFD]]
]("asyncRecvMsg")
proc cb(sock: AsyncFD): bool =
result = true
var dataBuffer = newString(size)
var iovec = IOVec(iov_base: dataBuffer.cstring,
iov_len: dataBuffer.len.csize_t)
let cmsgBufferLen = CMSG_SPACE(sizeof(AsyncFD).csize_t)
let cmsgBuffer = newString(cmsgBufferLen)
var msg = Tmsghdr(msg_iov: addr iovec,
msg_iovlen: 1,
msg_control: cmsgBuffer.cstring,
msg_controllen: cmsgBufferLen)
let cmsg: ptr Tcmsghdr = CMSG_FIRSTHDR(addr msg)
cmsg.cmsg_len = 0
cmsg.cmsg_level = 0
cmsg.cmsg_type = 0
let res = recvmsg(sock.SocketHandle, addr msg, 0)
if res < 0:
let lastError = osLastError()
if lastError.int32 != EINTR and
lastError.int32 != EWOULDBLOCK and
lastError.int32 != EAGAIN:
retFuture.fail(newOSError(lastError))
else:
result = false
return
var ancillaryData = none(AsyncFD)
if cmsg.cmsg_len > 0:
if cmsg.cmsg_len == CMSG_LEN(sizeof(AsyncFD).csize_t) and
cmsg.cmsg_level == SOL_SOCKET and
cmsg.cmsg_type == SCM_RIGHTS:
var ancillaryFd: AsyncFD
copyMem(addr ancillaryFd, CMSG_DATA(cmsg), sizeof(AsyncFD))
ancillaryData = some(ancillaryFd)
else:
retFuture.fail(newException(ValueError, "unexpected ancillary data"))
return
dataBuffer.setLen(msg.msg_iov.iov_len)
retFuture.complete((dataBuffer, ancillaryData))
addRead(fd, cb)
return retFuture