morph 0.1.0
Asynchronous bridge between GUI thread and business models
Loading...
Searching...
No Matches
morph::qt::QtWebSocketServer Class Reference

Qt WebSocket server that bridges incoming connections to a RemoteServer. More...

#include <qt_websocket_server.hpp>

Public Types

using Config = QtWebSocketServerConfig
 Alias for the per-connection limits configuration struct.

Public Member Functions

 QtWebSocketServer (::morph::backend::RemoteServer &server, quint16 port=0, std::optional< QSslConfiguration > tls=std::nullopt, QtWebSocketServerConfig cfg=QtWebSocketServerConfig{}, QObject *parent=nullptr)
 Constructs the server and prepares it to listen on port.
 ~QtWebSocketServer () override
 Closes the server and disconnects all clients.
 QtWebSocketServer (const QtWebSocketServer &)=delete
QtWebSocketServer & operator= (const QtWebSocketServer &)=delete
 QtWebSocketServer (QtWebSocketServer &&)=delete
QtWebSocketServer & operator= (QtWebSocketServer &&)=delete
bool listen ()
 Starts listening for incoming WebSocket connections.
quint16 port () const
 Returns the port the server is currently bound to.
void close ()
 Stops accepting new connections and closes the server socket.
bool closeGracefully (std::chrono::milliseconds deadline)
 Gracefully stops the server: refuse new work, let in-flight replies deliver, close each client with a proper WebSocket close frame, then hard-stop anything still connected.
Q_SLOT void onNewConnection ()
 Qt slot called when a new client connects.
Q_SLOT void onTextMessage (const QString &message)
 Qt slot called when a connected client sends a text message.
Q_SLOT void onDisconnected ()
 Qt slot called when a client disconnects.
Q_SLOT void onBytesWritten (qint64 bytes)
 Qt slot called when a client's socket has written bytes.

Detailed Description

Qt WebSocket server that bridges incoming connections to a RemoteServer.

Listens for WebSocket clients, receives their text messages, and forwards each one to RemoteServer::handle(). Replies are sent back to the originating client.

TLS
Pass a QSslConfiguration to enable wss://. The configuration should be built from a certificate file, a Qt resource, or a byte array before being passed in.
SSL-less Qt builds (QT_NO_SSL, including the standard Qt-for-WebAssembly build)
The constructor's tls parameter does not exist at all when Qt itself was configured without SSL — QSslConfiguration isn't a type Qt provides in that configuration. Such a server always constructs in NonSecureMode; see QtWebSocketBackend's equivalent doc comment for the client-side rationale.
Resource limits
Pass a QtWebSocketServerConfig to bound connection count, per-frame size, per-connection message rate, handshake/idle time, and how long a frame may stay unwritten. All fields default to unbounded, except maxMessageBytes, which defaults to the wire-layer cap, and sendTimeout, which defaults to 30 s.
Bind address & plaintext-exposure guard
listen() refuses — returns false and logs at morph::log::LogLevel::error — when cfg.bindAddress is not loopback, no TLS configuration was passed to the constructor, and cfg.allowPlaintextExposure is false. See QtWebSocketServerConfig and security.md's "Transport security" section.
Server-initiated events
Each connection is handed to RemoteServer::setConnectionWriter as it is accepted, so RemoteServer::post reaches it. Every frame the server writes to a connection, replies and events alike, counts toward that connection's backlog by the size of its encoded envelope until the socket has written it; when the backlog falls below backend::kEventBacklogLow, the server is told through RemoteServer::connectionDrained. A connection whose oldest unwritten frame is older than QtWebSocketServerConfig::sendTimeout is aborted.
Usage
Call listen() to start accepting connections, and port() to discover the bound port (useful when port was 0 — let the OS assign a free port). Call close() or destroy the object to stop the server.

Definition at line 138 of file qt_websocket_server.hpp.

Member Typedef Documentation

◆ Config

Alias for the per-connection limits configuration struct.

Definition at line 142 of file qt_websocket_server.hpp.

Constructor & Destructor Documentation

◆ QtWebSocketServer()

morph::qt::QtWebSocketServer::QtWebSocketServer ( ::morph::backend::RemoteServer & server,
quint16 port = 0,
std::optional< QSslConfiguration > tls = std::nullopt,
QtWebSocketServerConfig cfg = QtWebSocketServerConfig{},
QObject * parent = nullptr )
explicit

Constructs the server and prepares it to listen on port.

The server does not start accepting connections until listen() is called.

Parameters
serverRemoteServer instance that processes incoming messages.
portTCP port to listen on. Pass 0 to let the OS pick a free port.
tlsIf non-null, enables TLS (wss://) with this configuration. Not declared at all on an SSL-less Qt build (QT_NO_SSL) — see the class doc comment's "SSL-less Qt builds" section.
cfgPer-connection resource limits. Default: everything unbounded except maxMessageBytes, which defaults to the wire-layer cap.
parentOptional Qt parent object.

Member Function Documentation

◆ listen()

bool morph::qt::QtWebSocketServer::listen ( )

Starts listening for incoming WebSocket connections.

Refuses — returns false without binding, and logs at morph::log::LogLevel::error — when the configured bindAddress is not loopback, no TLS configuration was passed to the constructor, and allowPlaintextExposure is false. See QtWebSocketServerConfig.

Returns
true if the server successfully bound to the requested port.

◆ port()

quint16 morph::qt::QtWebSocketServer::port ( ) const
nodiscard

Returns the port the server is currently bound to.

When constructed with port 0, this returns the OS-assigned port after a successful listen() call.

Returns
Bound TCP port number.

◆ closeGracefully()

bool morph::qt::QtWebSocketServer::closeGracefully ( std::chrono::milliseconds deadline)

Gracefully stops the server: refuse new work, let in-flight replies deliver, close each client with a proper WebSocket close frame, then hard-stop anything still connected.

Sequence: QWebSocketServer::pauseAccepting() (no new connections), RemoteServer::beginShutdown() (new register/execute now fail fast with "server shutting down"), waiting up to deadline for RemoteServer::drainedWithin() to report every in-flight execute has replied, sending each still-connected client a real close frame (CloseCodeGoingAway, reason "server shutting down") instead of an abort, and finally running the close() hard stop for whatever deadline did not leave time to finish gracefully.

Pumps the Qt event loop internally while it waits, so it is safe to call from the Qt thread — which is also the thread that must run sendTextMessage for replies and close frames to actually reach clients.

Parameters
deadlineTotal time budget for the whole sequence, measured from the moment this call starts. Whatever the drain and graceful-close steps have not finished within it is hard-stopped exactly as close() does.
Returns
true if every in-flight execute drained before deadline elapsed; false if the hard stop had to reclaim stragglers.

◆ onTextMessage()

Q_SLOT void morph::qt::QtWebSocketServer::onTextMessage ( const QString & message)

Qt slot called when a connected client sends a text message.

Parameters
messageRaw text frame received from the client.

◆ onBytesWritten()

Q_SLOT void morph::qt::QtWebSocketServer::onBytesWritten ( qint64 bytes)

Qt slot called when a client's socket has written bytes.

Releases from the connection's backlog every frame those bytes complete, and re-arms its send timeout for the oldest frame left.

Parameters
bytesBytes the socket just wrote.

The documentation for this class was generated from the following file: