tssl.nim 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. discard """
  2. matrix: "--mm:refc; --mm:orc"
  3. joinable: false
  4. disabled: "freebsd" # see #15713
  5. disabled: "openbsd" # see #15713
  6. disabled: "netbsd" # see #15713
  7. """
  8. import std/[net, nativesockets, assertions, typedthreads]
  9. when defined(posix): import os, posix
  10. else:
  11. import winlean
  12. const SD_SEND = 1
  13. when not defined(ssl):
  14. {.error: "This test must be compiled with -d:ssl".}
  15. const DummyData = "dummy data\n"
  16. proc abruptShutdown(port: Port) {.thread.} =
  17. let clientContext = newContext(verifyMode = CVerifyNone)
  18. var client = newSocket(buffered = false)
  19. clientContext.wrapSocket(client)
  20. client.connect("localhost", port)
  21. discard client.recvLine()
  22. client.getFd.close()
  23. proc notifiedShutdown(port: Port) {.thread.} =
  24. let clientContext = newContext(verifyMode = CVerifyNone)
  25. var client = newSocket(buffered = false)
  26. clientContext.wrapSocket(client)
  27. client.connect("localhost", port)
  28. discard client.recvLine()
  29. client.close()
  30. proc main() =
  31. when defined(posix):
  32. var
  33. ignoreAction = Sigaction(sa_handler: SIG_IGN)
  34. oldSigPipeHandler: Sigaction
  35. if sigemptyset(ignoreAction.sa_mask) == -1:
  36. raiseOSError(osLastError(), "Couldn't create an empty signal set")
  37. if sigaction(SIGPIPE, ignoreAction, oldSigPipeHandler) == -1:
  38. raiseOSError(osLastError(), "Couldn't ignore SIGPIPE")
  39. let serverContext = newContext(verifyMode = CVerifyNone,
  40. certFile = "tests/testdata/mycert.pem",
  41. keyFile = "tests/testdata/mycert.pem")
  42. block peer_close_during_write_without_shutdown:
  43. var server = newSocket(buffered = false)
  44. defer: server.close()
  45. serverContext.wrapSocket(server)
  46. server.bindAddr(address = "localhost")
  47. let (_, port) = server.getLocalAddr()
  48. server.listen()
  49. var clientThread: Thread[Port]
  50. createThread(clientThread, abruptShutdown, port)
  51. var peer: Socket
  52. try:
  53. server.accept(peer)
  54. peer.send(DummyData)
  55. joinThread clientThread
  56. while true:
  57. # Send data until we get EPIPE.
  58. peer.send(DummyData, {})
  59. except OSError:
  60. discard
  61. finally:
  62. peer.close()
  63. when defined(posix):
  64. if sigaction(SIGPIPE, oldSigPipeHandler, nil) == -1:
  65. raiseOSError(osLastError(), "Couldn't restore SIGPIPE handler")
  66. block peer_close_before_received_shutdown:
  67. var server = newSocket(buffered = false)
  68. defer: server.close()
  69. serverContext.wrapSocket(server)
  70. server.bindAddr(address = "localhost")
  71. let (_, port) = server.getLocalAddr()
  72. server.listen()
  73. var clientThread: Thread[Port]
  74. createThread(clientThread, abruptShutdown, port)
  75. var peer: Socket
  76. try:
  77. server.accept(peer)
  78. peer.send(DummyData)
  79. joinThread clientThread
  80. # Tell the OS to close off the write side so shutdown attempts will
  81. # be met with SIGPIPE.
  82. when defined(posix):
  83. discard peer.getFd.shutdown(SHUT_WR)
  84. else:
  85. discard peer.getFd.shutdown(SD_SEND)
  86. finally:
  87. peer.close()
  88. block peer_close_after_received_shutdown:
  89. var server = newSocket(buffered = false)
  90. defer: server.close()
  91. serverContext.wrapSocket(server)
  92. server.bindAddr(address = "localhost")
  93. let (_, port) = server.getLocalAddr()
  94. server.listen()
  95. var clientThread: Thread[Port]
  96. createThread(clientThread, notifiedShutdown, port)
  97. var peer: Socket
  98. try:
  99. server.accept(peer)
  100. peer.send(DummyData)
  101. doAssert peer.recv(1024) == "" # Get the shutdown notification
  102. joinThread clientThread
  103. # Tell the OS to close off the write side so shutdown attempts will
  104. # be met with SIGPIPE.
  105. when defined(posix):
  106. discard peer.getFd.shutdown(SHUT_WR)
  107. else:
  108. discard peer.getFd.shutdown(SD_SEND)
  109. finally:
  110. peer.close()
  111. when isMainModule: main()