Added SafeDisconn for accept.
This commit is contained in:
parent
8b08e98e9f
commit
ef2f377bfa
4 changed files with 63 additions and 22 deletions
|
|
@ -524,7 +524,10 @@ when defined(windows) or defined(nimdoc):
|
||||||
if errcode == TOSErrorCode(-1):
|
if errcode == TOSErrorCode(-1):
|
||||||
retFuture.complete()
|
retFuture.complete()
|
||||||
else:
|
else:
|
||||||
retFuture.fail(newException(EOS, osErrorMsg(errcode)))
|
if flags.isDisconnectionError(errcode):
|
||||||
|
retFuture.complete()
|
||||||
|
else:
|
||||||
|
retFuture.fail(newException(EOS, osErrorMsg(errcode)))
|
||||||
)
|
)
|
||||||
|
|
||||||
let ret = WSASend(socket.TSocketHandle, addr dataBuf, 1, addr bytesReceived,
|
let ret = WSASend(socket.TSocketHandle, addr dataBuf, 1, addr bytesReceived,
|
||||||
|
|
@ -544,13 +547,19 @@ when defined(windows) or defined(nimdoc):
|
||||||
# free ``ol``.
|
# free ``ol``.
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc acceptAddr*(socket: TAsyncFD):
|
proc acceptAddr*(socket: TAsyncFD, flags = {TSocketFlags.SafeDisconn}):
|
||||||
PFuture[tuple[address: string, client: TAsyncFD]] =
|
PFuture[tuple[address: string, client: TAsyncFD]] =
|
||||||
## 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.
|
||||||
##
|
##
|
||||||
## The resulting client socket is automatically registered to dispatcher.
|
## The resulting client socket is automatically registered to the
|
||||||
|
## dispatcher.
|
||||||
|
##
|
||||||
|
## The ``accept`` call may result in an error if the connecting socket
|
||||||
|
## disconnects during the duration of the ``accept``. If the ``SafeDisconn``
|
||||||
|
## flag is specified then this error will not be raised and instead
|
||||||
|
## accept will be called again.
|
||||||
verifyPresence(socket)
|
verifyPresence(socket)
|
||||||
var retFuture = newFuture[tuple[address: string, client: TAsyncFD]]("acceptAddr")
|
var retFuture = newFuture[tuple[address: string, client: TAsyncFD]]("acceptAddr")
|
||||||
|
|
||||||
|
|
@ -584,6 +593,18 @@ when defined(windows) or defined(nimdoc):
|
||||||
client: clientSock.TAsyncFD)
|
client: clientSock.TAsyncFD)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
template failAccept(errcode): stmt =
|
||||||
|
if flags.isDisconnectionError(errcode):
|
||||||
|
var newAcceptFut = acceptAddr(socket, flags)
|
||||||
|
newAcceptFut.callback =
|
||||||
|
proc () =
|
||||||
|
if newAcceptFut.failed:
|
||||||
|
retFuture.fail(newAcceptFut.readError)
|
||||||
|
else:
|
||||||
|
retFuture.complete(newAcceptFut.read)
|
||||||
|
else:
|
||||||
|
retFuture.fail(newException(EOS, osErrorMsg(errcode)))
|
||||||
|
|
||||||
var ol = PCustomOverlapped()
|
var ol = PCustomOverlapped()
|
||||||
GC_ref(ol)
|
GC_ref(ol)
|
||||||
ol.data = TCompletionData(sock: socket, cb:
|
ol.data = TCompletionData(sock: socket, cb:
|
||||||
|
|
@ -592,7 +613,7 @@ when defined(windows) or defined(nimdoc):
|
||||||
if errcode == TOSErrorCode(-1):
|
if errcode == TOSErrorCode(-1):
|
||||||
completeAccept()
|
completeAccept()
|
||||||
else:
|
else:
|
||||||
retFuture.fail(newException(EOS, osErrorMsg(errcode)))
|
failAccept(errcode)
|
||||||
)
|
)
|
||||||
|
|
||||||
# http://msdn.microsoft.com/en-us/library/windows/desktop/ms737524%28v=vs.85%29.aspx
|
# http://msdn.microsoft.com/en-us/library/windows/desktop/ms737524%28v=vs.85%29.aspx
|
||||||
|
|
@ -605,7 +626,7 @@ when defined(windows) or defined(nimdoc):
|
||||||
if not ret:
|
if not ret:
|
||||||
let err = osLastError()
|
let err = osLastError()
|
||||||
if err.int32 != ERROR_IO_PENDING:
|
if err.int32 != ERROR_IO_PENDING:
|
||||||
retFuture.fail(newException(EOS, osErrorMsg(err)))
|
failAccept(err)
|
||||||
GC_unref(ol)
|
GC_unref(ol)
|
||||||
else:
|
else:
|
||||||
completeAccept()
|
completeAccept()
|
||||||
|
|
@ -749,7 +770,7 @@ else:
|
||||||
|
|
||||||
proc connect*(socket: TAsyncFD, address: string, port: TPort,
|
proc connect*(socket: TAsyncFD, address: string, port: TPort,
|
||||||
af = AF_INET): PFuture[void] =
|
af = AF_INET): PFuture[void] =
|
||||||
var retFuture = newFuture[void]()
|
var retFuture = newFuture[void]("connect")
|
||||||
|
|
||||||
proc cb(sock: TAsyncFD): bool =
|
proc cb(sock: TAsyncFD): bool =
|
||||||
# We have connected.
|
# We have connected.
|
||||||
|
|
@ -784,7 +805,7 @@ else:
|
||||||
|
|
||||||
proc recv*(socket: TAsyncFD, size: int,
|
proc recv*(socket: TAsyncFD, size: int,
|
||||||
flags = {TSocketFlags.SafeDisconn}): PFuture[string] =
|
flags = {TSocketFlags.SafeDisconn}): PFuture[string] =
|
||||||
var retFuture = newFuture[string]()
|
var retFuture = newFuture[string]("recv")
|
||||||
|
|
||||||
var readBuffer = newString(size)
|
var readBuffer = newString(size)
|
||||||
|
|
||||||
|
|
@ -815,7 +836,7 @@ else:
|
||||||
|
|
||||||
proc send*(socket: TAsyncFD, data: string,
|
proc send*(socket: TAsyncFD, data: string,
|
||||||
flags = {TSocketFlags.SafeDisconn}): PFuture[void] =
|
flags = {TSocketFlags.SafeDisconn}): PFuture[void] =
|
||||||
var retFuture = newFuture[void]()
|
var retFuture = newFuture[void]("send")
|
||||||
|
|
||||||
var written = 0
|
var written = 0
|
||||||
|
|
||||||
|
|
@ -845,9 +866,10 @@ else:
|
||||||
addWrite(socket, cb)
|
addWrite(socket, cb)
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc acceptAddr*(socket: TAsyncFD):
|
proc acceptAddr*(socket: TAsyncFD, flags = {TSocketFlags.SafeDisconn}):
|
||||||
PFuture[tuple[address: string, client: TAsyncFD]] =
|
PFuture[tuple[address: string, client: TAsyncFD]] =
|
||||||
var retFuture = newFuture[tuple[address: string, client: TAsyncFD]]()
|
var retFuture = newFuture[tuple[address: string,
|
||||||
|
client: TAsyncFD]]("acceptAddr")
|
||||||
proc cb(sock: TAsyncFD): bool =
|
proc cb(sock: TAsyncFD): bool =
|
||||||
result = true
|
result = true
|
||||||
var sockAddress: Tsockaddr_in
|
var sockAddress: Tsockaddr_in
|
||||||
|
|
@ -860,7 +882,10 @@ else:
|
||||||
if lastError.int32 == EINTR:
|
if lastError.int32 == EINTR:
|
||||||
return false
|
return false
|
||||||
else:
|
else:
|
||||||
retFuture.fail(newException(EOS, osErrorMsg(lastError)))
|
if flags.isDisconnectionError(lastError):
|
||||||
|
return false
|
||||||
|
else:
|
||||||
|
retFuture.fail(newException(EOS, osErrorMsg(lastError)))
|
||||||
else:
|
else:
|
||||||
register(client.TAsyncFD)
|
register(client.TAsyncFD)
|
||||||
retFuture.complete(($inet_ntoa(sockAddress.sin_addr), client.TAsyncFD))
|
retFuture.complete(($inet_ntoa(sockAddress.sin_addr), client.TAsyncFD))
|
||||||
|
|
@ -875,12 +900,13 @@ proc sleepAsync*(ms: int): PFuture[void] =
|
||||||
p.timers.add((epochTime() + (ms / 1000), retFuture))
|
p.timers.add((epochTime() + (ms / 1000), retFuture))
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc accept*(socket: TAsyncFD): PFuture[TAsyncFD] =
|
proc accept*(socket: TAsyncFD,
|
||||||
|
flags = {TSocketFlags.SafeDisconn}): PFuture[TAsyncFD] =
|
||||||
## 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[TAsyncFD]("accept")
|
var retFut = newFuture[TAsyncFD]("accept")
|
||||||
var fut = acceptAddr(socket)
|
var fut = acceptAddr(socket, flags)
|
||||||
fut.callback =
|
fut.callback =
|
||||||
proc (future: PFuture[tuple[address: string, client: TAsyncFD]]) =
|
proc (future: PFuture[tuple[address: string, client: TAsyncFD]]) =
|
||||||
assert future.finished
|
assert future.finished
|
||||||
|
|
|
||||||
|
|
@ -135,13 +135,13 @@ proc send*(socket: PAsyncSocket, data: string,
|
||||||
assert socket != nil
|
assert socket != nil
|
||||||
result = send(socket.fd.TAsyncFD, data, flags)
|
result = send(socket.fd.TAsyncFD, data, flags)
|
||||||
|
|
||||||
proc acceptAddr*(socket: PAsyncSocket):
|
proc acceptAddr*(socket: PAsyncSocket, flags = {TSocketFlags.SafeDisconn}):
|
||||||
PFuture[tuple[address: string, client: PAsyncSocket]] =
|
PFuture[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)
|
var fut = acceptAddr(socket.fd.TAsyncFD, flags)
|
||||||
fut.callback =
|
fut.callback =
|
||||||
proc (future: PFuture[tuple[address: string, client: TAsyncFD]]) =
|
proc (future: PFuture[tuple[address: string, client: TAsyncFD]]) =
|
||||||
assert future.finished
|
assert future.finished
|
||||||
|
|
@ -153,12 +153,13 @@ proc acceptAddr*(socket: PAsyncSocket):
|
||||||
retFuture.complete(resultTup)
|
retFuture.complete(resultTup)
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc accept*(socket: PAsyncSocket): PFuture[PAsyncSocket] =
|
proc accept*(socket: PAsyncSocket,
|
||||||
|
flags = {TSocketFlags.SafeDisconn}): PFuture[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)
|
var fut = acceptAddr(socket, flags)
|
||||||
fut.callback =
|
fut.callback =
|
||||||
proc (future: PFuture[tuple[address: string, client: PAsyncSocket]]) =
|
proc (future: PFuture[tuple[address: string, client: PAsyncSocket]]) =
|
||||||
assert future.finished
|
assert future.finished
|
||||||
|
|
|
||||||
|
|
@ -569,8 +569,8 @@ proc bindAddr*(socket: PSocket, port = TPort(0), address = "") {.
|
||||||
osError(osLastError())
|
osError(osLastError())
|
||||||
dealloc(aiList)
|
dealloc(aiList)
|
||||||
|
|
||||||
proc acceptAddr*(server: PSocket, client: var PSocket, address: var string) {.
|
proc acceptAddr*(server: PSocket, client: var PSocket, address: var string,
|
||||||
tags: [FReadIO].} =
|
flags = {TSocketFlags.SafeDisconn}) {.tags: [FReadIO].} =
|
||||||
## Blocks until a connection is being made from a client. When a connection
|
## Blocks until a connection is being made from a client. When a connection
|
||||||
## is made sets ``client`` to the client socket and ``address`` to the address
|
## is made sets ``client`` to the client socket and ``address`` to the address
|
||||||
## of the connecting client.
|
## of the connecting client.
|
||||||
|
|
@ -581,6 +581,11 @@ proc acceptAddr*(server: PSocket, client: var PSocket, address: var string) {.
|
||||||
##
|
##
|
||||||
## **Note**: ``client`` must be initialised (with ``new``), this function
|
## **Note**: ``client`` must be initialised (with ``new``), this function
|
||||||
## makes no effort to initialise the ``client`` variable.
|
## makes no effort to initialise the ``client`` variable.
|
||||||
|
##
|
||||||
|
## The ``accept`` call may result in an error if the connecting socket
|
||||||
|
## disconnects during the duration of the ``accept``. If the ``SafeDisconn``
|
||||||
|
## flag is specified then this error will not be raised and instead
|
||||||
|
## accept will be called again.
|
||||||
assert(client != nil)
|
assert(client != nil)
|
||||||
var sockAddress: Tsockaddr_in
|
var sockAddress: Tsockaddr_in
|
||||||
var addrLen = sizeof(sockAddress).TSocklen
|
var addrLen = sizeof(sockAddress).TSocklen
|
||||||
|
|
@ -589,6 +594,8 @@ proc acceptAddr*(server: PSocket, client: var PSocket, address: var string) {.
|
||||||
|
|
||||||
if sock == osInvalidSocket:
|
if sock == osInvalidSocket:
|
||||||
let err = osLastError()
|
let err = osLastError()
|
||||||
|
if flags.isDisconnectionError(err):
|
||||||
|
acceptAddr(server, client, address, flags)
|
||||||
osError(err)
|
osError(err)
|
||||||
else:
|
else:
|
||||||
client.fd = sock
|
client.fd = sock
|
||||||
|
|
@ -658,15 +665,20 @@ when false: #defined(ssl):
|
||||||
acceptAddrPlain(AcceptNoClient, AcceptSuccess):
|
acceptAddrPlain(AcceptNoClient, AcceptSuccess):
|
||||||
doHandshake()
|
doHandshake()
|
||||||
|
|
||||||
proc accept*(server: PSocket, client: var PSocket) {.tags: [FReadIO].} =
|
proc accept*(server: PSocket, client: var PSocket,
|
||||||
|
flags = {TSocketFlags.SafeDisconn}) {.tags: [FReadIO].} =
|
||||||
## Equivalent to ``acceptAddr`` but doesn't return the address, only the
|
## Equivalent to ``acceptAddr`` but doesn't return the address, only the
|
||||||
## socket.
|
## socket.
|
||||||
##
|
##
|
||||||
## **Note**: ``client`` must be initialised (with ``new``), this function
|
## **Note**: ``client`` must be initialised (with ``new``), this function
|
||||||
## makes no effort to initialise the ``client`` variable.
|
## makes no effort to initialise the ``client`` variable.
|
||||||
|
##
|
||||||
|
## The ``accept`` call may result in an error if the connecting socket
|
||||||
|
## disconnects during the duration of the ``accept``. If the ``SafeDisconn``
|
||||||
|
## flag is specified then this error will not be raised and instead
|
||||||
|
## accept will be called again.
|
||||||
var addrDummy = ""
|
var addrDummy = ""
|
||||||
acceptAddr(server, client, addrDummy)
|
acceptAddr(server, client, addrDummy, flags)
|
||||||
|
|
||||||
proc close*(socket: PSocket) =
|
proc close*(socket: PSocket) =
|
||||||
## Closes a socket.
|
## Closes a socket.
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@ News
|
||||||
- ``sequtils.distnct`` has been renamed to ``sequtils.deduplicate``.
|
- ``sequtils.distnct`` has been renamed to ``sequtils.deduplicate``.
|
||||||
- Added ``algorithm.reversed``
|
- Added ``algorithm.reversed``
|
||||||
- Added ``uri.combine`` and ``uri.parseUri``.
|
- Added ``uri.combine`` and ``uri.parseUri``.
|
||||||
|
- Some sockets procedures now support a ``SafeDisconn`` flag which causes
|
||||||
|
them to handle disconnection errors and not raise them.
|
||||||
|
|
||||||
2014-04-21 Version 0.9.4 released
|
2014-04-21 Version 0.9.4 released
|
||||||
=================================
|
=================================
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue