tests/auto/qsocks5socketengine/tst_qsocks5socketengine.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 
       
    43 #include <QtTest/QtTest>
       
    44 
       
    45 #include <qcoreapplication.h>
       
    46 
       
    47 #include <private/qsocks5socketengine_p.h>
       
    48 #include <qhostinfo.h>
       
    49 #include <qhostaddress.h>
       
    50 #include <qtcpsocket.h>
       
    51 #include <qhttp.h>
       
    52 #include <qauthenticator.h>
       
    53 #include <qdebug.h>
       
    54 #include <qtcpserver.h>
       
    55 #include <qmetatype.h>
       
    56 #include <qdebug.h>
       
    57 
       
    58 #include "../network-settings.h"
       
    59 
       
    60 Q_DECLARE_METATYPE(QQueue<QByteArray>)
       
    61 
       
    62 class tst_QSocks5SocketEngine : public QObject, public QAbstractSocketEngineReceiver
       
    63 {
       
    64     Q_OBJECT
       
    65 
       
    66 public:
       
    67     tst_QSocks5SocketEngine();
       
    68     virtual ~tst_QSocks5SocketEngine();
       
    69 
       
    70 
       
    71 public slots:
       
    72     void init();
       
    73     void cleanup();
       
    74 private slots:
       
    75     void construction();
       
    76     void errorTest_data();
       
    77     void errorTest();
       
    78     void simpleConnectToIMAP();
       
    79     void simpleErrorsAndStates();
       
    80     void udpTest();
       
    81     void serverTest();
       
    82     void tcpSocketBlockingTest();
       
    83     void tcpSocketNonBlockingTest();
       
    84     void downloadBigFile();
       
    85    // void tcpLoopbackPerformance();
       
    86     void passwordAuth();
       
    87     void passwordAuth2();
       
    88 
       
    89 protected slots:
       
    90     void tcpSocketNonBlocking_hostFound();
       
    91     void tcpSocketNonBlocking_connected();
       
    92     void tcpSocketNonBlocking_closed();
       
    93     void tcpSocketNonBlocking_readyRead();
       
    94     void tcpSocketNonBlocking_bytesWritten(qint64);
       
    95     void exitLoopSlot();
       
    96     void downloadBigFileSlot();
       
    97     void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth);
       
    98 
       
    99 private:
       
   100     void readNotification() { }
       
   101     void writeNotification() { }
       
   102     void exceptionNotification() { }
       
   103     void connectionNotification() { }
       
   104     QTcpSocket *tcpSocketNonBlocking_socket;
       
   105     QStringList tcpSocketNonBlocking_data;
       
   106     qint64 tcpSocketNonBlocking_totalWritten;
       
   107     QTcpSocket *tmpSocket;
       
   108     qint64 bytesAvailable;
       
   109 };
       
   110 
       
   111 class MiniSocks5Server: public QTcpServer
       
   112 {
       
   113     Q_OBJECT
       
   114 public:
       
   115     QQueue<QByteArray> responses;
       
   116 
       
   117     MiniSocks5Server(const QQueue<QByteArray> r)
       
   118         : responses(r)
       
   119     {
       
   120         listen();
       
   121         connect(this, SIGNAL(newConnection()), SLOT(handleNewConnection()));
       
   122     }
       
   123 
       
   124 private slots:
       
   125     void handleNewConnection()
       
   126     {
       
   127         QTcpSocket *client = nextPendingConnection();
       
   128         connect(client, SIGNAL(readyRead()), SLOT(handleClientCommand()));
       
   129         client->setProperty("pendingResponses", qVariantFromValue(responses));
       
   130     }
       
   131 
       
   132     void handleClientCommand()
       
   133     {
       
   134         // WARNING
       
   135         // this assumes that the client command is received in its entirety
       
   136         // should be ok, since SOCKSv5 commands are rather small
       
   137         QTcpSocket *client = static_cast<QTcpSocket *>(sender());
       
   138         QQueue<QByteArray> pendingResponses =
       
   139             qvariant_cast<QQueue<QByteArray> >(client->property("pendingResponses"));
       
   140         if (pendingResponses.isEmpty())
       
   141             client->disconnectFromHost();
       
   142         else
       
   143             client->write(pendingResponses.dequeue());
       
   144         client->setProperty("pendingResponses", qVariantFromValue(pendingResponses));
       
   145     }
       
   146 };
       
   147 
       
   148 tst_QSocks5SocketEngine::tst_QSocks5SocketEngine()
       
   149 {
       
   150     Q_SET_DEFAULT_IAP
       
   151 }
       
   152 
       
   153 tst_QSocks5SocketEngine::~tst_QSocks5SocketEngine()
       
   154 {
       
   155 }
       
   156 
       
   157 void tst_QSocks5SocketEngine::init()
       
   158 {
       
   159     tmpSocket = 0;
       
   160     bytesAvailable = 0;
       
   161 }
       
   162 
       
   163 void tst_QSocks5SocketEngine::cleanup()
       
   164 {
       
   165 }
       
   166 
       
   167 //---------------------------------------------------------------------------
       
   168 void tst_QSocks5SocketEngine::construction()
       
   169 {
       
   170     QSocks5SocketEngine socketDevice;
       
   171 
       
   172     QVERIFY(!socketDevice.isValid());
       
   173 
       
   174     // Initialize device
       
   175     QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
       
   176     QVERIFY(socketDevice.isValid());
       
   177     QVERIFY(socketDevice.protocol() == QAbstractSocket::IPv4Protocol);
       
   178     QVERIFY(socketDevice.socketType() == QAbstractSocket::TcpSocket);
       
   179     QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState);
       
   180    // QVERIFY(socketDevice.socketDescriptor() != -1);
       
   181     QVERIFY(socketDevice.localAddress() == QHostAddress());
       
   182     QVERIFY(socketDevice.localPort() == 0);
       
   183     QVERIFY(socketDevice.peerAddress() == QHostAddress());
       
   184     QVERIFY(socketDevice.peerPort() == 0);
       
   185     QVERIFY(socketDevice.error() == QAbstractSocket::UnknownSocketError);
       
   186 
       
   187     //QTest::ignoreMessage(QtWarningMsg, "QSocketLayer::bytesAvailable() was called in QAbstractSocket::UnconnectedState");
       
   188     QVERIFY(socketDevice.bytesAvailable() == 0);
       
   189 
       
   190     //QTest::ignoreMessage(QtWarningMsg, "QSocketLayer::hasPendingDatagrams() was called in QAbstractSocket::UnconnectedState");
       
   191     QVERIFY(!socketDevice.hasPendingDatagrams());
       
   192 }
       
   193 
       
   194 //---------------------------------------------------------------------------
       
   195 void tst_QSocks5SocketEngine::errorTest_data()
       
   196 {
       
   197     QTest::addColumn<QString>("hostname");
       
   198     QTest::addColumn<int>("port");
       
   199     QTest::addColumn<QString>("username");
       
   200     QTest::addColumn<QQueue<QByteArray> >("responses");
       
   201     QTest::addColumn<int>("expectedError");
       
   202 
       
   203     QQueue<QByteArray> responses;
       
   204     QTest::newRow("proxy-host-not-found") << "this-host-does-not-exist." << 1080 << QString()
       
   205                                           << responses
       
   206                                           << int(QAbstractSocket::ProxyNotFoundError);
       
   207     QTest::newRow("proxy-connection-refused") << "127.0.0.1" << 2 << QString()
       
   208                                               << responses
       
   209                                               << int(QAbstractSocket::ProxyConnectionRefusedError);
       
   210 
       
   211 #define REPLY(name, contents)                                           \
       
   212     static const char raw_ ## name [] = contents;                       \
       
   213     const QByteArray name = QByteArray::fromRawData(raw_ ## name, sizeof raw_ ## name - 1)
       
   214 
       
   215     REPLY(garbage, "\4\4\4\4");
       
   216     // authentication method replies
       
   217     REPLY(noAuthentication, "\5\0");
       
   218     REPLY(passwordAuthentication, "\5\2");
       
   219     REPLY(garbageAuthentication, "\5\177");
       
   220     REPLY(noAcceptableAuthentication, "\5\377");
       
   221     // authentication replies
       
   222     REPLY(authenticationAccepted, "\5\0");
       
   223     REPLY(authenticationNotAccepted, "\5\1");
       
   224     // connection replies
       
   225     REPLY(connectionAccepted, "\5\0\0\4\177\0\0\1\0\100");
       
   226     REPLY(connectionNotAllowed, "\5\2\0");
       
   227     REPLY(networkUnreachable, "\5\3\0");
       
   228     REPLY(hostUnreachable, "\5\4\0");
       
   229     REPLY(connectionRefused, "\5\5\0");
       
   230 
       
   231 #undef REPLY
       
   232 
       
   233     responses << garbage;
       
   234     QTest::newRow("garbage1") << QString() << 0 << QString() << responses
       
   235                               << int(QAbstractSocket::ProxyProtocolError);
       
   236 
       
   237     responses.clear();
       
   238     responses << noAuthentication << garbage;
       
   239     QTest::newRow("garbage2") << QString() << 0 << QString() << responses
       
   240                               << int(QAbstractSocket::ProxyProtocolError);
       
   241 
       
   242     responses.clear();
       
   243     responses << garbageAuthentication;
       
   244     QTest::newRow("unknown-auth-method") << QString() << 0 << QString()
       
   245                                          << responses
       
   246                                          << int(QAbstractSocket::SocketAccessError);
       
   247 
       
   248     responses.clear();
       
   249     responses << noAcceptableAuthentication;
       
   250     QTest::newRow("no-acceptable-authentication") << QString() << 0 << QString()
       
   251                                                   << responses
       
   252                                                   << int(QAbstractSocket::ProxyAuthenticationRequiredError);
       
   253 
       
   254     responses.clear();
       
   255     responses << passwordAuthentication << authenticationNotAccepted;
       
   256     QTest::newRow("authentication-required") << QString() << 0 << "foo"
       
   257                                              << responses
       
   258                                              << int(QAbstractSocket::ProxyAuthenticationRequiredError);
       
   259 
       
   260     responses.clear();
       
   261     responses << noAuthentication << connectionNotAllowed;
       
   262     QTest::newRow("connection-not-allowed") << QString() << 0 << QString()
       
   263                                             << responses
       
   264                                             << int(QAbstractSocket::SocketAccessError);
       
   265 
       
   266     responses.clear();
       
   267     responses << noAuthentication << networkUnreachable;
       
   268     QTest::newRow("network-unreachable") << QString() << 0 << QString()
       
   269                                          << responses
       
   270                                          << int(QAbstractSocket::NetworkError);
       
   271 
       
   272     responses.clear();
       
   273     responses << noAuthentication << hostUnreachable;
       
   274     QTest::newRow("host-unreachable") << QString() << 0 << QString()
       
   275                                       << responses
       
   276                                       << int(QAbstractSocket::HostNotFoundError);
       
   277 
       
   278     responses.clear();
       
   279     responses << noAuthentication << connectionRefused;
       
   280     QTest::newRow("connection-refused") << QString() << 0 << QString()
       
   281                                         << responses
       
   282                                         << int(QAbstractSocket::ConnectionRefusedError);
       
   283 }
       
   284 
       
   285 void tst_QSocks5SocketEngine::errorTest()
       
   286 {
       
   287     QFETCH(QString, hostname);
       
   288     QFETCH(int, port);
       
   289     QFETCH(QString, username);
       
   290     QFETCH(QQueue<QByteArray>, responses);
       
   291     QFETCH(int, expectedError);
       
   292 
       
   293     MiniSocks5Server server(responses);
       
   294 
       
   295     if (hostname.isEmpty()) {
       
   296         hostname = "127.0.0.1";
       
   297         port = server.serverPort();
       
   298     }
       
   299     QTcpSocket socket;
       
   300     socket.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, hostname, port, username, username));
       
   301     socket.connectToHost("0.1.2.3", 12345);
       
   302 
       
   303     connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)),
       
   304             &QTestEventLoop::instance(), SLOT(exitLoop()));
       
   305     QTestEventLoop::instance().enterLoop(10);
       
   306     QVERIFY(!QTestEventLoop::instance().timeout());
       
   307 
       
   308     QCOMPARE(int(socket.error()), expectedError);
       
   309 }
       
   310 
       
   311 //---------------------------------------------------------------------------
       
   312 void tst_QSocks5SocketEngine::simpleConnectToIMAP()
       
   313 {
       
   314     QSocks5SocketEngine socketDevice;
       
   315 
       
   316     // Initialize device
       
   317     QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
       
   318     QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState);
       
   319 
       
   320     socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
       
   321 
       
   322     QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143));
       
   323     QVERIFY(socketDevice.state() == QAbstractSocket::ConnectingState);
       
   324     QVERIFY(socketDevice.waitForWrite());
       
   325     QVERIFY(socketDevice.state() == QAbstractSocket::ConnectedState);
       
   326     QVERIFY(socketDevice.peerAddress() == QtNetworkSettings::serverIP());
       
   327 
       
   328     // Wait for the greeting
       
   329     QVERIFY(socketDevice.waitForRead());
       
   330 
       
   331     // Read the greeting
       
   332     qint64 available = socketDevice.bytesAvailable();
       
   333     QVERIFY(available > 0);
       
   334     QByteArray array;
       
   335     array.resize(available);
       
   336     QVERIFY(socketDevice.read(array.data(), array.size()) == available);
       
   337 
       
   338     // Check that the greeting is what we expect it to be
       
   339     QCOMPARE(array.constData(), QtNetworkSettings::expectedReplyIMAP().constData());
       
   340 
       
   341     // Write a logout message
       
   342     QByteArray array2 = "XXXX LOGOUT\r\n";
       
   343     QVERIFY(socketDevice.write(array2.data(),
       
   344                               array2.size()) == array2.size());
       
   345 
       
   346     // Wait for the response
       
   347     QVERIFY(socketDevice.waitForRead());
       
   348 
       
   349     available = socketDevice.bytesAvailable();
       
   350     QVERIFY(available > 0);
       
   351     array.resize(available);
       
   352     QVERIFY(socketDevice.read(array.data(), array.size()) == available);
       
   353 
       
   354     // Check that the greeting is what we expect it to be
       
   355     QCOMPARE(array.constData(), "* BYE LOGOUT received\r\nXXXX OK Completed\r\n");
       
   356 
       
   357     // Wait for the response
       
   358     QVERIFY(socketDevice.waitForRead());
       
   359     char c;
       
   360     QVERIFY(socketDevice.read(&c, sizeof(c)) == -1);
       
   361     QVERIFY(socketDevice.error() == QAbstractSocket::RemoteHostClosedError);
       
   362     QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState);
       
   363 }
       
   364 
       
   365 //---------------------------------------------------------------------------
       
   366 void tst_QSocks5SocketEngine::simpleErrorsAndStates()
       
   367 {
       
   368     {
       
   369         QSocks5SocketEngine socketDevice;
       
   370 
       
   371         // Initialize device
       
   372         QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
       
   373 
       
   374         socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
       
   375 
       
   376         QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState);
       
   377         QVERIFY(!socketDevice.connectToHost(QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first(), 8088));
       
   378         QVERIFY(socketDevice.state() == QAbstractSocket::ConnectingState);
       
   379         if (socketDevice.waitForWrite(15000)) {
       
   380             QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState ||
       
   381                     socketDevice.state() == QAbstractSocket::ConnectedState);
       
   382         } else {
       
   383             QVERIFY(socketDevice.error() == QAbstractSocket::SocketTimeoutError);
       
   384         }
       
   385     }
       
   386 
       
   387 }
       
   388 
       
   389 /*
       
   390 //---------------------------------------------------------------------------
       
   391 void tst_QSocks5SocketEngine::tcpLoopbackPerformance()
       
   392 {
       
   393     QTcpServer server;
       
   394 
       
   395     // Bind to any port on all interfaces
       
   396     QVERIFY(server.bind(QHostAddress("0.0.0.0"), 0));
       
   397     QVERIFY(server.state() == QAbstractSocket::BoundState);
       
   398     quint16 port = server.localPort();
       
   399 
       
   400     // Listen for incoming connections
       
   401     QVERIFY(server.listen());
       
   402     QVERIFY(server.state() == QAbstractSocket::ListeningState);
       
   403 
       
   404     // Initialize a Tcp socket
       
   405     QSocks5SocketEngine client;
       
   406     QVERIFY(client.initialize(QAbstractSocket::TcpSocket));
       
   407 
       
   408     client.setProxy(QHostAddress("80.232.37.158"), 1081);
       
   409 
       
   410     // Connect to our server
       
   411     if (!client.connectToHost(QHostAddress("127.0.0.1"), port)) {
       
   412         QVERIFY(client.waitForWrite());
       
   413         QVERIFY(client.connectToHost(QHostAddress("127.0.0.1"), port));
       
   414     }
       
   415 
       
   416     // The server accepts the connectio
       
   417     int socketDescriptor = server.accept();
       
   418     QVERIFY(socketDescriptor > 0);
       
   419 
       
   420     // A socket device is initialized on the server side, passing the
       
   421     // socket descriptor from accept(). It's pre-connected.
       
   422     QSocketLayer serverSocket;
       
   423     QVERIFY(serverSocket.initialize(socketDescriptor));
       
   424     QVERIFY(serverSocket.state() == QAbstractSocket::ConnectedState);
       
   425 
       
   426     const int messageSize = 1024 * 256;
       
   427     QByteArray message1(messageSize, '@');
       
   428     QByteArray answer(messageSize, '@');
       
   429 
       
   430     QTime timer;
       
   431     timer.start();
       
   432     qlonglong readBytes = 0;
       
   433     while (timer.elapsed() < 5000) {
       
   434         qlonglong written = serverSocket.write(message1.data(), message1.size());
       
   435         while (written > 0) {
       
   436             client.waitForRead();
       
   437             if (client.bytesAvailable() > 0) {
       
   438                 qlonglong readNow = client.read(answer.data(), answer.size());
       
   439                 written -= readNow;
       
   440                 readBytes += readNow;
       
   441             }
       
   442         }
       
   443     }
       
   444 
       
   445     qDebug("\t\t%.1fMB/%.1fs: %.1fMB/s",
       
   446            readBytes / (1024.0 * 1024.0),
       
   447            timer.elapsed() / 1024.0,
       
   448            (readBytes / (timer.elapsed() / 1000.0)) / (1024 * 1024));
       
   449 }
       
   450 */
       
   451 
       
   452 //---------------------------------------------------------------------------
       
   453 void tst_QSocks5SocketEngine::serverTest()
       
   454 {
       
   455     QSocks5SocketEngine server;
       
   456 
       
   457     // Initialize a Tcp socket
       
   458     QVERIFY(server.initialize(QAbstractSocket::TcpSocket));
       
   459 
       
   460     QNetworkProxy proxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
       
   461 
       
   462     server.setProxy(proxy);
       
   463 
       
   464     // Bind to any port on all interfaces
       
   465     QVERIFY(server.bind(QHostAddress("0.0.0.0"), 0));
       
   466     QVERIFY(server.state() == QAbstractSocket::BoundState);
       
   467 
       
   468     // Listen for incoming connections
       
   469     QVERIFY(server.listen());
       
   470     QVERIFY(server.state() == QAbstractSocket::ListeningState);
       
   471 
       
   472     // Initialize a Tcp socket
       
   473     QSocks5SocketEngine client;
       
   474     QVERIFY(client.initialize(QAbstractSocket::TcpSocket));
       
   475 
       
   476     client.setProxy(proxy);
       
   477 
       
   478    // QTest::wait(100000); // ### timing problem on win32
       
   479 
       
   480 
       
   481     // Connect to our server
       
   482     if (!client.connectToHost(server.localAddress(), server.localPort())) {
       
   483         QVERIFY(client.waitForWrite());
       
   484        // QTest::wait(100); // ### timing problem on win32
       
   485         QVERIFY(client.state() == QAbstractSocket::ConnectedState);
       
   486         //QTest::wait(100);
       
   487     }
       
   488 
       
   489     QVERIFY(server.waitForRead());
       
   490 
       
   491     // The server accepts the connection
       
   492     int socketDescriptor = server.accept();
       
   493     QVERIFY(socketDescriptor > 0);
       
   494 
       
   495     // A socket device is initialized on the server side, passing the
       
   496     // socket descriptor from accept(). It's pre-connected.
       
   497 
       
   498     QSocks5SocketEngine serverSocket;
       
   499     QVERIFY(serverSocket.initialize(socketDescriptor));
       
   500     QVERIFY(serverSocket.state() == QAbstractSocket::ConnectedState);
       
   501 
       
   502     QVERIFY(serverSocket.localAddress() == client.peerAddress());
       
   503     QVERIFY(serverSocket.localPort() == client.peerPort());
       
   504     // this seems depends on the socks server implementation, especially
       
   505     // when connecting /to/ the socks server /through/ the same socks server
       
   506     //QVERIFY(serverSocket.peerAddress() == client.localAddress());
       
   507     //QVERIFY(serverSocket.peerPort() == client.localPort());
       
   508 
       
   509     // The server socket sends a greeting to the client
       
   510     QByteArray greeting = "Greetings!";
       
   511     QVERIFY(serverSocket.write(greeting.data(),
       
   512                               greeting.size()) == greeting.size());
       
   513 
       
   514     // The client waits for the greeting to arrive
       
   515     QVERIFY(client.waitForRead());
       
   516     qint64 available = client.bytesAvailable();
       
   517     QVERIFY(available > 0);
       
   518 
       
   519     // The client reads the greeting and checks that it's correct
       
   520     QByteArray response;
       
   521     response.resize(available);
       
   522     QVERIFY(client.read(response.data(),
       
   523                        response.size()) == response.size());
       
   524     QCOMPARE(response, greeting);
       
   525 }
       
   526 
       
   527 
       
   528 //---------------------------------------------------------------------------
       
   529 void tst_QSocks5SocketEngine::udpTest()
       
   530 {
       
   531 #ifdef SYMBIAN_WINSOCK_CONNECTIVITY
       
   532     QSKIP("UDP works bads on non WinPCAP emulator setting", SkipAll);
       
   533 #endif
       
   534 
       
   535     QSocks5SocketEngine udpSocket;
       
   536 
       
   537     // Initialize device #1
       
   538     QVERIFY(udpSocket.initialize(QAbstractSocket::UdpSocket));
       
   539     QVERIFY(udpSocket.isValid());
       
   540 
       
   541     QNetworkProxy proxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
       
   542 
       
   543     udpSocket.setProxy(proxy);
       
   544 
       
   545     QVERIFY(udpSocket.protocol() == QAbstractSocket::IPv4Protocol);
       
   546     QVERIFY(udpSocket.socketType() == QAbstractSocket::UdpSocket);
       
   547     QVERIFY(udpSocket.state() == QAbstractSocket::UnconnectedState);
       
   548 
       
   549     // Bind #1
       
   550     QVERIFY(udpSocket.bind(QHostAddress("0.0.0.0"), 0));
       
   551     QVERIFY(udpSocket.state() == QAbstractSocket::BoundState);
       
   552     QVERIFY(udpSocket.localPort() != 0);
       
   553 
       
   554     // Initialize device #2
       
   555     QSocks5SocketEngine udpSocket2;
       
   556     QVERIFY(udpSocket2.initialize(QAbstractSocket::UdpSocket));
       
   557 
       
   558     udpSocket2.setProxy(proxy);
       
   559 
       
   560     // Connect device #2 to #1
       
   561     QVERIFY(udpSocket2.connectToHost(udpSocket.localAddress(), udpSocket.localPort()));
       
   562     QVERIFY(udpSocket2.state() == QAbstractSocket::ConnectedState);
       
   563 
       
   564     // Write a message to #1
       
   565     QByteArray message1 = "hei der";
       
   566     QVERIFY(udpSocket2.write(message1.data(),
       
   567                             message1.size()) == message1.size());
       
   568 
       
   569     // Read the message from #2
       
   570     QVERIFY(udpSocket.waitForRead());
       
   571     QVERIFY(udpSocket.hasPendingDatagrams());
       
   572     qint64 available = udpSocket.pendingDatagramSize();
       
   573     QVERIFY(available > 0);
       
   574     QByteArray answer;
       
   575     answer.resize(available);
       
   576     QHostAddress senderAddress;
       
   577     quint16 senderPort = 0;
       
   578     QVERIFY(udpSocket.readDatagram(answer.data(), answer.size(),
       
   579                                   &senderAddress,
       
   580                                   &senderPort) == message1.size());
       
   581     QVERIFY(senderAddress == udpSocket2.localAddress());
       
   582     QVERIFY(senderPort == udpSocket2.localPort());
       
   583 }
       
   584 
       
   585 void tst_QSocks5SocketEngine::tcpSocketBlockingTest()
       
   586 {
       
   587     QSocks5SocketEngineHandler socks5;
       
   588 
       
   589     QTcpSocket socket;
       
   590 
       
   591     // Connect
       
   592     socket.connectToHost(QtNetworkSettings::serverName(), 143);
       
   593     QVERIFY(socket.waitForConnected());
       
   594     QCOMPARE(socket.state(), QTcpSocket::ConnectedState);
       
   595 
       
   596     // Read greeting
       
   597     QVERIFY(socket.waitForReadyRead(5000));
       
   598     QString s = socket.readLine();
       
   599     QCOMPARE(s.toLatin1().constData(), QtNetworkSettings::expectedReplyIMAP().constData());
       
   600 
       
   601     // Write NOOP
       
   602     QCOMPARE((int) socket.write("1 NOOP\r\n", 8), 8);
       
   603 
       
   604     if (!socket.canReadLine())
       
   605         QVERIFY(socket.waitForReadyRead(5000));
       
   606 
       
   607     // Read response
       
   608     s = socket.readLine();
       
   609     QCOMPARE(s.toLatin1().constData(), "1 OK Completed\r\n");
       
   610 
       
   611     // Write LOGOUT
       
   612     QCOMPARE((int) socket.write("2 LOGOUT\r\n", 10), 10);
       
   613 
       
   614     if (!socket.canReadLine())
       
   615         QVERIFY(socket.waitForReadyRead(5000));
       
   616 
       
   617     // Read two lines of respose
       
   618     s = socket.readLine();
       
   619     QCOMPARE(s.toLatin1().constData(), "* BYE LOGOUT received\r\n");
       
   620 
       
   621     if (!socket.canReadLine())
       
   622         QVERIFY(socket.waitForReadyRead(5000));
       
   623 
       
   624     s = socket.readLine();
       
   625     QCOMPARE(s.toLatin1().constData(), "2 OK Completed\r\n");
       
   626 
       
   627     // Close the socket
       
   628     socket.close();
       
   629 
       
   630     // Check that it's closed
       
   631     QCOMPARE(socket.state(), QTcpSocket::UnconnectedState);
       
   632 }
       
   633 
       
   634 //----------------------------------------------------------------------------------
       
   635 
       
   636 void tst_QSocks5SocketEngine::tcpSocketNonBlockingTest()
       
   637 {
       
   638     QSocks5SocketEngineHandler socks5;
       
   639 
       
   640     QTcpSocket socket;
       
   641     connect(&socket, SIGNAL(hostFound()), SLOT(tcpSocketNonBlocking_hostFound()));
       
   642     connect(&socket, SIGNAL(connected()), SLOT(tcpSocketNonBlocking_connected()));
       
   643     connect(&socket, SIGNAL(disconnected()), SLOT(tcpSocketNonBlocking_closed()));
       
   644     connect(&socket, SIGNAL(bytesWritten(qint64)), SLOT(tcpSocketNonBlocking_bytesWritten(qint64)));
       
   645     connect(&socket, SIGNAL(readyRead()), SLOT(tcpSocketNonBlocking_readyRead()));
       
   646     tcpSocketNonBlocking_socket = &socket;
       
   647 
       
   648     // Connect
       
   649     socket.connectToHost(QtNetworkSettings::serverName(), 143);
       
   650     QCOMPARE(socket.state(), QTcpSocket::HostLookupState);
       
   651 
       
   652     QTestEventLoop::instance().enterLoop(30);
       
   653     if (QTestEventLoop::instance().timeout()) {
       
   654         QFAIL("Timed out");
       
   655     }
       
   656 
       
   657     if (socket.state() == QTcpSocket::ConnectingState) {
       
   658         QTestEventLoop::instance().enterLoop(30);
       
   659         if (QTestEventLoop::instance().timeout()) {
       
   660             QFAIL("Timed out");
       
   661         }
       
   662     }
       
   663 
       
   664     QCOMPARE(socket.state(), QTcpSocket::ConnectedState);
       
   665 
       
   666     QTestEventLoop::instance().enterLoop(30);
       
   667     if (QTestEventLoop::instance().timeout()) {
       
   668         QFAIL("Timed out");
       
   669     }
       
   670 
       
   671     // Read greeting
       
   672     QVERIFY(!tcpSocketNonBlocking_data.isEmpty());
       
   673     QCOMPARE(tcpSocketNonBlocking_data.at(0).toLatin1().constData(),
       
   674             QtNetworkSettings::expectedReplyIMAP().constData());
       
   675 
       
   676     tcpSocketNonBlocking_data.clear();
       
   677 
       
   678     tcpSocketNonBlocking_totalWritten = 0;
       
   679 
       
   680     // Write NOOP
       
   681     QCOMPARE((int) socket.write("1 NOOP\r\n", 8), 8);
       
   682 
       
   683 
       
   684     QTestEventLoop::instance().enterLoop(30);
       
   685     if (QTestEventLoop::instance().timeout()) {
       
   686         QFAIL("Timed out");
       
   687     }
       
   688 
       
   689     QVERIFY(tcpSocketNonBlocking_totalWritten == 8);
       
   690 
       
   691 
       
   692     QTestEventLoop::instance().enterLoop(30);
       
   693     if (QTestEventLoop::instance().timeout()) {
       
   694         QFAIL("Timed out");
       
   695     }
       
   696 
       
   697     // Read response
       
   698     QVERIFY(!tcpSocketNonBlocking_data.isEmpty());
       
   699     QCOMPARE(tcpSocketNonBlocking_data.at(0).toLatin1().constData(), "1 OK Completed\r\n");
       
   700     tcpSocketNonBlocking_data.clear();
       
   701 
       
   702 
       
   703     tcpSocketNonBlocking_totalWritten = 0;
       
   704 
       
   705     // Write LOGOUT
       
   706     QCOMPARE((int) socket.write("2 LOGOUT\r\n", 10), 10);
       
   707 
       
   708     QTestEventLoop::instance().enterLoop(30);
       
   709     if (QTestEventLoop::instance().timeout()) {
       
   710         QFAIL("Timed out");
       
   711     }
       
   712 
       
   713     QVERIFY(tcpSocketNonBlocking_totalWritten == 10);
       
   714 
       
   715     // Wait for greeting
       
   716     QTestEventLoop::instance().enterLoop(30);
       
   717     if (QTestEventLoop::instance().timeout()) {
       
   718         QFAIL("Timed out");
       
   719     }
       
   720 
       
   721     // Read two lines of respose
       
   722     QCOMPARE(tcpSocketNonBlocking_data.at(0).toLatin1().constData(), "* BYE LOGOUT received\r\n");
       
   723     QCOMPARE(tcpSocketNonBlocking_data.at(1).toLatin1().constData(), "2 OK Completed\r\n");
       
   724     tcpSocketNonBlocking_data.clear();
       
   725 
       
   726     // Close the socket
       
   727     socket.close();
       
   728 
       
   729     // Check that it's closed
       
   730     QCOMPARE(socket.state(), QTcpSocket::UnconnectedState);
       
   731 }
       
   732 
       
   733 void tst_QSocks5SocketEngine::tcpSocketNonBlocking_hostFound()
       
   734 {
       
   735     QTestEventLoop::instance().exitLoop();
       
   736 }
       
   737 
       
   738 void tst_QSocks5SocketEngine::tcpSocketNonBlocking_connected()
       
   739 {
       
   740     QTestEventLoop::instance().exitLoop();
       
   741 }
       
   742 
       
   743 void tst_QSocks5SocketEngine::tcpSocketNonBlocking_readyRead()
       
   744 {
       
   745     while (tcpSocketNonBlocking_socket->canReadLine())
       
   746         tcpSocketNonBlocking_data.append(tcpSocketNonBlocking_socket->readLine());
       
   747 
       
   748     QTestEventLoop::instance().exitLoop();
       
   749 }
       
   750 
       
   751 void tst_QSocks5SocketEngine::tcpSocketNonBlocking_bytesWritten(qint64 written)
       
   752 {
       
   753     tcpSocketNonBlocking_totalWritten += written;
       
   754     QTestEventLoop::instance().exitLoop();
       
   755 }
       
   756 
       
   757 void tst_QSocks5SocketEngine::tcpSocketNonBlocking_closed()
       
   758 {
       
   759 }
       
   760 
       
   761 //----------------------------------------------------------------------------------
       
   762 
       
   763 void tst_QSocks5SocketEngine::downloadBigFile()
       
   764 {
       
   765     QSocks5SocketEngineHandler socks5;
       
   766 
       
   767     if (tmpSocket)
       
   768         delete tmpSocket;
       
   769     tmpSocket = new QTcpSocket;
       
   770 
       
   771     connect(tmpSocket, SIGNAL(connected()), SLOT(exitLoopSlot()));
       
   772     connect(tmpSocket, SIGNAL(readyRead()), SLOT(downloadBigFileSlot()));
       
   773 
       
   774     tmpSocket->connectToHost(QtNetworkSettings::serverName(), 80);
       
   775 
       
   776     QTestEventLoop::instance().enterLoop(30);
       
   777     if (QTestEventLoop::instance().timeout())
       
   778         QFAIL("Network operation timed out");
       
   779 
       
   780     QByteArray hostName = QtNetworkSettings::serverName().toLatin1();
       
   781     QVERIFY(tmpSocket->state() == QAbstractSocket::ConnectedState);
       
   782     QVERIFY(tmpSocket->write("GET /mediumfile HTTP/1.0\r\n") > 0);
       
   783     QVERIFY(tmpSocket->write("HOST: ") > 0);
       
   784     QVERIFY(tmpSocket->write(hostName.data()) > 0);
       
   785     QVERIFY(tmpSocket->write("\r\n") > 0);
       
   786     QVERIFY(tmpSocket->write("\r\n") > 0);
       
   787 
       
   788     bytesAvailable = 0;
       
   789 
       
   790     QTime stopWatch;
       
   791     stopWatch.start();
       
   792 
       
   793 #if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
       
   794     QTestEventLoop::instance().enterLoop(60);
       
   795 #else
       
   796     QTestEventLoop::instance().enterLoop(180);
       
   797 #endif
       
   798     if (QTestEventLoop::instance().timeout())
       
   799         QFAIL("Network operation timed out");
       
   800 
       
   801     QCOMPARE(bytesAvailable, qint64(10000000));
       
   802 
       
   803     QVERIFY(tmpSocket->state() == QAbstractSocket::ConnectedState);
       
   804 
       
   805     /*qDebug("\t\t%.1fMB/%.1fs: %.1fMB/s",
       
   806            bytesAvailable / (1024.0 * 1024.0),
       
   807            stopWatch.elapsed() / 1024.0,
       
   808            (bytesAvailable / (stopWatch.elapsed() / 1000.0)) / (1024 * 1024));*/
       
   809 
       
   810     delete tmpSocket;
       
   811     tmpSocket = 0;
       
   812 }
       
   813 
       
   814 void tst_QSocks5SocketEngine::exitLoopSlot()
       
   815 {
       
   816     QTestEventLoop::instance().exitLoop();
       
   817 }
       
   818 
       
   819 
       
   820 void tst_QSocks5SocketEngine::downloadBigFileSlot()
       
   821 {
       
   822     QByteArray tmp=tmpSocket->readAll();
       
   823     int correction=tmp.indexOf((char)0,0); //skip header
       
   824     if (correction==-1) correction=0;
       
   825     bytesAvailable += (tmp.size()-correction);
       
   826     if (bytesAvailable >= 10000000)
       
   827         QTestEventLoop::instance().exitLoop();
       
   828 }
       
   829 
       
   830 void tst_QSocks5SocketEngine::passwordAuth()
       
   831 {
       
   832     QSocks5SocketEngine socketDevice;
       
   833 
       
   834     // Initialize device
       
   835     QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
       
   836     QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState);
       
   837 
       
   838     socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080, "qsockstest", "password"));
       
   839 
       
   840     // Connect to imap.trolltech.com's IP
       
   841     QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143));
       
   842     QVERIFY(socketDevice.state() == QAbstractSocket::ConnectingState);
       
   843     QVERIFY(socketDevice.waitForWrite());
       
   844     if (!socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143)) {
       
   845         qDebug("%d, %s", socketDevice.error(), socketDevice.errorString().toLatin1().constData());
       
   846     }
       
   847     QVERIFY(socketDevice.state() == QAbstractSocket::ConnectedState);
       
   848     QVERIFY(socketDevice.peerAddress() == QtNetworkSettings::serverIP());
       
   849 
       
   850     // Wait for the greeting
       
   851     QVERIFY(socketDevice.waitForRead());
       
   852 
       
   853     // Read the greeting
       
   854     qint64 available = socketDevice.bytesAvailable();
       
   855     QVERIFY(available > 0);
       
   856     QByteArray array;
       
   857     array.resize(available);
       
   858     QVERIFY(socketDevice.read(array.data(), array.size()) == available);
       
   859 
       
   860     // Check that the greeting is what we expect it to be
       
   861     QCOMPARE(array.constData(), QtNetworkSettings::expectedReplyIMAP().constData());
       
   862 
       
   863     // Write a logout message
       
   864     QByteArray array2 = "XXXX LOGOUT\r\n";
       
   865     QVERIFY(socketDevice.write(array2.data(),
       
   866                               array2.size()) == array2.size());
       
   867 
       
   868     // Wait for the response
       
   869     QVERIFY(socketDevice.waitForRead());
       
   870 
       
   871     available = socketDevice.bytesAvailable();
       
   872     QVERIFY(available > 0);
       
   873     array.resize(available);
       
   874     QVERIFY(socketDevice.read(array.data(), array.size()) == available);
       
   875 
       
   876     // Check that the greeting is what we expect it to be
       
   877     QCOMPARE(array.constData(), "* BYE LOGOUT received\r\nXXXX OK Completed\r\n");
       
   878 
       
   879     // Wait for the response
       
   880     QVERIFY(socketDevice.waitForRead());
       
   881     char c;
       
   882     QVERIFY(socketDevice.read(&c, sizeof(c)) == -1);
       
   883     QVERIFY(socketDevice.error() == QAbstractSocket::RemoteHostClosedError);
       
   884     QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState);
       
   885 }
       
   886 
       
   887 //----------------------------------------------------------------------------------
       
   888 
       
   889 void tst_QSocks5SocketEngine::proxyAuthenticationRequired(const QNetworkProxy &,
       
   890                                                           QAuthenticator *auth)
       
   891 {
       
   892     auth->setUser("qsockstest");
       
   893     auth->setPassword("password");
       
   894 }
       
   895 
       
   896 void tst_QSocks5SocketEngine::passwordAuth2()
       
   897 {
       
   898     QSocks5SocketEngine socketDevice;
       
   899 
       
   900     // Initialize device
       
   901     QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
       
   902     QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState);
       
   903 
       
   904     socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081));
       
   905     socketDevice.setReceiver(this);
       
   906 
       
   907     QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143));
       
   908     QVERIFY(socketDevice.state() == QAbstractSocket::ConnectingState);
       
   909     while (socketDevice.state() == QAbstractSocket::ConnectingState) {
       
   910         QVERIFY(socketDevice.waitForWrite());
       
   911         socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143);
       
   912     }
       
   913     if (socketDevice.state() != QAbstractSocket::ConnectedState)
       
   914         qDebug("%d, %s", socketDevice.error(), socketDevice.errorString().toLatin1().constData());
       
   915     QVERIFY(socketDevice.state() == QAbstractSocket::ConnectedState);
       
   916     QVERIFY(socketDevice.peerAddress() == QtNetworkSettings::serverIP());
       
   917 
       
   918     // Wait for the greeting
       
   919     QVERIFY(socketDevice.waitForRead());
       
   920 
       
   921     // Read the greeting
       
   922     qint64 available = socketDevice.bytesAvailable();
       
   923     QVERIFY(available > 0);
       
   924     QByteArray array;
       
   925     array.resize(available);
       
   926     QVERIFY(socketDevice.read(array.data(), array.size()) == available);
       
   927 
       
   928     // Check that the greeting is what we expect it to be
       
   929     QCOMPARE(array.constData(), QtNetworkSettings::expectedReplyIMAP().constData());
       
   930 
       
   931     // Write a logout message
       
   932     QByteArray array2 = "XXXX LOGOUT\r\n";
       
   933     QVERIFY(socketDevice.write(array2.data(),
       
   934                               array2.size()) == array2.size());
       
   935 
       
   936     // Wait for the response
       
   937     QVERIFY(socketDevice.waitForRead());
       
   938 
       
   939     available = socketDevice.bytesAvailable();
       
   940     QVERIFY(available > 0);
       
   941     array.resize(available);
       
   942     QVERIFY(socketDevice.read(array.data(), array.size()) == available);
       
   943 
       
   944     // Check that the greeting is what we expect it to be
       
   945     QCOMPARE(array.constData(), "* BYE LOGOUT received\r\nXXXX OK Completed\r\n");
       
   946 
       
   947     // Wait for the response
       
   948     QVERIFY(socketDevice.waitForRead());
       
   949     char c;
       
   950     QVERIFY(socketDevice.read(&c, sizeof(c)) == -1);
       
   951     QVERIFY(socketDevice.error() == QAbstractSocket::RemoteHostClosedError);
       
   952     QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState);
       
   953 }
       
   954 
       
   955 //----------------------------------------------------------------------------------
       
   956 
       
   957 QTEST_MAIN(tst_QSocks5SocketEngine)
       
   958 #include "tst_qsocks5socketengine.moc"