Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qsslserver.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// Copyright (C) 2016 Kurt Pattyn <pattyn.kurt@gmail.com>.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
181#include "qsslserver.h"
182#include "qsslserver_p.h"
183
184#include <QtNetwork/QSslSocket>
185#include <QtNetwork/QSslCipher>
186
188
193 sslConfiguration(QSslConfiguration::defaultConfiguration())
194{
195}
196
201 QTcpServer(QAbstractSocket::TcpSocket, *new QSslServerPrivate, parent)
202{
203}
204
213
223{
224 Q_D(QSslServer);
225 d->sslConfiguration = sslConfiguration;
226}
227
232{
233 const Q_D(QSslServer);
234 return d->sslConfiguration;
235}
236
257{
258 Q_D(QSslServer);
259 d->handshakeTimeout = timeout;
260}
261
268{
269 const Q_D(QSslServer);
270 return d->handshakeTimeout;
271}
272
281{
282 QSslSocket *pSslSocket = new QSslSocket(this);
283
284 pSslSocket->setSslConfiguration(sslConfiguration());
285
286 if (Q_LIKELY(pSslSocket->setSocketDescriptor(socket))) {
287 connect(pSslSocket, &QSslSocket::peerVerifyError, this,
288 [this, pSslSocket](const QSslError &error) {
289 Q_EMIT peerVerifyError(pSslSocket, error);
290 });
291 connect(pSslSocket, &QSslSocket::sslErrors, this,
292 [this, pSslSocket](const QList<QSslError> &errors) {
293 Q_EMIT sslErrors(pSslSocket, errors);
294 });
295 connect(pSslSocket, &QAbstractSocket::errorOccurred, this,
296 [this, pSslSocket](QAbstractSocket::SocketError error) {
297 Q_EMIT errorOccurred(pSslSocket, error);
298 if (!pSslSocket->isEncrypted())
299 pSslSocket->deleteLater();
300 });
301 connect(pSslSocket, &QSslSocket::encrypted, this, [this, pSslSocket]() {
302 Q_D(QSslServer);
303 d->removeSocketData(quintptr(pSslSocket));
304 pSslSocket->disconnect(this);
305 addPendingConnection(pSslSocket);
306 });
308 [this, pSslSocket](QSslPreSharedKeyAuthenticator *authenticator) {
309 Q_EMIT preSharedKeyAuthenticationRequired(pSslSocket, authenticator);
310 });
311 connect(pSslSocket, &QSslSocket::alertSent, this,
312 [this, pSslSocket](QSsl::AlertLevel level, QSsl::AlertType type,
313 const QString &description) {
314 Q_EMIT alertSent(pSslSocket, level, type, description);
315 });
316 connect(pSslSocket, &QSslSocket::alertReceived, this,
317 [this, pSslSocket](QSsl::AlertLevel level, QSsl::AlertType type,
318 const QString &description) {
319 Q_EMIT alertReceived(pSslSocket, level, type, description);
320 });
322 [this, pSslSocket](const QSslError &error) {
324 });
325
326 d_func()->initializeHandshakeProcess(pSslSocket);
327 }
328}
329
331{
332 Q_Q(QSslServer);
335
336 QMetaObject::Connection destroyed =
338 // This cast is not safe to use since the socket is inside the
339 // QObject dtor, but we only use the pointer value!
341 });
342 auto it = socketData.emplace(quintptr(socket), readyRead, destroyed, std::make_shared<QTimer>());
343 it->timeoutTimer->setSingleShot(true);
344 it->timeoutTimer->callOnTimeout(q, [this, socket]() { handleHandshakeTimedOut(socket); });
345 it->timeoutTimer->setInterval(handshakeTimeout);
346 it->timeoutTimer->start();
347}
348
349// This function may be called while in the socket's QObject dtor, __never__ use
350// the socket for anything other than a lookup!
352{
353 auto it = socketData.find(socket);
354 if (it != socketData.end()) {
355 it->disconnectSignals();
356 socketData.erase(it);
357 }
358}
359
361{
362 // max pending connections is int, so this cannot exceed that
364}
365
367{
368 Q_Q(QSslServer);
369 QSslSocket *socket = qobject_cast<QSslSocket *>(q->sender());
370 if (Q_UNLIKELY(!socket) || socket->bytesAvailable() <= 0)
371 return;
372
373 char byte = '\0';
374 if (socket->peek(&byte, 1) != 1) {
376 return;
377 }
378
379 auto it = socketData.find(quintptr(socket));
380 const bool foundData = it != socketData.end();
381 if (foundData && it->readyReadConnection)
382 QObject::disconnect(std::exchange(it->readyReadConnection, {}));
383
384 constexpr char CLIENT_HELLO = 0x16;
385 if (byte != CLIENT_HELLO) {
388 return;
389 }
390
391 // Be nice and restart the timeout timer since some progress was made
392 if (foundData)
393 it->timeoutTimer->start();
394
395 socket->startServerEncryption();
396 Q_EMIT q->startedEncryptionHandshake(socket);
397}
398
409
411
412#include "moc_qsslserver.cpp"
virtual bool isReadNotificationEnabled() const =0
The QAbstractSocket class provides the base functionality common to all socket types.
void errorOccurred(QAbstractSocket::SocketError)
qint64 bytesAvailable() const override
Returns the number of incoming bytes that are waiting to be read.
virtual void disconnectFromHost()
Attempts to close the socket.
SocketError
This enum describes the socket errors that can occur.
void readyRead()
This signal is emitted once every time new data is available for reading from the device's current re...
qint64 peek(char *data, qint64 maxlen)
\inmodule QtCore Represents a handle to a signal-slot (or signal-functor) connection.
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3236
void destroyed(QObject *=nullptr)
This signal is emitted immediately before the object obj is destroyed, after any instances of QPointe...
void deleteLater()
\threadsafe
Definition qobject.cpp:2435
The QSslConfiguration class holds the configuration and state of an SSL connection.
The QSslError class provides an SSL error.
Definition qsslerror.h:21
The QSslPreSharedKeyAuthenticator class provides authentication data for pre shared keys (PSK) cipher...
void initializeHandshakeProcess(QSslSocket *socket)
void removeSocketData(quintptr socket)
void checkClientHelloAndContinue()
int totalPendingConnections() const override
QHash< quintptr, SocketData > socketData
void handleHandshakeTimedOut(QSslSocket *socket)
\inmodule QtNetwork
Definition qsslserver.h:25
void setSslConfiguration(const QSslConfiguration &sslConfiguration)
Sets the sslConfiguration to use for all following incoming connections.
void peerVerifyError(QSslSocket *socket, const QSslError &error)
QSslServer can emit this signal several times during the SSL handshake, before encryption has been es...
void errorOccurred(QSslSocket *socket, QAbstractSocket::SocketError error)
This signal is emitted after an error occurred during handshake.
void handshakeInterruptedOnError(QSslSocket *socket, const QSslError &error)
QSslServer emits this signal if a certificate verification error was found by socket and if early err...
QSslConfiguration sslConfiguration() const
Returns the current ssl configuration.
void incomingConnection(qintptr socket) override
Called when a new connection is established.
void setHandshakeTimeout(int timeout)
Sets the timeout to use for all incoming handshakes, in milliseconds.
void alertSent(QSslSocket *socket, QSsl::AlertLevel level, QSsl::AlertType type, const QString &description)
QSslServer emits this signal if an alert message was sent from socket to a peer.
void alertReceived(QSslSocket *socket, QSsl::AlertLevel level, QSsl::AlertType type, const QString &description)
QSslServer emits this signal if an alert message was received by the socket from a peer.
void sslErrors(QSslSocket *socket, const QList< QSslError > &errors)
QSslServer emits this signal after the SSL handshake to indicate that one or more errors have occurre...
~QSslServer() override
Destroys the QSslServer.
int handshakeTimeout() const
Returns the currently configured handshake timeout.
QSslServer(QObject *parent=nullptr)
Constructs a new QSslServer with the given parent.
void preSharedKeyAuthenticationRequired(QSslSocket *socket, QSslPreSharedKeyAuthenticator *authenticator)
QSslServer emits this signal when socket negotiates a PSK ciphersuite, and therefore PSK authenticati...
The QSslSocket class provides an SSL encrypted socket for both clients and servers.
Definition qsslsocket.h:29
void sslErrors(const QList< QSslError > &errors)
QSslSocket emits this signal after the SSL handshake to indicate that one or more errors have occurre...
void alertSent(QSsl::AlertLevel level, QSsl::AlertType type, const QString &description)
QSslSocket emits this signal if an alert message was sent to a peer.
void peerVerifyError(const QSslError &error)
void preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator)
void encrypted()
This signal is emitted when QSslSocket enters encrypted mode.
void alertReceived(QSsl::AlertLevel level, QSsl::AlertType type, const QString &description)
QSslSocket emits this signal if an alert message was received from a peer.
void handshakeInterruptedOnError(const QSslError &error)
QSslSocket emits this signal if a certificate verification error was found and if early error reporti...
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QAbstractSocketEngine * socketEngine
virtual int totalPendingConnections() const
The QTcpServer class provides a TCP-based server.
Definition qtcpserver.h:22
void addPendingConnection(QTcpSocket *socket)
This function is called by QTcpServer::incomingConnection() to add the socket to the list of pending ...
QSet< QString >::iterator it
AlertLevel
Describes the level of an alert message.
Definition qssl.h:86
AlertType
Enumerates possible codes that an alert message can have.
Definition qssl.h:93
Combined button and popup list for selecting options.
#define Q_UNLIKELY(x)
#define Q_LIKELY(x)
DBusConnection const char DBusError * error
GLenum GLuint GLint level
GLbitfield GLuint64 timeout
[4]
GLenum type
GLhandleARB obj
[2]
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
#define Q_EMIT
size_t quintptr
Definition qtypes.h:167
ptrdiff_t qintptr
Definition qtypes.h:166
QTcpSocket * socket
[1]