Qt 4.8
qtcpserver.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 //#define QTCPSERVER_DEBUG
43 
109 #include "private/qobject_p.h"
110 #include "qalgorithms.h"
111 #include "qhostaddress.h"
112 #include "qlist.h"
113 #include "qpointer.h"
114 #include "qabstractsocketengine_p.h"
115 #include "qtcpserver.h"
116 #include "qtcpsocket.h"
117 #include "qnetworkproxy.h"
118 
120 
121 #define Q_CHECK_SOCKETENGINE(returnValue) do { \
122  if (!d->socketEngine) { \
123  return returnValue; \
124  } } while (0)
125 
127 {
129 public:
132 
134 
137 
140 
143 
145 
146 #ifndef QT_NO_NETWORKPROXY
148  QNetworkProxy resolveProxy(const QHostAddress &address, quint16 port);
149 #endif
150 
151  // from QAbstractSocketEngineReceiver
152  void readNotification();
153  inline void writeNotification() {}
154  inline void exceptionNotification() {}
155  inline void connectionNotification() {}
156 #ifndef QT_NO_NETWORKPROXY
158 #endif
159 
160 };
161 
165  : port(0)
166  , state(QAbstractSocket::UnconnectedState)
167  , socketEngine(0)
168  , serverSocketError(QAbstractSocket::UnknownSocketError)
169  , maxConnections(30)
170 {
171 }
172 
176 {
177 }
178 
179 #ifndef QT_NO_NETWORKPROXY
180 
188 {
189  if (address == QHostAddress::LocalHost ||
190  address == QHostAddress::LocalHostIPv6)
191  return QNetworkProxy::NoProxy;
192 
193  QList<QNetworkProxy> proxies;
195  // a non-default proxy was set with setProxy
196  proxies << proxy;
197  } else {
198  // try the application settings instead
200  proxies = QNetworkProxyFactory::proxyForQuery(query);
201  }
202 
203  // return the first that we can use
204  foreach (const QNetworkProxy &p, proxies) {
206  return p;
207  }
208 
209  // no proxy found
210  // DefaultProxy will raise an error
212 }
213 #endif
214 
218 {
219  Q_Q(QTcpServer);
220  for (;;) {
222 #if defined (QTCPSERVER_DEBUG)
223  qDebug("QTcpServerPrivate::_q_processIncomingConnection() too many connections");
224 #endif
227  return;
228  }
229 
230  int descriptor = socketEngine->accept();
231  if (descriptor == -1)
232  break;
233 #if defined (QTCPSERVER_DEBUG)
234  qDebug("QTcpServerPrivate::_q_processIncomingConnection() accepted socket %i", descriptor);
235 #endif
236  q->incomingConnection(descriptor);
237 
238  QPointer<QTcpServer> that = q;
239  emit q->newConnection();
240  if (!that || !q->isListening())
241  return;
242  }
243 }
244 
253  : QObject(*new QTcpServerPrivate, parent)
254 {
255 }
256 
267 {
268  close();
269 }
270 
281 bool QTcpServer::listen(const QHostAddress &address, quint16 port)
282 {
283  Q_D(QTcpServer);
284  if (d->state == QAbstractSocket::ListeningState) {
285  qWarning("QTcpServer::listen() called when already listening");
286  return false;
287  }
288 
290 
291 #ifdef QT_NO_NETWORKPROXY
292  static const QNetworkProxy &proxy = *(QNetworkProxy *)0;
293 #else
294  QNetworkProxy proxy = d->resolveProxy(address, port);
295 #endif
296 
297  delete d->socketEngine;
299  if (!d->socketEngine) {
301  d->serverSocketErrorString = tr("Operation on socket is not supported");
302  return false;
303  }
304 #ifndef QT_NO_BEARERMANAGEMENT
305  //copy network session down to the socket engine (if it has been set)
306  d->socketEngine->setProperty("_q_networksession", property("_q_networksession"));
307 #endif
308  if (!d->socketEngine->initialize(QAbstractSocket::TcpSocket, proto)) {
309  d->serverSocketError = d->socketEngine->error();
310  d->serverSocketErrorString = d->socketEngine->errorString();
311  return false;
312  }
313 
314 #if defined(Q_OS_UNIX)
315  // Under Unix, we want to be able to bind to the port, even if a socket on
316  // the same address-port is in TIME_WAIT. Under Windows this is possible
317  // anyway -- furthermore, the meaning of reusable on Windows is different:
318  // it means that you can use the same address-port for multiple listening
319  // sockets.
320  // Don't abort though if we can't set that option. For example the socks
321  // engine doesn't support that option, but that shouldn't prevent us from
322  // trying to bind/listen.
323  d->socketEngine->setOption(QAbstractSocketEngine::AddressReusable, 1);
324 #endif
325 
326  if (!d->socketEngine->bind(address, port)) {
327  d->serverSocketError = d->socketEngine->error();
328  d->serverSocketErrorString = d->socketEngine->errorString();
329  return false;
330  }
331 
332  if (!d->socketEngine->listen()) {
333  d->serverSocketError = d->socketEngine->error();
334  d->serverSocketErrorString = d->socketEngine->errorString();
335  return false;
336  }
337 
338  d->socketEngine->setReceiver(d);
339  d->socketEngine->setReadNotificationEnabled(true);
340 
342  d->address = d->socketEngine->localAddress();
343  d->port = d->socketEngine->localPort();
344 
345 #if defined (QTCPSERVER_DEBUG)
346  qDebug("QTcpServer::listen(%i, \"%s\") == true (listening on port %i)", port,
347  address.toString().toLatin1().constData(), d->socketEngine->localPort());
348 #endif
349  return true;
350 }
351 
359 {
360  Q_D(const QTcpServer);
361  Q_CHECK_SOCKETENGINE(false);
362  return d->socketEngine->state() == QAbstractSocket::ListeningState;
363 }
364 
372 {
373  Q_D(QTcpServer);
374 
375  qDeleteAll(d->pendingConnections);
376  d->pendingConnections.clear();
377 
378  if (d->socketEngine) {
379  d->socketEngine->close();
380  QT_TRY {
381  d->socketEngine->deleteLater();
382  } QT_CATCH(const std::bad_alloc &) {
383  // in out of memory situations, the socketEngine
384  // will be deleted in ~QTcpServer (it's a child-object of this)
385  }
386  d->socketEngine = 0;
387  }
388 
390 }
391 
402 {
403  Q_D(const QTcpServer);
405  return d->socketEngine->socketDescriptor();
406 }
407 
418 {
419  Q_D(QTcpServer);
420  if (isListening()) {
421  qWarning("QTcpServer::setSocketDescriptor() called when already listening");
422  return false;
423  }
424 
425  if (d->socketEngine)
426  delete d->socketEngine;
427  d->socketEngine = QAbstractSocketEngine::createSocketEngine(socketDescriptor, this);
428  if (!d->socketEngine) {
430  d->serverSocketErrorString = tr("Operation on socket is not supported");
431  return false;
432  }
433 #ifndef QT_NO_BEARERMANAGEMENT
434  //copy network session down to the socket engine (if it has been set)
435  d->socketEngine->setProperty("_q_networksession", property("_q_networksession"));
436 #endif
437  if (!d->socketEngine->initialize(socketDescriptor, QAbstractSocket::ListeningState)) {
438  d->serverSocketError = d->socketEngine->error();
439  d->serverSocketErrorString = d->socketEngine->errorString();
440 #if defined (QTCPSERVER_DEBUG)
441  qDebug("QTcpServer::setSocketDescriptor(%i) failed (%s)", socketDescriptor,
442  d->serverSocketErrorString.toLatin1().constData());
443 #endif
444  return false;
445  }
446 
447  d->socketEngine->setReceiver(d);
448  d->socketEngine->setReadNotificationEnabled(true);
449 
450  d->state = d->socketEngine->state();
451  d->address = d->socketEngine->localAddress();
452  d->port = d->socketEngine->localPort();
453 
454 #if defined (QTCPSERVER_DEBUG)
455  qDebug("QTcpServer::setSocketDescriptor(%i) succeeded.", socketDescriptor);
456 #endif
457  return true;
458 }
459 
467 {
468  Q_D(const QTcpServer);
470  return d->socketEngine->localPort();
471 }
472 
480 {
481  Q_D(const QTcpServer);
483  return d->socketEngine->localAddress();
484 }
485 
505 bool QTcpServer::waitForNewConnection(int msec, bool *timedOut)
506 {
507  Q_D(QTcpServer);
508  if (d->state != QAbstractSocket::ListeningState)
509  return false;
510 
511  if (!d->socketEngine->waitForRead(msec, timedOut)) {
512  d->serverSocketError = d->socketEngine->error();
513  d->serverSocketErrorString = d->socketEngine->errorString();
514  return false;
515  }
516 
517  if (timedOut && *timedOut)
518  return false;
519 
520  d->readNotification();
521 
522  return true;
523 }
524 
532 {
533  return !d_func()->pendingConnections.isEmpty();
534 }
535 
555 {
556  Q_D(QTcpServer);
557  if (d->pendingConnections.isEmpty())
558  return 0;
559 
560  if (!d->socketEngine->isReadNotificationEnabled())
561  d->socketEngine->setReadNotificationEnabled(true);
562 
563  return d->pendingConnections.takeFirst();
564 }
565 
590 {
591 #if defined (QTCPSERVER_DEBUG)
592  qDebug("QTcpServer::incomingConnection(%i)", socketDescriptor);
593 #endif
594 
595  QTcpSocket *socket = new QTcpSocket(this);
596  socket->setSocketDescriptor(socketDescriptor);
597  addPendingConnection(socket);
598 }
599 
612 {
613  d_func()->pendingConnections.append(socket);
614 }
615 
631 void QTcpServer::setMaxPendingConnections(int numConnections)
632 {
633  d_func()->maxConnections = numConnections;
634 }
635 
643 {
644  return d_func()->maxConnections;
645 }
646 
653 {
654  return d_func()->serverSocketError;
655 }
656 
664 {
665  return d_func()->serverSocketErrorString;
666 }
667 
668 #ifndef QT_NO_NETWORKPROXY
669 
684 void QTcpServer::setProxy(const QNetworkProxy &networkProxy)
685 {
686  Q_D(QTcpServer);
687  d->proxy = networkProxy;
688 }
689 
702 {
703  Q_D(const QTcpServer);
704  return d->proxy;
705 }
706 #endif // QT_NO_NETWORKPROXY
707 
709 
710 #include "moc_qtcpserver.cpp"
711 
QNetworkProxy::ProxyType type() const
Returns the proxy type for this instance.
virtual bool isReadNotificationEnabled() const =0
double d
Definition: qnumeric_p.h:62
QString serverSocketErrorString
Definition: qtcpserver.cpp:142
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
void writeNotification()
Definition: qtcpserver.cpp:153
void setMaxPendingConnections(int numConnections)
Sets the maximum number of pending accepted connections to numConnections.
Definition: qtcpserver.cpp:631
static QAbstractSocketEngine * createSocketEngine(QAbstractSocket::SocketType socketType, const QNetworkProxy &, QObject *parent)
bool listen(const QHostAddress &address=QHostAddress::Any, quint16 port=0)
Tells the server to listen for incoming connections on address address and port port.
Definition: qtcpserver.cpp:281
static QString tr(const char *sourceText, const char *comment=0, int n=-1)
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
NetworkLayerProtocol
This enum describes the network layer protocol values used in Qt.
QString errorString() const
Returns a human readable description of the last error that occurred.
Definition: qtcpserver.cpp:663
The QString class provides a Unicode character string.
Definition: qstring.h:83
virtual int accept()=0
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
#define Q_D(Class)
Definition: qglobal.h:2482
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...
bool isListening() const
Returns true if the server is currently listening for incoming connections; otherwise returns false...
Definition: qtcpserver.cpp:358
The QPointer class is a template class that provides guarded pointers to QObject. ...
Definition: qpointer.h:54
QAbstractSocketEngine * socketEngine
Definition: qtcpserver.cpp:139
virtual void incomingConnection(int handle)
This virtual function is called by QTcpServer when a new connection is available. ...
Definition: qtcpserver.cpp:589
#define Q_Q(Class)
Definition: qglobal.h:2483
SocketState
This enum describes the different states in which a socket can be.
Q_CORE_EXPORT void qDebug(const char *,...)
The QNetworkProxy class provides a network layer proxy.
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
virtual bool hasPendingConnections() const
Returns true if the server has a pending connection; otherwise returns false.
Definition: qtcpserver.cpp:531
QAbstractSocket::SocketError serverSocketError
Definition: qtcpserver.cpp:141
Capabilities capabilities() const
Returns the capabilities of this proxy server.
void connectionNotification()
Definition: qtcpserver.cpp:155
virtual QTcpSocket * nextPendingConnection()
Returns the next pending connection as a connected QTcpSocket object.
Definition: qtcpserver.cpp:554
#define emit
Definition: qobjectdefs.h:76
bool setSocketDescriptor(int socketDescriptor, SocketState state=ConnectedState, OpenMode openMode=ReadWrite)
Initializes QAbstractSocket with the native socket descriptor socketDescriptor.
SocketError
This enum describes the socket errors that can occur.
unsigned short quint16
Definition: qglobal.h:936
Q_CORE_EXPORT void qWarning(const char *,...)
int maxPendingConnections() const
Returns the maximum number of pending accepted connections.
Definition: qtcpserver.cpp:642
int socketDescriptor() const
Returns the native socket descriptor the server uses to listen for incoming instructions, or -1 if the server is not listening.
Definition: qtcpserver.cpp:401
#define Q_CHECK_SOCKETENGINE(returnValue)
Definition: qtcpserver.cpp:121
The QTcpSocket class provides a TCP socket.
Definition: qtcpsocket.h:56
QString toString() const
Returns the address as a string.
bool waitForNewConnection(int msec=0, bool *timedOut=0)
Waits for at most msec milliseconds or until an incoming connection is available. ...
Definition: qtcpserver.cpp:505
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
#define QT_CATCH(A)
Definition: qglobal.h:1537
The QAuthenticator class provides an authentication object.
The QNetworkProxyQuery class is used to query the proxy settings for a socket.
Definition: qnetworkproxy.h:60
void addPendingConnection(QTcpSocket *socket)
This function is called by QTcpServer::incomingConnection() to add the socket to the list of pending ...
Definition: qtcpserver.cpp:611
void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)
Definition: qtcpserver.cpp:157
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
#define Q_DECLARE_PUBLIC(Class)
Definition: qglobal.h:2477
QNetworkProxy proxy
Definition: qtcpserver.cpp:147
QAbstractSocket::NetworkLayerProtocol protocol() const
Returns the network layer protocol of the host address.
virtual ~QTcpServer()
Destroys the QTcpServer object.
Definition: qtcpserver.cpp:266
QHostAddress address
Definition: qtcpserver.cpp:136
QAbstractSocket::SocketError serverError() const
Returns an error code for the last error that occurred.
Definition: qtcpserver.cpp:652
bool setSocketDescriptor(int socketDescriptor)
Sets the socket descriptor this server should use when listening for incoming connections to socketDe...
Definition: qtcpserver.cpp:417
void setProxy(const QNetworkProxy &networkProxy)
Sets the explicit network proxy for this socket to networkProxy.
Definition: qtcpserver.cpp:684
The QTcpServer class provides a TCP-based server.
Definition: qtcpserver.h:61
QAbstractSocket::SocketState state
Definition: qtcpserver.cpp:138
QTcpServer(QObject *parent=0)
Constructs a QTcpServer object.
Definition: qtcpserver.cpp:252
quint16 serverPort() const
Returns the server&#39;s port if the server is listening for connections; otherwise returns 0...
Definition: qtcpserver.cpp:466
QNetworkProxy proxy() const
Returns the network proxy for this socket.
Definition: qtcpserver.cpp:701
QVariant property(const char *name) const
Returns the value of the object&#39;s name property.
Definition: qobject.cpp:3807
QObject * parent
Definition: qobject.h:92
QHostAddress serverAddress() const
Returns the server&#39;s address if the server is listening for connections; otherwise returns QHostAddre...
Definition: qtcpserver.cpp:479
void close()
Closes the server.
Definition: qtcpserver.cpp:371
The QHostAddress class provides an IP address.
Definition: qhostaddress.h:70
virtual void setReadNotificationEnabled(bool enable)=0
QNetworkProxy resolveProxy(const QHostAddress &address, quint16 port)
Resolve the proxy to its final value.
Definition: qtcpserver.cpp:187
The QAbstractSocket class provides the base functionality common to all socket types.
QList< QTcpSocket * > pendingConnections
Definition: qtcpserver.cpp:133
Q_OUTOFLINE_TEMPLATE void qDeleteAll(ForwardIterator begin, ForwardIterator end)
Definition: qalgorithms.h:319
#define QT_TRY
Definition: qglobal.h:1536
void exceptionNotification()
Definition: qtcpserver.cpp:154
The QList class is a template class that provides lists.
Definition: qdatastream.h:62