diff --git a/ixwebsocket/IXSocket.cpp b/ixwebsocket/IXSocket.cpp index 461f85fe..317e6006 100644 --- a/ixwebsocket/IXSocket.cpp +++ b/ixwebsocket/IXSocket.cpp @@ -45,17 +45,14 @@ namespace ix close(); } - void Socket::poll(const OnPollCallback& onPollCallback, int timeoutSecs) + PollResultType Socket::poll(int timeoutSecs) { if (_sockfd == -1) { - if (onPollCallback) onPollCallback(PollResultType::Error); - return; + return PollResultType::Error; } - PollResultType pollResult = isReadyToRead(1000 * timeoutSecs); - - if (onPollCallback) onPollCallback(pollResult); + return isReadyToRead(1000 * timeoutSecs); } PollResultType Socket::select(bool readyToRead, int timeoutMs) diff --git a/ixwebsocket/IXSocket.h b/ixwebsocket/IXSocket.h index 4bfae38d..0167f5b7 100644 --- a/ixwebsocket/IXSocket.h +++ b/ixwebsocket/IXSocket.h @@ -37,8 +37,6 @@ namespace ix class Socket { public: - using OnPollCallback = std::function; - Socket(int fd = -1); virtual ~Socket(); bool init(std::string& errorMsg); @@ -46,8 +44,7 @@ namespace ix void configure(); // Functions to check whether there is activity on the socket - void poll(const OnPollCallback& onPollCallback, - int timeoutSecs = kDefaultPollTimeout); + PollResultType poll(int timeoutSecs = kDefaultPollTimeout); bool wakeUpFromPoll(uint8_t wakeUpCode); PollResultType isReadyToWrite(int timeoutMs); diff --git a/ixwebsocket/IXWebSocketTransport.cpp b/ixwebsocket/IXWebSocketTransport.cpp index ee267e08..1f65fb8f 100644 --- a/ixwebsocket/IXWebSocketTransport.cpp +++ b/ixwebsocket/IXWebSocketTransport.cpp @@ -232,9 +232,15 @@ namespace ix void WebSocketTransport::poll() { - _socket->poll( - [this](PollResultType pollResult) + PollResultType pollResult = _socket->poll(_pingIntervalOrTimeoutGCDSecs); + + if (_readyState == OPEN) + { + // if (1) ping timeout is enabled and (2) duration since last received ping response (PONG) + // exceeds the maximum delay, then close the connection + if (pingTimeoutExceeded()) { +<<<<<<< HEAD if (_readyState == OPEN) { // if (1) ping timeout is enabled and (2) duration since last received ping response (PONG) @@ -252,78 +258,88 @@ namespace ix sendPing(ss.str()); } } +======= + close(1011, "Ping timeout"); + } + // If (1) ping is enabled and no ping has been sent for a duration + // exceeding our ping interval, send a ping to the server. + else if (pingIntervalExceeded()) + { + std::stringstream ss; + ss << kPingMessage << "::" << _pingIntervalSecs << "s"; + sendPing(ss.str()); + } + } - // Make sure we send all the buffered data - // there can be a lot of it for large messages. - if (pollResult == PollResultType::SendRequest) + // Make sure we send all the buffered data + // there can be a lot of it for large messages. + if (pollResult == PollResultType::SendRequest) + { + while (!isSendBufferEmpty() && !_requestInitCancellation) + { + // Wait with a 10ms timeout until the socket is ready to write. + // This way we are not busy looping + PollResultType result = _socket->isReadyToWrite(10); + + if (result == PollResultType::Error) { - while (!isSendBufferEmpty() && !_requestInitCancellation) + _socket->close(); + setReadyState(CLOSED); + break; + } + else if (result == PollResultType::ReadyForWrite) + { + sendOnSocket(); + } + } + } + else if (pollResult == PollResultType::ReadyForRead) + { + while (true) + { + ssize_t ret = _socket->recv((char*)&_readbuf[0], _readbuf.size()); + + if (ret < 0 && (_socket->getErrno() == EWOULDBLOCK || + _socket->getErrno() == EAGAIN)) + { + break; + } + else if (ret <= 0) + { + _rxbuf.clear(); + _socket->close(); { - // Wait with a 10ms timeout until the socket is ready to write. - // This way we are not busy looping - PollResultType result = _socket->isReadyToWrite(10); - - if (result == PollResultType::Error) - { - _socket->close(); - setReadyState(CLOSED); - break; - } - else if (result == PollResultType::ReadyForWrite) - { - sendOnSocket(); - } + std::lock_guard lock(_closeDataMutex); + _closeCode = kAbnormalCloseCode; + _closeReason = kAbnormalCloseMessage; + _closeWireSize = 0; } + setReadyState(CLOSED); + break; } - else if (pollResult == PollResultType::ReadyForRead) + else { - while (true) - { - ssize_t ret = _socket->recv((char*)&_readbuf[0], _readbuf.size()); + _rxbuf.insert(_rxbuf.end(), + _readbuf.begin(), + _readbuf.begin() + ret); + } + } + } + else if (pollResult == PollResultType::Error) + { + _socket->close(); + } + else if (pollResult == PollResultType::CloseRequest) + { + _socket->close(); + } - if (ret < 0 && (_socket->getErrno() == EWOULDBLOCK || - _socket->getErrno() == EAGAIN)) - { - break; - } - else if (ret <= 0) - { - _rxbuf.clear(); - _socket->close(); - { - std::lock_guard lock(_closeDataMutex); - _closeCode = kAbnormalCloseCode; - _closeReason = kAbnormalCloseMessage; - _closeWireSize = 0; - } - setReadyState(CLOSED); - break; - } - else - { - _rxbuf.insert(_rxbuf.end(), - _readbuf.begin(), - _readbuf.begin() + ret); - } - } - } - else if (pollResult == PollResultType::Error) - { - _socket->close(); - } - else if (pollResult == PollResultType::CloseRequest) - { - _socket->close(); - } - - // Avoid a race condition where we get stuck in select - // while closing. - if (_readyState == CLOSING) - { - _socket->close(); - } - }, - _pingIntervalOrTimeoutGCDSecs); + // Avoid a race condition where we get stuck in select + // while closing. + if (_readyState == CLOSING) + { + _socket->close(); + } } bool WebSocketTransport::isSendBufferEmpty() const