1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtNetwork module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | //#define QTCPSERVER_DEBUG |
41 | |
42 | /*! \class QTcpServer |
43 | |
44 | \brief The QTcpServer class provides a TCP-based server. |
45 | |
46 | \reentrant |
47 | \ingroup network |
48 | \inmodule QtNetwork |
49 | |
50 | This class makes it possible to accept incoming TCP connections. |
51 | You can specify the port or have QTcpServer pick one |
52 | automatically. You can listen on a specific address or on all the |
53 | machine's addresses. |
54 | |
55 | Call listen() to have the server listen for incoming connections. |
56 | The newConnection() signal is then emitted each time a client |
57 | connects to the server. |
58 | |
59 | Call nextPendingConnection() to accept the pending connection as |
60 | a connected QTcpSocket. The function returns a pointer to a |
61 | QTcpSocket in QAbstractSocket::ConnectedState that you can use for |
62 | communicating with the client. |
63 | |
64 | If an error occurs, serverError() returns the type of error, and |
65 | errorString() can be called to get a human readable description of |
66 | what happened. |
67 | |
68 | When listening for connections, the address and port on which the |
69 | server is listening are available as serverAddress() and |
70 | serverPort(). |
71 | |
72 | Calling close() makes QTcpServer stop listening for incoming |
73 | connections. |
74 | |
75 | Although QTcpServer is mostly designed for use with an event |
76 | loop, it's possible to use it without one. In that case, you must |
77 | use waitForNewConnection(), which blocks until either a |
78 | connection is available or a timeout expires. |
79 | |
80 | \sa QTcpSocket, {Fortune Server Example}, {Threaded Fortune Server Example}, |
81 | {Loopback Example}, {Torrent Example} |
82 | */ |
83 | |
84 | /*! \fn void QTcpServer::newConnection() |
85 | |
86 | This signal is emitted every time a new connection is available. |
87 | |
88 | \sa hasPendingConnections(), nextPendingConnection() |
89 | */ |
90 | |
91 | /*! \fn void QTcpServer::acceptError(QAbstractSocket::SocketError socketError) |
92 | \since 5.0 |
93 | |
94 | This signal is emitted when accepting a new connection results in an error. |
95 | The \a socketError parameter describes the type of error that occurred. |
96 | |
97 | \sa pauseAccepting(), resumeAccepting() |
98 | */ |
99 | |
100 | #include "qtcpserver.h" |
101 | #include "qtcpserver_p.h" |
102 | |
103 | #include "qalgorithms.h" |
104 | #include "qhostaddress.h" |
105 | #include "qlist.h" |
106 | #include "qpointer.h" |
107 | #include "qabstractsocketengine_p.h" |
108 | #include "qtcpsocket.h" |
109 | #include "qnetworkproxy.h" |
110 | |
111 | QT_BEGIN_NAMESPACE |
112 | |
113 | #define Q_CHECK_SOCKETENGINE(returnValue) do { \ |
114 | if (!d->socketEngine) { \ |
115 | return returnValue; \ |
116 | } } while (0) |
117 | |
118 | /*! \internal |
119 | */ |
120 | QTcpServerPrivate::QTcpServerPrivate() |
121 | : port(0) |
122 | , socketType(QAbstractSocket::UnknownSocketType) |
123 | , state(QAbstractSocket::UnconnectedState) |
124 | , socketEngine(nullptr) |
125 | , serverSocketError(QAbstractSocket::UnknownSocketError) |
126 | , maxConnections(30) |
127 | { |
128 | } |
129 | |
130 | /*! \internal |
131 | */ |
132 | QTcpServerPrivate::~QTcpServerPrivate() |
133 | { |
134 | } |
135 | |
136 | #ifndef QT_NO_NETWORKPROXY |
137 | /*! \internal |
138 | |
139 | Resolve the proxy to its final value. |
140 | */ |
141 | QNetworkProxy QTcpServerPrivate::resolveProxy(const QHostAddress &address, quint16 port) |
142 | { |
143 | if (address.isLoopback()) |
144 | return QNetworkProxy::NoProxy; |
145 | |
146 | QList<QNetworkProxy> proxies; |
147 | if (proxy.type() != QNetworkProxy::DefaultProxy) { |
148 | // a non-default proxy was set with setProxy |
149 | proxies << proxy; |
150 | } else { |
151 | // try the application settings instead |
152 | QNetworkProxyQuery query(port, QString(), |
153 | socketType == QAbstractSocket::SctpSocket ? |
154 | QNetworkProxyQuery::SctpServer : |
155 | QNetworkProxyQuery::TcpServer); |
156 | proxies = QNetworkProxyFactory::proxyForQuery(query); |
157 | } |
158 | |
159 | // return the first that we can use |
160 | for (const QNetworkProxy &p : qAsConst(t&: proxies)) { |
161 | if (socketType == QAbstractSocket::TcpSocket && |
162 | (p.capabilities() & QNetworkProxy::ListeningCapability) != 0) |
163 | return p; |
164 | |
165 | if (socketType == QAbstractSocket::SctpSocket && |
166 | (p.capabilities() & QNetworkProxy::SctpListeningCapability) != 0) |
167 | return p; |
168 | } |
169 | |
170 | // no proxy found |
171 | // DefaultProxy will raise an error |
172 | return QNetworkProxy(QNetworkProxy::DefaultProxy); |
173 | } |
174 | #endif |
175 | |
176 | /*! \internal |
177 | */ |
178 | void QTcpServerPrivate::configureCreatedSocket() |
179 | { |
180 | #if defined(Q_OS_UNIX) |
181 | // Under Unix, we want to be able to bind to the port, even if a socket on |
182 | // the same address-port is in TIME_WAIT. Under Windows this is possible |
183 | // anyway -- furthermore, the meaning of reusable on Windows is different: |
184 | // it means that you can use the same address-port for multiple listening |
185 | // sockets. |
186 | // Don't abort though if we can't set that option. For example the socks |
187 | // engine doesn't support that option, but that shouldn't prevent us from |
188 | // trying to bind/listen. |
189 | socketEngine->setOption(option: QAbstractSocketEngine::AddressReusable, value: 1); |
190 | #endif |
191 | } |
192 | |
193 | /*! \internal |
194 | */ |
195 | void QTcpServerPrivate::readNotification() |
196 | { |
197 | Q_Q(QTcpServer); |
198 | for (;;) { |
199 | if (pendingConnections.count() >= maxConnections) { |
200 | #if defined (QTCPSERVER_DEBUG) |
201 | qDebug("QTcpServerPrivate::_q_processIncomingConnection() too many connections" ); |
202 | #endif |
203 | if (socketEngine->isReadNotificationEnabled()) |
204 | socketEngine->setReadNotificationEnabled(false); |
205 | return; |
206 | } |
207 | |
208 | int descriptor = socketEngine->accept(); |
209 | if (descriptor == -1) { |
210 | if (socketEngine->error() != QAbstractSocket::TemporaryError) { |
211 | q->pauseAccepting(); |
212 | serverSocketError = socketEngine->error(); |
213 | serverSocketErrorString = socketEngine->errorString(); |
214 | emit q->acceptError(socketError: serverSocketError); |
215 | } |
216 | break; |
217 | } |
218 | #if defined (QTCPSERVER_DEBUG) |
219 | qDebug("QTcpServerPrivate::_q_processIncomingConnection() accepted socket %i" , descriptor); |
220 | #endif |
221 | q->incomingConnection(handle: descriptor); |
222 | |
223 | QPointer<QTcpServer> that = q; |
224 | emit q->newConnection(); |
225 | if (!that || !q->isListening()) |
226 | return; |
227 | } |
228 | } |
229 | |
230 | /*! |
231 | Constructs a QTcpServer object. |
232 | |
233 | \a parent is passed to the QObject constructor. |
234 | |
235 | \sa listen(), setSocketDescriptor() |
236 | */ |
237 | QTcpServer::QTcpServer(QObject *parent) |
238 | : QObject(*new QTcpServerPrivate, parent) |
239 | { |
240 | Q_D(QTcpServer); |
241 | #if defined(QTCPSERVER_DEBUG) |
242 | qDebug("QTcpServer::QTcpServer(%p)" , parent); |
243 | #endif |
244 | d->socketType = QAbstractSocket::TcpSocket; |
245 | } |
246 | |
247 | /*! |
248 | Destroys the QTcpServer object. If the server is listening for |
249 | connections, the socket is automatically closed. |
250 | |
251 | Any client \l{QTcpSocket}s that are still connected must either |
252 | disconnect or be reparented before the server is deleted. |
253 | |
254 | \sa close() |
255 | */ |
256 | QTcpServer::~QTcpServer() |
257 | { |
258 | #if defined(QTCPSERVER_DEBUG) |
259 | qDebug("QTcpServer::~QTcpServer()" ); |
260 | #endif |
261 | close(); |
262 | } |
263 | |
264 | /*! \internal |
265 | |
266 | Constructs a new server object with socket of type \a socketType. The \a |
267 | parent argument is passed to QObject's constructor. |
268 | */ |
269 | QTcpServer::QTcpServer(QAbstractSocket::SocketType socketType, QTcpServerPrivate &dd, |
270 | QObject *parent) : QObject(dd, parent) |
271 | { |
272 | Q_D(QTcpServer); |
273 | #if defined(QTCPSERVER_DEBUG) |
274 | qDebug("QTcpServer::QTcpServer(%sSocket, QTcpServerPrivate == %p, parent == %p)" , |
275 | socketType == QAbstractSocket::TcpSocket ? "Tcp" |
276 | : socketType == QAbstractSocket::UdpSocket ? "Udp" |
277 | : socketType == QAbstractSocket::SctpSocket ? "Sctp" |
278 | : "Unknown" , &dd, parent); |
279 | #endif |
280 | d->socketType = socketType; |
281 | } |
282 | |
283 | /*! |
284 | Tells the server to listen for incoming connections on address \a |
285 | address and port \a port. If \a port is 0, a port is chosen |
286 | automatically. If \a address is QHostAddress::Any, the server |
287 | will listen on all network interfaces. |
288 | |
289 | Returns \c true on success; otherwise returns \c false. |
290 | |
291 | \sa isListening() |
292 | */ |
293 | bool QTcpServer::listen(const QHostAddress &address, quint16 port) |
294 | { |
295 | Q_D(QTcpServer); |
296 | if (d->state == QAbstractSocket::ListeningState) { |
297 | qWarning(msg: "QTcpServer::listen() called when already listening" ); |
298 | return false; |
299 | } |
300 | |
301 | QAbstractSocket::NetworkLayerProtocol proto = address.protocol(); |
302 | QHostAddress addr = address; |
303 | |
304 | #ifdef QT_NO_NETWORKPROXY |
305 | static const QNetworkProxy &proxy = *(QNetworkProxy *)0; |
306 | #else |
307 | QNetworkProxy proxy = d->resolveProxy(address: addr, port); |
308 | #endif |
309 | |
310 | delete d->socketEngine; |
311 | d->socketEngine = QAbstractSocketEngine::createSocketEngine(socketType: d->socketType, proxy, parent: this); |
312 | if (!d->socketEngine) { |
313 | d->serverSocketError = QAbstractSocket::UnsupportedSocketOperationError; |
314 | d->serverSocketErrorString = tr(s: "Operation on socket is not supported" ); |
315 | return false; |
316 | } |
317 | #ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section |
318 | //copy network session down to the socket engine (if it has been set) |
319 | d->socketEngine->setProperty(name: "_q_networksession" , value: property(name: "_q_networksession" )); |
320 | #endif |
321 | if (!d->socketEngine->initialize(type: d->socketType, protocol: proto)) { |
322 | d->serverSocketError = d->socketEngine->error(); |
323 | d->serverSocketErrorString = d->socketEngine->errorString(); |
324 | return false; |
325 | } |
326 | proto = d->socketEngine->protocol(); |
327 | if (addr.protocol() == QAbstractSocket::AnyIPProtocol && proto == QAbstractSocket::IPv4Protocol) |
328 | addr = QHostAddress::AnyIPv4; |
329 | |
330 | d->configureCreatedSocket(); |
331 | |
332 | if (!d->socketEngine->bind(address: addr, port)) { |
333 | d->serverSocketError = d->socketEngine->error(); |
334 | d->serverSocketErrorString = d->socketEngine->errorString(); |
335 | return false; |
336 | } |
337 | |
338 | if (!d->socketEngine->listen()) { |
339 | d->serverSocketError = d->socketEngine->error(); |
340 | d->serverSocketErrorString = d->socketEngine->errorString(); |
341 | return false; |
342 | } |
343 | |
344 | d->socketEngine->setReceiver(d); |
345 | d->socketEngine->setReadNotificationEnabled(true); |
346 | |
347 | d->state = QAbstractSocket::ListeningState; |
348 | d->address = d->socketEngine->localAddress(); |
349 | d->port = d->socketEngine->localPort(); |
350 | |
351 | #if defined (QTCPSERVER_DEBUG) |
352 | qDebug("QTcpServer::listen(%i, \"%s\") == true (listening on port %i)" , port, |
353 | address.toString().toLatin1().constData(), d->socketEngine->localPort()); |
354 | #endif |
355 | return true; |
356 | } |
357 | |
358 | /*! |
359 | Returns \c true if the server is currently listening for incoming |
360 | connections; otherwise returns \c false. |
361 | |
362 | \sa listen() |
363 | */ |
364 | bool QTcpServer::isListening() const |
365 | { |
366 | Q_D(const QTcpServer); |
367 | Q_CHECK_SOCKETENGINE(false); |
368 | return d->socketEngine->state() == QAbstractSocket::ListeningState; |
369 | } |
370 | |
371 | /*! |
372 | Closes the server. The server will no longer listen for incoming |
373 | connections. |
374 | |
375 | \sa listen() |
376 | */ |
377 | void QTcpServer::close() |
378 | { |
379 | Q_D(QTcpServer); |
380 | |
381 | qDeleteAll(c: d->pendingConnections); |
382 | d->pendingConnections.clear(); |
383 | |
384 | if (d->socketEngine) { |
385 | d->socketEngine->close(); |
386 | QT_TRY { |
387 | d->socketEngine->deleteLater(); |
388 | } QT_CATCH(const std::bad_alloc &) { |
389 | // in out of memory situations, the socketEngine |
390 | // will be deleted in ~QTcpServer (it's a child-object of this) |
391 | } |
392 | d->socketEngine = nullptr; |
393 | } |
394 | |
395 | d->state = QAbstractSocket::UnconnectedState; |
396 | } |
397 | |
398 | /*! |
399 | Returns the native socket descriptor the server uses to listen |
400 | for incoming instructions, or -1 if the server is not listening. |
401 | |
402 | If the server is using QNetworkProxy, the returned descriptor may |
403 | not be usable with native socket functions. |
404 | |
405 | \sa setSocketDescriptor(), isListening() |
406 | */ |
407 | qintptr QTcpServer::socketDescriptor() const |
408 | { |
409 | Q_D(const QTcpServer); |
410 | Q_CHECK_SOCKETENGINE(-1); |
411 | return d->socketEngine->socketDescriptor(); |
412 | } |
413 | |
414 | /*! |
415 | Sets the socket descriptor this server should use when listening |
416 | for incoming connections to \a socketDescriptor. Returns \c true if |
417 | the socket is set successfully; otherwise returns \c false. |
418 | |
419 | The socket is assumed to be in listening state. |
420 | |
421 | \sa socketDescriptor(), isListening() |
422 | */ |
423 | bool QTcpServer::setSocketDescriptor(qintptr socketDescriptor) |
424 | { |
425 | Q_D(QTcpServer); |
426 | if (isListening()) { |
427 | qWarning(msg: "QTcpServer::setSocketDescriptor() called when already listening" ); |
428 | return false; |
429 | } |
430 | |
431 | if (d->socketEngine) |
432 | delete d->socketEngine; |
433 | d->socketEngine = QAbstractSocketEngine::createSocketEngine(socketDescriptor, parent: this); |
434 | if (!d->socketEngine) { |
435 | d->serverSocketError = QAbstractSocket::UnsupportedSocketOperationError; |
436 | d->serverSocketErrorString = tr(s: "Operation on socket is not supported" ); |
437 | return false; |
438 | } |
439 | #ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section |
440 | //copy network session down to the socket engine (if it has been set) |
441 | d->socketEngine->setProperty(name: "_q_networksession" , value: property(name: "_q_networksession" )); |
442 | #endif |
443 | if (!d->socketEngine->initialize(socketDescriptor, socketState: QAbstractSocket::ListeningState)) { |
444 | d->serverSocketError = d->socketEngine->error(); |
445 | d->serverSocketErrorString = d->socketEngine->errorString(); |
446 | #if defined (QTCPSERVER_DEBUG) |
447 | qDebug("QTcpServer::setSocketDescriptor(%i) failed (%s)" , socketDescriptor, |
448 | d->serverSocketErrorString.toLatin1().constData()); |
449 | #endif |
450 | return false; |
451 | } |
452 | |
453 | d->socketEngine->setReceiver(d); |
454 | d->socketEngine->setReadNotificationEnabled(true); |
455 | |
456 | d->state = d->socketEngine->state(); |
457 | d->address = d->socketEngine->localAddress(); |
458 | d->port = d->socketEngine->localPort(); |
459 | |
460 | #if defined (QTCPSERVER_DEBUG) |
461 | qDebug("QTcpServer::setSocketDescriptor(%i) succeeded." , socketDescriptor); |
462 | #endif |
463 | return true; |
464 | } |
465 | |
466 | /*! |
467 | Returns the server's port if the server is listening for |
468 | connections; otherwise returns 0. |
469 | |
470 | \sa serverAddress(), listen() |
471 | */ |
472 | quint16 QTcpServer::serverPort() const |
473 | { |
474 | Q_D(const QTcpServer); |
475 | Q_CHECK_SOCKETENGINE(0); |
476 | return d->socketEngine->localPort(); |
477 | } |
478 | |
479 | /*! |
480 | Returns the server's address if the server is listening for |
481 | connections; otherwise returns QHostAddress::Null. |
482 | |
483 | \sa serverPort(), listen() |
484 | */ |
485 | QHostAddress QTcpServer::serverAddress() const |
486 | { |
487 | Q_D(const QTcpServer); |
488 | Q_CHECK_SOCKETENGINE(QHostAddress(QHostAddress::Null)); |
489 | return d->socketEngine->localAddress(); |
490 | } |
491 | |
492 | /*! |
493 | Waits for at most \a msec milliseconds or until an incoming |
494 | connection is available. Returns \c true if a connection is |
495 | available; otherwise returns \c false. If the operation timed out |
496 | and \a timedOut is not \nullptr, *\a timedOut will be set to true. |
497 | |
498 | This is a blocking function call. Its use is disadvised in a |
499 | single-threaded GUI application, since the whole application will |
500 | stop responding until the function returns. |
501 | waitForNewConnection() is mostly useful when there is no event |
502 | loop available. |
503 | |
504 | The non-blocking alternative is to connect to the newConnection() |
505 | signal. |
506 | |
507 | If msec is -1, this function will not time out. |
508 | |
509 | \sa hasPendingConnections(), nextPendingConnection() |
510 | */ |
511 | bool QTcpServer::waitForNewConnection(int msec, bool *timedOut) |
512 | { |
513 | Q_D(QTcpServer); |
514 | if (d->state != QAbstractSocket::ListeningState) |
515 | return false; |
516 | |
517 | if (!d->socketEngine->waitForRead(msecs: msec, timedOut)) { |
518 | d->serverSocketError = d->socketEngine->error(); |
519 | d->serverSocketErrorString = d->socketEngine->errorString(); |
520 | return false; |
521 | } |
522 | |
523 | if (timedOut && *timedOut) |
524 | return false; |
525 | |
526 | d->readNotification(); |
527 | |
528 | return true; |
529 | } |
530 | |
531 | /*! |
532 | Returns \c true if the server has a pending connection; otherwise |
533 | returns \c false. |
534 | |
535 | \sa nextPendingConnection(), setMaxPendingConnections() |
536 | */ |
537 | bool QTcpServer::hasPendingConnections() const |
538 | { |
539 | return !d_func()->pendingConnections.isEmpty(); |
540 | } |
541 | |
542 | /*! |
543 | Returns the next pending connection as a connected QTcpSocket |
544 | object. |
545 | |
546 | The socket is created as a child of the server, which means that |
547 | it is automatically deleted when the QTcpServer object is |
548 | destroyed. It is still a good idea to delete the object |
549 | explicitly when you are done with it, to avoid wasting memory. |
550 | |
551 | \nullptr is returned if this function is called when there are no pending |
552 | connections. |
553 | |
554 | \note The returned QTcpSocket object cannot be used from another |
555 | thread. If you want to use an incoming connection from another thread, |
556 | you need to override incomingConnection(). |
557 | |
558 | \sa hasPendingConnections() |
559 | */ |
560 | QTcpSocket *QTcpServer::nextPendingConnection() |
561 | { |
562 | Q_D(QTcpServer); |
563 | if (d->pendingConnections.isEmpty()) |
564 | return nullptr; |
565 | |
566 | if (!d->socketEngine) { |
567 | qWarning(msg: "QTcpServer::nextPendingConnection() called while not listening" ); |
568 | } else if (!d->socketEngine->isReadNotificationEnabled()) { |
569 | d->socketEngine->setReadNotificationEnabled(true); |
570 | } |
571 | |
572 | return d->pendingConnections.takeFirst(); |
573 | } |
574 | |
575 | /*! |
576 | This virtual function is called by QTcpServer when a new |
577 | connection is available. The \a socketDescriptor argument is the |
578 | native socket descriptor for the accepted connection. |
579 | |
580 | The base implementation creates a QTcpSocket, sets the socket |
581 | descriptor and then stores the QTcpSocket in an internal list of |
582 | pending connections. Finally newConnection() is emitted. |
583 | |
584 | Reimplement this function to alter the server's behavior when a |
585 | connection is available. |
586 | |
587 | If this server is using QNetworkProxy then the \a socketDescriptor |
588 | may not be usable with native socket functions, and should only be |
589 | used with QTcpSocket::setSocketDescriptor(). |
590 | |
591 | \note If another socket is created in the reimplementation |
592 | of this method, it needs to be added to the Pending Connections mechanism |
593 | by calling addPendingConnection(). |
594 | |
595 | \note If you want to handle an incoming connection as a new QTcpSocket |
596 | object in another thread you have to pass the socketDescriptor |
597 | to the other thread and create the QTcpSocket object there and |
598 | use its setSocketDescriptor() method. |
599 | |
600 | \sa newConnection(), nextPendingConnection(), addPendingConnection() |
601 | */ |
602 | void QTcpServer::incomingConnection(qintptr socketDescriptor) |
603 | { |
604 | #if defined (QTCPSERVER_DEBUG) |
605 | qDebug("QTcpServer::incomingConnection(%i)" , socketDescriptor); |
606 | #endif |
607 | |
608 | QTcpSocket *socket = new QTcpSocket(this); |
609 | socket->setSocketDescriptor(socketDescriptor); |
610 | addPendingConnection(socket); |
611 | } |
612 | |
613 | /*! |
614 | This function is called by QTcpServer::incomingConnection() |
615 | to add the \a socket to the list of pending incoming connections. |
616 | |
617 | \note Don't forget to call this member from reimplemented |
618 | incomingConnection() if you do not want to break the |
619 | Pending Connections mechanism. |
620 | |
621 | \sa incomingConnection() |
622 | \since 4.7 |
623 | */ |
624 | void QTcpServer::addPendingConnection(QTcpSocket* socket) |
625 | { |
626 | d_func()->pendingConnections.append(t: socket); |
627 | } |
628 | |
629 | /*! |
630 | Sets the maximum number of pending accepted connections to \a |
631 | numConnections. QTcpServer will accept no more than \a |
632 | numConnections incoming connections before |
633 | nextPendingConnection() is called. By default, the limit is 30 |
634 | pending connections. |
635 | |
636 | Clients may still able to connect after the server has reached |
637 | its maximum number of pending connections (i.e., QTcpSocket can |
638 | still emit the connected() signal). QTcpServer will stop |
639 | accepting the new connections, but the operating system may |
640 | still keep them in queue. |
641 | |
642 | \sa maxPendingConnections(), hasPendingConnections() |
643 | */ |
644 | void QTcpServer::setMaxPendingConnections(int numConnections) |
645 | { |
646 | d_func()->maxConnections = numConnections; |
647 | } |
648 | |
649 | /*! |
650 | Returns the maximum number of pending accepted connections. The |
651 | default is 30. |
652 | |
653 | \sa setMaxPendingConnections(), hasPendingConnections() |
654 | */ |
655 | int QTcpServer::maxPendingConnections() const |
656 | { |
657 | return d_func()->maxConnections; |
658 | } |
659 | |
660 | /*! |
661 | Returns an error code for the last error that occurred. |
662 | |
663 | \sa errorString() |
664 | */ |
665 | QAbstractSocket::SocketError QTcpServer::serverError() const |
666 | { |
667 | return d_func()->serverSocketError; |
668 | } |
669 | |
670 | /*! |
671 | Returns a human readable description of the last error that |
672 | occurred. |
673 | |
674 | \sa serverError() |
675 | */ |
676 | QString QTcpServer::errorString() const |
677 | { |
678 | return d_func()->serverSocketErrorString; |
679 | } |
680 | |
681 | /*! |
682 | \since 5.0 |
683 | |
684 | Pauses accepting new connections. Queued connections will remain in queue. |
685 | |
686 | \sa resumeAccepting() |
687 | */ |
688 | void QTcpServer::pauseAccepting() |
689 | { |
690 | d_func()->socketEngine->setReadNotificationEnabled(false); |
691 | } |
692 | |
693 | /*! |
694 | \since 5.0 |
695 | |
696 | Resumes accepting new connections. |
697 | |
698 | \sa pauseAccepting() |
699 | */ |
700 | void QTcpServer::resumeAccepting() |
701 | { |
702 | d_func()->socketEngine->setReadNotificationEnabled(true); |
703 | } |
704 | |
705 | #ifndef QT_NO_NETWORKPROXY |
706 | /*! |
707 | \since 4.1 |
708 | |
709 | Sets the explicit network proxy for this socket to \a networkProxy. |
710 | |
711 | To disable the use of a proxy for this socket, use the |
712 | QNetworkProxy::NoProxy proxy type: |
713 | |
714 | \snippet code/src_network_socket_qtcpserver.cpp 0 |
715 | |
716 | \sa proxy(), QNetworkProxy |
717 | */ |
718 | void QTcpServer::setProxy(const QNetworkProxy &networkProxy) |
719 | { |
720 | Q_D(QTcpServer); |
721 | d->proxy = networkProxy; |
722 | } |
723 | |
724 | /*! |
725 | \since 4.1 |
726 | |
727 | Returns the network proxy for this socket. |
728 | By default QNetworkProxy::DefaultProxy is used. |
729 | |
730 | \sa setProxy(), QNetworkProxy |
731 | */ |
732 | QNetworkProxy QTcpServer::proxy() const |
733 | { |
734 | Q_D(const QTcpServer); |
735 | return d->proxy; |
736 | } |
737 | #endif // QT_NO_NETWORKPROXY |
738 | |
739 | QT_END_NAMESPACE |
740 | |
741 | #include "moc_qtcpserver.cpp" |
742 | |
743 | |