Skip to content

Instantly share code, notes, and snippets.

@niv
Created January 27, 2016 17:52
Show Gist options
  • Save niv/a42f9862a6e0ef1fd9ce to your computer and use it in GitHub Desktop.
Save niv/a42f9862a6e0ef1fd9ce to your computer and use it in GitHub Desktop.
import asyncdispatch, asyncnet, nativesockets, net, os
from posix import sendto
type ReadResultInet* = tuple[data: string, address: string, port: Port]
proc recvFrom*(socket: AsyncSocket, size: int,
flags = {SocketFlag.SafeDisconn}): Future[ReadResultInet] =
# Stolen pretty much as-is from asyncnet.recv.
var retFuture = newFuture[ReadResultInet]()
var readBuffer = newString(size)
var sockAddress: SockAddr_in
var addrLen = sizeof(sockAddress).SockLen
proc cb(sock: AsyncFD): bool =
var nullpkt: ReadResultInet
result = true
let res = recvfrom(sock.SocketHandle, cstring(readBuffer),
size.cint, 0, cast[ptr SockAddr](addr(sockAddress)), addr(addrLen))
if res < 0:
let lastError = osLastError()
if lastError.int32 notin {EINTR, EWOULDBLOCK, EAGAIN}:
if flags.isDisconnectionError(lastError):
retFuture.complete(nullpkt)
else:
retFuture.fail(newException(OSError, osErrorMsg(lastError)))
else:
result = false # We still want this callback to be called.
elif res == 0:
# Disconnected
retFuture.complete(nullpkt)
else:
var goodpkt: ReadResultInet
readBuffer.setLen(res)
goodpkt.data = readBuffer
goodpkt.address = $inet_ntoa(sockAddress.sin_addr)
goodpkt.port = nativesockets.ntohs(sockAddress.sin_port).Port
retFuture.complete(goodpkt)
addRead(socket.getFd().AsyncFD, cb)
return retFuture
proc sendTo*(sock: AsyncSocket, address: string, port: Port, data: string,
flags = 0'i32): int =
# This is basically the same as net.sendTo. Best would be to have a
# proc that takes a SocketHandle instead and just redirect both there.
var aiList = getAddrInfo(address, port, AF_INET)
var success = false
var it = aiList
while it != nil:
result = posix.sendto(sock.getFd(),
cast[pointer](cstring(data)),
data.len.cint,
flags.cint,
it.ai_addr, it.ai_addrlen.SockLen)
if result != -1'i32:
success = true
break
it = it.ai_next
dealloc(aiList)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment