The SSL socket API must preserve nonblocking socket semantics. The Apple CFStream backend used to call CFReadStreamRead directly here, which can block when the TLS connection is established but no application data is available.
| 117 | // CFStream backend used to call CFReadStreamRead directly here, which can block |
| 118 | // when the TLS connection is established but no application data is available. |
| 119 | TEST(dmSSLSocket, ReceiveWithoutApplicationDataReturnsWouldBlock) |
| 120 | { |
| 121 | #if !defined(__MACH__) |
| 122 | SKIP(); |
| 123 | #endif |
| 124 | |
| 125 | dmSocket::Socket socket = dmSocket::INVALID_SOCKET_HANDLE; |
| 126 | dmSSLSocket::Socket ssl_socket = dmSSLSocket::INVALID_SOCKET_HANDLE; |
| 127 | |
| 128 | ConnectTLSSocket(&socket, &ssl_socket); |
| 129 | ASSERT_EQ(dmSocket::RESULT_OK, dmSSLSocket::SetReceiveTimeout(ssl_socket, 1000)); |
| 130 | |
| 131 | char response[4096]; |
| 132 | int received = -1; |
| 133 | uint64_t start = dmTime::GetMonotonicTime(); |
| 134 | dmSocket::Result receive_result = dmSSLSocket::Receive(ssl_socket, response, sizeof(response), &received); |
| 135 | uint64_t elapsed = dmTime::GetMonotonicTime() - start; |
| 136 | |
| 137 | ASSERT_EQ(dmSocket::RESULT_WOULDBLOCK, receive_result); |
| 138 | ASSERT_EQ(0, received); |
| 139 | ASSERT_LT(elapsed, 100 * 1000ULL); |
| 140 | |
| 141 | CloseSockets(socket, ssl_socket); |
| 142 | } |
| 143 | |
| 144 | // Reproduces the extension-websocket#65 read pattern: send the websocket |
| 145 | // handshake as several SSL writes, wait for the raw TCP socket to become |
nothing calls this directly
no test coverage detected