File indexing completed on 2025-01-05 04:37:31

0001 /*
0002     SPDX-FileCopyrightText: 2010 Joris Guisson <joris.guisson@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include <QObject>
0008 #include <QtTest>
0009 
0010 #include <ctime>
0011 #include <unistd.h>
0012 #include <util/functions.h>
0013 #include <util/log.h>
0014 #include <utp/connection.h>
0015 #include <utp/utpserver.h>
0016 #include <utp/utpsocket.h>
0017 
0018 #define PACKETS_TO_SEND 20
0019 #define TEST_DATA "This is the packet loss test\n"
0020 
0021 using namespace utp;
0022 using namespace bt;
0023 
0024 /**
0025     Server which simulates packet loss
0026 */
0027 class CongestionTestServer : public UTPServer
0028 {
0029     Q_OBJECT
0030 public:
0031     CongestionTestServer(QObject *parent = nullptr)
0032         : UTPServer(parent)
0033         , congestion_delay(200)
0034     {
0035     }
0036 
0037     virtual ~CongestionTestServer()
0038     {
0039     }
0040 
0041     virtual bool sendTo(const QByteArray &data, const net::Address &addr)
0042     {
0043     }
0044 
0045     virtual bool sendTo(const bt::Uint8 *data, const bt::Uint32 size, const net::Address &addr)
0046     {
0047     }
0048 
0049     void setCongestionDelay(int cd)
0050     {
0051         congestion_delay = cd;
0052     }
0053 
0054 public:
0055     void delayedSend()
0056     {
0057     }
0058 
0059 private:
0060     int congestion_delay;
0061 };
0062 
0063 class SendThread : public QThread
0064 {
0065 public:
0066     SendThread(Connection::Ptr outgoing, QObject *parent = nullptr)
0067         : QThread(parent)
0068         , outgoing(outgoing)
0069     {
0070     }
0071 
0072     virtual void run()
0073     {
0074         char test[] = TEST_DATA;
0075         int sent = 0;
0076         while (sent < PACKETS_TO_SEND) {
0077             int ret = outgoing->send((const bt::Uint8 *)test, strlen(test));
0078             if (ret > 0) {
0079                 sent++;
0080             }
0081 
0082             msleep(200);
0083         }
0084 
0085         while (!outgoing->allDataSent())
0086             sleep(1);
0087 
0088         Out(SYS_UTP | LOG_DEBUG) << "Transmitted " << sent << " packets " << endl;
0089         outgoing->dumpStats();
0090     }
0091 
0092     Connection::Ptr outgoing;
0093 };
0094 
0095 class CongestionTest : public QEventLoop
0096 {
0097 public:
0098     CongestionTest(QObject *parent = 0)
0099         : QEventLoop(parent)
0100     {
0101     }
0102 
0103 public:
0104     void accepted()
0105     {
0106         incoming = srv.acceptedConnection().toStrongRef();
0107         exit();
0108     }
0109 
0110     void endEventLoop()
0111     {
0112         exit();
0113     }
0114 
0115 private:
0116     void initTestCase()
0117     {
0118         bt::InitLog("congestiontest.log");
0119 
0120         incoming = outgoing = 0;
0121         port = 50000;
0122         while (port < 60000) {
0123             if (!srv.changePort(port))
0124                 port++;
0125             else
0126                 break;
0127         }
0128 
0129         srv.setCreateSockets(false);
0130         srv.start();
0131     }
0132 
0133     void cleanupTestCase()
0134     {
0135         srv.stop();
0136     }
0137 
0138     void testConnect()
0139     {
0140         net::Address addr("127.0.0.1", port);
0141         connect(&srv, &CongestionTestServer::accepted, this, &CongestionTest::accepted, Qt::QueuedConnection);
0142         outgoing = srv.connectTo(addr);
0143         QVERIFY(outgoing != 0);
0144         QTimer::singleShot(5000, this, &CongestionTest::endEventLoop); // use a 5 second timeout
0145         exec();
0146         QVERIFY(incoming != 0);
0147     }
0148 
0149     void testCongestionTest()
0150     {
0151         bt::Out(SYS_UTP | LOG_DEBUG) << "testCongestionTest" << bt::endl;
0152         if (outgoing->connectionState() != CS_CONNECTED || incoming->connectionState() != CS_CONNECTED) {
0153             QSKIP("Not Connected", SkipAll);
0154             return;
0155         }
0156         /*
0157         srv.setCongestionTestSimulation(true,0.1); // Drop 10 % of all packets
0158         SendThread st(outgoing);
0159         st.start(); // The thread will start sending a whole bunch of data
0160         int received = 0;
0161         QString received_data;
0162         while (!st.isFinished())
0163         {
0164             bt::Uint32 ba = incoming->bytesAvailable();
0165             if (ba > 0)
0166             {
0167                 QByteArray data(ba,0);
0168                 int ret = incoming->recv((bt::Uint8*)data.data(),ba);
0169                 if (ret > 0)
0170                 {
0171                     received_data.append(data);
0172                     received += ret;
0173                 }
0174             }
0175             else
0176             {
0177                 usleep(50000);
0178             }
0179         }
0180 
0181         st.wait();
0182         Out(SYS_UTP|LOG_DEBUG) << "Received " << received << " bytes:" << endl;
0183         Out(SYS_UTP|LOG_DEBUG) << received_data << endl;
0184         incoming->dumpStats();
0185         QVERIFY(incoming->bytesAvailable() == 0);
0186         QVERIFY(received_data.count(TEST_DATA) == PACKETS_TO_SEND);
0187         QVERIFY(outgoing->allDataSent());
0188         */
0189     }
0190 
0191 private:
0192 private:
0193     Connection::Ptr incoming;
0194     Connection::Ptr outgoing;
0195     CongestionTestServer srv;
0196     int port;
0197 };
0198 
0199 QTEST_MAIN(CongestionTest)