summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/posix/posix.nim48
-rw-r--r--lib/pure/asyncio.nim23
-rw-r--r--lib/pure/osproc.nim2
-rw-r--r--lib/pure/sockets.nim21
-rw-r--r--lib/system.nim4
-rw-r--r--lib/windows/winlean.nim8
-rw-r--r--lib/wrappers/openssl.nim4
7 files changed, 68 insertions, 42 deletions
diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim
index 107129b7a..806c255ee 100644
--- a/lib/posix/posix.nim
+++ b/lib/posix/posix.nim
@@ -81,8 +81,7 @@ else:
       ## A type representing a directory stream.   
   
 type
-  TSocketHandle* = cint # The type used to represent socket descripters
-                        # Should this be distinct? Is this the right place?
+  TSocketHandle* = distinct cint # The type used to represent socket descriptors
 
   Tdirent* {.importc: "struct dirent", 
              header: "<dirent.h>", final, pure.} = object ## dirent_t struct
@@ -1794,7 +1793,7 @@ proc dlopen*(a1: cstring, a2: cint): pointer {.importc, header: "<dlfcn.h>".}
 proc dlsym*(a1: pointer, a2: cstring): pointer {.importc, header: "<dlfcn.h>".}
 
 proc creat*(a1: cstring, a2: Tmode): cint {.importc, header: "<fcntl.h>".}
-proc fcntl*(a1: cint, a2: cint): cint {.varargs, importc, header: "<fcntl.h>".}
+proc fcntl*(a1: cint | TSocketHandle, a2: cint): cint {.varargs, importc, header: "<fcntl.h>".}
 proc open*(a1: cstring, a2: cint): cint {.varargs, importc, header: "<fcntl.h>".}
 proc posix_fadvise*(a1: cint, a2, a3: Toff, a4: cint): cint {.
   importc, header: "<fcntl.h>".}
@@ -2071,7 +2070,7 @@ proc access*(a1: cstring, a2: cint): cint {.importc, header: "<unistd.h>".}
 proc alarm*(a1: cint): cint {.importc, header: "<unistd.h>".}
 proc chdir*(a1: cstring): cint {.importc, header: "<unistd.h>".}
 proc chown*(a1: cstring, a2: Tuid, a3: Tgid): cint {.importc, header: "<unistd.h>".}
-proc close*(a1: cint): cint {.importc, header: "<unistd.h>".}
+proc close*(a1: cint | TSocketHandle): cint {.importc, header: "<unistd.h>".}
 proc confstr*(a1: cint, a2: cstring, a3: int): int {.importc, header: "<unistd.h>".}
 proc crypt*(a1, a2: cstring): cstring {.importc, header: "<unistd.h>".}
 proc ctermid*(a1: cstring): cstring {.importc, header: "<unistd.h>".}
@@ -2349,9 +2348,9 @@ proc strerror*(errnum: cint): cstring {.importc, header: "<string.h>".}
 proc hstrerror*(herrnum: cint): cstring {.importc, header: "<netdb.h>".}
 
 proc FD_CLR*(a1: cint, a2: var Tfd_set) {.importc, header: "<sys/select.h>".}
-proc FD_ISSET*(a1: cint, a2: var Tfd_set): cint {.
+proc FD_ISSET*(a1: cint | TSocketHandle, a2: var Tfd_set): cint {.
   importc, header: "<sys/select.h>".}
-proc FD_SET*(a1: cint, a2: var Tfd_set) {.importc, header: "<sys/select.h>".}
+proc FD_SET*(a1: cint | TSocketHandle, a2: var Tfd_set) {.importc, header: "<sys/select.h>".}
 proc FD_ZERO*(a1: var Tfd_set) {.importc, header: "<sys/select.h>".}
 
 proc pselect*(a1: cint, a2, a3, a4: ptr Tfd_set, a5: ptr ttimespec,
@@ -2431,44 +2430,49 @@ proc CMSG_NXTHDR*(mhdr: ptr TMsgHdr, cmsg: ptr TCMsgHdr): ptr TCmsgHdr {.
 proc CMSG_FIRSTHDR*(mhdr: ptr TMsgHdr): ptr TCMsgHdr {.
   importc, header: "<sys/socket.h>".}
 
-proc accept*(a1: cint, a2: ptr Tsockaddr, a3: ptr Tsocklen): cint {.
+const
+  INVALID_SOCKET* = TSocketHandle(-1)
+
+proc `==`*(x, y: TSocketHandle): bool {.borrow.}
+
+proc accept*(a1: TSocketHandle, a2: ptr Tsockaddr, a3: ptr Tsocklen): TSocketHandle {.
   importc, header: "<sys/socket.h>".}
 
-proc bindSocket*(a1: cint, a2: ptr Tsockaddr, a3: Tsocklen): cint {.
+proc bindSocket*(a1: TSocketHandle, a2: ptr Tsockaddr, a3: Tsocklen): cint {.
   importc: "bind", header: "<sys/socket.h>".}
   ## is Posix's ``bind``, because ``bind`` is a reserved word
   
-proc connect*(a1: cint, a2: ptr Tsockaddr, a3: Tsocklen): cint {.
+proc connect*(a1: TSocketHandle, a2: ptr Tsockaddr, a3: Tsocklen): cint {.
   importc, header: "<sys/socket.h>".}
-proc getpeername*(a1: cint, a2: ptr Tsockaddr, a3: ptr Tsocklen): cint {.
+proc getpeername*(a1: TSocketHandle, a2: ptr Tsockaddr, a3: ptr Tsocklen): cint {.
   importc, header: "<sys/socket.h>".}
-proc getsockname*(a1: cint, a2: ptr Tsockaddr, a3: ptr Tsocklen): cint {.
+proc getsockname*(a1: TSocketHandle, a2: ptr Tsockaddr, a3: ptr Tsocklen): cint {.
   importc, header: "<sys/socket.h>".}
 
-proc getsockopt*(a1, a2, a3: cint, a4: pointer, a5: ptr Tsocklen): cint {.
+proc getsockopt*(a1: TSocketHandle, a2, a3: cint, a4: pointer, a5: ptr Tsocklen): cint {.
   importc, header: "<sys/socket.h>".}
 
-proc listen*(a1, a2: cint): cint {.
+proc listen*(a1: TSocketHandle, a2: cint): cint {.
   importc, header: "<sys/socket.h>".}
-proc recv*(a1: cint, a2: pointer, a3: int, a4: cint): int {.
+proc recv*(a1: TSocketHandle, a2: pointer, a3: int, a4: cint): int {.
   importc, header: "<sys/socket.h>".}
-proc recvfrom*(a1: cint, a2: pointer, a3: int, a4: cint,
+proc recvfrom*(a1: TSocketHandle, a2: pointer, a3: int, a4: cint,
         a5: ptr Tsockaddr, a6: ptr Tsocklen): int {.
   importc, header: "<sys/socket.h>".}
-proc recvmsg*(a1: cint, a2: ptr Tmsghdr, a3: cint): int {.
+proc recvmsg*(a1: TSocketHandle, a2: ptr Tmsghdr, a3: cint): int {.
   importc, header: "<sys/socket.h>".}
-proc send*(a1: cint, a2: pointer, a3: int, a4: cint): int {.
+proc send*(a1: TSocketHandle, a2: pointer, a3: int, a4: cint): int {.
   importc, header: "<sys/socket.h>".}
-proc sendmsg*(a1: cint, a2: ptr Tmsghdr, a3: cint): int {.
+proc sendmsg*(a1: TSocketHandle, a2: ptr Tmsghdr, a3: cint): int {.
   importc, header: "<sys/socket.h>".}
-proc sendto*(a1: cint, a2: pointer, a3: int, a4: cint, a5: ptr Tsockaddr,
+proc sendto*(a1: TSocketHandle, a2: pointer, a3: int, a4: cint, a5: ptr Tsockaddr,
              a6: Tsocklen): int {.
   importc, header: "<sys/socket.h>".}
-proc setsockopt*(a1, a2, a3: cint, a4: pointer, a5: Tsocklen): cint {.
+proc setsockopt*(a1: TSocketHandle, a2, a3: cint, a4: pointer, a5: Tsocklen): cint {.
   importc, header: "<sys/socket.h>".}
-proc shutdown*(a1, a2: cint): cint {.
+proc shutdown*(a1: TSocketHandle, a2: cint): cint {.
   importc, header: "<sys/socket.h>".}
-proc socket*(a1, a2, a3: cint): cint {.
+proc socket*(a1, a2, a3: cint): TSocketHandle {.
   importc, header: "<sys/socket.h>".}
 proc sockatmark*(a1: cint): cint {.
   importc, header: "<sys/socket.h>".}
diff --git a/lib/pure/asyncio.nim b/lib/pure/asyncio.nim
index 48a22bbe8..c4a07d751 100644
--- a/lib/pure/asyncio.nim
+++ b/lib/pure/asyncio.nim
@@ -213,6 +213,7 @@ proc asyncSockHandleRead(h: PObject) =
   else:
     PAsyncSocket(h).handleAccept(PAsyncSocket(h))
 
+proc close*(sock: PAsyncSocket)
 proc asyncSockHandleWrite(h: PObject) =
   when defined(ssl):
     if PAsyncSocket(h).socket.isSSL and not
@@ -230,15 +231,19 @@ proc asyncSockHandleWrite(h: PObject) =
   else:
     if PAsyncSocket(h).sendBuffer != "":
       let sock = PAsyncSocket(h)
-      let bytesSent = sock.socket.sendAsync(sock.sendBuffer)
-      assert bytesSent > 0
-      if bytesSent != sock.sendBuffer.len:
-        sock.sendBuffer = sock.sendBuffer[bytesSent .. -1]
-      elif bytesSent == sock.sendBuffer.len:
-        sock.sendBuffer = ""
-      
-      if PAsyncSocket(h).handleWrite != nil:
-        PAsyncSocket(h).handleWrite(PAsyncSocket(h))
+      try:
+        let bytesSent = sock.socket.sendAsync(sock.sendBuffer)
+        assert bytesSent > 0
+        if bytesSent != sock.sendBuffer.len:
+          sock.sendBuffer = sock.sendBuffer[bytesSent .. -1]
+        elif bytesSent == sock.sendBuffer.len:
+          sock.sendBuffer = ""
+        
+        if PAsyncSocket(h).handleWrite != nil:
+          PAsyncSocket(h).handleWrite(PAsyncSocket(h))
+      except EOS:
+        # Most likely the socket closed before the full buffer could be sent to it.
+        sock.close() # TODO: Provide a handleError for users?
     else:
       if PAsyncSocket(h).handleWrite != nil:
         PAsyncSocket(h).handleWrite(PAsyncSocket(h))
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index a3d72d73c..754e34b85 100644
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -236,8 +236,8 @@ proc execProcesses*(cmds: openArray[string],
             inc(i)
             if i > high(cmds): break
     for j in 0..m-1:
-      if q[j] != nil: close(q[j])
       result = max(waitForExit(q[j]), result)
+      if q[j] != nil: close(q[j])
   else:
     for i in 0..high(cmds):
       var p = startCmd(cmds[i], options=options)
diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim
index 516d0d8bc..9c0cb98c7 100644
--- a/lib/pure/sockets.nim
+++ b/lib/pure/sockets.nim
@@ -126,7 +126,19 @@ type
 
   ETimeout* = object of ESynch
 
+let
+  InvalidSocket*: TSocket = nil ## invalid socket
+
+when defined(windows):
+  let
+    OSInvalidSocket = winlean.INVALID_SOCKET
+else:
+  let
+    OSInvalidSocket = posix.INVALID_SOCKET
+
 proc newTSocket(fd: TSocketHandle, isBuff: bool): TSocket =
+  if fd == OSInvalidSocket:
+    return nil
   new(result)
   result.fd = fd
   result.isBuffered = isBuff
@@ -134,9 +146,6 @@ proc newTSocket(fd: TSocketHandle, isBuff: bool): TSocket =
     result.currPos = 0
   result.nonblocking = false
 
-let
-  InvalidSocket*: TSocket = nil ## invalid socket
-
 proc `==`*(a, b: TPort): bool {.borrow.}
   ## ``==`` for ports.
 
@@ -211,7 +220,9 @@ else:
 
 proc socket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM,
              protocol: TProtocol = IPPROTO_TCP, buffered = true): TSocket =
-  ## Creates a new socket; returns `InvalidSocket` if an error occurs.  
+  ## Creates a new socket; returns `InvalidSocket` if an error occurs.
+  
+  # TODO: Perhaps this should just raise EOS when an error occurs.
   when defined(Windows):
     result = newTSocket(winlean.socket(ord(domain), ord(typ), ord(protocol)), buffered)
   else:
@@ -456,7 +467,7 @@ template acceptAddrPlain(noClientRet, successRet: expr,
   var sock = accept(server.fd, cast[ptr TSockAddr](addr(sockAddress)),
                     addr(addrLen))
   
-  if sock < 0:
+  if sock == OSInvalidSocket:
     let err = OSLastError()
     when defined(windows):
       if err.int32 == WSAEINPROGRESS:
diff --git a/lib/system.nim b/lib/system.nim
index 174912519..b2d19a885 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -849,7 +849,7 @@ const
     ## a string that describes the application type. Possible values:
     ## "console", "gui", "lib".
   
-  seqShallowFlag = 1 shl (sizeof(int)*8-1)
+  seqShallowFlag = low(int)
   
 proc compileOption*(option: string): bool {.
   magic: "CompileOption", noSideEffect.}
@@ -1791,7 +1791,7 @@ when defined(JS):
 
 elif hostOS != "standalone":
   {.push stack_trace:off, profiler:off.}
-  proc add*(x: var string, y: cstring) {.noStackFrame.} =
+  proc add*(x: var string, y: cstring) =
     var i = 0
     while y[i] != '\0':
       add(x, y[i])
diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim
index 40b24cc0a..c9d595d2c 100644
--- a/lib/windows/winlean.nim
+++ b/lib/windows/winlean.nim
@@ -335,6 +335,9 @@ const
 proc WSAGetLastError*(): cint {.importc: "WSAGetLastError", dynlib: ws2dll.}
 
 type
+  TSocketHandle* = distinct int
+
+type
   TWSAData* {.pure, final, importc: "WSADATA", header: "Winsock2.h".} = object 
     wVersion, wHighVersion: int16
     szDescription: array[0..WSADESCRIPTION_LEN, char]
@@ -389,8 +392,6 @@ type
     h_addrtype*: int16
     h_length*: int16
     h_addr_list*: cstringArray
-    
-  TSocketHandle* = int # Make distinct? Is this the right place for this?
   
   TFdSet* {.pure, final.} = object
     fd_count*: cint # unsigned
@@ -413,6 +414,9 @@ type
 
 var
   SOMAXCONN* {.importc, header: "Winsock2.h".}: cint
+  INVALID_SOCKET* {.importc, header: "Winsock2.h".}: TSocketHandle
+
+proc `==`*(x, y: TSocketHandle): bool {.borrow.}
 
 proc getservbyname*(name, proto: cstring): ptr TServent {.
   stdcall, importc: "getservbyname", dynlib: ws2dll.}
diff --git a/lib/wrappers/openssl.nim b/lib/wrappers/openssl.nim
index f310c969b..af72d04eb 100644
--- a/lib/wrappers/openssl.nim
+++ b/lib/wrappers/openssl.nim
@@ -45,6 +45,7 @@ when defined(WINDOWS):
   const 
     DLLSSLName = "(ssleay32|libssl32).dll"
     DLLUtilName = "libeay32.dll"
+  from winlean import TSocketHandle
 else:
   const
     versions = "(|.1.0.0|.0.9.9|.0.9.8|.0.9.7|.0.9.6|.0.9.5|.0.9.4)"
@@ -56,6 +57,7 @@ else:
     const 
       DLLSSLName = "libssl.so" & versions
       DLLUtilName = "libcrypto.so" & versions
+  from posix import TSocketHandle
 
 type 
   SslStruct {.final, pure.} = object
@@ -225,7 +227,7 @@ proc SSL_CTX_use_PrivateKey_file*(ctx: PSSL_CTX,
 proc SSL_CTX_check_private_key*(ctx: PSSL_CTX): cInt{.cdecl, dynlib: DLLSSLName, 
     importc.}
 
-proc SSL_set_fd*(ssl: PSSL, fd: cint): cint{.cdecl, dynlib: DLLSSLName, importc.}
+proc SSL_set_fd*(ssl: PSSL, fd: TSocketHandle): cint{.cdecl, dynlib: DLLSSLName, importc.}
 
 proc SSL_shutdown*(ssl: PSSL): cInt{.cdecl, dynlib: DLLSSLName, importc.}
 proc SSL_connect*(ssl: PSSL): cint{.cdecl, dynlib: DLLSSLName, importc.}