<html><head></head><body><div style="font-family: Verdana;font-size: 12.0px;"><div>
<div>I looked at the private implementation of QWebSocketServer, <a data-ref="QWebSocketServerPrivate" data-ref-filename="QWebSocketServerPrivate" href="https://code.woboq.org/qt5/qtwebsockets/src/websockets/qwebsocketserver_p.h.html#QWebSocketServerPrivate">QWebSocketServerPrivate</a>.</div>

<div> </div>

<div>I haven't tested it, but there are a few concerns:</div>

<div> </div>

<div>1. That for <dfn data-ref="_ZNK23QWebSocketServerPrivate11errorStringEv" data-ref-filename="_ZNK23QWebSocketServerPrivate11errorStringEv" id="_ZNK23QWebSocketServerPrivate11errorStringEv">errorString</dfn>(), it first checks if it doesn't have an error then returns the QTcpSocket errorString(). But if you just look at serverError() it only reports it's own error and nothing at the QTcpSocket level. This means that if you only check serverError() you won't catch QTcpServer error. This is probably a bug. QWebSocketProtocol::<a data-ref="QWebSocketProtocol::CloseCode" data-ref-filename="QWebSocketProtocol..CloseCode" href="https://code.woboq.org/qt5/qtwebsockets/src/websockets/qwebsocketprotocol.h.html#QWebSocketProtocol::CloseCode">CloseCode</a> needs to be able to express QAbstractSocket::SocketErrors as well.</div>

<div> </div>

<div>2. <a data-ref="QWebSocketServerPrivate" data-ref-filename="QWebSocketServerPrivate" href="https://code.woboq.org/qt5/qtwebsockets/src/websockets/qwebsocketserver_p.h.html#QWebSocketServerPrivate">QWebSocketServerPrivate</a>::<dfn data-ref="_ZN23QWebSocketServerPrivate17handshakeReceivedEv" data-ref-filename="_ZN23QWebSocketServerPrivate17handshakeReceivedEv" id="_ZN23QWebSocketServerPrivate17handshakeReceivedEv">handshakeReceived</dfn>() has a check of <a data-ref="31pTcpSocket" data-ref-filename="31pTcpSocket" href="https://code.woboq.org/qt5/qtwebsockets/src/websockets/qwebsocketserver_p.cpp.html#31pTcpSocket">pTcpSocket</a>-><a data-ref="_ZNK15QAbstractSocket14bytesAvailableEv" data-ref-filename="_ZNK15QAbstractSocket14bytesAvailableEv" href="https://code.woboq.org/qt5/qtbase/src/network/socket/qabstractsocket.cpp.html#_ZNK15QAbstractSocket14bytesAvailableEv">bytesAvailable</a>()).<a data-ref="_ZNK10QByteArray8endsWithERKS_" data-ref-filename="_ZNK10QByteArray8endsWithERKS_" href="https://code.woboq.org/qt5/qtbase/src/corelib/tools/qbytearray.cpp.html#_ZNK10QByteArray8endsWithERKS_">endsWith</a>(<a data-ref="_M/QByteArrayLiteral" href="https://code.woboq.org/qt5/qtbase/src/corelib/tools/qbytearray.h.html#144">QByteArrayLiteral</a>(<q>"\r\n\r\n"</q>) Such position-reliant checks are bad form. There's no reason for it to end with, it should probably be using contains()</div>

<div>
<div> </div>

<div>3. There are multiple `if` blocks that don't set an error. This isn't wrong, as the handhake bytes may come in slowly and take multiple re-parsings, (something to add to your fuzzer?) but you can wind up in an uncaught error state.</div>

<div> </div>

<div> </div>

<div> </div>

<div name="quote" style="margin:10px 5px 5px 10px; padding: 10px 0 10px 10px; border-left:2px solid #C3D9E5; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">
<div style="margin:0 0 10px 0;"><b>Sent:</b> Thursday, April 04, 2019 at 10:07 AM<br/>
<b>From:</b> "Jason H" <jhihn@gmx.com><br/>
<b>To:</b> "Narolewski Jakub" <izowiuz@gmail.com><br/>
<b>Cc:</b> interest@qt-project.org<br/>
<b>Subject:</b> Re: [Interest] QWebSocketServer - server randomly stops accepting connections</div>

<div name="quoted-content">
<div style="font-family: Verdana;font-size: 12.0px;">
<div>
<div>So, yeah, I was thinking of QTcpServer::incommingConnection(). That function is used in multithreadding because you use the descriptor to make a socket on the proper thread. Looks like QWebSocketServer is not multithreaded. </div>

<div> </div>

<div>I've used Qt's websockets, and I've used QTcpServer extensively on 5-nines stuff. Never saw anything like this. </div>

<div> </div>

<div>Next steps: </div>

<div>- <a href="https://code.woboq.org/qt5/qtwebsockets/src/websockets/qwebsocketserver.h.html#QWebSocketServer" target="_blank">QWebSocketServer</a>::<dfn id="_ZN16QWebSocketServer24setMaxPendingConnectionsEi">setMaxPendingConnections</dfn>() set this to 0, 1, or 100, see what (if anything) changes.</div>

<div>- Use QTcpServer to and QWebSocketServer::handleConnection(QTcpSocket*) to handle the connection yourself just to get QWebSocketServer out of the initial connection stuff.</div>

<div> </div>

<div>Whatever the cause, I think you're in bug territory, either in Qt or the linux kernel. Both of those is unlikely.  There is one more possibilty, if you're using secure sockets, maybe something is failing at the SSL level? Like your SSL implementation stops working for whatever reason?</div>

<div> </div>

<div>
<div style="margin: 10.0px 5.0px 5.0px 10.0px;padding: 10.0px 0 10.0px 10.0px;border-left: 2.0px solid rgb(195,217,229);">
<div style="margin: 0 0 10.0px 0;"><b>Sent:</b> Thursday, April 04, 2019 at 9:13 AM<br/>
<b>From:</b> "Narolewski Jakub" <izowiuz@gmail.com><br/>
<b>To:</b> "Jason H" <jhihn@gmx.com><br/>
<b>Cc:</b> interest@qt-project.org<br/>
<b>Subject:</b> Re: [Interest] QWebSocketServer - server randomly stops accepting connections</div>

<div>
<div><span style="font-family: sans-serif;font-size: 12.8px;">That's the thing. I already handle connections and disconnections in my code - including logging relevant information.</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">When I implemented this I heavily based on the example that you linked to.</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">WSS communication is single threaded - only way to communicate with the outside world from different thread is to send custom QEvent onto the Server instance.</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">QWebSocketServer does not seem to have the method incomingConnection in it's public API or maybe I already went mad :P I react to the QWebSocketServer::newConnectio</span><span style="font-family: sans-serif;font-size: 12.8px;">n signal.</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">Last RST from client at 33 second mark is our client-side timeout.</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">This is the code that handles websocket stuff, I have stripped some parts that are less important:</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">// server connects</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">connect(m_wsServer, &QWebSocketServer::acceptError</span><span style="font-family: sans-serif;font-size: 12.8px;">, this, [this](QAbstractSocket::Socket</span><span style="font-family: sans-serif;font-size: 12.8px;">Error socketError) {</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">        qCritical() << "QWebSocketServer - acceptError:" << socketError;</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">});</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">connect(m_wsServer, &QWebSocketServer::peerVerifyE</span><span style="font-family: sans-serif;font-size: 12.8px;">rror, this, [this](const QSslError& error) {</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">        qCritical() << "QWebSocketServer - peerVerifyError:" << error;</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">});</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">connect(m_wsServer, &QWebSocketServer::serverError</span><span style="font-family: sans-serif;font-size: 12.8px;">, this, [this](QWebSocketProtocol::Clo</span><span style="font-family: sans-serif;font-size: 12.8px;">seCode closeCode) {</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">        qCritical() << "QWebSocketServer - serverError:" << closeCode;</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">});</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">connect(m_wsServer, &QWebSocketServer::sslErrors, this, [this](const QList<QSslError>& errors) {</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">        qCritical() << "QWebSocketServer - sslErrors:" << errors;</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">});</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">connect(m_wsServer, &QWebSocketServer::closed, this, [this]() {</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">        qCritical() << "QWebSocketServer - closed, serverError():" << m_wsServer->errorString();</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">});</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">connect(m_wsServer, &QWebSocketServer::newConnecti</span><span style="font-family: sans-serif;font-size: 12.8px;">on, this, [this]() {</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">        QWebSocket* clientSocket = m_wsServer->nextPendingConnect</span><span style="font-family: sans-serif;font-size: 12.8px;">ion();</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">        qInfo() << "Got connection from client:" << clientSocket->peerAddress();</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">        [ client initialization stuff ]</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">        connect(clientSocket, &QWebSocket::binaryMessageRece</span><span style="font-family: sans-serif;font-size: 12.8px;">ived, this, [this](const QByteArray& message) {</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">                auto client = sender()->property("client").v</span><span style="font-family: sans-serif;font-size: 12.8px;">alue<Client*>();</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">                [ message deserialization ]</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">        });</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">        connect(clientSocket, &QWebSocket::disconnected, this, [this]() {</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">                auto client = sender()->property("client").v</span><span style="font-family: sans-serif;font-size: 12.8px;">alue<Client*>();</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">                qInfo() << client->sayHello() << "is disconnected.";</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">                client->handleDisconnection();</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">                [ clinet cleanup stuff ]</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">        });</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">});</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">Client's handleDisconnection() function does:</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">void i9ms::Client::handleDisconnect</span><span style="font-family: sans-serif;font-size: 12.8px;">ion()</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">{</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">        m_isConnected = false;</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">        m_websocket->deleteLater();</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">        m_websocket   = nullptr;</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">}</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">Nothing from this lands in system logs. It seems that QWebSocketServer::newConnectio</span><span style="font-family: sans-serif;font-size: 12.8px;">n() is just not emited.</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">As I wrote earlier I have a timerEvent that logs QWebSocketServer's state - once every ten minutes.</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">It happily reports that server is listening, has no pending connections and it's internal 'errorString' is empty - even if it is mute from the outside.</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">It's hard for me to pinpoint exactly what causes this. 'Time' is my best guess.</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">I'm also not sure if quantity of connections plays a role here.</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">I have a 'fuzzer-bot' that spams hundreds of connections and messages at the server in short period of time.</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">Malformed messages, out-of-order client state changes, ugly words - you name it we have it.</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">QWebSocketServer handles it well enough for us but then, at some time in future WHILE being completely idle, server goes silent.</span><br style="font-family: sans-serif;font-size: 12.8px;"/>
<span style="font-family: sans-serif;font-size: 12.8px;">On the other hand I can start the server, connect - disconnect one client, leave it for a while in idle and same thing happens, leaving me one step closer to dementia.</span><br/>
 
<div class="gmail_quote">
<div class="gmail_attr">On Wed, 3 Apr 2019, 22:32 Jason H, <<a href="mailto:jhihn@gmx.com" onclick="parent.window.location.href='mailto:jhihn@gmx.com'; return false;" target="_blank">jhihn@gmx.com</a>> wrote:</div>

<blockquote class="gmail_quote" style="margin: 0 0 0 0.8ex;border-left: 1.0px rgb(204,204,204) solid;padding-left: 1.0ex;">
<div>
<div style="font-family: Verdana;font-size: 12.0px;">
<div>Addendum, </div>

<div> </div>

<div>How much does you code diverge from the example? <a href="https://doc.qt.io/qt-5/echoserver.html" target="_blank">https://doc.qt.io/qt-5/echoserver.html</a></div>

<div>Can you hack that to receive your traffic or augment your code to to do what it does?</div>

<div>Note that the QWebSocket server does not take ownership of the QWebSocket, you have to track that manually. Using the code they provide, I would also log your connected clients. See the slot
<pre> EchoServer::socketDisconnected()</pre>
</div>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
_______________________________________________ Interest mailing list Interest@qt-project.org <a href="https://lists.qt-project.org/listinfo/interest" target="_blank">https://lists.qt-project.org/listinfo/interest</a></div>
</div>
</div>
</div></div></body></html>