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
qtcpserver.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4//#define QTCPSERVER_DEBUG
5
76#include "qtcpserver.h"
77#include "qtcpserver_p.h"
78
79#include "qalgorithms.h"
80#include "qhostaddress.h"
81#include "qlist.h"
82#include "qpointer.h"
84#include "qtcpsocket.h"
85#include "qnetworkproxy.h"
86
88
89#define Q_CHECK_SOCKETENGINE(returnValue) do { \
90 if (!d->socketEngine) { \
91 return returnValue; \
92 } } while (0)
93
97 : port(0)
98 , socketType(QAbstractSocket::UnknownSocketType)
99 , state(QAbstractSocket::UnconnectedState)
100 , socketEngine(nullptr)
101 , serverSocketError(QAbstractSocket::UnknownSocketError)
102 , maxConnections(30)
103{
104}
105
111
112#ifndef QT_NO_NETWORKPROXY
118{
119 if (address.isLoopback())
121
122 QList<QNetworkProxy> proxies;
124 // a non-default proxy was set with setProxy
125 proxies << proxy;
126 } else {
127 // try the application settings instead
133 }
134
135 // return the first that we can use
136 for (const QNetworkProxy &p : std::as_const(proxies)) {
138 (p.capabilities() & QNetworkProxy::ListeningCapability) != 0)
139 return p;
140
142 (p.capabilities() & QNetworkProxy::SctpListeningCapability) != 0)
143 return p;
144 }
145
146 // no proxy found
147 // DefaultProxy will raise an error
149}
150#endif
151
155{
156#if defined(Q_OS_UNIX)
157 // Under Unix, we want to be able to bind to the port, even if a socket on
158 // the same address-port is in TIME_WAIT. Under Windows this is possible
159 // anyway -- furthermore, the meaning of reusable on Windows is different:
160 // it means that you can use the same address-port for multiple listening
161 // sockets.
162 // Don't abort though if we can't set that option. For example the socks
163 // engine doesn't support that option, but that shouldn't prevent us from
164 // trying to bind/listen.
166#endif
167}
168
172{
173 Q_Q(QTcpServer);
174 for (;;) {
176#if defined (QTCPSERVER_DEBUG)
177 qDebug("QTcpServerPrivate::_q_processIncomingConnection() too many connections");
178#endif
181 return;
182 }
183
184 qintptr descriptor = socketEngine->accept();
185 if (descriptor == -1) {
187 q->pauseAccepting();
190 emit q->acceptError(serverSocketError);
191 }
192 break;
193 }
194#if defined (QTCPSERVER_DEBUG)
195 qDebug("QTcpServerPrivate::_q_processIncomingConnection() accepted socket %i", descriptor);
196#endif
197 QPointer<QTcpServer> that = q;
198 q->incomingConnection(descriptor);
199
200 if (that)
201 emit q->newConnection();
202
203 if (!that || !q->isListening())
204 return;
205 }
206}
207
221
230 : QObject(*new QTcpServerPrivate, parent)
231{
232 Q_D(QTcpServer);
233#if defined(QTCPSERVER_DEBUG)
234 qDebug("QTcpServer::QTcpServer(%p)", parent);
235#endif
236 d->socketType = QAbstractSocket::TcpSocket;
237}
238
249{
250#if defined(QTCPSERVER_DEBUG)
251 qDebug("QTcpServer::~QTcpServer()");
252#endif
253 close();
254}
255
262 QObject *parent) : QObject(dd, parent)
263{
264 Q_D(QTcpServer);
265#if defined(QTCPSERVER_DEBUG)
266 qDebug("QTcpServer::QTcpServer(%sSocket, QTcpServerPrivate == %p, parent == %p)",
270 : "Unknown", &dd, parent);
271#endif
272 d->socketType = socketType;
273}
274
286{
287 Q_D(QTcpServer);
288 if (d->state == QAbstractSocket::ListeningState) {
289 qWarning("QTcpServer::listen() called when already listening");
290 return false;
291 }
292
295
296#ifdef QT_NO_NETWORKPROXY
297 static const QNetworkProxy &proxy = *(QNetworkProxy *)0;
298#else
299 QNetworkProxy proxy = d->resolveProxy(addr, port);
300#endif
301
302 delete d->socketEngine;
303 d->socketEngine = QAbstractSocketEngine::createSocketEngine(d->socketType, proxy, this);
304 if (!d->socketEngine) {
306 d->serverSocketErrorString = tr("Operation on socket is not supported");
307 return false;
308 }
309 if (!d->socketEngine->initialize(d->socketType, proto)) {
310 d->serverSocketError = d->socketEngine->error();
311 d->serverSocketErrorString = d->socketEngine->errorString();
312 return false;
313 }
314 proto = d->socketEngine->protocol();
317
318 d->configureCreatedSocket();
319
320 if (!d->socketEngine->bind(addr, port)) {
321 d->serverSocketError = d->socketEngine->error();
322 d->serverSocketErrorString = d->socketEngine->errorString();
323 return false;
324 }
325
326 if (!d->socketEngine->listen(d->listenBacklog)) {
327 d->serverSocketError = d->socketEngine->error();
328 d->serverSocketErrorString = d->socketEngine->errorString();
329 return false;
330 }
331
332 d->socketEngine->setReceiver(d);
333 d->socketEngine->setReadNotificationEnabled(true);
334
336 d->address = d->socketEngine->localAddress();
337 d->port = d->socketEngine->localPort();
338
339#if defined (QTCPSERVER_DEBUG)
340 qDebug("QTcpServer::listen(%i, \"%s\") == true (listening on port %i)", port,
341 address.toString().toLatin1().constData(), d->socketEngine->localPort());
342#endif
343 return true;
344}
345
353{
354 Q_D(const QTcpServer);
356 return d->socketEngine->state() == QAbstractSocket::ListeningState;
357}
358
366{
367 Q_D(QTcpServer);
368
369 qDeleteAll(d->pendingConnections);
370 d->pendingConnections.clear();
371
372 if (d->socketEngine) {
373 d->socketEngine->close();
374 QT_TRY {
375 d->socketEngine->deleteLater();
376 } QT_CATCH(const std::bad_alloc &) {
377 // in out of memory situations, the socketEngine
378 // will be deleted in ~QTcpServer (it's a child-object of this)
379 }
380 d->socketEngine = nullptr;
381 }
382
384}
385
396{
397 Q_D(const QTcpServer);
399 return d->socketEngine->socketDescriptor();
400}
401
412{
413 Q_D(QTcpServer);
414 if (isListening()) {
415 qWarning("QTcpServer::setSocketDescriptor() called when already listening");
416 return false;
417 }
418
419 if (d->socketEngine)
420 delete d->socketEngine;
422 if (!d->socketEngine) {
424 d->serverSocketErrorString = tr("Operation on socket is not supported");
425 return false;
426 }
427 if (!d->socketEngine->initialize(socketDescriptor, QAbstractSocket::ListeningState)) {
428 d->serverSocketError = d->socketEngine->error();
429 d->serverSocketErrorString = d->socketEngine->errorString();
430#if defined (QTCPSERVER_DEBUG)
431 qDebug("QTcpServer::setSocketDescriptor(%i) failed (%s)", socketDescriptor,
432 d->serverSocketErrorString.toLatin1().constData());
433#endif
434 return false;
435 }
436
437 d->socketEngine->setReceiver(d);
438 d->socketEngine->setReadNotificationEnabled(true);
439
440 d->state = d->socketEngine->state();
441 d->address = d->socketEngine->localAddress();
442 d->port = d->socketEngine->localPort();
443
444#if defined (QTCPSERVER_DEBUG)
445 qDebug("QTcpServer::setSocketDescriptor(%i) succeeded.", socketDescriptor);
446#endif
447 return true;
448}
449
457{
458 Q_D(const QTcpServer);
460 return d->socketEngine->localPort();
461}
462
470{
471 Q_D(const QTcpServer);
473 return d->socketEngine->localAddress();
474}
475
495bool QTcpServer::waitForNewConnection(int msec, bool *timedOut)
496{
497 Q_D(QTcpServer);
499 return false;
500
501 if (!d->socketEngine->waitForRead(QDeadlineTimer(msec), timedOut)) {
502 d->serverSocketError = d->socketEngine->error();
503 d->serverSocketErrorString = d->socketEngine->errorString();
504 return false;
505 }
506
507 if (timedOut && *timedOut)
508 return false;
509
510 d->readNotification();
511
512 return true;
513}
514
522{
523 return !d_func()->pendingConnections.isEmpty();
524}
525
545{
546 Q_D(QTcpServer);
547 if (d->pendingConnections.isEmpty())
548 return nullptr;
549
550 if (!d->socketEngine) {
551 qWarning("QTcpServer::nextPendingConnection() called while not listening");
552 } else if (!d->socketEngine->isReadNotificationEnabled()) {
553 d->socketEngine->setReadNotificationEnabled(true);
554 }
555
556 return d->pendingConnections.takeFirst();
557}
558
587{
588#if defined (QTCPSERVER_DEBUG)
589 qDebug("QTcpServer::incomingConnection(%i)", socketDescriptor);
590#endif
591
592 QTcpSocket *socket = new QTcpSocket(this);
595}
596
611{
612 d_func()->pendingConnections.append(socket);
613 emit pendingConnectionAvailable(QPrivateSignal());
614}
615
632{
633 d_func()->maxConnections = numConnections;
634}
635
643{
644 return d_func()->maxConnections;
645}
646
659{
660 d_func()->listenBacklog = size;
661}
662
671{
672 return d_func()->listenBacklog;
673}
674
681{
682 return d_func()->serverSocketError;
683}
684
692{
693 return d_func()->serverSocketErrorString;
694}
695
704{
705 d_func()->socketEngine->setReadNotificationEnabled(false);
706}
707
716{
717 d_func()->socketEngine->setReadNotificationEnabled(true);
718}
719
720#ifndef QT_NO_NETWORKPROXY
733void QTcpServer::setProxy(const QNetworkProxy &networkProxy)
734{
735 Q_D(QTcpServer);
736 d->proxy = networkProxy;
737}
738
748{
749 Q_D(const QTcpServer);
750 return d->proxy;
751}
752#endif // QT_NO_NETWORKPROXY
753
755
756#include "moc_qtcpserver.cpp"
757
QAbstractSocket::SocketError error() const
virtual bool isReadNotificationEnabled() const =0
virtual qintptr accept()=0
virtual void setReadNotificationEnabled(bool enable)=0
static QAbstractSocketEngine * createSocketEngine(QAbstractSocket::SocketType socketType, const QNetworkProxy &, QObject *parent)
virtual bool setOption(SocketOption option, int value)=0
The QAbstractSocket class provides the base functionality common to all socket types.
static constexpr auto IPv4Protocol
static constexpr auto AnyIPProtocol
SocketError
This enum describes the socket errors that can occur.
SocketType
This enum describes the transport layer protocol.
virtual bool setSocketDescriptor(qintptr socketDescriptor, SocketState state=ConnectedState, OpenMode openMode=ReadWrite)
Initializes QAbstractSocket with the native socket descriptor socketDescriptor.
\inmodule QtCore
The QHostAddress class provides an IP address.
qsizetype size() const noexcept
Definition qlist.h:397
static QList< QNetworkProxy > proxyForQuery(const QNetworkProxyQuery &query)
This function takes the query request, query, examines the details of the type of socket or request a...
The QNetworkProxyQuery class is used to query the proxy settings for a socket.
The QNetworkProxy class provides a network layer proxy.
QNetworkProxy::ProxyType type() const
Returns the proxy type for this instance.
\inmodule QtCore
Definition qobject.h:103
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QAbstractSocket::SocketError serverSocketError
QAbstractSocketEngine * socketEngine
QNetworkProxy resolveProxy(const QHostAddress &address, quint16 port)
QString serverSocketErrorString
virtual void configureCreatedSocket()
QNetworkProxy proxy
virtual int totalPendingConnections() const
QAbstractSocket::SocketType socketType
void readNotification() override
QList< QTcpSocket * > pendingConnections
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 ...
void setListenBacklogSize(int size)
Sets the backlog queue size of to be accepted connections to size.
void pauseAccepting()
void setProxy(const QNetworkProxy &networkProxy)
virtual bool hasPendingConnections() const
Returns true if the server has a pending connection; otherwise returns false.
qintptr socketDescriptor() const
Returns the native socket descriptor the server uses to listen for incoming instructions,...
QTcpServer(QObject *parent=nullptr)
Constructs a QTcpServer object.
virtual void incomingConnection(qintptr handle)
This virtual function is called by QTcpServer when a new connection is available.
QHostAddress serverAddress() const
Returns the server's address if the server is listening for connections; otherwise returns QHostAddre...
QString errorString() const
Returns a human readable description of the last error that occurred.
bool setSocketDescriptor(qintptr socketDescriptor)
Sets the socket descriptor this server should use when listening for incoming connections to socketDe...
int listenBacklogSize() const
Returns the backlog queue size of to be accepted connections.
void resumeAccepting()
virtual QTcpSocket * nextPendingConnection()
Returns the next pending connection as a connected QTcpSocket object.
int maxPendingConnections() const
Returns the maximum number of pending accepted connections.
bool listen(const QHostAddress &address=QHostAddress::Any, quint16 port=0)
Tells the server to listen for incoming connections on address address and port port.
virtual ~QTcpServer()
Destroys the QTcpServer object.
bool isListening() const
Returns true if the server is currently listening for incoming connections; otherwise returns false.
quint16 serverPort() const
Returns the server's port if the server is listening for connections; otherwise returns 0.
void pendingConnectionAvailable(QPrivateSignal)
This signal is emitted every time a new connection has been added to the pending connections queue.
void setMaxPendingConnections(int numConnections)
Sets the maximum number of pending accepted connections to numConnections.
QAbstractSocket::SocketError serverError() const
Returns an error code for the last error that occurred.
QNetworkProxy proxy() const
bool waitForNewConnection(int msec=0, bool *timedOut=nullptr)
Waits for at most msec milliseconds or until an incoming connection is available.
void close()
Closes the server.
The QTcpSocket class provides a TCP socket.
Definition qtcpsocket.h:18
qDeleteAll(list.begin(), list.end())
else opt state
[0]
Combined button and popup list for selecting options.
#define Q_CHECK_SOCKETENGINE(returnValue)
EGLOutputPortEXT port
static QT_BEGIN_NAMESPACE const char * socketType(QSocketNotifier::Type type)
#define QT_CATCH(A)
#define QT_TRY
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum query
GLenum const void * addr
GLuint GLuint64EXT address
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLfloat GLfloat p
[1]
#define tr(X)
#define emit
unsigned short quint16
Definition qtypes.h:48
ptrdiff_t qintptr
Definition qtypes.h:166
QObject::connect nullptr
QTcpSocket * socket
[1]