implement asyncSendMsg
This commit is contained in:
parent
ce782be7f1
commit
8a5b3d41b6
|
@ -1,4 +1,22 @@
|
|||
import asyncdispatch, threadpool, osproc
|
||||
from os import
|
||||
osLastError,
|
||||
newOsError
|
||||
from posix import
|
||||
SOL_SOCKET,
|
||||
SCM_RIGHTS,
|
||||
EINTR,
|
||||
EWOULDBLOCK,
|
||||
EAGAIN,
|
||||
IOVec,
|
||||
Tmsghdr,
|
||||
Tcmsghdr,
|
||||
SocketHandle,
|
||||
CMSG_SPACE,
|
||||
CMSG_FIRSTHDR,
|
||||
CMSG_LEN,
|
||||
CMSG_DATA,
|
||||
sendmsg
|
||||
|
||||
## asyncReadline as discussed at https://github.com/nim-lang/Nim/issues/11564
|
||||
proc asyncReadline*(): Future[string] =
|
||||
|
@ -26,3 +44,47 @@ proc asyncExecCmd*(command: string): Future[int] =
|
|||
true
|
||||
addEvent(event, callback)
|
||||
return future
|
||||
|
||||
proc asyncSendMsg*(fd: AsyncFD,
|
||||
data: string,
|
||||
fds: openArray[AsyncFD] = []): Future[void] =
|
||||
var retFuture = newFuture[void]("asyncSendMsg")
|
||||
|
||||
proc cb(sock: AsyncFD): bool =
|
||||
# FIXME: if file descriptors are given in fds, check if sock is a unix socket
|
||||
result = true
|
||||
|
||||
# sendmsg needs an array of iovec structs as described in the writev(2) man
|
||||
# page. The message is passed as a msghdr struct which may contain ancillary
|
||||
# data, see sendmsg(2) man page. We use ancillary data exclusively for
|
||||
# passing file descriptors if any are given in fds.
|
||||
var iovec = IOVec(iov_base: data.cstring,
|
||||
iov_len: data.len.csize_t)
|
||||
var msg = Tmsghdr(msg_iov: addr iovec,
|
||||
msg_iovlen: 1)
|
||||
if fds.len > 0:
|
||||
# assemble ancillary data, see cmsg(3) man page
|
||||
let cmsgBufferLen = CMSG_SPACE(sizeof(AsyncFD).csize_t * fds.len.csize_t)
|
||||
let cmsgBuffer = newString(cmsgBufferLen)
|
||||
msg.msg_control = cmsgBuffer.cstring
|
||||
msg.msg_controllen = cmsgBufferLen
|
||||
let cmsg: ptr Tcmsghdr = CMSG_FIRSTHDR(addr msg)
|
||||
cmsg.cmsg_len = CMSG_LEN(sizeof(AsyncFD).csize_t * fds.len.csize_t)
|
||||
cmsg.cmsg_level = SOL_SOCKET
|
||||
cmsg.cmsg_type = SCM_RIGHTS
|
||||
copyMem(CMSG_DATA(cmsg), unsafeAddr fds[0], sizeof(AsyncFD) * fds.len)
|
||||
|
||||
let res = sendmsg(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
|
||||
else:
|
||||
retFuture.complete()
|
||||
|
||||
addWrite(fd, cb)
|
||||
return retFuture
|
||||
|
|
Loading…
Reference in New Issue