final fixes, with timeout
This commit is contained in:
parent
2dfd141897
commit
3a9fe7c480
@ -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,8 +305,8 @@ 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.")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user