diff options
author | Dominik Picheta <dominikpicheta@googlemail.com> | 2014-12-18 00:58:52 +0000 |
---|---|---|
committer | Dominik Picheta <dominikpicheta@googlemail.com> | 2014-12-18 00:58:52 +0000 |
commit | a58b4cfda7a574f6c8cf090f7ab16531db8815d7 (patch) | |
tree | 480639a1ddf0228ef093744e045a3ebd3dcfd2d2 /lib | |
parent | 2024ca454f0bc8673450297bee39733e9044b776 (diff) | |
parent | 1b614ffc8044d9efcf5ae5c9ad59f2416e8ccfa2 (diff) | |
download | Nim-a58b4cfda7a574f6c8cf090f7ab16531db8815d7.tar.gz |
Merge pull request #1746 from cowboy-coders/socket_close_clean
Fix close procedure in the net module
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pure/net.nim | 40 | ||||
-rw-r--r-- | lib/wrappers/openssl.nim | 13 |
2 files changed, 40 insertions, 13 deletions
diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 8afc6c5c5..28b84eb39 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -256,7 +256,21 @@ proc socketError*(socket: Socket, err: int = -1, async = false, else: raiseSSLError("Not enough data on socket.") of SSL_ERROR_WANT_X509_LOOKUP: raiseSSLError("Function for x509 lookup has been called.") - of SSL_ERROR_SYSCALL, SSL_ERROR_SSL: + of SSL_ERROR_SYSCALL: + var errStr = "IO error has occured " + let sslErr = ErrPeekLastError() + if sslErr == 0 and err == 0: + errStr.add "because an EOF was observed that violates the protocol" + elif sslErr == 0 and err == -1: + errStr.add "in the BIO layer" + else: + let errStr = $ErrErrorString(sslErr, nil) + raiseSSLError(errStr & ": " & errStr) + let osMsg = osErrorMsg osLastError() + if osMsg != "": + errStr.add ". The OS reports: " & osMsg + raise newException(OSError, errStr) + of SSL_ERROR_SSL: raiseSSLError() else: raiseSSLError("Unknown Error") @@ -418,15 +432,21 @@ proc accept*(server: Socket, client: var Socket, proc close*(socket: Socket) = ## Closes a socket. - socket.fd.close() - when defined(ssl): - if socket.isSSL: - let res = SSLShutdown(socket.sslHandle) - if res == 0: - if SSLShutdown(socket.sslHandle) != 1: - socketError(socket) - elif res != 1: - socketError(socket) + try: + when defined(ssl): + if socket.isSSL: + ErrClearError() + # As we are closing the underlying socket immediately afterwards, + # it is valid, under the TLS standard, to perform a unidirectional + # shutdown i.e not wait for the peers "close notify" alert with a second + # call to SSLShutdown + let res = SSLShutdown(socket.sslHandle) + if res == 0: + discard + elif res != 1: + socketError(socket, res) + finally: + socket.fd.close() proc toCInt*(opt: SOBool): cint = ## Converts a ``SOBool`` into its Socket Option cint representation. diff --git a/lib/wrappers/openssl.nim b/lib/wrappers/openssl.nim index 6e85fb9dd..ba25fbf1a 100644 --- a/lib/wrappers/openssl.nim +++ b/lib/wrappers/openssl.nim @@ -89,6 +89,8 @@ type {.deprecated: [PSSL: SslPtr, PSSL_CTX: SslCtx, PBIO: BIO].} const + SSL_SENT_SHUTDOWN* = 1 + SSL_RECEIVED_SHUTDOWN* = 2 EVP_MAX_MD_SIZE* = 16 + 20 SSL_ERROR_NONE* = 0 SSL_ERROR_SSL* = 1 @@ -233,6 +235,8 @@ proc SSL_CTX_check_private_key*(ctx: SslCtx): cInt{.cdecl, dynlib: DLLSSLName, proc SSL_set_fd*(ssl: SslPtr, fd: SocketHandle): cint{.cdecl, dynlib: DLLSSLName, importc.} proc SSL_shutdown*(ssl: SslPtr): cInt{.cdecl, dynlib: DLLSSLName, importc.} +proc SSL_set_shutdown*(ssl: SslPtr, mode: cint) {.cdecl, dynlib: DLLSSLName, importc: "SSL_set_shutdown".} +proc SSL_get_shutdown*(ssl: SslPtr): cint {.cdecl, dynlib: DLLSSLName, importc: "SSL_get_shutdown".} proc SSL_connect*(ssl: SslPtr): cint{.cdecl, dynlib: DLLSSLName, importc.} proc SSL_read*(ssl: SslPtr, buf: pointer, num: int): cint{.cdecl, dynlib: DLLSSLName, importc.} proc SSL_write*(ssl: SslPtr, buf: cstring, num: int): cint{.cdecl, dynlib: DLLSSLName, importc.} @@ -314,6 +318,11 @@ proc sslDoHandshake*(ssl: SslPtr): cint {.cdecl, dynlib: DLLSSLName, importc: "SSL_do_handshake".} + +proc ErrClearError*(){.cdecl, dynlib: DLLUtilName, importc: "ERR_clear_error".} +proc ErrFreeStrings*(){.cdecl, dynlib: DLLUtilName, importc: "ERR_free_strings".} +proc ErrRemoveState*(pid: cInt){.cdecl, dynlib: DLLUtilName, importc: "ERR_remove_state".} + when true: discard else: @@ -414,9 +423,7 @@ else: # function ErrErrorString(e: cInt; buf: PChar): PChar; proc SSLeayversion*(t: cInt): cstring{.cdecl, dynlib: DLLUtilName, importc.} - proc ErrClearError*(){.cdecl, dynlib: DLLUtilName, importc.} - proc ErrFreeStrings*(){.cdecl, dynlib: DLLUtilName, importc.} - proc ErrRemoveState*(pid: cInt){.cdecl, dynlib: DLLUtilName, importc.} + proc OPENSSLaddallalgorithms*(){.cdecl, dynlib: DLLUtilName, importc.} proc CRYPTOcleanupAllExData*(){.cdecl, dynlib: DLLUtilName, importc.} proc RandScreen*(){.cdecl, dynlib: DLLUtilName, importc.} |