implement asyncRecvMsg
This commit is contained in:
parent
742c047480
commit
2f49216e15
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue