Case fixes for network modules.

This commit is contained in:
Dominik Picheta 2014-08-30 11:59:08 +01:00
commit cff2a0c0b4
5 changed files with 129 additions and 126 deletions

View file

@ -13,7 +13,7 @@ import os, oids, tables, strutils, macros, times
import rawsockets, net import rawsockets, net
export Port, SocketFlags export Port, SocketFlag
#{.injectStmt: newGcInvariant().} #{.injectStmt: newGcInvariant().}
@ -223,11 +223,11 @@ proc processTimers(p: PDispatcherBase) =
when defined(windows) or defined(nimdoc): when defined(windows) or defined(nimdoc):
import winlean, sets, hashes import winlean, sets, hashes
type type
TCompletionKey = dword TCompletionKey = Dword
TCompletionData* = object TCompletionData* = object
sock: TAsyncFD sock: TAsyncFD
cb: proc (sock: TAsyncFD, bytesTransferred: DWORD, cb: proc (sock: TAsyncFD, bytesTransferred: Dword,
errcode: OSErrorCode) {.closure,gcsafe.} errcode: OSErrorCode) {.closure,gcsafe.}
PDispatcher* = ref object of PDispatcherBase PDispatcher* = ref object of PDispatcherBase
@ -283,7 +283,7 @@ when defined(windows) or defined(nimdoc):
let llTimeout = let llTimeout =
if timeout == -1: winlean.INFINITE if timeout == -1: winlean.INFINITE
else: timeout.int32 else: timeout.int32
var lpNumberOfBytesTransferred: DWORD var lpNumberOfBytesTransferred: Dword
var lpCompletionKey: ULONG var lpCompletionKey: ULONG
var customOverlapped: PCustomOverlapped var customOverlapped: PCustomOverlapped
let res = GetQueuedCompletionStatus(p.ioPort, let res = GetQueuedCompletionStatus(p.ioPort,
@ -321,10 +321,10 @@ when defined(windows) or defined(nimdoc):
proc initPointer(s: SocketHandle, func: var pointer, guid: var TGUID): bool = proc initPointer(s: SocketHandle, func: var pointer, guid: var TGUID): bool =
# Ref: https://github.com/powdahound/twisted/blob/master/twisted/internet/iocpreactor/iocpsupport/winsock_pointers.c # Ref: https://github.com/powdahound/twisted/blob/master/twisted/internet/iocpreactor/iocpsupport/winsock_pointers.c
var bytesRet: DWORD var bytesRet: Dword
func = nil func = nil
result = WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, addr guid, result = WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, addr guid,
sizeof(TGUID).dword, addr func, sizeof(pointer).DWORD, sizeof(TGUID).Dword, addr func, sizeof(pointer).Dword,
addr bytesRet, nil, nil) == 0 addr bytesRet, nil, nil) == 0
proc initAll() = proc initAll() =
@ -337,44 +337,44 @@ when defined(windows) or defined(nimdoc):
raiseOSError(osLastError()) raiseOSError(osLastError())
proc connectEx(s: SocketHandle, name: ptr TSockAddr, namelen: cint, proc connectEx(s: SocketHandle, name: ptr TSockAddr, namelen: cint,
lpSendBuffer: pointer, dwSendDataLength: dword, lpSendBuffer: pointer, dwSendDataLength: Dword,
lpdwBytesSent: PDWORD, lpOverlapped: POVERLAPPED): bool = lpdwBytesSent: PDword, lpOverlapped: POVERLAPPED): bool =
if connectExPtr.isNil: raise newException(ValueError, "Need to initialise ConnectEx().") if connectExPtr.isNil: raise newException(ValueError, "Need to initialise ConnectEx().")
let func = let func =
cast[proc (s: SocketHandle, name: ptr TSockAddr, namelen: cint, cast[proc (s: SocketHandle, name: ptr TSockAddr, namelen: cint,
lpSendBuffer: pointer, dwSendDataLength: dword, lpSendBuffer: pointer, dwSendDataLength: Dword,
lpdwBytesSent: PDWORD, lpOverlapped: POVERLAPPED): bool {.stdcall,gcsafe.}](connectExPtr) lpdwBytesSent: PDword, lpOverlapped: POVERLAPPED): bool {.stdcall,gcsafe.}](connectExPtr)
result = func(s, name, namelen, lpSendBuffer, dwSendDataLength, lpdwBytesSent, result = func(s, name, namelen, lpSendBuffer, dwSendDataLength, lpdwBytesSent,
lpOverlapped) lpOverlapped)
proc acceptEx(listenSock, acceptSock: SocketHandle, lpOutputBuffer: pointer, proc acceptEx(listenSock, acceptSock: SocketHandle, lpOutputBuffer: pointer,
dwReceiveDataLength, dwLocalAddressLength, dwReceiveDataLength, dwLocalAddressLength,
dwRemoteAddressLength: DWORD, lpdwBytesReceived: PDWORD, dwRemoteAddressLength: Dword, lpdwBytesReceived: PDword,
lpOverlapped: POVERLAPPED): bool = lpOverlapped: POVERLAPPED): bool =
if acceptExPtr.isNil: raise newException(ValueError, "Need to initialise AcceptEx().") if acceptExPtr.isNil: raise newException(ValueError, "Need to initialise AcceptEx().")
let func = let func =
cast[proc (listenSock, acceptSock: SocketHandle, lpOutputBuffer: pointer, cast[proc (listenSock, acceptSock: SocketHandle, lpOutputBuffer: pointer,
dwReceiveDataLength, dwLocalAddressLength, dwReceiveDataLength, dwLocalAddressLength,
dwRemoteAddressLength: DWORD, lpdwBytesReceived: PDWORD, dwRemoteAddressLength: Dword, lpdwBytesReceived: PDword,
lpOverlapped: POVERLAPPED): bool {.stdcall,gcsafe.}](acceptExPtr) lpOverlapped: POVERLAPPED): bool {.stdcall,gcsafe.}](acceptExPtr)
result = func(listenSock, acceptSock, lpOutputBuffer, dwReceiveDataLength, result = func(listenSock, acceptSock, lpOutputBuffer, dwReceiveDataLength,
dwLocalAddressLength, dwRemoteAddressLength, lpdwBytesReceived, dwLocalAddressLength, dwRemoteAddressLength, lpdwBytesReceived,
lpOverlapped) lpOverlapped)
proc getAcceptExSockaddrs(lpOutputBuffer: pointer, proc getAcceptExSockaddrs(lpOutputBuffer: pointer,
dwReceiveDataLength, dwLocalAddressLength, dwRemoteAddressLength: DWORD, dwReceiveDataLength, dwLocalAddressLength, dwRemoteAddressLength: Dword,
LocalSockaddr: ptr ptr TSockAddr, LocalSockaddrLength: lpint, LocalSockaddr: ptr ptr TSockAddr, LocalSockaddrLength: LPInt,
RemoteSockaddr: ptr ptr TSockAddr, RemoteSockaddrLength: lpint) = RemoteSockaddr: ptr ptr TSockAddr, RemoteSockaddrLength: LPInt) =
if getAcceptExSockAddrsPtr.isNil: if getAcceptExSockAddrsPtr.isNil:
raise newException(ValueError, "Need to initialise getAcceptExSockAddrs().") raise newException(ValueError, "Need to initialise getAcceptExSockAddrs().")
let func = let func =
cast[proc (lpOutputBuffer: pointer, cast[proc (lpOutputBuffer: pointer,
dwReceiveDataLength, dwLocalAddressLength, dwReceiveDataLength, dwLocalAddressLength,
dwRemoteAddressLength: DWORD, LocalSockaddr: ptr ptr TSockAddr, dwRemoteAddressLength: Dword, LocalSockaddr: ptr ptr TSockAddr,
LocalSockaddrLength: lpint, RemoteSockaddr: ptr ptr TSockAddr, LocalSockaddrLength: LPInt, RemoteSockaddr: ptr ptr TSockAddr,
RemoteSockaddrLength: lpint) {.stdcall,gcsafe.}](getAcceptExSockAddrsPtr) RemoteSockaddrLength: LPInt) {.stdcall,gcsafe.}](getAcceptExSockAddrsPtr)
func(lpOutputBuffer, dwReceiveDataLength, dwLocalAddressLength, func(lpOutputBuffer, dwReceiveDataLength, dwLocalAddressLength,
dwRemoteAddressLength, LocalSockaddr, LocalSockaddrLength, dwRemoteAddressLength, LocalSockaddr, LocalSockaddrLength,
@ -407,7 +407,7 @@ when defined(windows) or defined(nimdoc):
var ol = PCustomOverlapped() var ol = PCustomOverlapped()
GC_ref(ol) GC_ref(ol)
ol.data = TCompletionData(sock: socket, cb: ol.data = TCompletionData(sock: socket, cb:
proc (sock: TAsyncFD, bytesCount: DWORD, errcode: OSErrorCode) = proc (sock: TAsyncFD, bytesCount: Dword, errcode: OSErrorCode) =
if not retFuture.finished: if not retFuture.finished:
if errcode == OSErrorCode(-1): if errcode == OSErrorCode(-1):
retFuture.complete() retFuture.complete()
@ -462,12 +462,12 @@ when defined(windows) or defined(nimdoc):
dataBuf.buf = cast[cstring](alloc0(size)) dataBuf.buf = cast[cstring](alloc0(size))
dataBuf.len = size dataBuf.len = size
var bytesReceived: DWORD var bytesReceived: Dword
var flagsio = flags.toOSFlags().DWORD var flagsio = flags.toOSFlags().Dword
var ol = PCustomOverlapped() var ol = PCustomOverlapped()
GC_ref(ol) GC_ref(ol)
ol.data = TCompletionData(sock: socket, cb: ol.data = TCompletionData(sock: socket, cb:
proc (sock: TAsyncFD, bytesCount: DWORD, errcode: OSErrorCode) = proc (sock: TAsyncFD, bytesCount: Dword, errcode: OSErrorCode) =
if not retFuture.finished: if not retFuture.finished:
if errcode == OSErrorCode(-1): if errcode == OSErrorCode(-1):
if bytesCount == 0 and dataBuf.buf[0] == '\0': if bytesCount == 0 and dataBuf.buf[0] == '\0':
@ -541,11 +541,11 @@ when defined(windows) or defined(nimdoc):
dataBuf.buf = data # since this is not used in a callback, this is fine dataBuf.buf = data # since this is not used in a callback, this is fine
dataBuf.len = data.len dataBuf.len = data.len
var bytesReceived, lowFlags: DWORD var bytesReceived, lowFlags: Dword
var ol = PCustomOverlapped() var ol = PCustomOverlapped()
GC_ref(ol) GC_ref(ol)
ol.data = TCompletionData(sock: socket, cb: ol.data = TCompletionData(sock: socket, cb:
proc (sock: TAsyncFD, bytesCount: DWORD, errcode: OSErrorCode) = proc (sock: TAsyncFD, bytesCount: Dword, errcode: OSErrorCode) =
if not retFuture.finished: if not retFuture.finished:
if errcode == OSErrorCode(-1): if errcode == OSErrorCode(-1):
retFuture.complete() retFuture.complete()
@ -594,10 +594,10 @@ when defined(windows) or defined(nimdoc):
const lpOutputLen = 1024 const lpOutputLen = 1024
var lpOutputBuf = newString(lpOutputLen) var lpOutputBuf = newString(lpOutputLen)
var dwBytesReceived: DWORD var dwBytesReceived: Dword
let dwReceiveDataLength = 0.DWORD # We don't want any data to be read. let dwReceiveDataLength = 0.Dword # We don't want any data to be read.
let dwLocalAddressLength = DWORD(sizeof (Tsockaddr_in) + 16) let dwLocalAddressLength = Dword(sizeof (Tsockaddr_in) + 16)
let dwRemoteAddressLength = DWORD(sizeof(Tsockaddr_in) + 16) let dwRemoteAddressLength = Dword(sizeof(Tsockaddr_in) + 16)
template completeAccept(): stmt {.immediate, dirty.} = template completeAccept(): stmt {.immediate, dirty.} =
var listenSock = socket var listenSock = socket
@ -606,12 +606,12 @@ when defined(windows) or defined(nimdoc):
sizeof(listenSock).TSockLen) sizeof(listenSock).TSockLen)
if setoptRet != 0: raiseOSError(osLastError()) if setoptRet != 0: raiseOSError(osLastError())
var LocalSockaddr, RemoteSockaddr: ptr TSockAddr var localSockaddr, remoteSockaddr: ptr TSockAddr
var localLen, remoteLen: int32 var localLen, remoteLen: int32
getAcceptExSockaddrs(addr lpOutputBuf[0], dwReceiveDataLength, getAcceptExSockaddrs(addr lpOutputBuf[0], dwReceiveDataLength,
dwLocalAddressLength, dwRemoteAddressLength, dwLocalAddressLength, dwRemoteAddressLength,
addr LocalSockaddr, addr localLen, addr localSockaddr, addr localLen,
addr RemoteSockaddr, addr remoteLen) addr remoteSockaddr, addr remoteLen)
register(clientSock.TAsyncFD) register(clientSock.TAsyncFD)
# TODO: IPv6. Check ``sa_family``. http://stackoverflow.com/a/9212542/492186 # TODO: IPv6. Check ``sa_family``. http://stackoverflow.com/a/9212542/492186
retFuture.complete( retFuture.complete(
@ -634,7 +634,7 @@ when defined(windows) or defined(nimdoc):
var ol = PCustomOverlapped() var ol = PCustomOverlapped()
GC_ref(ol) GC_ref(ol)
ol.data = TCompletionData(sock: socket, cb: ol.data = TCompletionData(sock: socket, cb:
proc (sock: TAsyncFD, bytesCount: DWORD, errcode: OSErrorCode) = proc (sock: TAsyncFD, bytesCount: Dword, errcode: OSErrorCode) =
if not retFuture.finished: if not retFuture.finished:
if errcode == OSErrorCode(-1): if errcode == OSErrorCode(-1):
completeAccept() completeAccept()

View file

@ -8,21 +8,21 @@
import asyncdispatch, asyncnet, strutils, parseutils, os, times import asyncdispatch, asyncnet, strutils, parseutils, os, times
from ftpclient import TFtpBase, EInvalidReply, TFtpEvent from ftpclient import FtpBaseObj, ReplyError, FtpEvent
from net import bufferSize from net import BufferSize
type type
TAsyncFtpClient* = TFtpBase[PAsyncSocket] AsyncFtpClientObj* = FtpBaseObj[AsyncSocket]
PAsyncFtpClient* = ref TAsyncFtpClient AsyncFtpClient* = ref AsyncFtpClientObj
ProgressChangedProc* = ProgressChangedProc* =
proc (total, progress: BiggestInt, speed: float): proc (total, progress: BiggestInt, speed: float):
PFuture[void] {.closure, gcsafe.} Future[void] {.closure, gcsafe.}
proc expectReply(ftp: PAsyncFtpClient): PFuture[TaintedString] = proc expectReply(ftp: AsyncFtpClient): Future[TaintedString] =
result = ftp.csock.recvLine() result = ftp.csock.recvLine()
proc send*(ftp: PAsyncFtpClient, m: string): PFuture[TaintedString] {.async.} = proc send*(ftp: AsyncFtpClient, m: string): Future[TaintedString] {.async.} =
## Send a message to the server, and wait for a primary reply. ## Send a message to the server, and wait for a primary reply.
## ``\c\L`` is added for you. ## ``\c\L`` is added for you.
await ftp.csock.send(m & "\c\L") await ftp.csock.send(m & "\c\L")
@ -31,11 +31,11 @@ proc send*(ftp: PAsyncFtpClient, m: string): PFuture[TaintedString] {.async.} =
proc assertReply(received: TaintedString, expected: varargs[string]) = proc assertReply(received: TaintedString, expected: varargs[string]) =
for i in items(expected): for i in items(expected):
if received.string.startsWith(i): return if received.string.startsWith(i): return
raise newException(EInvalidReply, raise newException(ReplyError,
"Expected reply '$1' got: $2" % "Expected reply '$1' got: $2" %
[expected.join("' or '"), received.string]) [expected.join("' or '"), received.string])
proc pasv(ftp: PAsyncFtpClient) {.async.} = proc pasv(ftp: AsyncFtpClient) {.async.} =
## Negotiate a data connection. ## Negotiate a data connection.
ftp.dsock = newAsyncSocket() ftp.dsock = newAsyncSocket()
@ -46,13 +46,13 @@ proc pasv(ftp: PAsyncFtpClient) {.async.} =
var ip = nums[0.. -3] var ip = nums[0.. -3]
var port = nums[-2.. -1] var port = nums[-2.. -1]
var properPort = port[0].parseInt()*256+port[1].parseInt() var properPort = port[0].parseInt()*256+port[1].parseInt()
await ftp.dsock.connect(ip.join("."), TPort(properPort.toU16)) await ftp.dsock.connect(ip.join("."), Port(properPort.toU16))
ftp.dsockConnected = True ftp.dsockConnected = true
proc normalizePathSep(path: string): string = proc normalizePathSep(path: string): string =
return replace(path, '\\', '/') return replace(path, '\\', '/')
proc connect*(ftp: PAsyncFtpClient) {.async.} = proc connect*(ftp: AsyncFtpClient) {.async.} =
## Connect to the FTP server specified by ``ftp``. ## Connect to the FTP server specified by ``ftp``.
await ftp.csock.connect(ftp.address, ftp.port) await ftp.csock.connect(ftp.address, ftp.port)
@ -69,21 +69,21 @@ proc connect*(ftp: PAsyncFtpClient) {.async.} =
if ftp.pass != "": if ftp.pass != "":
assertReply(await(ftp.send("PASS " & ftp.pass)), "230") assertReply(await(ftp.send("PASS " & ftp.pass)), "230")
proc pwd*(ftp: PAsyncFtpClient): PFuture[TaintedString] {.async.} = proc pwd*(ftp: AsyncFtpClient): Future[TaintedString] {.async.} =
## Returns the current working directory. ## Returns the current working directory.
let wd = await ftp.send("PWD") let wd = await ftp.send("PWD")
assertReply wd, "257" assertReply wd, "257"
return wd.string.captureBetween('"').TaintedString # " return wd.string.captureBetween('"').TaintedString # "
proc cd*(ftp: PAsyncFtpClient, dir: string) {.async.} = proc cd*(ftp: AsyncFtpClient, dir: string) {.async.} =
## Changes the current directory on the remote FTP server to ``dir``. ## Changes the current directory on the remote FTP server to ``dir``.
assertReply(await(ftp.send("CWD " & dir.normalizePathSep)), "250") assertReply(await(ftp.send("CWD " & dir.normalizePathSep)), "250")
proc cdup*(ftp: PAsyncFtpClient) {.async.} = proc cdup*(ftp: AsyncFtpClient) {.async.} =
## Changes the current directory to the parent of the current directory. ## Changes the current directory to the parent of the current directory.
assertReply(await(ftp.send("CDUP")), "200") assertReply(await(ftp.send("CDUP")), "200")
proc getLines(ftp: PAsyncFtpClient): PFuture[string] {.async.} = proc getLines(ftp: AsyncFtpClient): Future[string] {.async.} =
## Downloads text data in ASCII mode ## Downloads text data in ASCII mode
result = "" result = ""
assert ftp.dsockConnected assert ftp.dsockConnected
@ -96,7 +96,7 @@ proc getLines(ftp: PAsyncFtpClient): PFuture[string] {.async.} =
assertReply(await(ftp.expectReply()), "226") assertReply(await(ftp.expectReply()), "226")
proc listDirs*(ftp: PAsyncFtpClient, dir = ""): PFuture[seq[string]] {.async.} = proc listDirs*(ftp: AsyncFtpClient, dir = ""): Future[seq[string]] {.async.} =
## Returns a list of filenames in the given directory. If ``dir`` is "", ## Returns a list of filenames in the given directory. If ``dir`` is "",
## the current directory is used. If ``async`` is true, this ## the current directory is used. If ``async`` is true, this
## function will return immediately and it will be your job to ## function will return immediately and it will be your job to
@ -107,13 +107,13 @@ proc listDirs*(ftp: PAsyncFtpClient, dir = ""): PFuture[seq[string]] {.async.} =
result = splitLines(await ftp.getLines()) result = splitLines(await ftp.getLines())
proc existsFile*(ftp: PAsyncFtpClient, file: string): PFuture[bool] {.async.} = proc existsFile*(ftp: AsyncFtpClient, file: string): Future[bool] {.async.} =
## Determines whether ``file`` exists. ## Determines whether ``file`` exists.
var files = await ftp.listDirs() var files = await ftp.listDirs()
for f in items(files): for f in items(files):
if f.normalizePathSep == file.normalizePathSep: return true if f.normalizePathSep == file.normalizePathSep: return true
proc createDir*(ftp: PAsyncFtpClient, dir: string, recursive = false){.async.} = proc createDir*(ftp: AsyncFtpClient, dir: string, recursive = false){.async.} =
## Creates a directory ``dir``. If ``recursive`` is true, the topmost ## Creates a directory ``dir``. If ``recursive`` is true, the topmost
## subdirectory of ``dir`` will be created first, following the secondmost... ## subdirectory of ``dir`` will be created first, following the secondmost...
## etc. this allows you to give a full path as the ``dir`` without worrying ## etc. this allows you to give a full path as the ``dir`` without worrying
@ -123,14 +123,14 @@ proc createDir*(ftp: PAsyncFtpClient, dir: string, recursive = false){.async.} =
else: else:
var reply = TaintedString"" var reply = TaintedString""
var previousDirs = "" var previousDirs = ""
for p in split(dir, {os.dirSep, os.altSep}): for p in split(dir, {os.DirSep, os.AltSep}):
if p != "": if p != "":
previousDirs.add(p) previousDirs.add(p)
reply = await ftp.send("MKD " & previousDirs) reply = await ftp.send("MKD " & previousDirs)
previousDirs.add('/') previousDirs.add('/')
assertReply reply, "257" assertReply reply, "257"
proc chmod*(ftp: PAsyncFtpClient, path: string, proc chmod*(ftp: AsyncFtpClient, path: string,
permissions: set[TFilePermission]) {.async.} = permissions: set[TFilePermission]) {.async.} =
## Changes permission of ``path`` to ``permissions``. ## Changes permission of ``path`` to ``permissions``.
var userOctal = 0 var userOctal = 0
@ -152,7 +152,7 @@ proc chmod*(ftp: PAsyncFtpClient, path: string,
assertReply(await(ftp.send("SITE CHMOD " & perm & assertReply(await(ftp.send("SITE CHMOD " & perm &
" " & path.normalizePathSep)), "200") " " & path.normalizePathSep)), "200")
proc list*(ftp: PAsyncFtpClient, dir = ""): PFuture[string] {.async.} = proc list*(ftp: AsyncFtpClient, dir = ""): Future[string] {.async.} =
## Lists all files in ``dir``. If ``dir`` is ``""``, uses the current ## Lists all files in ``dir``. If ``dir`` is ``""``, uses the current
## working directory. ## working directory.
await ftp.pasv() await ftp.pasv()
@ -162,7 +162,7 @@ proc list*(ftp: PAsyncFtpClient, dir = ""): PFuture[string] {.async.} =
result = await ftp.getLines() result = await ftp.getLines()
proc retrText*(ftp: PAsyncFtpClient, file: string): PFuture[string] {.async.} = proc retrText*(ftp: AsyncFtpClient, file: string): Future[string] {.async.} =
## Retrieves ``file``. File must be ASCII text. ## Retrieves ``file``. File must be ASCII text.
await ftp.pasv() await ftp.pasv()
let reply = await ftp.send("RETR " & file.normalizePathSep) let reply = await ftp.send("RETR " & file.normalizePathSep)
@ -170,13 +170,13 @@ proc retrText*(ftp: PAsyncFtpClient, file: string): PFuture[string] {.async.} =
result = await ftp.getLines() result = await ftp.getLines()
proc getFile(ftp: PAsyncFtpClient, file: TFile, total: BiggestInt, proc getFile(ftp: AsyncFtpClient, file: TFile, total: BiggestInt,
onProgressChanged: ProgressChangedProc) {.async.} = onProgressChanged: ProgressChangedProc) {.async.} =
assert ftp.dsockConnected assert ftp.dsockConnected
var progress = 0 var progress = 0
var progressInSecond = 0 var progressInSecond = 0
var countdownFut = sleepAsync(1000) var countdownFut = sleepAsync(1000)
var dataFut = ftp.dsock.recv(bufferSize) var dataFut = ftp.dsock.recv(BufferSize)
while ftp.dsockConnected: while ftp.dsockConnected:
await dataFut or countdownFut await dataFut or countdownFut
if countdownFut.finished: if countdownFut.finished:
@ -191,20 +191,20 @@ proc getFile(ftp: PAsyncFtpClient, file: TFile, total: BiggestInt,
progress.inc(data.len) progress.inc(data.len)
progressInSecond.inc(data.len) progressInSecond.inc(data.len)
file.write(data) file.write(data)
dataFut = ftp.dsock.recv(bufferSize) dataFut = ftp.dsock.recv(BufferSize)
else: else:
ftp.dsockConnected = False ftp.dsockConnected = false
assertReply(await(ftp.expectReply()), "226") assertReply(await(ftp.expectReply()), "226")
proc defaultOnProgressChanged*(total, progress: BiggestInt, proc defaultOnProgressChanged*(total, progress: BiggestInt,
speed: float): PFuture[void] {.nimcall,gcsafe.} = speed: float): Future[void] {.nimcall,gcsafe.} =
## Default FTP ``onProgressChanged`` handler. Does nothing. ## Default FTP ``onProgressChanged`` handler. Does nothing.
result = newFuture[void]() result = newFuture[void]()
#echo(total, " ", progress, " ", speed) #echo(total, " ", progress, " ", speed)
result.complete() result.complete()
proc retrFile*(ftp: PAsyncFtpClient, file, dest: string, proc retrFile*(ftp: AsyncFtpClient, file, dest: string,
onProgressChanged = defaultOnProgressChanged) {.async.} = onProgressChanged = defaultOnProgressChanged) {.async.} =
## Downloads ``file`` and saves it to ``dest``. ## Downloads ``file`` and saves it to ``dest``.
## The ``EvRetr`` event is passed to the specified ``handleEvent`` function ## The ``EvRetr`` event is passed to the specified ``handleEvent`` function
@ -215,14 +215,14 @@ proc retrFile*(ftp: PAsyncFtpClient, file, dest: string,
var reply = await ftp.send("RETR " & file.normalizePathSep) var reply = await ftp.send("RETR " & file.normalizePathSep)
assertReply reply, ["125", "150"] assertReply reply, ["125", "150"]
if {'(', ')'} notin reply.string: if {'(', ')'} notin reply.string:
raise newException(EInvalidReply, "Reply has no file size.") raise newException(ReplyError, "Reply has no file size.")
var fileSize: biggestInt var fileSize: BiggestInt
if reply.string.captureBetween('(', ')').parseBiggestInt(fileSize) == 0: if reply.string.captureBetween('(', ')').parseBiggestInt(fileSize) == 0:
raise newException(EInvalidReply, "Reply has no file size.") raise newException(ReplyError, "Reply has no file size.")
await getFile(ftp, destFile, fileSize, onProgressChanged) await getFile(ftp, destFile, fileSize, onProgressChanged)
proc doUpload(ftp: PAsyncFtpClient, file: TFile, proc doUpload(ftp: AsyncFtpClient, file: TFile,
onProgressChanged: ProgressChangedProc) {.async.} = onProgressChanged: ProgressChangedProc) {.async.} =
assert ftp.dsockConnected assert ftp.dsockConnected
@ -231,7 +231,7 @@ proc doUpload(ftp: PAsyncFtpClient, file: TFile,
var progress = 0 var progress = 0
var progressInSecond = 0 var progressInSecond = 0
var countdownFut = sleepAsync(1000) var countdownFut = sleepAsync(1000)
var sendFut: PFuture[void] = nil var sendFut: Future[void] = nil
while ftp.dsockConnected: while ftp.dsockConnected:
if sendFut == nil or sendFut.finished: if sendFut == nil or sendFut.finished:
progress.inc(data.len) progress.inc(data.len)
@ -255,7 +255,7 @@ proc doUpload(ftp: PAsyncFtpClient, file: TFile,
await countdownFut or sendFut await countdownFut or sendFut
proc storeFile*(ftp: PAsyncFtpClient, file, dest: string, proc storeFile*(ftp: AsyncFtpClient, file, dest: string,
onProgressChanged = defaultOnProgressChanged) {.async.} = onProgressChanged = defaultOnProgressChanged) {.async.} =
## Uploads ``file`` to ``dest`` on the remote FTP server. Usage of this ## Uploads ``file`` to ``dest`` on the remote FTP server. Usage of this
## function asynchronously is recommended to view the progress of ## function asynchronously is recommended to view the progress of
@ -271,9 +271,9 @@ proc storeFile*(ftp: PAsyncFtpClient, file, dest: string,
await doUpload(ftp, destFile, onProgressChanged) await doUpload(ftp, destFile, onProgressChanged)
proc newAsyncFtpClient*(address: string, port = TPort(21), proc newAsyncFtpClient*(address: string, port = Port(21),
user, pass = ""): PAsyncFtpClient = user, pass = ""): AsyncFtpClient =
## Creates a new ``PAsyncFtpClient`` object. ## Creates a new ``AsyncFtpClient`` object.
new result new result
result.user = user result.user = user
result.pass = pass result.pass = pass
@ -284,7 +284,7 @@ proc newAsyncFtpClient*(address: string, port = TPort(21),
when isMainModule: when isMainModule:
var ftp = newAsyncFtpClient("example.com", user = "test", pass = "test") var ftp = newAsyncFtpClient("example.com", user = "test", pass = "test")
proc main(ftp: PAsyncFtpClient) {.async.} = proc main(ftp: AsyncFtpClient) {.async.} =
await ftp.connect() await ftp.connect()
echo await ftp.pwd() echo await ftp.pwd()
echo await ftp.listDirs() echo await ftp.listDirs()

View file

@ -91,9 +91,11 @@ import sockets, os
## getSocket(s).accept(client) ## getSocket(s).accept(client)
when defined(windows): when defined(windows):
from winlean import TimeVal, SocketHandle, FdSet, FD_ZERO, FD_SET, FD_ISSET, select from winlean import TimeVal, SocketHandle, FdSet, FD_ZERO, FD_SET,
fdSet, FD_ISSET, select
else: else:
from posix import TimeVal, SocketHandle, FdSet, FD_ZERO, FD_SET, FD_ISSET, select from posix import TimeVal, SocketHandle, FdSet, FD_ZERO, FD_SET,
fdSet, FD_ISSET, select
type type
DelegateObj* = object DelegateObj* = object
@ -113,33 +115,32 @@ type
Dispatcher* = ref DispatcherObj Dispatcher* = ref DispatcherObj
DispatcherObj = object DispatcherObj = object
delegates: seq[PDelegate] delegates: seq[Delegate]
AsyncSocket* = ref AsyncSocketObj AsyncSocket* = ref AsyncSocketObj
AsyncSocketObj* = object of RootObj AsyncSocketObj* = object of RootObj
socket: Socket socket: Socket
info: SocketStatus info: SocketStatus
handleRead*: proc (s: PAsyncSocket) {.closure, gcsafe.} handleRead*: proc (s: AsyncSocket) {.closure, gcsafe.}
handleWrite: proc (s: PAsyncSocket) {.closure, gcsafe.} handleWrite: proc (s: AsyncSocket) {.closure, gcsafe.}
handleConnect*: proc (s: PAsyncSocket) {.closure, gcsafe.} handleConnect*: proc (s: AsyncSocket) {.closure, gcsafe.}
handleAccept*: proc (s: PAsyncSocket) {.closure, gcsafe.} handleAccept*: proc (s: AsyncSocket) {.closure, gcsafe.}
handleTask*: proc (s: PAsyncSocket) {.closure, gcsafe.} handleTask*: proc (s: AsyncSocket) {.closure, gcsafe.}
lineBuffer: TaintedString ## Temporary storage for ``readLine`` lineBuffer: TaintedString ## Temporary storage for ``readLine``
sendBuffer: string ## Temporary storage for ``send`` sendBuffer: string ## Temporary storage for ``send``
sslNeedAccept: bool sslNeedAccept: bool
proto: TProtocol proto: Protocol
deleg: PDelegate deleg: Delegate
SocketStatus* = enum SocketStatus* = enum
SockIdle, SockConnecting, SockConnected, SockListening, SockClosed, SockIdle, SockConnecting, SockConnected, SockListening, SockClosed,
SockUDPBound SockUDPBound
{.deprecated: [TDelegate: DelegateObj, PDelegate: Delegate, {.deprecated: [TDelegate: DelegateObj, PDelegate: Delegate,
TProcessOption: ProcessOption,
TInfo: SocketStatus, PAsyncSocket: AsyncSocket, TAsyncSocket: AsyncSocketObj, TInfo: SocketStatus, PAsyncSocket: AsyncSocket, TAsyncSocket: AsyncSocketObj,
TDispatcher: DispatcherObj, PDispatcher: Dispatcher, TDispatcher: DispatcherObj, PDispatcher: Dispatcher,
].} ].}
@ -176,7 +177,7 @@ proc asyncSocket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM,
result = newAsyncSocket() result = newAsyncSocket()
result.socket = socket(domain, typ, protocol, buffered) result.socket = socket(domain, typ, protocol, buffered)
result.proto = protocol result.proto = protocol
if result.socket == invalidSocket: osError(osLastError()) if result.socket == invalidSocket: raiseOSError(osLastError())
result.socket.setBlocking(false) result.socket.setBlocking(false)
proc toAsyncSocket*(sock: TSocket, state: TInfo = SockConnected): PAsyncSocket = proc toAsyncSocket*(sock: TSocket, state: TInfo = SockConnected): PAsyncSocket =
@ -366,7 +367,7 @@ proc acceptAddr*(server: PAsyncSocket, client: var PAsyncSocket,
client.sslNeedAccept = false client.sslNeedAccept = false
client.info = SockConnected client.info = SockConnected
if c == invalidSocket: socketError(server.socket) if c == invalidSocket: raiseSocketError(server.socket)
c.setBlocking(false) # TODO: Needs to be tested. c.setBlocking(false) # TODO: Needs to be tested.
# deleg.open is set in ``toDelegate``. # deleg.open is set in ``toDelegate``.
@ -490,7 +491,7 @@ proc recvLine*(s: PAsyncSocket, line: var TaintedString): bool {.deprecated.} =
of RecvDisconnected: of RecvDisconnected:
result = true result = true
of RecvFail: of RecvFail:
s.socketError(async = true) s.raiseSocketError(async = true)
result = false result = false
{.pop.} {.pop.}
@ -544,19 +545,19 @@ proc send*(sock: PAsyncSocket, data: string) =
sock.sendBuffer.add(data[bytesSent .. -1]) sock.sendBuffer.add(data[bytesSent .. -1])
sock.deleg.mode = fmReadWrite sock.deleg.mode = fmReadWrite
proc timeValFromMilliseconds(timeout = 500): TTimeVal = proc timeValFromMilliseconds(timeout = 500): TimeVal =
if timeout != -1: if timeout != -1:
var seconds = timeout div 1000 var seconds = timeout div 1000
result.tv_sec = seconds.int32 result.tv_sec = seconds.int32
result.tv_usec = ((timeout - seconds * 1000) * 1000).int32 result.tv_usec = ((timeout - seconds * 1000) * 1000).int32
proc createFdSet(fd: var TFdSet, s: seq[PDelegate], m: var int) = proc createFdSet(fd: var FdSet, s: seq[Delegate], m: var int) =
FD_ZERO(fd) FD_ZERO(fd)
for i in items(s): for i in items(s):
m = max(m, int(i.fd)) m = max(m, int(i.fd))
FD_SET(i.fd, fd) fdSet(i.fd, fd)
proc pruneSocketSet(s: var seq[PDelegate], fd: var TFdSet) = proc pruneSocketSet(s: var seq[Delegate], fd: var FdSet) =
var i = 0 var i = 0
var L = s.len var L = s.len
while i < L: while i < L:
@ -569,9 +570,9 @@ proc pruneSocketSet(s: var seq[PDelegate], fd: var TFdSet) =
proc select(readfds, writefds, exceptfds: var seq[PDelegate], proc select(readfds, writefds, exceptfds: var seq[PDelegate],
timeout = 500): int = timeout = 500): int =
var tv {.noInit.}: TTimeVal = timeValFromMilliseconds(timeout) var tv {.noInit.}: TimeVal = timeValFromMilliseconds(timeout)
var rd, wr, ex: TFdSet var rd, wr, ex: FdSet
var m = 0 var m = 0
createFdSet(rd, readfds, m) createFdSet(rd, readfds, m)
createFdSet(wr, writefds, m) createFdSet(wr, writefds, m)
@ -681,7 +682,7 @@ when isMainModule:
proc main = proc main =
var d = newDispatcher() var d = newDispatcher()
var s = AsyncSocket() var s = asyncSocket()
s.connect("amber.tenthbit.net", TPort(6667)) s.connect("amber.tenthbit.net", TPort(6667))
s.handleConnect = s.handleConnect =
proc (s: PAsyncSocket) = proc (s: PAsyncSocket) =
@ -691,7 +692,7 @@ when isMainModule:
testRead(s, 1) testRead(s, 1)
d.register(s) d.register(s)
var server = AsyncSocket() var server = asyncSocket()
server.handleAccept = server.handleAccept =
proc (s: PAsyncSocket) = proc (s: PAsyncSocket) =
testAccept(s, d, 78) testAccept(s, d, 78)

View file

@ -64,7 +64,7 @@ type
proc newSocket(fd: TAsyncFD, isBuff: bool): PAsyncSocket = proc newSocket(fd: TAsyncFD, isBuff: bool): PAsyncSocket =
assert fd != osInvalidSocket.TAsyncFD assert fd != osInvalidSocket.TAsyncFD
new(result.PSocket) new(result.PSocket)
result.fd = fd.TSocketHandle result.fd = fd.SocketHandle
result.isBuffered = isBuff result.isBuffered = isBuff
if isBuff: if isBuff:
result.currPos = 0 result.currPos = 0
@ -75,15 +75,15 @@ proc newAsyncSocket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM,
result = newSocket(newAsyncRawSocket(domain, typ, protocol), buffered) result = newSocket(newAsyncRawSocket(domain, typ, protocol), buffered)
proc connect*(socket: PAsyncSocket, address: string, port: TPort, proc connect*(socket: PAsyncSocket, address: string, port: TPort,
af = AF_INET): PFuture[void] = af = AF_INET): Future[void] =
## Connects ``socket`` to server at ``address:port``. ## Connects ``socket`` to server at ``address:port``.
## ##
## Returns a ``PFuture`` which will complete when the connection succeeds ## Returns a ``Future`` which will complete when the connection succeeds
## or an error occurs. ## or an error occurs.
result = connect(socket.fd.TAsyncFD, address, port, af) result = connect(socket.fd.TAsyncFD, address, port, af)
proc readIntoBuf(socket: PAsyncSocket, proc readIntoBuf(socket: PAsyncSocket,
flags: set[TSocketFlags]): PFuture[int] {.async.} = flags: set[TSocketFlags]): Future[int] {.async.} =
var data = await recv(socket.fd.TAsyncFD, BufferSize, flags) var data = await recv(socket.fd.TAsyncFD, BufferSize, flags)
if data.len != 0: if data.len != 0:
copyMem(addr socket.buffer[0], addr data[0], data.len) copyMem(addr socket.buffer[0], addr data[0], data.len)
@ -92,7 +92,7 @@ proc readIntoBuf(socket: PAsyncSocket,
result = data.len result = data.len
proc recv*(socket: PAsyncSocket, size: int, proc recv*(socket: PAsyncSocket, size: int,
flags = {TSocketFlags.SafeDisconn}): PFuture[string] {.async.} = flags = {TSocketFlags.SafeDisconn}): Future[string] {.async.} =
## Reads ``size`` bytes from ``socket``. Returned future will complete once ## Reads ``size`` bytes from ``socket``. Returned future will complete once
## all of the requested data is read. If socket is disconnected during the ## all of the requested data is read. If socket is disconnected during the
## recv operation then the future may complete with only a part of the ## recv operation then the future may complete with only a part of the
@ -131,21 +131,21 @@ proc recv*(socket: PAsyncSocket, size: int,
result = await recv(socket.fd.TAsyncFD, size, flags) result = await recv(socket.fd.TAsyncFD, size, flags)
proc send*(socket: PAsyncSocket, data: string, proc send*(socket: PAsyncSocket, data: string,
flags = {TSocketFlags.SafeDisconn}): PFuture[void] = flags = {TSocketFlags.SafeDisconn}): Future[void] =
## Sends ``data`` to ``socket``. The returned future will complete once all ## Sends ``data`` to ``socket``. The returned future will complete once all
## data has been sent. ## data has been sent.
assert socket != nil assert socket != nil
result = send(socket.fd.TAsyncFD, data, flags) result = send(socket.fd.TAsyncFD, data, flags)
proc acceptAddr*(socket: PAsyncSocket, flags = {TSocketFlags.SafeDisconn}): proc acceptAddr*(socket: PAsyncSocket, flags = {TSocketFlags.SafeDisconn}):
PFuture[tuple[address: string, client: PAsyncSocket]] = Future[tuple[address: string, client: PAsyncSocket]] =
## Accepts a new connection. Returns a future containing the client socket ## Accepts a new connection. Returns a future containing the client socket
## corresponding to that connection and the remote address of the client. ## corresponding to that connection and the remote address of the client.
## The future will complete when the connection is successfully accepted. ## The future will complete when the connection is successfully accepted.
var retFuture = newFuture[tuple[address: string, client: PAsyncSocket]]("asyncnet.acceptAddr") var retFuture = newFuture[tuple[address: string, client: PAsyncSocket]]("asyncnet.acceptAddr")
var fut = acceptAddr(socket.fd.TAsyncFD, flags) var fut = acceptAddr(socket.fd.TAsyncFD, flags)
fut.callback = fut.callback =
proc (future: PFuture[tuple[address: string, client: TAsyncFD]]) = proc (future: Future[tuple[address: string, client: TAsyncFD]]) =
assert future.finished assert future.finished
if future.failed: if future.failed:
retFuture.fail(future.readError) retFuture.fail(future.readError)
@ -156,14 +156,14 @@ proc acceptAddr*(socket: PAsyncSocket, flags = {TSocketFlags.SafeDisconn}):
return retFuture return retFuture
proc accept*(socket: PAsyncSocket, proc accept*(socket: PAsyncSocket,
flags = {TSocketFlags.SafeDisconn}): PFuture[PAsyncSocket] = flags = {TSocketFlags.SafeDisconn}): Future[PAsyncSocket] =
## Accepts a new connection. Returns a future containing the client socket ## Accepts a new connection. Returns a future containing the client socket
## corresponding to that connection. ## corresponding to that connection.
## The future will complete when the connection is successfully accepted. ## The future will complete when the connection is successfully accepted.
var retFut = newFuture[PAsyncSocket]("asyncnet.accept") var retFut = newFuture[PAsyncSocket]("asyncnet.accept")
var fut = acceptAddr(socket, flags) var fut = acceptAddr(socket, flags)
fut.callback = fut.callback =
proc (future: PFuture[tuple[address: string, client: PAsyncSocket]]) = proc (future: Future[tuple[address: string, client: PAsyncSocket]]) =
assert future.finished assert future.finished
if future.failed: if future.failed:
retFut.fail(future.readError) retFut.fail(future.readError)
@ -172,7 +172,7 @@ proc accept*(socket: PAsyncSocket,
return retFut return retFut
proc recvLine*(socket: PAsyncSocket, proc recvLine*(socket: PAsyncSocket,
flags = {TSocketFlags.SafeDisconn}): PFuture[string] {.async.} = flags = {TSocketFlags.SafeDisconn}): Future[string] {.async.} =
## Reads a line of data from ``socket``. Returned future will complete once ## Reads a line of data from ``socket``. Returned future will complete once
## a full line is read or an error occurs. ## a full line is read or an error occurs.
## ##
@ -282,23 +282,23 @@ when isMainModule:
var sock = newAsyncSocket() var sock = newAsyncSocket()
var f = connect(sock, "irc.freenode.net", TPort(6667)) var f = connect(sock, "irc.freenode.net", TPort(6667))
f.callback = f.callback =
proc (future: PFuture[void]) = proc (future: Future[void]) =
echo("Connected in future!") echo("Connected in future!")
for i in 0 .. 50: for i in 0 .. 50:
var recvF = recv(sock, 10) var recvF = recv(sock, 10)
recvF.callback = recvF.callback =
proc (future: PFuture[string]) = proc (future: Future[string]) =
echo("Read ", future.read.len, ": ", future.read.repr) echo("Read ", future.read.len, ": ", future.read.repr)
elif test == LowServer: elif test == LowServer:
var sock = newAsyncSocket() var sock = newAsyncSocket()
sock.bindAddr(TPort(6667)) sock.bindAddr(TPort(6667))
sock.listen() sock.listen()
proc onAccept(future: PFuture[PAsyncSocket]) = proc onAccept(future: Future[PAsyncSocket]) =
let client = future.read let client = future.read
echo "Accepted ", client.fd.cint echo "Accepted ", client.fd.cint
var t = send(client, "test\c\L") var t = send(client, "test\c\L")
t.callback = t.callback =
proc (future: PFuture[void]) = proc (future: Future[void]) =
echo("Send") echo("Send")
client.close() client.close()

View file

@ -35,6 +35,10 @@ when defined(ssl):
SSLAcceptResult* = enum SSLAcceptResult* = enum
AcceptNoClient = 0, AcceptNoHandshake, AcceptSuccess AcceptNoClient = 0, AcceptNoHandshake, AcceptSuccess
{.deprecated: [ESSL: SSLError, TSSLCVerifyMode: SSLCVerifyMode,
TSSLProtVersion: SSLProtVersion, PSSLContext: SSLContext,
TSSLAcceptResult: SSLAcceptResult].}
const const
BufferSize*: int = 4000 ## size of a buffered socket's buffer BufferSize*: int = 4000 ## size of a buffered socket's buffer
@ -74,9 +78,7 @@ type
{.deprecated: [TSocketFlags: SocketFlag, ETimeout: TimeoutError, {.deprecated: [TSocketFlags: SocketFlag, ETimeout: TimeoutError,
TReadLineResult: ReadLineResult, TSOBool: SOBool, PSocket: Socket, TReadLineResult: ReadLineResult, TSOBool: SOBool, PSocket: Socket,
TSocketImpl: SocketImpl, ESSL: SSLError, TSSLCVerifyMode: SSLCVerifyMode, TSocketImpl: SocketImpl].}
TSSLProtVersion: SSLProtVersion, PSSLContext: SSLContext,
TSSLAcceptResult: SSLAcceptResult].}
proc isDisconnectionError*(flags: set[SocketFlag], proc isDisconnectionError*(flags: set[SocketFlag],
lastError: OSErrorCode): bool = lastError: OSErrorCode): bool =
@ -98,7 +100,7 @@ proc toOSFlags*(socketFlags: set[SocketFlag]): cint =
result = result or MSG_PEEK result = result or MSG_PEEK
of SocketFlag.SafeDisconn: continue of SocketFlag.SafeDisconn: continue
proc createSocket(fd: TSocketHandle, isBuff: bool): Socket = proc createSocket(fd: SocketHandle, isBuff: bool): Socket =
assert fd != osInvalidSocket assert fd != osInvalidSocket
new(result) new(result)
result.fd = fd result.fd = fd
@ -276,19 +278,19 @@ proc bindAddr*(socket: Socket, port = Port(0), address = "") {.
## If ``address`` is "" then ADDR_ANY will be bound. ## If ``address`` is "" then ADDR_ANY will be bound.
if address == "": if address == "":
var name: TSockaddr_in var name: Sockaddr_in
when useWinVersion: when useWinVersion:
name.sin_family = toInt(AF_INET).int16 name.sin_family = toInt(AF_INET).int16
else: else:
name.sin_family = toInt(AF_INET) name.sin_family = toInt(AF_INET)
name.sin_port = htons(int16(port)) name.sin_port = htons(int16(port))
name.sin_addr.s_addr = htonl(INADDR_ANY) name.sin_addr.s_addr = htonl(INADDR_ANY)
if bindAddr(socket.fd, cast[ptr TSockAddr](addr(name)), if bindAddr(socket.fd, cast[ptr SockAddr](addr(name)),
sizeof(name).TSocklen) < 0'i32: sizeof(name).Socklen) < 0'i32:
raiseOSError(osLastError()) raiseOSError(osLastError())
else: else:
var aiList = getAddrInfo(address, port, AF_INET) var aiList = getAddrInfo(address, port, AF_INET)
if bindAddr(socket.fd, aiList.ai_addr, aiList.ai_addrlen.TSocklen) < 0'i32: if bindAddr(socket.fd, aiList.ai_addr, aiList.ai_addrlen.Socklen) < 0'i32:
dealloc(aiList) dealloc(aiList)
raiseOSError(osLastError()) raiseOSError(osLastError())
dealloc(aiList) dealloc(aiList)
@ -311,9 +313,9 @@ proc acceptAddr*(server: Socket, client: var Socket, address: var string,
## flag is specified then this error will not be raised and instead ## flag is specified then this error will not be raised and instead
## accept will be called again. ## accept will be called again.
assert(client != nil) assert(client != nil)
var sockAddress: TSockaddr_in var sockAddress: Sockaddr_in
var addrLen = sizeof(sockAddress).TSocklen var addrLen = sizeof(sockAddress).Socklen
var sock = accept(server.fd, cast[ptr TSockAddr](addr(sockAddress)), var sock = accept(server.fd, cast[ptr SockAddr](addr(sockAddress)),
addr(addrLen)) addr(addrLen))
if sock == osInvalidSocket: if sock == osInvalidSocket:
@ -452,7 +454,7 @@ proc connect*(socket: Socket, address: string, port = Port(0),
var lastError: OSErrorCode var lastError: OSErrorCode
var it = aiList var it = aiList
while it != nil: while it != nil:
if connect(socket.fd, it.ai_addr, it.ai_addrlen.TSocklen) == 0'i32: if connect(socket.fd, it.ai_addr, it.ai_addrlen.SockLen) == 0'i32:
success = true success = true
break break
else: lastError = osLastError() else: lastError = osLastError()
@ -751,10 +753,10 @@ proc recvFrom*(socket: Socket, data: var string, length: int,
# TODO: Buffered sockets # TODO: Buffered sockets
data.setLen(length) data.setLen(length)
var sockAddress: TSockaddr_in var sockAddress: SockAddrIn
var addrLen = sizeof(sockAddress).TSocklen var addrLen = sizeof(sockAddress).SockLen
result = recvfrom(socket.fd, cstring(data), length.cint, flags.cint, result = recvfrom(socket.fd, cstring(data), length.cint, flags.cint,
cast[ptr TSockAddr](addr(sockAddress)), addr(addrLen)) cast[ptr SockAddr](addr(sockAddress)), addr(addrLen))
if result != -1: if result != -1:
data.setLen(result) data.setLen(result)
@ -831,7 +833,7 @@ proc sendTo*(socket: Socket, address: string, port: Port, data: pointer,
var it = aiList var it = aiList
while it != nil: while it != nil:
result = sendto(socket.fd, data, size.cint, flags.cint, it.ai_addr, result = sendto(socket.fd, data, size.cint, flags.cint, it.ai_addr,
it.ai_addrlen.TSocklen) it.ai_addrlen.SockLen)
if result != -1'i32: if result != -1'i32:
success = true success = true
break break
@ -864,7 +866,7 @@ proc connectAsync(socket: Socket, name: string, port = Port(0),
var lastError: OSErrorCode var lastError: OSErrorCode
var it = aiList var it = aiList
while it != nil: while it != nil:
var ret = connect(socket.fd, it.ai_addr, it.ai_addrlen.TSocklen) var ret = connect(socket.fd, it.ai_addr, it.ai_addrlen.SockLen)
if ret == 0'i32: if ret == 0'i32:
success = true success = true
break break
@ -907,7 +909,7 @@ proc connect*(socket: Socket, address: string, port = Port(0), timeout: int,
proc isSSL*(socket: Socket): bool = return socket.isSSL proc isSSL*(socket: Socket): bool = return socket.isSSL
## Determines whether ``socket`` is a SSL socket. ## Determines whether ``socket`` is a SSL socket.
proc getFD*(socket: Socket): TSocketHandle = return socket.fd proc getFD*(socket: Socket): SocketHandle = return socket.fd
## Returns the socket's file descriptor ## Returns the socket's file descriptor
type type