diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/posix/posix.nim | 48 | ||||
-rw-r--r-- | lib/pure/asyncio.nim | 23 | ||||
-rw-r--r-- | lib/pure/osproc.nim | 2 | ||||
-rw-r--r-- | lib/pure/sockets.nim | 21 | ||||
-rw-r--r-- | lib/system.nim | 4 | ||||
-rw-r--r-- | lib/windows/winlean.nim | 8 | ||||
-rw-r--r-- | lib/wrappers/openssl.nim | 4 |
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.} |