LibWebSocket: Fixed occasional infinite loop with TLS sockets

This was caused by a double notifier on the TLS socket, which caused
the TLS code to freak out about not being able to read properly. In
addition, the existing loop inside of drain_read() has been replaced by
code that actually works, and which includes new warnings when the
drain method is called before initialization is done or after the
websocket gets closed.
This commit is contained in:
DexesTTP 2021-05-18 00:28:06 +02:00 committed by Andreas Kling
parent 2754112a7a
commit 812875bc89
Notes: sideshowbarker 2024-07-18 17:53:24 +09:00
3 changed files with 24 additions and 19 deletions

View file

@ -26,15 +26,13 @@ void TLSv12WebSocketConnectionImpl::connect(ConnectionInfo const& connection)
VERIFY(on_ready_to_read);
m_socket = TLS::TLSv12::construct(this);
m_notifier = Core::Notifier::construct(m_socket->fd(), Core::Notifier::Read);
m_notifier->on_ready_to_read = [this] {
on_ready_to_read();
};
m_socket->set_root_certificates(DefaultRootCACertificates::the().certificates());
m_socket->on_tls_error = [this](TLS::AlertDescription) {
on_connection_error();
};
m_socket->on_tls_ready_to_read = [this] {
on_ready_to_read();
};
m_socket->on_tls_ready_to_write = [this] {
on_connected();
};

View file

@ -38,7 +38,6 @@ public:
virtual void discard_connection() override;
private:
RefPtr<Core::Notifier> m_notifier;
RefPtr<TLS::TLSv12> m_socket;
};

View file

@ -114,19 +114,27 @@ void WebSocket::drain_read()
return;
}
while (m_impl->can_read()) {
if (m_state == WebSocket::InternalState::WaitingForServerHandshake) {
read_server_handshake();
return;
}
if (m_state == WebSocket::InternalState::Open) {
read_frame();
return;
}
if (m_state == WebSocket::InternalState::Closing) {
read_frame();
return;
}
switch (m_state) {
case InternalState::NotStarted:
case InternalState::EstablishingProtocolConnection:
case InternalState::SendingClientHandshake: {
auto initializing_bytes = m_impl->read(1024);
dbgln("drain_read() was called on a websocket that isn't opened yet. Read {} bytes from the socket.", initializing_bytes.size());
} break;
case InternalState::WaitingForServerHandshake: {
read_server_handshake();
} break;
case InternalState::Open:
case InternalState::Closing: {
read_frame();
} break;
case InternalState::Closed:
case InternalState::Errored: {
auto closed_bytes = m_impl->read(1024);
dbgln("drain_read() was called on a closed websocket. Read {} bytes from the socket.", closed_bytes.size());
} break;
default:
VERIFY_NOT_REACHED();
}
}