summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorDominik Picheta <dominikpicheta@gmail.com>2016-09-06 20:35:02 +0200
committerDominik Picheta <dominikpicheta@gmail.com>2016-09-06 20:35:02 +0200
commit87eb3a105d4a2b6f9e9fd18bc6cca18d458d1cca (patch)
treef8dc123faac2515fecf3e32573f520809232b4ca
parent3760a8b973781ac3a9b06fa1c054c489f9c7ce3e (diff)
downloadNim-87eb3a105d4a2b6f9e9fd18bc6cca18d458d1cca.tar.gz
Some small fixes to changes introduced by #4683.
-rw-r--r--lib/pure/asyncdispatch.nim108
-rw-r--r--lib/pure/asyncfile.nim2
-rw-r--r--lib/pure/asyncnet.nim2
3 files changed, 30 insertions, 82 deletions
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim
index e8b29b26e..33b600718 100644
--- a/lib/pure/asyncdispatch.nim
+++ b/lib/pure/asyncdispatch.nim
@@ -750,7 +750,7 @@ when defined(windows) or defined(nimdoc):
     return retFuture
 
   proc recvInto*(socket: AsyncFD, buf: pointer, size: int,
-                flags = {SocketFlag.SafeDisconn}): Future[int] =
+                 flags = {SocketFlag.SafeDisconn}): Future[int] =
     ## Reads **up to** ``size`` bytes from ``socket`` into ``buf``, which must
     ## at least be of that size. Returned future will complete once all the
     ## data requested is read, a part of the data has been read, or the socket
@@ -784,7 +784,10 @@ when defined(windows) or defined(nimdoc):
       proc (fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) =
         if not retFuture.finished:
           if errcode == OSErrorCode(-1):
-            retFuture.complete(bytesCount)
+            if bytesCount == 0 and dataBuf.buf[0] == '\0':
+              retFuture.complete(0)
+            else:
+              retFuture.complete(bytesCount)
           else:
             if flags.isDisconnectionError(errcode):
               retFuture.complete(0)
@@ -861,54 +864,6 @@ when defined(windows) or defined(nimdoc):
       # free ``ol``.
     return retFuture
 
-  proc send*(socket: AsyncFD, data: string,
-             flags = {SocketFlag.SafeDisconn}): Future[void] =
-    ## Sends ``data`` to ``socket``. The returned future will complete once all
-    ## data has been sent.
-    verifyPresence(socket)
-    var retFuture = newFuture[void]("send")
-
-    var dataBuf: TWSABuf
-    dataBuf.buf = data
-    GC_ref(data) # we need to protect data until send operation is completed
-                 # or failed.
-    dataBuf.len = data.len.ULONG
-
-    var bytesReceived, lowFlags: Dword
-    var ol = PCustomOverlapped()
-    GC_ref(ol)
-    ol.data = CompletionData(fd: socket, cb:
-      proc (fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) =
-        GC_unref(data) # if operation completed `data` must be released.
-        if not retFuture.finished:
-          if errcode == OSErrorCode(-1):
-            retFuture.complete()
-          else:
-            if flags.isDisconnectionError(errcode):
-              retFuture.complete()
-            else:
-              retFuture.fail(newException(OSError, osErrorMsg(errcode)))
-    )
-
-    let ret = WSASend(socket.SocketHandle, addr dataBuf, 1, addr bytesReceived,
-                      lowFlags, cast[POVERLAPPED](ol), nil)
-    if ret == -1:
-      let err = osLastError()
-      if err.int32 != ERROR_IO_PENDING:
-        GC_unref(ol)
-        GC_unref(data) # if operation failed `data` must be released, because
-                       # completion routine will not be called.
-        if flags.isDisconnectionError(err):
-          retFuture.complete()
-        else:
-          retFuture.fail(newException(OSError, osErrorMsg(err)))
-    else:
-      retFuture.complete()
-      # 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
-
   proc sendTo*(socket: AsyncFD, data: pointer, size: int, saddr: ptr SockAddr,
                saddrLen: Socklen,
                flags = {SocketFlag.SafeDisconn}): Future[void] =
@@ -1501,38 +1456,6 @@ else:
     addWrite(socket, cb)
     return retFuture
 
-  proc send*(socket: AsyncFD, data: string,
-             flags = {SocketFlag.SafeDisconn}): Future[void] =
-    var retFuture = newFuture[void]("send")
-
-    var written = 0
-
-    proc cb(sock: AsyncFD): bool =
-      result = true
-      let netSize = data.len-written
-      var d = data.cstring
-      let res = send(sock.SocketHandle, addr d[written], netSize.cint,
-                     MSG_NOSIGNAL)
-      if res < 0:
-        let lastError = osLastError()
-        if lastError.int32 notin {EINTR, EWOULDBLOCK, EAGAIN}:
-          if flags.isDisconnectionError(lastError):
-            retFuture.complete()
-          else:
-            retFuture.fail(newException(OSError, osErrorMsg(lastError)))
-        else:
-          result = false # We still want this callback to be called.
-      else:
-        written.inc(res)
-        if res != netSize:
-          result = false # We still have data to send.
-        else:
-          retFuture.complete()
-    # TODO: The following causes crashes.
-    #if not cb(socket):
-    addWrite(socket, cb)
-    return retFuture
-
   proc sendTo*(socket: AsyncFD, data: pointer, size: int, saddr: ptr SockAddr,
                saddrLen: SockLen,
                flags = {SocketFlag.SafeDisconn}): Future[void] =
@@ -1655,6 +1578,27 @@ proc accept*(socket: AsyncFD,
         retFut.complete(future.read.client)
   return retFut
 
+proc send*(socket: AsyncFD, data: string,
+           flags = {SocketFlag.SafeDisconn}): Future[void] =
+  ## Sends ``data`` to ``socket``. The returned future will complete once all
+  ## data has been sent.
+  var retFuture = newFuture[void]("send")
+
+  var copiedData = data
+  GC_ref(copiedData) # we need to protect data until send operation is completed
+               # or failed.
+
+  let sendFut = socket.send(addr copiedData[0], data.len, flags)
+  sendFut.cb =
+    proc () =
+      GC_unref(copiedData)
+      if sendFut.failed:
+        retFuture.fail(sendFut.error)
+      else:
+        retFuture.complete()
+
+  return retFuture
+
 # -- Await Macro
 include asyncmacro
 
diff --git a/lib/pure/asyncfile.nim b/lib/pure/asyncfile.nim
index 8801c64d0..ffe6a391e 100644
--- a/lib/pure/asyncfile.nim
+++ b/lib/pure/asyncfile.nim
@@ -24,6 +24,8 @@
 
 import asyncdispatch, os
 
+# TODO: Fix duplication introduced by PR #4683.
+
 when defined(windows) or defined(nimdoc):
   import winlean
 else:
diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim
index c7691f45c..dbf895d18 100644
--- a/lib/pure/asyncnet.nim
+++ b/lib/pure/asyncnet.nim
@@ -62,6 +62,8 @@ import os
 
 export SOBool
 
+# TODO: Remove duplication introduced by PR #4683.
+
 const defineSsl = defined(ssl) or defined(nimdoc)
 
 when defineSsl: