If accept fails, stop accepting new connections and emit error signal.
[profile/ivi/qtbase.git] / tests / auto / network / socket / qtcpserver / tst_qtcpserver.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the test suite 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 #include <qglobal.h>
43 // To prevent windows system header files from re-defining min/max
44 #define NOMINMAX
45 #if defined(_WIN32)
46 #include <winsock2.h>
47 #else
48 #include <sys/types.h>
49 #include <sys/socket.h>
50 #define SOCKET int
51 #define INVALID_SOCKET -1
52 #endif
53
54 #include <QtTest/QtTest>
55
56 #ifndef Q_OS_WIN
57 #include <unistd.h>
58 #include <sys/ioctl.h>
59 #endif
60
61 #include <qcoreapplication.h>
62 #include <qtcpsocket.h>
63 #include <qtcpserver.h>
64 #include <qhostaddress.h>
65 #include <qprocess.h>
66 #include <qstringlist.h>
67 #include <qplatformdefs.h>
68 #include <qhostinfo.h>
69
70 #include <QNetworkProxy>
71
72 #include <QNetworkSession>
73 #include <QNetworkConfiguration>
74 #include <QNetworkConfigurationManager>
75 #include "../../../network-settings.h"
76
77 class tst_QTcpServer : public QObject
78 {
79     Q_OBJECT
80
81 public:
82     tst_QTcpServer();
83     virtual ~tst_QTcpServer();
84
85
86 public slots:
87     void initTestCase_data();
88     void initTestCase();
89     void init();
90     void cleanup();
91 private slots:
92     void getSetCheck();
93     void constructing();
94     void clientServerLoop();
95     void ipv6Server();
96     void dualStack_data();
97     void dualStack();
98     void ipv6ServerMapped();
99     void crashTests();
100     void maxPendingConnections();
101     void listenError();
102     void waitForConnectionTest();
103     void setSocketDescriptor();
104     void listenWhileListening();
105 #ifndef QT_NO_PROCESS
106     void addressReusable();
107 #endif
108     void setNewSocketDescriptorBlocking();
109     void invalidProxy_data();
110     void invalidProxy();
111     void proxyFactory_data();
112     void proxyFactory();
113
114     void qtbug14268_peek();
115
116     void serverAddress_data();
117     void serverAddress();
118
119     void qtbug6305_data() { serverAddress_data(); }
120     void qtbug6305();
121
122     void linkLocal();
123
124     void eagainBlockingAccept();
125
126 private:
127 #ifndef QT_NO_BEARERMANAGEMENT
128     QNetworkSession *networkSession;
129 #endif
130     QString crashingServerDir;
131 };
132
133 // Testing get/set functions
134 void tst_QTcpServer::getSetCheck()
135 {
136     QTcpServer obj1;
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());
145 }
146
147 tst_QTcpServer::tst_QTcpServer()
148 {
149 }
150
151 tst_QTcpServer::~tst_QTcpServer()
152 {
153 }
154
155 void tst_QTcpServer::initTestCase_data()
156 {
157     QTest::addColumn<bool>("setProxy");
158     QTest::addColumn<int>("proxyType");
159
160     QTest::newRow("WithoutProxy") << false << 0;
161     QTest::newRow("WithSocks5Proxy") << true << int(QNetworkProxy::Socks5Proxy);
162
163     crashingServerDir = QFINDTESTDATA("crashingServer");
164     QVERIFY2(!crashingServerDir.isEmpty(), qPrintable(
165         QString::fromLatin1("Couldn't find crashingServer dir starting from %1.").arg(QDir::currentPath())));
166 }
167
168 void tst_QTcpServer::initTestCase()
169 {
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());
176 #endif
177 }
178
179 void tst_QTcpServer::init()
180 {
181     QFETCH_GLOBAL(bool, setProxy);
182     if (setProxy) {
183         QFETCH_GLOBAL(int, proxyType);
184         if (proxyType == QNetworkProxy::Socks5Proxy) {
185             QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
186         }
187     }
188 }
189
190 void tst_QTcpServer::cleanup()
191 {
192     QNetworkProxy::setApplicationProxy(QNetworkProxy::DefaultProxy);
193 }
194
195 //----------------------------------------------------------------------------------
196
197 void tst_QTcpServer::constructing()
198 {
199     QTcpServer socket;
200
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);
209
210     // Check the state of the socket layer?
211 }
212
213 //----------------------------------------------------------------------------------
214 void tst_QTcpServer::clientServerLoop()
215 {
216     QTcpServer server;
217
218     QSignalSpy spy(&server, SIGNAL(newConnection()));
219
220     QVERIFY(!server.isListening());
221     QVERIFY(!server.hasPendingConnections());
222     QVERIFY(server.listen(QHostAddress::Any, 11423));
223     QVERIFY(server.isListening());
224
225     QTcpSocket client;
226
227     QHostAddress serverAddress = QHostAddress::LocalHost;
228     if (!(server.serverAddress() == QHostAddress::Any) && !(server.serverAddress() == QHostAddress::AnyIPv6) && !(server.serverAddress() == QHostAddress::AnyIPv4))
229         serverAddress = server.serverAddress();
230
231     client.connectToHost(serverAddress, server.serverPort());
232     QVERIFY(client.waitForConnected(5000));
233
234     QVERIFY(server.waitForNewConnection(5000));
235     QVERIFY(server.hasPendingConnections());
236
237     QCOMPARE(spy.count(), 1);
238
239     QTcpSocket *serverSocket = server.nextPendingConnection();
240     QVERIFY(serverSocket != 0);
241
242     QVERIFY(serverSocket->write("Greetings, client!\n", 19) == 19);
243     serverSocket->flush();
244
245     QVERIFY(client.waitForReadyRead(5000));
246     QByteArray arr = client.readAll();
247     QCOMPARE(arr.constData(), "Greetings, client!\n");
248
249     QVERIFY(client.write("Well, hello to you!\n", 20) == 20);
250     client.flush();
251
252     QVERIFY(serverSocket->waitForReadyRead(5000));
253     arr = serverSocket->readAll();
254     QCOMPARE(arr.constData(), "Well, hello to you!\n");
255 }
256
257 //----------------------------------------------------------------------------------
258 void tst_QTcpServer::ipv6Server()
259 {
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)
263     QTcpServer server;
264     if (!server.listen(QHostAddress::LocalHostIPv6, 8944)) {
265         QVERIFY(server.serverError() == QAbstractSocket::UnsupportedSocketOperationError);
266         return;
267     }
268
269     QVERIFY(server.serverPort() == 8944);
270     QVERIFY(server.serverAddress() == QHostAddress::LocalHostIPv6);
271
272     QTcpSocket client;
273     client.connectToHost("::1", 8944);
274     QVERIFY(client.waitForConnected(5000));
275
276     QVERIFY(server.waitForNewConnection());
277     QVERIFY(server.hasPendingConnections());
278
279     QTcpSocket *serverSocket = 0;
280     QVERIFY((serverSocket = server.nextPendingConnection()));
281     serverSocket->close();
282     delete serverSocket;
283 }
284
285 Q_DECLARE_METATYPE(QHostAddress);
286
287 void tst_QTcpServer::dualStack_data()
288 {
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;
295 }
296
297 void tst_QTcpServer::dualStack()
298 {
299     QFETCH_GLOBAL(bool, setProxy);
300     if (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);
305     QFETCH(bool, v4ok);
306     QFETCH(bool, v6ok);
307
308     QTcpServer server;
309     QVERIFY(server.listen(bindAddress));
310
311     QTcpSocket v4client;
312     v4client.connectToHost(QHostAddress::LocalHost, server.serverPort());
313
314     QTcpSocket v6client;
315     v6client.connectToHost(QHostAddress::LocalHostIPv6, server.serverPort());
316
317     QCOMPARE(v4client.waitForConnected(5000), v4ok);
318     QCOMPARE(v6client.waitForConnected(5000), v6ok);
319 }
320
321 //----------------------------------------------------------------------------------
322 void tst_QTcpServer::ipv6ServerMapped()
323 {
324     QFETCH_GLOBAL(bool, setProxy);
325     if (setProxy)
326         return;
327
328     QTcpServer server;
329     QVERIFY(server.listen(QHostAddress::LocalHost));
330
331     // let's try the normal case
332     QTcpSocket client1;
333     client1.connectToHost("127.0.0.1", server.serverPort());
334     QVERIFY(server.waitForNewConnection(5000));
335     delete server.nextPendingConnection();
336
337     if (!QtNetworkSettings::hasIPv6())
338         QSKIP("system doesn't support ipv6!");
339
340     // let's try the mapped one in the nice format
341     QTcpSocket client2;
342     client2.connectToHost("::ffff:127.0.0.1", server.serverPort());
343     QVERIFY(server.waitForNewConnection(5000));
344     delete server.nextPendingConnection();
345
346     // let's try the mapped in hex format
347     QTcpSocket client3;
348     client3.connectToHost("::ffff:7F00:0001", server.serverPort());
349     QVERIFY(server.waitForNewConnection(5000));
350     delete server.nextPendingConnection();
351
352     // However connecting to the v6 localhost should not work
353     QTcpSocket client4;
354     client4.connectToHost("::1", server.serverPort());
355     QVERIFY(!server.waitForNewConnection(5000));
356 }
357
358 //----------------------------------------------------------------------------------
359 void tst_QTcpServer::crashTests()
360 {
361     QTcpServer server;
362     server.close();
363     QVERIFY(server.listen());
364 }
365
366 //----------------------------------------------------------------------------------
367 void tst_QTcpServer::maxPendingConnections()
368 {
369     QFETCH_GLOBAL(bool, setProxy);
370     if (setProxy) {
371         QFETCH_GLOBAL(int, proxyType);
372         if (proxyType == QNetworkProxy::Socks5Proxy)
373             QSKIP("With socks5 only 1 connection is allowed ever");
374     }
375     //### sees to fail sometimes ... a timing issue with the test on windows
376     QTcpServer server;
377     server.setMaxPendingConnections(2);
378
379     QTcpSocket socket1;
380     QTcpSocket socket2;
381     QTcpSocket socket3;
382
383     QVERIFY(server.listen());
384
385     socket1.connectToHost(QHostAddress::LocalHost, server.serverPort());
386     socket2.connectToHost(QHostAddress::LocalHost, server.serverPort());
387     socket3.connectToHost(QHostAddress::LocalHost, server.serverPort());
388
389     QVERIFY(server.waitForNewConnection(5000));
390
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);
397
398     QVERIFY(server.waitForNewConnection(5000));
399
400     QVERIFY(server.hasPendingConnections());
401     QVERIFY(server.nextPendingConnection());
402 }
403
404 //----------------------------------------------------------------------------------
405 void tst_QTcpServer::listenError()
406 {
407     QFETCH_GLOBAL(bool, setProxy);
408     if (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");
412     }
413     QTcpServer server;
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");
417 }
418
419 class ThreadConnector : public QThread
420 {
421 public:
422     ThreadConnector(const QHostAddress &host, quint16 port)
423         : host(host), port(port)
424     { }
425
426     ~ThreadConnector()
427     {
428         wait();
429     }
430
431 protected:
432     void run()
433     {
434         sleep(2);
435
436         QTcpSocket socket;
437         socket.connectToHost(host, port);
438
439         QEventLoop loop;
440         QTimer::singleShot(5000, &loop, SLOT(quit()));
441         loop.exec();
442     }
443
444 private:
445     QHostAddress host;
446     quint16 port;
447 };
448
449 //----------------------------------------------------------------------------------
450 void tst_QTcpServer::waitForConnectionTest()
451 {
452
453     QFETCH_GLOBAL(bool, setProxy);
454     if (setProxy) {
455         QFETCH_GLOBAL(int, proxyType);
456         if (proxyType == QNetworkProxy::Socks5Proxy)
457             QSKIP("Localhost servers don't work well with SOCKS5");
458     }
459
460     QTcpSocket findLocalIpSocket;
461     findLocalIpSocket.connectToHost(QtNetworkSettings::serverName(), 143);
462     QVERIFY(findLocalIpSocket.waitForConnected(5000));
463
464     QTcpServer server;
465     bool timeout = false;
466     QVERIFY(server.listen(findLocalIpSocket.localAddress()));
467     QVERIFY(!server.waitForNewConnection(1000, &timeout));
468     QCOMPARE(server.serverError(), QAbstractSocket::SocketTimeoutError);
469     QVERIFY(timeout);
470
471     ThreadConnector connector(findLocalIpSocket.localAddress(), server.serverPort());
472     connector.start();
473
474 #if defined(Q_OS_WINCE)
475     QVERIFY(server.waitForNewConnection(9000, &timeout));
476 #else
477     QVERIFY(server.waitForNewConnection(3000, &timeout));
478 #endif
479     QVERIFY(!timeout);
480 }
481
482 //----------------------------------------------------------------------------------
483 void tst_QTcpServer::setSocketDescriptor()
484 {
485     QTcpServer server;
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
489 #ifdef Q_OS_WIN
490     // ensure winsock is started
491     WSADATA wsaData;
492     QVERIFY(WSAStartup(MAKEWORD(2,0), &wsaData) == NO_ERROR);
493 #endif
494
495     SOCKET sock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
496
497     QVERIFY(sock != INVALID_SOCKET);
498
499     sockaddr_in sin;
500     memset(&sin, 0, sizeof(sockaddr_in));
501     sin.sin_family = AF_INET;
502     sin.sin_port = 0;
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));
507
508 #ifdef Q_OS_WIN
509     WSACleanup();
510 #endif
511 }
512
513 //----------------------------------------------------------------------------------
514 void tst_QTcpServer::listenWhileListening()
515 {
516     QTcpServer server;
517     QVERIFY(server.listen());
518     QTest::ignoreMessage(QtWarningMsg, "QTcpServer::listen() called when already listening");
519     QVERIFY(!server.listen());
520 }
521
522 //----------------------------------------------------------------------------------
523
524 class SeverWithBlockingSockets : public QTcpServer
525 {
526 public:
527     SeverWithBlockingSockets()
528         : ok(false) { }
529
530     bool ok;
531
532 protected:
533     void incomingConnection(qintptr socketDescriptor)
534     {
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);
540 #else
541         ok = ::ioctl(socketDescriptor, FIONBIO, &arg) == 0;
542         ::close(socketDescriptor);
543 #endif
544     }
545 };
546
547 #ifndef QT_NO_PROCESS
548 void tst_QTcpServer::addressReusable()
549 {
550     QFETCH_GLOBAL(bool, setProxy);
551     if (setProxy) {
552         QFETCH_GLOBAL(int, proxyType);
553         if (proxyType == QNetworkProxy::Socks5Proxy)
554             QSKIP("With socks5 this test does not make senans at the momment");
555     }
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.
560     QProcess process;
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())));
565     int waitCount = 5;
566     while (waitCount-- && !QFile::exists(signalName))
567         QTest::qWait(1000);
568     QVERIFY(QFile::exists(signalName));
569     QFile::remove(signalName);
570 #else
571     // The crashingServer process will crash once it gets a connection.
572     QProcess process;
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));
578 #endif
579
580     QTcpSocket socket;
581     socket.connectToHost(QHostAddress::LocalHost, 49199);
582     QVERIFY(socket.waitForConnected(5000));
583
584     QVERIFY(process.waitForFinished(30000));
585
586     // Give the system some time.
587     QTest::qSleep(10);
588
589     QTcpServer server;
590     QVERIFY(server.listen(QHostAddress::LocalHost, 49199));
591 }
592 #endif
593
594 void tst_QTcpServer::setNewSocketDescriptorBlocking()
595 {
596     QFETCH_GLOBAL(bool, setProxy);
597     if (setProxy) {
598         QFETCH_GLOBAL(int, proxyType);
599         if (proxyType == QNetworkProxy::Socks5Proxy)
600             QSKIP("With socks5 we can not make the socket descripter blocking");
601     }
602     SeverWithBlockingSockets server;
603     QVERIFY(server.listen());
604
605     QTcpSocket socket;
606     socket.connectToHost(QHostAddress::LocalHost, server.serverPort());
607     QVERIFY(server.waitForNewConnection(5000));
608     QVERIFY(server.ok);
609 }
610
611 void tst_QTcpServer::invalidProxy_data()
612 {
613     QTest::addColumn<int>("type");
614     QTest::addColumn<QString>("host");
615     QTest::addColumn<int>("port");
616     QTest::addColumn<int>("expectedError");
617
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);
623
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);
629 }
630
631 void tst_QTcpServer::invalidProxy()
632 {
633     QFETCH_GLOBAL(bool, setProxy);
634     if (setProxy)
635         return;
636
637     QFETCH(int, type);
638     QFETCH(QString, host);
639     QFETCH(int, port);
640     QNetworkProxy::ProxyType proxyType = QNetworkProxy::ProxyType(type);
641     QNetworkProxy proxy(proxyType, host, port);
642
643     QTcpServer server;
644     server.setProxy(proxy);
645     bool listenResult = server.listen();
646
647     QVERIFY(!listenResult);
648     QVERIFY(!server.errorString().isEmpty());
649
650     // note: the following test is not a hard failure.
651     // Sometimes, error codes change for the better
652     QTEST(int(server.serverError()), "expectedError");
653 }
654
655 // copied from tst_qnetworkreply.cpp
656 class MyProxyFactory: public QNetworkProxyFactory
657 {
658 public:
659     int callCount;
660     QList<QNetworkProxy> toReturn;
661     QNetworkProxyQuery lastQuery;
662     inline MyProxyFactory() { clear(); }
663
664     inline void clear()
665     {
666         callCount = 0;
667         toReturn = QList<QNetworkProxy>() << QNetworkProxy::DefaultProxy;
668         lastQuery = QNetworkProxyQuery();
669     }
670
671     virtual QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query)
672     {
673         lastQuery = query;
674         ++callCount;
675         return toReturn;
676     }
677 };
678
679 void tst_QTcpServer::proxyFactory_data()
680 {
681     QTest::addColumn<QList<QNetworkProxy> >("proxyList");
682     QTest::addColumn<QNetworkProxy>("proxyUsed");
683     QTest::addColumn<bool>("fails");
684     QTest::addColumn<int>("expectedError");
685
686     QList<QNetworkProxy> proxyList;
687
688     // tests that do get to listen
689
690     proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
691     QTest::newRow("socks5")
692         << proxyList << proxyList.at(0)
693         << false << int(QAbstractSocket::UnknownSocketError);
694
695     proxyList.clear();
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);
701
702     proxyList.clear();
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);
709
710     // tests that fail to listen
711     proxyList.clear();
712     proxyList << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128);
713     QTest::newRow("http")
714         << proxyList << proxyList.at(0)
715         << true << int(QAbstractSocket::UnsupportedSocketOperationError);
716
717     proxyList.clear();
718     proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128);
719     QTest::newRow("cachinghttp")
720         << proxyList << QNetworkProxy()
721         << true << int(QAbstractSocket::UnsupportedSocketOperationError);
722
723     proxyList.clear();
724     proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121);
725     QTest::newRow("ftp")
726         << proxyList << QNetworkProxy()
727         << true << int(QAbstractSocket::UnsupportedSocketOperationError);
728
729     proxyList.clear();
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);
735 }
736
737 void tst_QTcpServer::proxyFactory()
738 {
739     QFETCH_GLOBAL(bool, setProxy);
740     if (setProxy)
741         return;
742
743     QFETCH(QList<QNetworkProxy>, proxyList);
744     QFETCH(QNetworkProxy, proxyUsed);
745     QFETCH(bool, fails);
746
747     MyProxyFactory *factory = new MyProxyFactory;
748     factory->toReturn = proxyList;
749     QNetworkProxyFactory::setApplicationProxyFactory(factory);
750
751     QTcpServer server;
752     bool listenResult = server.listen();
753
754     // Verify that the factory was called properly
755     QCOMPARE(factory->callCount, 1);
756     QCOMPARE(factory->lastQuery, QNetworkProxyQuery(0, QString(), QNetworkProxyQuery::TcpServer));
757
758     QCOMPARE(listenResult, !fails);
759     QCOMPARE(server.errorString().isEmpty(), !fails);
760
761     // note: the following test is not a hard failure.
762     // Sometimes, error codes change for the better
763     QTEST(int(server.serverError()), "expectedError");
764 }
765
766 class Qtbug14268Helper : public QObject
767 {
768     Q_OBJECT
769 public:
770     QByteArray lastDataPeeked;
771 public slots:
772     void newConnection() {
773         QTcpServer* server=static_cast<QTcpServer*>(sender());
774         QTcpSocket* s=server->nextPendingConnection();
775         connect(s,SIGNAL(readyRead()),this,SLOT(onServerReadyRead()));
776     }
777     void onServerReadyRead() {
778         QTcpSocket* clientSocket=static_cast<QTcpSocket*>(sender());
779         lastDataPeeked = clientSocket->peek(128*1024).toHex();
780         QTestEventLoop::instance().exitLoop();
781     }
782 };
783
784 // there is a similar test inside tst_qtcpsocket that uses the waitFor* functions instead
785 void tst_QTcpServer::qtbug14268_peek()
786 {
787     QFETCH_GLOBAL(bool, setProxy);
788     if (setProxy)
789         return;
790
791     QTcpServer server;
792     server.listen();
793
794     Qtbug14268Helper helper;
795     QObject::connect(&server, SIGNAL(newConnection()), &helper, SLOT(newConnection()));
796
797     QTcpSocket client;
798     client.connectToHost(QHostAddress::LocalHost, server.serverPort());
799     QVERIFY(client.waitForConnected(2000));
800
801     client.write("abc\n");
802     QTestEventLoop::instance().enterLoop(5);
803     QVERIFY(!QTestEventLoop::instance().timeout());
804     QVERIFY(helper.lastDataPeeked == QByteArray("6162630a"));
805
806     client.write("def\n");
807     QTestEventLoop::instance().enterLoop(5);
808     QVERIFY(!QTestEventLoop::instance().timeout());
809     QVERIFY(helper.lastDataPeeked == QByteArray("6162630a6465660a"));
810
811     client.write("ghi\n");
812     QTestEventLoop::instance().enterLoop(5);
813     QVERIFY(!QTestEventLoop::instance().timeout());
814     QVERIFY(helper.lastDataPeeked == QByteArray("6162630a6465660a6768690a"));
815 }
816
817 void tst_QTcpServer::serverAddress_data()
818 {
819     QTest::addColumn<QHostAddress>("listenAddress");
820     QTest::addColumn<QHostAddress>("serverAddress");
821 #ifdef Q_OS_WIN
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
824     else
825 #endif
826     if (QtNetworkSettings::hasIPv6())
827         QTest::newRow("Any") << QHostAddress(QHostAddress::Any) << QHostAddress(QHostAddress::Any);
828     else
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;
838     }
839 }
840
841 void tst_QTcpServer::serverAddress()
842 {
843     QFETCH_GLOBAL(bool, setProxy);
844     if (setProxy)
845         return;
846
847     QFETCH(QHostAddress, listenAddress);
848     QFETCH(QHostAddress, serverAddress);
849     QTcpServer server;
850
851     // TODO: why does this QSKIP?
852     if (!server.listen(listenAddress))
853         QSKIP(qPrintable(server.errorString()));
854     QCOMPARE(server.serverAddress(), serverAddress);
855 }
856
857 // on OS X, calling listen() multiple times would succeed each time, which is
858 // most definitely not wanted.
859 void tst_QTcpServer::qtbug6305()
860 {
861     QFETCH_GLOBAL(bool, setProxy);
862     if (setProxy)
863         return;
864
865     QFETCH(QHostAddress, listenAddress);
866
867     QTcpServer server;
868     QVERIFY2(server.listen(listenAddress), qPrintable(server.errorString()));
869
870     QTcpServer server2;
871     QVERIFY(!server2.listen(listenAddress, server.serverPort())); // second listen should fail
872 }
873
874 void tst_QTcpServer::linkLocal()
875 {
876     QFETCH_GLOBAL(bool, setProxy);
877     if (setProxy)
878         return;
879
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"))
890                 continue;
891             foreach (QNetworkAddressEntry addressEntry, iface.addressEntries()) {
892                 QHostAddress addr = addressEntry.ip();
893                 if (addr.isInSubnet(localMaskv4, 16)) {
894                     addresses << addr;
895                     qDebug() << addr;
896                 }
897                 else if (!addr.scopeId().isEmpty() && addr.isInSubnet(localMaskv6, 64)) {
898                     scopes << addr.scopeId();
899                     addresses << addr;
900                     qDebug() << addr;
901                 }
902             }
903         }
904     }
905     if (addresses.isEmpty())
906         QSKIP("no link local addresses");
907
908     QList<QTcpServer*> servers;
909     quint16 port = 0;
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
914         servers << server;
915     }
916
917     QList<QTcpSocket*> clients;
918     foreach (const QHostAddress& addr, addresses) {
919         //unbound socket
920         QTcpSocket *socket = new QTcpSocket;
921         socket->connectToHost(addr, port);
922         QVERIFY(socket->waitForConnected(5000));
923         clients << socket;
924         //bound socket
925         socket = new QTcpSocket;
926         QVERIFY(socket->bind(addr));
927         socket->connectToHost(addr, port);
928         QVERIFY(socket->waitForConnected(5000));
929         clients << socket;
930     }
931
932     //each server should have two connections
933     foreach (QTcpServer* server, servers) {
934         QTcpSocket* remote;
935         //qDebug() << "checking for connections" << server->serverAddress() << ":" << server->serverPort();
936         QVERIFY(server->waitForNewConnection(5000));
937         QVERIFY(remote = server->nextPendingConnection());
938         remote->close();
939         delete remote;
940         if (!server->hasPendingConnections())
941             QVERIFY(server->waitForNewConnection(5000));
942         QVERIFY(remote = server->nextPendingConnection());
943         remote->close();
944         delete remote;
945         QVERIFY(!server->hasPendingConnections());
946     }
947
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.
953
954     qDeleteAll(clients);
955     qDeleteAll(servers);
956 }
957
958 void tst_QTcpServer::eagainBlockingAccept()
959 {
960     QTcpServer server;
961     server.listen(QHostAddress::LocalHost, 7896);
962
963     // Receiving a new connection causes TemporaryError, but shouldn't pause accepting.
964     QTcpSocket s;
965     s.connectToHost(QHostAddress::LocalHost, 7896);
966     QSignalSpy spy(&server, SIGNAL(newConnection()));
967     QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 1, 500);
968     s.close();
969
970     // To test try again, should connect just fine.
971     s.connectToHost(QHostAddress::LocalHost, 7896);
972     QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 2, 500);
973     s.close();
974     server.close();
975 }
976
977 QTEST_MAIN(tst_QTcpServer)
978 #include "tst_qtcpserver.moc"