final fixes, with timeout
This commit is contained in:
		@@ -262,13 +262,11 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        while (true)
 | 
					        while (true)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (_stop) return;
 | 
					            if (_stop && !isClosing()) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // 1. Make sure we are always connected
 | 
					            // 1. Make sure we are always connected
 | 
				
			||||||
            reconnectPerpetuallyIfDisconnected();
 | 
					            reconnectPerpetuallyIfDisconnected();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (_stop) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // 2. Poll to see if there's any new data available
 | 
					            // 2. Poll to see if there's any new data available
 | 
				
			||||||
            WebSocketTransport::PollPostTreatment pollPostTreatment = _ws.poll();
 | 
					            WebSocketTransport::PollPostTreatment pollPostTreatment = _ws.poll();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -317,7 +315,7 @@ namespace ix
 | 
				
			|||||||
            // 4. In blocking mode, getting out of this function is triggered by
 | 
					            // 4. In blocking mode, getting out of this function is triggered by
 | 
				
			||||||
            //    an explicit disconnection from the callback, or by the remote end
 | 
					            //    an explicit disconnection from the callback, or by the remote end
 | 
				
			||||||
            //    closing the connection, ie isConnected() == false.
 | 
					            //    closing the connection, ie isConnected() == false.
 | 
				
			||||||
            if (!_thread.joinable() && !isConnected() && !_automaticReconnection) return;
 | 
					            if (!_thread.joinable() && !(isConnected() || isClosing()) && !_automaticReconnection) return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,6 +68,7 @@ namespace ix
 | 
				
			|||||||
    const int WebSocketTransport::kDefaultPingIntervalSecs(-1);
 | 
					    const int WebSocketTransport::kDefaultPingIntervalSecs(-1);
 | 
				
			||||||
    const int WebSocketTransport::kDefaultPingTimeoutSecs(-1);
 | 
					    const int WebSocketTransport::kDefaultPingTimeoutSecs(-1);
 | 
				
			||||||
    const bool WebSocketTransport::kDefaultEnablePong(true);
 | 
					    const bool WebSocketTransport::kDefaultEnablePong(true);
 | 
				
			||||||
 | 
					    const int WebSocketTransport::kClosingMaximumWaitingDelayInMs(500);
 | 
				
			||||||
    constexpr size_t WebSocketTransport::kChunkSize;
 | 
					    constexpr size_t WebSocketTransport::kChunkSize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const uint16_t WebSocketTransport::kInternalErrorCode(1011);
 | 
					    const uint16_t WebSocketTransport::kInternalErrorCode(1011);
 | 
				
			||||||
@@ -87,6 +88,7 @@ namespace ix
 | 
				
			|||||||
        _closeRemote(false),
 | 
					        _closeRemote(false),
 | 
				
			||||||
        _enablePerMessageDeflate(false),
 | 
					        _enablePerMessageDeflate(false),
 | 
				
			||||||
        _requestInitCancellation(false),
 | 
					        _requestInitCancellation(false),
 | 
				
			||||||
 | 
					        _closingTimePoint(std::chrono::steady_clock::now()),
 | 
				
			||||||
        _enablePong(kDefaultEnablePong),
 | 
					        _enablePong(kDefaultEnablePong),
 | 
				
			||||||
        _pingIntervalSecs(kDefaultPingIntervalSecs),
 | 
					        _pingIntervalSecs(kDefaultPingIntervalSecs),
 | 
				
			||||||
        _pingTimeoutSecs(kDefaultPingTimeoutSecs),
 | 
					        _pingTimeoutSecs(kDefaultPingTimeoutSecs),
 | 
				
			||||||
@@ -243,9 +245,19 @@ namespace ix
 | 
				
			|||||||
        return now - _lastReceivePongTimePoint > std::chrono::seconds(_pingTimeoutSecs);
 | 
					        return now - _lastReceivePongTimePoint > std::chrono::seconds(_pingTimeoutSecs);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool WebSocketTransport::closingDelayExceeded()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::lock_guard<std::mutex> lock(_closingTimePointMutex);
 | 
				
			||||||
 | 
					        auto now = std::chrono::steady_clock::now();
 | 
				
			||||||
 | 
					        return now - _closingTimePoint > std::chrono::milliseconds(kClosingMaximumWaitingDelayInMs);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    WebSocketTransport::PollPostTreatment WebSocketTransport::poll()
 | 
					    WebSocketTransport::PollPostTreatment WebSocketTransport::poll()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        PollResultType pollResult = _socket->poll(_pingIntervalOrTimeoutGCDSecs);
 | 
					        // we need to have no timeout if state is CLOSING
 | 
				
			||||||
 | 
					        int timeoutDelayinS = (_readyState == CLOSING) ? 0 : _pingIntervalOrTimeoutGCDSecs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        PollResultType pollResult = _socket->poll(timeoutDelayinS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (_readyState == OPEN)
 | 
					        if (_readyState == OPEN)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -293,7 +305,7 @@ namespace ix
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                ssize_t ret = _socket->recv((char*)&_readbuf[0], _readbuf.size());
 | 
					                ssize_t ret = _socket->recv((char*)&_readbuf[0], _readbuf.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (ret < 0 && (_socket->getErrno() == EWOULDBLOCK ||
 | 
					                if (ret < 0 && _readyState != CLOSING && (_socket->getErrno() == EWOULDBLOCK ||
 | 
				
			||||||
                                                          _socket->getErrno() == EAGAIN))
 | 
					                                                          _socket->getErrno() == EAGAIN))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
@@ -324,7 +336,7 @@ namespace ix
 | 
				
			|||||||
            _socket->close();
 | 
					            _socket->close();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (_readyState == CLOSING)
 | 
					        if (_readyState == CLOSING && closingDelayExceeded())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // close code and reason were set when calling close()
 | 
					            // close code and reason were set when calling close()
 | 
				
			||||||
            _socket->close();
 | 
					            _socket->close();
 | 
				
			||||||
@@ -926,8 +938,13 @@ namespace ix
 | 
				
			|||||||
            _closeWireSize = closeWireSize;
 | 
					            _closeWireSize = closeWireSize;
 | 
				
			||||||
            _closeRemote = remote;
 | 
					            _closeRemote = remote;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::lock_guard<std::mutex> lock(_closingTimePointMutex);
 | 
				
			||||||
 | 
					            _closingTimePoint = std::chrono::steady_clock::now();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        setReadyState(CLOSING);
 | 
					        setReadyState(CLOSING);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // wake up the poll, but do not close yet
 | 
				
			||||||
        _socket->wakeUpFromPoll(Socket::kSendRequest);
 | 
					        _socket->wakeUpFromPoll(Socket::kSendRequest);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -169,6 +169,10 @@ namespace ix
 | 
				
			|||||||
        // Used to cancel dns lookup + socket connect + http upgrade
 | 
					        // Used to cancel dns lookup + socket connect + http upgrade
 | 
				
			||||||
        std::atomic<bool> _requestInitCancellation;
 | 
					        std::atomic<bool> _requestInitCancellation;
 | 
				
			||||||
              
 | 
					              
 | 
				
			||||||
 | 
					        mutable std::mutex _closingTimePointMutex;
 | 
				
			||||||
 | 
					        std::chrono::time_point<std::chrono::steady_clock>_closingTimePoint;
 | 
				
			||||||
 | 
					        static const int kClosingMaximumWaitingDelayInMs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Constants for dealing with closing conneections
 | 
					        // Constants for dealing with closing conneections
 | 
				
			||||||
        static const uint16_t kInternalErrorCode;
 | 
					        static const uint16_t kInternalErrorCode;
 | 
				
			||||||
        static const uint16_t kAbnormalCloseCode;
 | 
					        static const uint16_t kAbnormalCloseCode;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -231,7 +231,7 @@ namespace
 | 
				
			|||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/*
 | 
					
 | 
				
			||||||
TEST_CASE("Websocket_client_close_default", "[close]")
 | 
					TEST_CASE("Websocket_client_close_default", "[close]")
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    SECTION("Make sure that close code and reason was used and sent to server.")
 | 
					    SECTION("Make sure that close code and reason was used and sent to server.")
 | 
				
			||||||
@@ -289,7 +289,7 @@ TEST_CASE("Websocket_client_close_default", "[close]")
 | 
				
			|||||||
        ix::reportWebSocketTraffic();
 | 
					        ix::reportWebSocketTraffic();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
*/
 | 
					
 | 
				
			||||||
TEST_CASE("Websocket_client_close_params_given", "[close]")
 | 
					TEST_CASE("Websocket_client_close_params_given", "[close]")
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    SECTION("Make sure that close code and reason was used and sent to server.")
 | 
					    SECTION("Make sure that close code and reason was used and sent to server.")
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user