diff options
Diffstat (limited to 'tests/stdlib/tssl.nim')
-rw-r--r-- | tests/stdlib/tssl.nim | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/tests/stdlib/tssl.nim b/tests/stdlib/tssl.nim new file mode 100644 index 000000000..1628b9326 --- /dev/null +++ b/tests/stdlib/tssl.nim @@ -0,0 +1,138 @@ +discard """ + matrix: "--mm:refc; --mm:orc" + joinable: false + disabled: "freebsd" # see #15713 + disabled: "openbsd" # see #15713 + disabled: "netbsd" # see #15713 +""" + +import std/[net, nativesockets, assertions, typedthreads] + +when defined(posix): import os, posix +else: + import winlean + const SD_SEND = 1 + +when not defined(ssl): + {.error: "This test must be compiled with -d:ssl".} + +const DummyData = "dummy data\n" + +proc abruptShutdown(port: Port) {.thread.} = + let clientContext = newContext(verifyMode = CVerifyNone) + var client = newSocket(buffered = false) + clientContext.wrapSocket(client) + client.connect("localhost", port) + + discard client.recvLine() + client.getFd.close() + +proc notifiedShutdown(port: Port) {.thread.} = + let clientContext = newContext(verifyMode = CVerifyNone) + var client = newSocket(buffered = false) + clientContext.wrapSocket(client) + client.connect("localhost", port) + + discard client.recvLine() + client.close() + +proc main() = + when defined(posix): + var + ignoreAction = Sigaction(sa_handler: SIG_IGN) + oldSigPipeHandler: Sigaction + if sigemptyset(ignoreAction.sa_mask) == -1: + raiseOSError(osLastError(), "Couldn't create an empty signal set") + if sigaction(SIGPIPE, ignoreAction, oldSigPipeHandler) == -1: + raiseOSError(osLastError(), "Couldn't ignore SIGPIPE") + + let serverContext = newContext(verifyMode = CVerifyNone, + certFile = "tests/testdata/mycert.pem", + keyFile = "tests/testdata/mycert.pem") + + block peer_close_during_write_without_shutdown: + var server = newSocket(buffered = false) + defer: server.close() + serverContext.wrapSocket(server) + server.bindAddr(address = "localhost") + let (_, port) = server.getLocalAddr() + server.listen() + + var clientThread: Thread[Port] + createThread(clientThread, abruptShutdown, port) + + var peer: Socket + try: + server.accept(peer) + peer.send(DummyData) + + joinThread clientThread + + while true: + # Send data until we get EPIPE. + peer.send(DummyData, {}) + except OSError: + discard + finally: + peer.close() + + when defined(posix): + if sigaction(SIGPIPE, oldSigPipeHandler, nil) == -1: + raiseOSError(osLastError(), "Couldn't restore SIGPIPE handler") + + block peer_close_before_received_shutdown: + var server = newSocket(buffered = false) + defer: server.close() + serverContext.wrapSocket(server) + server.bindAddr(address = "localhost") + let (_, port) = server.getLocalAddr() + server.listen() + + var clientThread: Thread[Port] + createThread(clientThread, abruptShutdown, port) + + var peer: Socket + try: + server.accept(peer) + peer.send(DummyData) + + joinThread clientThread + + # Tell the OS to close off the write side so shutdown attempts will + # be met with SIGPIPE. + when defined(posix): + discard peer.getFd.shutdown(SHUT_WR) + else: + discard peer.getFd.shutdown(SD_SEND) + finally: + peer.close() + + block peer_close_after_received_shutdown: + var server = newSocket(buffered = false) + defer: server.close() + serverContext.wrapSocket(server) + server.bindAddr(address = "localhost") + let (_, port) = server.getLocalAddr() + server.listen() + + var clientThread: Thread[Port] + createThread(clientThread, notifiedShutdown, port) + + var peer: Socket + try: + server.accept(peer) + peer.send(DummyData) + + doAssert peer.recv(1024) == "" # Get the shutdown notification + joinThread clientThread + + # Tell the OS to close off the write side so shutdown attempts will + # be met with SIGPIPE. + when defined(posix): + discard peer.getFd.shutdown(SHUT_WR) + else: + discard peer.getFd.shutdown(SD_SEND) + finally: + peer.close() + +when isMainModule: main() |