Resolve bugs based on unreliable bytesReceived value.
This commit is contained in:
parent
6e6c15081d
commit
6fa6fdeb34
2 changed files with 21 additions and 53 deletions
|
|
@ -659,34 +659,14 @@ when defined(windows) or defined(nimdoc):
|
||||||
retFuture.complete("")
|
retFuture.complete("")
|
||||||
else:
|
else:
|
||||||
retFuture.fail(newException(OSError, osErrorMsg(err)))
|
retFuture.fail(newException(OSError, osErrorMsg(err)))
|
||||||
elif ret == 0 and bytesReceived == 0 and dataBuf.buf[0] == '\0':
|
elif ret == 0:
|
||||||
# We have to ensure that the buffer is empty because WSARecv will tell
|
if bytesReceived != 0:
|
||||||
# us immediately when it was disconnected, even when there is still
|
var data = newString(bytesReceived)
|
||||||
# data in the buffer.
|
copyMem(addr data[0], addr dataBuf.buf[0], bytesReceived)
|
||||||
# We want to give the user as much data as we can. So we only return
|
retFuture.complete($data)
|
||||||
# the empty string (which signals a disconnection) when there is
|
else:
|
||||||
# nothing left to read.
|
if hasOverlappedIoCompleted(cast[POVERLAPPED](ol)):
|
||||||
retFuture.complete("")
|
retFuture.complete("")
|
||||||
# TODO: "For message-oriented sockets, where a zero byte message is often
|
|
||||||
# allowable, a failure with an error code of WSAEDISCON is used to
|
|
||||||
# indicate graceful closure."
|
|
||||||
# ~ http://msdn.microsoft.com/en-us/library/ms741688%28v=vs.85%29.aspx
|
|
||||||
else:
|
|
||||||
# Request to read completed immediately.
|
|
||||||
# From my tests bytesReceived isn't reliable.
|
|
||||||
let realSize =
|
|
||||||
if bytesReceived == 0:
|
|
||||||
size
|
|
||||||
else:
|
|
||||||
bytesReceived
|
|
||||||
var data = newString(realSize)
|
|
||||||
assert realSize <= size
|
|
||||||
copyMem(addr data[0], addr dataBuf.buf[0], realSize)
|
|
||||||
#dealloc dataBuf.buf
|
|
||||||
retFuture.complete($data)
|
|
||||||
# We don't deallocate ``ol`` here because even though this completed
|
|
||||||
# immediately poll will still be notified about its completion and it will
|
|
||||||
# free ``ol``.
|
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc recvInto*(socket: AsyncFD, buf: cstring, size: int,
|
proc recvInto*(socket: AsyncFD, buf: cstring, size: int,
|
||||||
|
|
@ -749,31 +729,12 @@ when defined(windows) or defined(nimdoc):
|
||||||
retFuture.complete(0)
|
retFuture.complete(0)
|
||||||
else:
|
else:
|
||||||
retFuture.fail(newException(OSError, osErrorMsg(err)))
|
retFuture.fail(newException(OSError, osErrorMsg(err)))
|
||||||
elif ret == 0 and bytesReceived == 0 and dataBuf.buf[0] == '\0':
|
elif ret == 0:
|
||||||
# We have to ensure that the buffer is empty because WSARecv will tell
|
if bytesReceived != 0:
|
||||||
# us immediately when it was disconnected, even when there is still
|
retFuture.complete(bytesReceived)
|
||||||
# data in the buffer.
|
else:
|
||||||
# We want to give the user as much data as we can. So we only return
|
if hasOverlappedIoCompleted(cast[POVERLAPPED](ol)):
|
||||||
# the empty string (which signals a disconnection) when there is
|
retFuture.complete(bytesReceived)
|
||||||
# nothing left to read.
|
|
||||||
retFuture.complete(0)
|
|
||||||
# TODO: "For message-oriented sockets, where a zero byte message is often
|
|
||||||
# allowable, a failure with an error code of WSAEDISCON is used to
|
|
||||||
# indicate graceful closure."
|
|
||||||
# ~ http://msdn.microsoft.com/en-us/library/ms741688%28v=vs.85%29.aspx
|
|
||||||
else:
|
|
||||||
# Request to read completed immediately.
|
|
||||||
# From my tests bytesReceived isn't reliable.
|
|
||||||
let realSize =
|
|
||||||
if bytesReceived == 0:
|
|
||||||
size
|
|
||||||
else:
|
|
||||||
bytesReceived
|
|
||||||
assert realSize <= size
|
|
||||||
retFuture.complete(realSize)
|
|
||||||
# We don't deallocate ``ol`` here because even though this completed
|
|
||||||
# immediately poll will still be notified about its completion and it will
|
|
||||||
# free ``ol``.
|
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc send*(socket: AsyncFD, data: string,
|
proc send*(socket: AsyncFD, data: string,
|
||||||
|
|
|
||||||
|
|
@ -759,6 +759,7 @@ const
|
||||||
WSAENETRESET* = 10052
|
WSAENETRESET* = 10052
|
||||||
WSAETIMEDOUT* = 10060
|
WSAETIMEDOUT* = 10060
|
||||||
ERROR_NETNAME_DELETED* = 64
|
ERROR_NETNAME_DELETED* = 64
|
||||||
|
STATUS_PENDING* = 0x103
|
||||||
|
|
||||||
proc createIoCompletionPort*(FileHandle: Handle, ExistingCompletionPort: Handle,
|
proc createIoCompletionPort*(FileHandle: Handle, ExistingCompletionPort: Handle,
|
||||||
CompletionKey: ULONG_PTR,
|
CompletionKey: ULONG_PTR,
|
||||||
|
|
@ -775,6 +776,12 @@ proc getOverlappedResult*(hFile: Handle, lpOverlapped: POVERLAPPED,
|
||||||
lpNumberOfBytesTransferred: var DWORD, bWait: WINBOOL): WINBOOL{.
|
lpNumberOfBytesTransferred: var DWORD, bWait: WINBOOL): WINBOOL{.
|
||||||
stdcall, dynlib: "kernel32", importc: "GetOverlappedResult".}
|
stdcall, dynlib: "kernel32", importc: "GetOverlappedResult".}
|
||||||
|
|
||||||
|
# this is copy of HasOverlappedIoCompleted() macro from <winbase.h>
|
||||||
|
# because we have declared own OVERLAPPED structure with member names not
|
||||||
|
# compatible with original names.
|
||||||
|
template hasOverlappedIoCompleted*(lpOverlapped): bool =
|
||||||
|
(cast[uint](lpOverlapped.internal) != STATUS_PENDING)
|
||||||
|
|
||||||
const
|
const
|
||||||
IOC_OUT* = 0x40000000
|
IOC_OUT* = 0x40000000
|
||||||
IOC_IN* = 0x80000000
|
IOC_IN* = 0x80000000
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue