1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the test suite of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
43 // To prevent windows system header files from re-defining min/max
48 #include <sys/types.h>
49 #include <sys/socket.h>
51 #define INVALID_SOCKET -1
54 #include <QtTest/QtTest>
58 #include <sys/ioctl.h>
61 #include <qcoreapplication.h>
62 #include <qtcpsocket.h>
63 #include <qtcpserver.h>
64 #include <qhostaddress.h>
66 #include <qstringlist.h>
67 #include <qplatformdefs.h>
68 #include <qhostinfo.h>
70 #include <QNetworkProxy>
72 #include <QNetworkSession>
73 #include <QNetworkConfiguration>
74 #include <QNetworkConfigurationManager>
75 #include "../../../network-settings.h"
77 class tst_QTcpServer : public QObject
83 virtual ~tst_QTcpServer();
87 void initTestCase_data();
94 void clientServerLoop();
96 void dualStack_data();
98 void ipv6ServerMapped();
100 void maxPendingConnections();
102 void waitForConnectionTest();
103 void setSocketDescriptor();
104 void listenWhileListening();
105 #ifndef QT_NO_PROCESS
106 void addressReusable();
108 void setNewSocketDescriptorBlocking();
109 void invalidProxy_data();
111 void proxyFactory_data();
114 void qtbug14268_peek();
116 void serverAddress_data();
117 void serverAddress();
119 void qtbug6305_data() { serverAddress_data(); }
124 void eagainBlockingAccept();
127 #ifndef QT_NO_BEARERMANAGEMENT
128 QNetworkSession *networkSession;
130 QString crashingServerDir;
133 // Testing get/set functions
134 void tst_QTcpServer::getSetCheck()
137 // int QTcpServer::maxPendingConnections()
138 // void QTcpServer::setMaxPendingConnections(int)
139 obj1.setMaxPendingConnections(0);
140 QCOMPARE(0, obj1.maxPendingConnections());
141 obj1.setMaxPendingConnections(INT_MIN);
142 QCOMPARE(INT_MIN, obj1.maxPendingConnections());
143 obj1.setMaxPendingConnections(INT_MAX);
144 QCOMPARE(INT_MAX, obj1.maxPendingConnections());
147 tst_QTcpServer::tst_QTcpServer()
151 tst_QTcpServer::~tst_QTcpServer()
155 void tst_QTcpServer::initTestCase_data()
157 QTest::addColumn<bool>("setProxy");
158 QTest::addColumn<int>("proxyType");
160 QTest::newRow("WithoutProxy") << false << 0;
161 QTest::newRow("WithSocks5Proxy") << true << int(QNetworkProxy::Socks5Proxy);
163 crashingServerDir = QFINDTESTDATA("crashingServer");
164 QVERIFY2(!crashingServerDir.isEmpty(), qPrintable(
165 QString::fromLatin1("Couldn't find crashingServer dir starting from %1.").arg(QDir::currentPath())));
168 void tst_QTcpServer::initTestCase()
170 QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
171 #ifndef QT_NO_BEARERMANAGEMENT
172 QNetworkConfigurationManager man;
173 networkSession = new QNetworkSession(man.defaultConfiguration(), this);
174 networkSession->open();
175 QVERIFY(networkSession->waitForOpened());
179 void tst_QTcpServer::init()
181 QFETCH_GLOBAL(bool, setProxy);
183 QFETCH_GLOBAL(int, proxyType);
184 if (proxyType == QNetworkProxy::Socks5Proxy) {
185 QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
190 void tst_QTcpServer::cleanup()
192 QNetworkProxy::setApplicationProxy(QNetworkProxy::DefaultProxy);
195 //----------------------------------------------------------------------------------
197 void tst_QTcpServer::constructing()
201 // Check the initial state of the QTcpSocket.
202 QCOMPARE(socket.isListening(), false);
203 QCOMPARE((int)socket.serverPort(), 0);
204 QCOMPARE(socket.serverAddress(), QHostAddress());
205 QCOMPARE(socket.maxPendingConnections(), 30);
206 QCOMPARE(socket.hasPendingConnections(), false);
207 QCOMPARE(socket.socketDescriptor(), (qintptr)-1);
208 QCOMPARE(socket.serverError(), QAbstractSocket::UnknownSocketError);
210 // Check the state of the socket layer?
213 //----------------------------------------------------------------------------------
214 void tst_QTcpServer::clientServerLoop()
218 QSignalSpy spy(&server, SIGNAL(newConnection()));
220 QVERIFY(!server.isListening());
221 QVERIFY(!server.hasPendingConnections());
222 QVERIFY(server.listen(QHostAddress::Any, 11423));
223 QVERIFY(server.isListening());
227 QHostAddress serverAddress = QHostAddress::LocalHost;
228 if (!(server.serverAddress() == QHostAddress::Any) && !(server.serverAddress() == QHostAddress::AnyIPv6) && !(server.serverAddress() == QHostAddress::AnyIPv4))
229 serverAddress = server.serverAddress();
231 client.connectToHost(serverAddress, server.serverPort());
232 QVERIFY(client.waitForConnected(5000));
234 QVERIFY(server.waitForNewConnection(5000));
235 QVERIFY(server.hasPendingConnections());
237 QCOMPARE(spy.count(), 1);
239 QTcpSocket *serverSocket = server.nextPendingConnection();
240 QVERIFY(serverSocket != 0);
242 QVERIFY(serverSocket->write("Greetings, client!\n", 19) == 19);
243 serverSocket->flush();
245 QVERIFY(client.waitForReadyRead(5000));
246 QByteArray arr = client.readAll();
247 QCOMPARE(arr.constData(), "Greetings, client!\n");
249 QVERIFY(client.write("Well, hello to you!\n", 20) == 20);
252 QVERIFY(serverSocket->waitForReadyRead(5000));
253 arr = serverSocket->readAll();
254 QCOMPARE(arr.constData(), "Well, hello to you!\n");
257 //----------------------------------------------------------------------------------
258 void tst_QTcpServer::ipv6Server()
260 if (!QtNetworkSettings::hasIPv6())
261 QSKIP("system doesn't support ipv6!");
262 //### need to enter the event loop for the server to get the connection ?? ( windows)
264 if (!server.listen(QHostAddress::LocalHostIPv6, 8944)) {
265 QVERIFY(server.serverError() == QAbstractSocket::UnsupportedSocketOperationError);
269 QVERIFY(server.serverPort() == 8944);
270 QVERIFY(server.serverAddress() == QHostAddress::LocalHostIPv6);
273 client.connectToHost("::1", 8944);
274 QVERIFY(client.waitForConnected(5000));
276 QVERIFY(server.waitForNewConnection());
277 QVERIFY(server.hasPendingConnections());
279 QTcpSocket *serverSocket = 0;
280 QVERIFY((serverSocket = server.nextPendingConnection()));
281 serverSocket->close();
285 Q_DECLARE_METATYPE(QHostAddress);
287 void tst_QTcpServer::dualStack_data()
289 QTest::addColumn<QHostAddress>("bindAddress");
290 QTest::addColumn<bool>("v4ok");
291 QTest::addColumn<bool>("v6ok");
292 QTest::newRow("any") << QHostAddress(QHostAddress::Any) << true << true;
293 QTest::newRow("anyIPv4") << QHostAddress(QHostAddress::AnyIPv4) << true << false;
294 QTest::newRow("anyIPv6") << QHostAddress(QHostAddress::AnyIPv6) << false << true;
297 void tst_QTcpServer::dualStack()
299 QFETCH_GLOBAL(bool, setProxy);
301 QSKIP("test server proxy doesn't support ipv6");
302 if (!QtNetworkSettings::hasIPv6())
303 QSKIP("system doesn't support ipv6!");
304 QFETCH(QHostAddress, bindAddress);
309 QVERIFY(server.listen(bindAddress));
312 v4client.connectToHost(QHostAddress::LocalHost, server.serverPort());
315 v6client.connectToHost(QHostAddress::LocalHostIPv6, server.serverPort());
317 QCOMPARE(v4client.waitForConnected(5000), v4ok);
318 QCOMPARE(v6client.waitForConnected(5000), v6ok);
321 //----------------------------------------------------------------------------------
322 void tst_QTcpServer::ipv6ServerMapped()
324 QFETCH_GLOBAL(bool, setProxy);
329 QVERIFY(server.listen(QHostAddress::LocalHost));
331 // let's try the normal case
333 client1.connectToHost("127.0.0.1", server.serverPort());
334 QVERIFY(server.waitForNewConnection(5000));
335 delete server.nextPendingConnection();
337 if (!QtNetworkSettings::hasIPv6())
338 QSKIP("system doesn't support ipv6!");
340 // let's try the mapped one in the nice format
342 client2.connectToHost("::ffff:127.0.0.1", server.serverPort());
343 QVERIFY(server.waitForNewConnection(5000));
344 delete server.nextPendingConnection();
346 // let's try the mapped in hex format
348 client3.connectToHost("::ffff:7F00:0001", server.serverPort());
349 QVERIFY(server.waitForNewConnection(5000));
350 delete server.nextPendingConnection();
352 // However connecting to the v6 localhost should not work
354 client4.connectToHost("::1", server.serverPort());
355 QVERIFY(!server.waitForNewConnection(5000));
358 //----------------------------------------------------------------------------------
359 void tst_QTcpServer::crashTests()
363 QVERIFY(server.listen());
366 //----------------------------------------------------------------------------------
367 void tst_QTcpServer::maxPendingConnections()
369 QFETCH_GLOBAL(bool, setProxy);
371 QFETCH_GLOBAL(int, proxyType);
372 if (proxyType == QNetworkProxy::Socks5Proxy)
373 QSKIP("With socks5 only 1 connection is allowed ever");
375 //### sees to fail sometimes ... a timing issue with the test on windows
377 server.setMaxPendingConnections(2);
383 QVERIFY(server.listen());
385 socket1.connectToHost(QHostAddress::LocalHost, server.serverPort());
386 socket2.connectToHost(QHostAddress::LocalHost, server.serverPort());
387 socket3.connectToHost(QHostAddress::LocalHost, server.serverPort());
389 QVERIFY(server.waitForNewConnection(5000));
391 QVERIFY(server.hasPendingConnections());
392 QVERIFY(server.nextPendingConnection());
393 QVERIFY(server.hasPendingConnections());
394 QVERIFY(server.nextPendingConnection());
395 QVERIFY(!server.hasPendingConnections());
396 QCOMPARE(server.nextPendingConnection(), (QTcpSocket*)0);
398 QVERIFY(server.waitForNewConnection(5000));
400 QVERIFY(server.hasPendingConnections());
401 QVERIFY(server.nextPendingConnection());
404 //----------------------------------------------------------------------------------
405 void tst_QTcpServer::listenError()
407 QFETCH_GLOBAL(bool, setProxy);
409 QFETCH_GLOBAL(int, proxyType);
410 if (proxyType == QNetworkProxy::Socks5Proxy)
411 QSKIP("With socks5 we can not make hard requirements on the address or port");
414 QVERIFY(!server.listen(QHostAddress("1.2.3.4"), 0));
415 QCOMPARE(server.serverError(), QAbstractSocket::SocketAddressNotAvailableError);
416 QCOMPARE(server.errorString().toLatin1().constData(), "The address is not available");
419 class ThreadConnector : public QThread
422 ThreadConnector(const QHostAddress &host, quint16 port)
423 : host(host), port(port)
437 socket.connectToHost(host, port);
440 QTimer::singleShot(5000, &loop, SLOT(quit()));
449 //----------------------------------------------------------------------------------
450 void tst_QTcpServer::waitForConnectionTest()
453 QFETCH_GLOBAL(bool, setProxy);
455 QFETCH_GLOBAL(int, proxyType);
456 if (proxyType == QNetworkProxy::Socks5Proxy)
457 QSKIP("Localhost servers don't work well with SOCKS5");
460 QTcpSocket findLocalIpSocket;
461 findLocalIpSocket.connectToHost(QtNetworkSettings::serverName(), 143);
462 QVERIFY(findLocalIpSocket.waitForConnected(5000));
465 bool timeout = false;
466 QVERIFY(server.listen(findLocalIpSocket.localAddress()));
467 QVERIFY(!server.waitForNewConnection(1000, &timeout));
468 QCOMPARE(server.serverError(), QAbstractSocket::SocketTimeoutError);
471 ThreadConnector connector(findLocalIpSocket.localAddress(), server.serverPort());
474 #if defined(Q_OS_WINCE)
475 QVERIFY(server.waitForNewConnection(9000, &timeout));
477 QVERIFY(server.waitForNewConnection(3000, &timeout));
482 //----------------------------------------------------------------------------------
483 void tst_QTcpServer::setSocketDescriptor()
486 QVERIFY(!server.setSocketDescriptor(42));
487 QCOMPARE(server.serverError(), QAbstractSocket::UnsupportedSocketOperationError);
488 //adopting Open C sockets is not supported, neither is adopting externally created RSocket
490 // ensure winsock is started
492 QVERIFY(WSAStartup(MAKEWORD(2,0), &wsaData) == NO_ERROR);
495 SOCKET sock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
497 QVERIFY(sock != INVALID_SOCKET);
500 memset(&sin, 0, sizeof(sockaddr_in));
501 sin.sin_family = AF_INET;
503 sin.sin_addr.s_addr = 0x00000000;
504 QVERIFY(::bind(sock, (sockaddr*)&sin, sizeof(sockaddr_in)) == 0);
505 QVERIFY(::listen(sock, 10) == 0);
506 QVERIFY(server.setSocketDescriptor(sock));
513 //----------------------------------------------------------------------------------
514 void tst_QTcpServer::listenWhileListening()
517 QVERIFY(server.listen());
518 QTest::ignoreMessage(QtWarningMsg, "QTcpServer::listen() called when already listening");
519 QVERIFY(!server.listen());
522 //----------------------------------------------------------------------------------
524 class SeverWithBlockingSockets : public QTcpServer
527 SeverWithBlockingSockets()
533 void incomingConnection(qintptr socketDescriptor)
535 // how a user woulddo it (qabstractsocketengine is not public)
536 unsigned long arg = 0;
537 #if defined(Q_OS_WIN)
538 ok = ::ioctlsocket(socketDescriptor, FIONBIO, &arg) == 0;
539 ::closesocket(socketDescriptor);
541 ok = ::ioctl(socketDescriptor, FIONBIO, &arg) == 0;
542 ::close(socketDescriptor);
547 #ifndef QT_NO_PROCESS
548 void tst_QTcpServer::addressReusable()
550 QFETCH_GLOBAL(bool, setProxy);
552 QFETCH_GLOBAL(int, proxyType);
553 if (proxyType == QNetworkProxy::Socks5Proxy)
554 QSKIP("With socks5 this test does not make senans at the momment");
556 #if defined(Q_OS_WINCE)
557 QString signalName = QString::fromLatin1("/test_signal.txt");
558 QFile::remove(signalName);
559 // The crashingServer process will crash once it gets a connection.
561 QString processExe = crashingServerDir + "/crashingServer";
562 process.start(processExe);
563 QVERIFY2(process.waitForStarted(), qPrintable(
564 QString::fromLatin1("Could not start %1: %2").arg(processExe, process.errorString())));
566 while (waitCount-- && !QFile::exists(signalName))
568 QVERIFY(QFile::exists(signalName));
569 QFile::remove(signalName);
571 // The crashingServer process will crash once it gets a connection.
573 QString processExe = crashingServerDir + "/crashingServer";
574 process.start(processExe);
575 QVERIFY2(process.waitForStarted(), qPrintable(
576 QString::fromLatin1("Could not start %1: %2").arg(processExe, process.errorString())));
577 QVERIFY(process.waitForReadyRead(5000));
581 socket.connectToHost(QHostAddress::LocalHost, 49199);
582 QVERIFY(socket.waitForConnected(5000));
584 QVERIFY(process.waitForFinished(30000));
586 // Give the system some time.
590 QVERIFY(server.listen(QHostAddress::LocalHost, 49199));
594 void tst_QTcpServer::setNewSocketDescriptorBlocking()
596 QFETCH_GLOBAL(bool, setProxy);
598 QFETCH_GLOBAL(int, proxyType);
599 if (proxyType == QNetworkProxy::Socks5Proxy)
600 QSKIP("With socks5 we can not make the socket descripter blocking");
602 SeverWithBlockingSockets server;
603 QVERIFY(server.listen());
606 socket.connectToHost(QHostAddress::LocalHost, server.serverPort());
607 QVERIFY(server.waitForNewConnection(5000));
611 void tst_QTcpServer::invalidProxy_data()
613 QTest::addColumn<int>("type");
614 QTest::addColumn<QString>("host");
615 QTest::addColumn<int>("port");
616 QTest::addColumn<int>("expectedError");
618 QString fluke = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
619 QTest::newRow("ftp-proxy") << int(QNetworkProxy::FtpCachingProxy) << fluke << 143
620 << int(QAbstractSocket::UnsupportedSocketOperationError);
621 QTest::newRow("http-proxy") << int(QNetworkProxy::HttpProxy) << fluke << 3128
622 << int(QAbstractSocket::UnsupportedSocketOperationError);
624 QTest::newRow("no-such-host") << int(QNetworkProxy::Socks5Proxy)
625 << "this-host-will-never-exist.troll.no" << 1080
626 << int(QAbstractSocket::ProxyNotFoundError);
627 QTest::newRow("socks5-on-http") << int(QNetworkProxy::Socks5Proxy) << fluke << 3128
628 << int(QAbstractSocket::SocketTimeoutError);
631 void tst_QTcpServer::invalidProxy()
633 QFETCH_GLOBAL(bool, setProxy);
638 QFETCH(QString, host);
640 QNetworkProxy::ProxyType proxyType = QNetworkProxy::ProxyType(type);
641 QNetworkProxy proxy(proxyType, host, port);
644 server.setProxy(proxy);
645 bool listenResult = server.listen();
647 QVERIFY(!listenResult);
648 QVERIFY(!server.errorString().isEmpty());
650 // note: the following test is not a hard failure.
651 // Sometimes, error codes change for the better
652 QTEST(int(server.serverError()), "expectedError");
655 // copied from tst_qnetworkreply.cpp
656 class MyProxyFactory: public QNetworkProxyFactory
660 QList<QNetworkProxy> toReturn;
661 QNetworkProxyQuery lastQuery;
662 inline MyProxyFactory() { clear(); }
667 toReturn = QList<QNetworkProxy>() << QNetworkProxy::DefaultProxy;
668 lastQuery = QNetworkProxyQuery();
671 virtual QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query)
679 void tst_QTcpServer::proxyFactory_data()
681 QTest::addColumn<QList<QNetworkProxy> >("proxyList");
682 QTest::addColumn<QNetworkProxy>("proxyUsed");
683 QTest::addColumn<bool>("fails");
684 QTest::addColumn<int>("expectedError");
686 QList<QNetworkProxy> proxyList;
688 // tests that do get to listen
690 proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
691 QTest::newRow("socks5")
692 << proxyList << proxyList.at(0)
693 << false << int(QAbstractSocket::UnknownSocketError);
696 proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128)
697 << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
698 QTest::newRow("cachinghttp+socks5")
699 << proxyList << proxyList.at(1)
700 << false << int(QAbstractSocket::UnknownSocketError);
703 proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
704 << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128)
705 << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
706 QTest::newRow("ftp+cachinghttp+socks5")
707 << proxyList << proxyList.at(2)
708 << false << int(QAbstractSocket::UnknownSocketError);
710 // tests that fail to listen
712 proxyList << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128);
713 QTest::newRow("http")
714 << proxyList << proxyList.at(0)
715 << true << int(QAbstractSocket::UnsupportedSocketOperationError);
718 proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128);
719 QTest::newRow("cachinghttp")
720 << proxyList << QNetworkProxy()
721 << true << int(QAbstractSocket::UnsupportedSocketOperationError);
724 proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121);
726 << proxyList << QNetworkProxy()
727 << true << int(QAbstractSocket::UnsupportedSocketOperationError);
730 proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
731 << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128);
732 QTest::newRow("ftp+cachinghttp")
733 << proxyList << QNetworkProxy()
734 << true << int(QAbstractSocket::UnsupportedSocketOperationError);
737 void tst_QTcpServer::proxyFactory()
739 QFETCH_GLOBAL(bool, setProxy);
743 QFETCH(QList<QNetworkProxy>, proxyList);
744 QFETCH(QNetworkProxy, proxyUsed);
747 MyProxyFactory *factory = new MyProxyFactory;
748 factory->toReturn = proxyList;
749 QNetworkProxyFactory::setApplicationProxyFactory(factory);
752 bool listenResult = server.listen();
754 // Verify that the factory was called properly
755 QCOMPARE(factory->callCount, 1);
756 QCOMPARE(factory->lastQuery, QNetworkProxyQuery(0, QString(), QNetworkProxyQuery::TcpServer));
758 QCOMPARE(listenResult, !fails);
759 QCOMPARE(server.errorString().isEmpty(), !fails);
761 // note: the following test is not a hard failure.
762 // Sometimes, error codes change for the better
763 QTEST(int(server.serverError()), "expectedError");
766 class Qtbug14268Helper : public QObject
770 QByteArray lastDataPeeked;
772 void newConnection() {
773 QTcpServer* server=static_cast<QTcpServer*>(sender());
774 QTcpSocket* s=server->nextPendingConnection();
775 connect(s,SIGNAL(readyRead()),this,SLOT(onServerReadyRead()));
777 void onServerReadyRead() {
778 QTcpSocket* clientSocket=static_cast<QTcpSocket*>(sender());
779 lastDataPeeked = clientSocket->peek(128*1024).toHex();
780 QTestEventLoop::instance().exitLoop();
784 // there is a similar test inside tst_qtcpsocket that uses the waitFor* functions instead
785 void tst_QTcpServer::qtbug14268_peek()
787 QFETCH_GLOBAL(bool, setProxy);
794 Qtbug14268Helper helper;
795 QObject::connect(&server, SIGNAL(newConnection()), &helper, SLOT(newConnection()));
798 client.connectToHost(QHostAddress::LocalHost, server.serverPort());
799 QVERIFY(client.waitForConnected(2000));
801 client.write("abc\n");
802 QTestEventLoop::instance().enterLoop(5);
803 QVERIFY(!QTestEventLoop::instance().timeout());
804 QVERIFY(helper.lastDataPeeked == QByteArray("6162630a"));
806 client.write("def\n");
807 QTestEventLoop::instance().enterLoop(5);
808 QVERIFY(!QTestEventLoop::instance().timeout());
809 QVERIFY(helper.lastDataPeeked == QByteArray("6162630a6465660a"));
811 client.write("ghi\n");
812 QTestEventLoop::instance().enterLoop(5);
813 QVERIFY(!QTestEventLoop::instance().timeout());
814 QVERIFY(helper.lastDataPeeked == QByteArray("6162630a6465660a6768690a"));
817 void tst_QTcpServer::serverAddress_data()
819 QTest::addColumn<QHostAddress>("listenAddress");
820 QTest::addColumn<QHostAddress>("serverAddress");
822 if (QSysInfo::windowsVersion() < QSysInfo::WV_6_0)
823 QTest::newRow("Any") << QHostAddress(QHostAddress::Any) << QHostAddress(QHostAddress::AnyIPv4); //windows XP doesn't support dual stack sockets
826 if (QtNetworkSettings::hasIPv6())
827 QTest::newRow("Any") << QHostAddress(QHostAddress::Any) << QHostAddress(QHostAddress::Any);
829 QTest::newRow("Any") << QHostAddress(QHostAddress::Any) << QHostAddress(QHostAddress::AnyIPv4);
830 QTest::newRow("AnyIPv4") << QHostAddress(QHostAddress::AnyIPv4) << QHostAddress(QHostAddress::AnyIPv4);
831 if (QtNetworkSettings::hasIPv6())
832 QTest::newRow("AnyIPv6") << QHostAddress(QHostAddress::AnyIPv6) << QHostAddress(QHostAddress::AnyIPv6);
833 foreach (const QHostAddress& addr, QNetworkInterface::allAddresses()) {
834 if (addr.isInSubnet(QHostAddress::parseSubnet("fe80::/10"))
835 || addr.isInSubnet(QHostAddress::parseSubnet("169.254/16")))
836 continue; //cannot bind on link local addresses
837 QTest::newRow(qPrintable(addr.toString())) << addr << addr;
841 void tst_QTcpServer::serverAddress()
843 QFETCH_GLOBAL(bool, setProxy);
847 QFETCH(QHostAddress, listenAddress);
848 QFETCH(QHostAddress, serverAddress);
851 // TODO: why does this QSKIP?
852 if (!server.listen(listenAddress))
853 QSKIP(qPrintable(server.errorString()));
854 QCOMPARE(server.serverAddress(), serverAddress);
857 // on OS X, calling listen() multiple times would succeed each time, which is
858 // most definitely not wanted.
859 void tst_QTcpServer::qtbug6305()
861 QFETCH_GLOBAL(bool, setProxy);
865 QFETCH(QHostAddress, listenAddress);
868 QVERIFY2(server.listen(listenAddress), qPrintable(server.errorString()));
871 QVERIFY(!server2.listen(listenAddress, server.serverPort())); // second listen should fail
874 void tst_QTcpServer::linkLocal()
876 QFETCH_GLOBAL(bool, setProxy);
880 QList <QHostAddress> addresses;
881 QSet <QString> scopes;
882 QHostAddress localMaskv4("169.254.0.0");
883 QHostAddress localMaskv6("fe80::");
884 foreach (const QNetworkInterface& iface, QNetworkInterface::allInterfaces()) {
885 //Windows preallocates link local addresses to interfaces that are down.
886 //These may or may not work depending on network driver (they do not work for the Bluetooth PAN driver)
887 if (iface.flags() & QNetworkInterface::IsUp) {
888 // Do not connect to the Teredo Tunneling interface on Windows Xp.
889 if (iface.humanReadableName() == QString("Teredo Tunneling Pseudo-Interface"))
891 foreach (QNetworkAddressEntry addressEntry, iface.addressEntries()) {
892 QHostAddress addr = addressEntry.ip();
893 if (addr.isInSubnet(localMaskv4, 16)) {
897 else if (!addr.scopeId().isEmpty() && addr.isInSubnet(localMaskv6, 64)) {
898 scopes << addr.scopeId();
905 if (addresses.isEmpty())
906 QSKIP("no link local addresses");
908 QList<QTcpServer*> servers;
910 foreach (const QHostAddress& addr, addresses) {
911 QTcpServer *server = new QTcpServer;
912 QVERIFY(server->listen(addr, port));
913 port = server->serverPort(); //listen to same port on different interfaces
917 QList<QTcpSocket*> clients;
918 foreach (const QHostAddress& addr, addresses) {
920 QTcpSocket *socket = new QTcpSocket;
921 socket->connectToHost(addr, port);
922 QVERIFY(socket->waitForConnected(5000));
925 socket = new QTcpSocket;
926 QVERIFY(socket->bind(addr));
927 socket->connectToHost(addr, port);
928 QVERIFY(socket->waitForConnected(5000));
932 //each server should have two connections
933 foreach (QTcpServer* server, servers) {
935 //qDebug() << "checking for connections" << server->serverAddress() << ":" << server->serverPort();
936 QVERIFY(server->waitForNewConnection(5000));
937 QVERIFY(remote = server->nextPendingConnection());
940 if (!server->hasPendingConnections())
941 QVERIFY(server->waitForNewConnection(5000));
942 QVERIFY(remote = server->nextPendingConnection());
945 QVERIFY(!server->hasPendingConnections());
948 //Connecting to the same address with different scope should normally fail
949 //However it will pass if there are two interfaces connected to the same physical network,
950 //e.g. connected via wired and wireless interfaces, or two wired NICs.
951 //which is a reasonably common case.
952 //So this is not auto tested.
958 void tst_QTcpServer::eagainBlockingAccept()
961 server.listen(QHostAddress::LocalHost, 7896);
963 // Receiving a new connection causes TemporaryError, but shouldn't pause accepting.
965 s.connectToHost(QHostAddress::LocalHost, 7896);
966 QSignalSpy spy(&server, SIGNAL(newConnection()));
967 QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 1, 500);
970 // To test try again, should connect just fine.
971 s.connectToHost(QHostAddress::LocalHost, 7896);
972 QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 2, 500);
977 QTEST_MAIN(tst_QTcpServer)
978 #include "tst_qtcpserver.moc"