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(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(QAbstractSocketEngine::AddressReusable, 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(serverSocketError); |
215 | } |
216 | break; |
217 | } |
218 | #if defined (QTCPSERVER_DEBUG) |
219 | qDebug("QTcpServerPrivate::_q_processIncomingConnection() accepted socket %i" , descriptor); |
220 | #endif |
221 | q->incomingConnection(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("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(addr, port); |
308 | #endif |
309 | |
310 | delete d->socketEngine; |
311 | d->socketEngine = QAbstractSocketEngine::createSocketEngine(d->socketType, proxy, this); |
312 | if (!d->socketEngine) { |
313 | d->serverSocketError = QAbstractSocket::UnsupportedSocketOperationError; |
314 | d->serverSocketErrorString = tr("Operation on socket is not supported" ); |
315 | return false; |
316 | } |
317 | if (!d->socketEngine->initialize(d->socketType, proto)) { |
318 | d->serverSocketError = d->socketEngine->error(); |
319 | d->serverSocketErrorString = d->socketEngine->errorString(); |
320 | return false; |
321 | } |
322 | proto = d->socketEngine->protocol(); |
323 | if (addr.protocol() == QAbstractSocket::AnyIPProtocol && proto == QAbstractSocket::IPv4Protocol) |
324 | addr = QHostAddress::AnyIPv4; |
325 | |
326 | d->configureCreatedSocket(); |
327 | |
328 | if (!d->socketEngine->bind(addr, port)) { |
329 | d->serverSocketError = d->socketEngine->error(); |
330 | d->serverSocketErrorString = d->socketEngine->errorString(); |
331 | return false; |
332 | } |
333 | |
334 | if (!d->socketEngine->listen()) { |
335 | d->serverSocketError = d->socketEngine->error(); |
336 | d->serverSocketErrorString = d->socketEngine->errorString(); |
337 | return false; |
338 | } |
339 | |
340 | d->socketEngine->setReceiver(d); |
341 | d->socketEngine->setReadNotificationEnabled(true); |
342 | |
343 | d->state = QAbstractSocket::ListeningState; |
344 | d->address = d->socketEngine->localAddress(); |
345 | d->port = d->socketEngine->localPort(); |
346 | |
347 | #if defined (QTCPSERVER_DEBUG) |
348 | qDebug("QTcpServer::listen(%i, \"%s\") == true (listening on port %i)" , port, |
349 | address.toString().toLatin1().constData(), d->socketEngine->localPort()); |
350 | #endif |
351 | return true; |
352 | } |
353 | |
354 | /*! |
355 | Returns \c true if the server is currently listening for incoming |
356 | connections; otherwise returns \c false. |
357 | |
358 | \sa listen() |
359 | */ |
360 | bool QTcpServer::isListening() const |
361 | { |
362 | Q_D(const QTcpServer); |
363 | Q_CHECK_SOCKETENGINE(false); |
364 | return d->socketEngine->state() == QAbstractSocket::ListeningState; |
365 | } |
366 | |
367 | /*! |
368 | Closes the server. The server will no longer listen for incoming |
369 | connections. |
370 | |
371 | \sa listen() |
372 | */ |
373 | void QTcpServer::close() |
374 | { |
375 | Q_D(QTcpServer); |
376 | |
377 | qDeleteAll(d->pendingConnections); |
378 | d->pendingConnections.clear(); |
379 | |
380 | if (d->socketEngine) { |
381 | d->socketEngine->close(); |
382 | QT_TRY { |
383 | d->socketEngine->deleteLater(); |
384 | } QT_CATCH(const std::bad_alloc &) { |
385 | // in out of memory situations, the socketEngine |
386 | // will be deleted in ~QTcpServer (it's a child-object of this) |
387 | } |
388 | d->socketEngine = nullptr; |
389 | } |
390 | |
391 | d->state = QAbstractSocket::UnconnectedState; |
392 | } |
393 | |
394 | /*! |
395 | Returns the native socket descriptor the server uses to listen |
396 | for incoming instructions, or -1 if the server is not listening. |
397 | |
398 | If the server is using QNetworkProxy, the returned descriptor may |
399 | not be usable with native socket functions. |
400 | |
401 | \sa setSocketDescriptor(), isListening() |
402 | */ |
403 | qintptr QTcpServer::socketDescriptor() const |
404 | { |
405 | Q_D(const QTcpServer); |
406 | Q_CHECK_SOCKETENGINE(-1); |
407 | return d->socketEngine->socketDescriptor(); |
408 | } |
409 | |
410 | /*! |
411 | Sets the socket descriptor this server should use when listening |
412 | for incoming connections to \a socketDescriptor. Returns \c true if |
413 | the socket is set successfully; otherwise returns \c false. |
414 | |
415 | The socket is assumed to be in listening state. |
416 | |
417 | \sa socketDescriptor(), isListening() |
418 | */ |
419 | bool QTcpServer::setSocketDescriptor(qintptr socketDescriptor) |
420 | { |
421 | Q_D(QTcpServer); |
422 | if (isListening()) { |
423 | qWarning("QTcpServer::setSocketDescriptor() called when already listening" ); |
424 | return false; |
425 | } |
426 | |
427 | if (d->socketEngine) |
428 | delete d->socketEngine; |
429 | d->socketEngine = QAbstractSocketEngine::createSocketEngine(socketDescriptor, this); |
430 | if (!d->socketEngine) { |
431 | d->serverSocketError = QAbstractSocket::UnsupportedSocketOperationError; |
432 | d->serverSocketErrorString = tr("Operation on socket is not supported" ); |
433 | return false; |
434 | } |
435 | if (!d->socketEngine->initialize(socketDescriptor, QAbstractSocket::ListeningState)) { |
436 | d->serverSocketError = d->socketEngine->error(); |
437 | d->serverSocketErrorString = d->socketEngine->errorString(); |
438 | #if defined (QTCPSERVER_DEBUG) |
439 | qDebug("QTcpServer::setSocketDescriptor(%i) failed (%s)" , socketDescriptor, |
440 | d->serverSocketErrorString.toLatin1().constData()); |
441 | #endif |
442 | return false; |
443 | } |
444 | |
445 | d->socketEngine->setReceiver(d); |
446 | d->socketEngine->setReadNotificationEnabled(true); |
447 | |
448 | d->state = d->socketEngine->state(); |
449 | d->address = d->socketEngine->localAddress(); |
450 | d->port = d->socketEngine->localPort(); |
451 | |
452 | #if defined (QTCPSERVER_DEBUG) |
453 | qDebug("QTcpServer::setSocketDescriptor(%i) succeeded." , socketDescriptor); |
454 | #endif |
455 | return true; |
456 | } |
457 | |
458 | /*! |
459 | Returns the server's port if the server is listening for |
460 | connections; otherwise returns 0. |
461 | |
462 | \sa serverAddress(), listen() |
463 | */ |
464 | quint16 QTcpServer::serverPort() const |
465 | { |
466 | Q_D(const QTcpServer); |
467 | Q_CHECK_SOCKETENGINE(0); |
468 | return d->socketEngine->localPort(); |
469 | } |
470 | |
471 | /*! |
472 | Returns the server's address if the server is listening for |
473 | connections; otherwise returns QHostAddress::Null. |
474 | |
475 | \sa serverPort(), listen() |
476 | */ |
477 | QHostAddress QTcpServer::serverAddress() const |
478 | { |
479 | Q_D(const QTcpServer); |
480 | Q_CHECK_SOCKETENGINE(QHostAddress(QHostAddress::Null)); |
481 | return d->socketEngine->localAddress(); |
482 | } |
483 | |
484 | /*! |
485 | Waits for at most \a msec milliseconds or until an incoming |
486 | connection is available. Returns \c true if a connection is |
487 | available; otherwise returns \c false. If the operation timed out |
488 | and \a timedOut is not \nullptr, *\a timedOut will be set to true. |
489 | |
490 | This is a blocking function call. Its use is disadvised in a |
491 | single-threaded GUI application, since the whole application will |
492 | stop responding until the function returns. |
493 | waitForNewConnection() is mostly useful when there is no event |
494 | loop available. |
495 | |
496 | The non-blocking alternative is to connect to the newConnection() |
497 | signal. |
498 | |
499 | If msec is -1, this function will not time out. |
500 | |
501 | \sa hasPendingConnections(), nextPendingConnection() |
502 | */ |
503 | bool QTcpServer::waitForNewConnection(int msec, bool *timedOut) |
504 | { |
505 | Q_D(QTcpServer); |
506 | if (d->state != QAbstractSocket::ListeningState) |
507 | return false; |
508 | |
509 | if (!d->socketEngine->waitForRead(msec, timedOut)) { |
510 | d->serverSocketError = d->socketEngine->error(); |
511 | d->serverSocketErrorString = d->socketEngine->errorString(); |
512 | return false; |
513 | } |
514 | |
515 | if (timedOut && *timedOut) |
516 | return false; |
517 | |
518 | d->readNotification(); |
519 | |
520 | return true; |
521 | } |
522 | |
523 | /*! |
524 | Returns \c true if the server has a pending connection; otherwise |
525 | returns \c false. |
526 | |
527 | \sa nextPendingConnection(), setMaxPendingConnections() |
528 | */ |
529 | bool QTcpServer::hasPendingConnections() const |
530 | { |
531 | return !d_func()->pendingConnections.isEmpty(); |
532 | } |
533 | |
534 | /*! |
535 | Returns the next pending connection as a connected QTcpSocket |
536 | object. |
537 | |
538 | The socket is created as a child of the server, which means that |
539 | it is automatically deleted when the QTcpServer object is |
540 | destroyed. It is still a good idea to delete the object |
541 | explicitly when you are done with it, to avoid wasting memory. |
542 | |
543 | \nullptr is returned if this function is called when there are no pending |
544 | connections. |
545 | |
546 | \note The returned QTcpSocket object cannot be used from another |
547 | thread. If you want to use an incoming connection from another thread, |
548 | you need to override incomingConnection(). |
549 | |
550 | \sa hasPendingConnections() |
551 | */ |
552 | QTcpSocket *QTcpServer::nextPendingConnection() |
553 | { |
554 | Q_D(QTcpServer); |
555 | if (d->pendingConnections.isEmpty()) |
556 | return nullptr; |
557 | |
558 | if (!d->socketEngine) { |
559 | qWarning("QTcpServer::nextPendingConnection() called while not listening" ); |
560 | } else if (!d->socketEngine->isReadNotificationEnabled()) { |
561 | d->socketEngine->setReadNotificationEnabled(true); |
562 | } |
563 | |
564 | return d->pendingConnections.takeFirst(); |
565 | } |
566 | |
567 | /*! |
568 | This virtual function is called by QTcpServer when a new |
569 | connection is available. The \a socketDescriptor argument is the |
570 | native socket descriptor for the accepted connection. |
571 | |
572 | The base implementation creates a QTcpSocket, sets the socket |
573 | descriptor and then stores the QTcpSocket in an internal list of |
574 | pending connections. Finally newConnection() is emitted. |
575 | |
576 | Reimplement this function to alter the server's behavior when a |
577 | connection is available. |
578 | |
579 | If this server is using QNetworkProxy then the \a socketDescriptor |
580 | may not be usable with native socket functions, and should only be |
581 | used with QTcpSocket::setSocketDescriptor(). |
582 | |
583 | \note If another socket is created in the reimplementation |
584 | of this method, it needs to be added to the Pending Connections mechanism |
585 | by calling addPendingConnection(). |
586 | |
587 | \note If you want to handle an incoming connection as a new QTcpSocket |
588 | object in another thread you have to pass the socketDescriptor |
589 | to the other thread and create the QTcpSocket object there and |
590 | use its setSocketDescriptor() method. |
591 | |
592 | \sa newConnection(), nextPendingConnection(), addPendingConnection() |
593 | */ |
594 | void QTcpServer::incomingConnection(qintptr socketDescriptor) |
595 | { |
596 | #if defined (QTCPSERVER_DEBUG) |
597 | qDebug("QTcpServer::incomingConnection(%i)" , socketDescriptor); |
598 | #endif |
599 | |
600 | QTcpSocket *socket = new QTcpSocket(this); |
601 | socket->setSocketDescriptor(socketDescriptor); |
602 | addPendingConnection(socket); |
603 | } |
604 | |
605 | /*! |
606 | This function is called by QTcpServer::incomingConnection() |
607 | to add the \a socket to the list of pending incoming connections. |
608 | |
609 | \note Don't forget to call this member from reimplemented |
610 | incomingConnection() if you do not want to break the |
611 | Pending Connections mechanism. |
612 | |
613 | \sa incomingConnection() |
614 | \since 4.7 |
615 | */ |
616 | void QTcpServer::addPendingConnection(QTcpSocket* socket) |
617 | { |
618 | d_func()->pendingConnections.append(socket); |
619 | } |
620 | |
621 | /*! |
622 | Sets the maximum number of pending accepted connections to \a |
623 | numConnections. QTcpServer will accept no more than \a |
624 | numConnections incoming connections before |
625 | nextPendingConnection() is called. By default, the limit is 30 |
626 | pending connections. |
627 | |
628 | Clients may still able to connect after the server has reached |
629 | its maximum number of pending connections (i.e., QTcpSocket can |
630 | still emit the connected() signal). QTcpServer will stop |
631 | accepting the new connections, but the operating system may |
632 | still keep them in queue. |
633 | |
634 | \sa maxPendingConnections(), hasPendingConnections() |
635 | */ |
636 | void QTcpServer::setMaxPendingConnections(int numConnections) |
637 | { |
638 | d_func()->maxConnections = numConnections; |
639 | } |
640 | |
641 | /*! |
642 | Returns the maximum number of pending accepted connections. The |
643 | default is 30. |
644 | |
645 | \sa setMaxPendingConnections(), hasPendingConnections() |
646 | */ |
647 | int QTcpServer::maxPendingConnections() const |
648 | { |
649 | return d_func()->maxConnections; |
650 | } |
651 | |
652 | /*! |
653 | Returns an error code for the last error that occurred. |
654 | |
655 | \sa errorString() |
656 | */ |
657 | QAbstractSocket::SocketError QTcpServer::serverError() const |
658 | { |
659 | return d_func()->serverSocketError; |
660 | } |
661 | |
662 | /*! |
663 | Returns a human readable description of the last error that |
664 | occurred. |
665 | |
666 | \sa serverError() |
667 | */ |
668 | QString QTcpServer::errorString() const |
669 | { |
670 | return d_func()->serverSocketErrorString; |
671 | } |
672 | |
673 | /*! |
674 | \since 5.0 |
675 | |
676 | Pauses accepting new connections. Queued connections will remain in queue. |
677 | |
678 | \sa resumeAccepting() |
679 | */ |
680 | void QTcpServer::pauseAccepting() |
681 | { |
682 | d_func()->socketEngine->setReadNotificationEnabled(false); |
683 | } |
684 | |
685 | /*! |
686 | \since 5.0 |
687 | |
688 | Resumes accepting new connections. |
689 | |
690 | \sa pauseAccepting() |
691 | */ |
692 | void QTcpServer::resumeAccepting() |
693 | { |
694 | d_func()->socketEngine->setReadNotificationEnabled(true); |
695 | } |
696 | |
697 | #ifndef QT_NO_NETWORKPROXY |
698 | /*! |
699 | \since 4.1 |
700 | |
701 | Sets the explicit network proxy for this socket to \a networkProxy. |
702 | |
703 | To disable the use of a proxy for this socket, use the |
704 | QNetworkProxy::NoProxy proxy type: |
705 | |
706 | \snippet code/src_network_socket_qtcpserver.cpp 0 |
707 | |
708 | \sa proxy(), QNetworkProxy |
709 | */ |
710 | void QTcpServer::setProxy(const QNetworkProxy &networkProxy) |
711 | { |
712 | Q_D(QTcpServer); |
713 | d->proxy = networkProxy; |
714 | } |
715 | |
716 | /*! |
717 | \since 4.1 |
718 | |
719 | Returns the network proxy for this socket. |
720 | By default QNetworkProxy::DefaultProxy is used. |
721 | |
722 | \sa setProxy(), QNetworkProxy |
723 | */ |
724 | QNetworkProxy QTcpServer::proxy() const |
725 | { |
726 | Q_D(const QTcpServer); |
727 | return d->proxy; |
728 | } |
729 | #endif // QT_NO_NETWORKPROXY |
730 | |
731 | QT_END_NAMESPACE |
732 | |
733 | #include "moc_qtcpserver.cpp" |
734 | |
735 | |