File indexing completed on 2024-04-28 04:44:20
0001 /* 0002 SPDX-FileCopyrightText: 2015 (c) Matthieu Gallien <matthieu_gallien@yahoo.fr> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include "upnpssdpengine.h" 0008 0009 #include "upnpdiscoveryresult.h" 0010 0011 #include <QtCore/QDebug> 0012 #include <QtCore/QScopedPointer> 0013 #include <QtCore/QStringList> 0014 0015 #include <QtNetwork/QUdpSocket> 0016 0017 #include <QtTest/QtTest> 0018 #include <utility> 0019 0020 0021 #include <sys/socket.h> 0022 #include <sys/types.h> 0023 0024 class MockSsdpClient : public QObject 0025 { 0026 0027 Q_OBJECT 0028 0029 public: 0030 explicit MockSsdpClient(quint16 aPortNumber, QByteArray aExpectedQuery, QStringList aAnswerData, 0031 bool aAutoRefresh, int aRefreshPeriod = 1000, 0032 QStringList aAnnounceData = {}, 0033 QObject *parent = nullptr) 0034 : QObject(parent) 0035 , mPortNumber(aPortNumber) 0036 , mClientSocket() 0037 , mAnswerData(std::move(aAnswerData)) 0038 , mExpectedQuery(std::move(aExpectedQuery)) 0039 , mHttpClientSocket() 0040 , mAutoRefresh(aAutoRefresh) 0041 , mRefreshPeriod(aRefreshPeriod) 0042 , mAnnounceData(std::move(aAnnounceData)) 0043 , mAutoRefreshTimer() 0044 , mSender() 0045 , mSenderPort(12345) 0046 { 0047 connect(&mAutoRefreshTimer, &QTimer::timeout, this, &MockSsdpClient::refreshAnnounce); 0048 0049 if (mAutoRefresh) { 0050 mAutoRefreshTimer.setSingleShot(false); 0051 mAutoRefreshTimer.start(mRefreshPeriod * 1000); 0052 } 0053 } 0054 0055 void listen() 0056 { 0057 connect(&mClientSocket, &QUdpSocket::readyRead, this, &MockSsdpClient::dataReceived); 0058 0059 mClientSocket.bind(QHostAddress::AnyIPv4, mPortNumber, QAbstractSocket::ShareAddress | QAbstractSocket::ReuseAddressHint); 0060 mClientSocket.joinMulticastGroup(QHostAddress(QStringLiteral("239.255.255.250"))); 0061 mClientSocket.setSocketOption(QAbstractSocket::MulticastLoopbackOption, 1); 0062 mClientSocket.setSocketOption(QAbstractSocket::MulticastTtlOption, 4); 0063 0064 connect(&mHttpClientSocket, &QUdpSocket::readyRead, this, &MockSsdpClient::httpDataReceived); 0065 0066 mHttpClientSocket.bind(QHostAddress::AnyIPv4, 8200); 0067 0068 auto result = mAnnounceSocket.bind(QHostAddress(QStringLiteral("239.255.255.250")), 1900, QAbstractSocket::ShareAddress); 0069 //qDebug() << "bind" << QHostAddress::AnyIPv4 << (result ? "true" : "false"); 0070 result = mAnnounceSocket.joinMulticastGroup(QHostAddress(QStringLiteral("239.255.255.250"))); 0071 qDebug() << "joinMulticastGroup" << (result ? "true" : "false") << mAnnounceSocket.errorString(); 0072 0073 mAnnounceSocket.setSocketOption(QAbstractSocket::MulticastLoopbackOption, { 1 }); 0074 mAnnounceSocket.setSocketOption(QAbstractSocket::MulticastTtlOption, { 4 }); 0075 } 0076 0077 public Q_SLOTS: 0078 0079 void dataReceived() 0080 { 0081 while (mClientSocket.hasPendingDatagrams()) { 0082 QByteArray datagram; 0083 datagram.resize(mClientSocket.pendingDatagramSize()); 0084 0085 mClientSocket.readDatagram(datagram.data(), datagram.size(), 0086 &mSender, &mSenderPort); 0087 0088 QVERIFY(mExpectedQuery.isEmpty() || datagram == mExpectedQuery); 0089 0090 QTest::qSleep(1700); 0091 0092 for (auto &answer : mAnswerData) { 0093 mClientSocket.writeDatagram(answer.toLatin1(), mSender, mSenderPort); 0094 } 0095 } 0096 mClientSocket.close(); 0097 } 0098 0099 void httpDataReceived() 0100 { 0101 while (mClientSocket.hasPendingDatagrams()) { 0102 QByteArray datagram; 0103 datagram.resize(mClientSocket.pendingDatagramSize()); 0104 QHostAddress sender; 0105 quint16 senderPort; 0106 0107 mClientSocket.readDatagram(datagram.data(), datagram.size(), 0108 &sender, &senderPort); 0109 0110 qDebug() << "httpDataReceived" << datagram; 0111 } 0112 } 0113 0114 void refreshAnnounce() 0115 { 0116 qDebug() << "refreshAnnounce"; 0117 for (auto &announcement : mAnnounceData) { 0118 mAnnounceSocket.writeDatagram(announcement.toLatin1(), QHostAddress(QStringLiteral("239.255.255.250")), mPortNumber); 0119 } 0120 } 0121 0122 private: 0123 quint16 mPortNumber; 0124 0125 QUdpSocket mClientSocket; 0126 0127 QUdpSocket mAnnounceSocket; 0128 0129 QStringList mAnswerData; 0130 0131 QByteArray mExpectedQuery; 0132 0133 QUdpSocket mHttpClientSocket; 0134 0135 bool mAutoRefresh; 0136 0137 int mRefreshPeriod; 0138 0139 QStringList mAnnounceData; 0140 0141 QTimer mAutoRefreshTimer; 0142 0143 QHostAddress mSender; 0144 0145 quint16 mSenderPort; 0146 }; 0147 0148 class SsdpTests : public QObject 0149 { 0150 Q_OBJECT 0151 0152 public: 0153 SsdpTests(QObject *parent = nullptr) 0154 : QObject(parent) 0155 { 0156 } 0157 0158 private Q_SLOTS: 0159 0160 void initTestCase() 0161 { 0162 qRegisterMetaType<UpnpSearchQuery>("UpnpSearchQuery"); 0163 } 0164 0165 void searchAll_data() 0166 { 0167 QTest::addColumn<UpnpSsdpEngine::SEARCH_TYPE>("searchType"); 0168 QTest::addColumn<QString>("searchCriteria"); 0169 QTest::addColumn<QByteArray>("ssdpRequest"); 0170 QTest::addColumn<QStringList>("ssdpAnswers"); 0171 QTest::addColumn<QList<UpnpDiscoveryResult>>("results"); 0172 0173 QTest::newRow("all devices") << UpnpSsdpEngine::AllDevices 0174 << QString() 0175 << QByteArray("M-SEARCH * HTTP/1.1\r\n" 0176 "HOST: 239.255.255.250:11900\r\n" 0177 "MAN: \"ssdp:discover\"\r\n" 0178 "MX: 2\r\n" 0179 "ST: ssdp:all\r\n\r\n") 0180 << QStringList({ QStringLiteral("HTTP/1.1 200 OK\r\n" 0181 "CACHE-CONTROL: max-age=1800\r\n" 0182 "DATE: mar., 27 oct. 2015 21:03:35 G\x7F\r\n" 0183 "ST: uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e\r\n" 0184 "USN: uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e\r\n" 0185 "EXT:\r\n" 0186 "SERVER: Debian DLNADOC/1.50 UPnP/1.0 MiniDLNA/1.1.4\r\n" 0187 "LOCATION: http://127.0.0.1:8200/rootDesc.xml\r\n" 0188 "Content-Length: 0\r\n\r\n"), 0189 QStringLiteral("HTTP/1.1 200 OK\r\n" 0190 "CACHE-CONTROL: max-age=1800\r\n" 0191 "DATE: mar., 27 oct. 2015 21:03:35 G\x7F\r\n" 0192 "ST: upnp:rootdevice\r\n" 0193 "USN: uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::upnp:rootdevice\r\n" 0194 "EXT:\r\n" 0195 "SERVER: Debian DLNADOC/1.50 UPnP/1.0 MiniDLNA/1.1.4\r\n" 0196 "LOCATION: http://127.0.0.1:8200/rootDesc.xml\r\n" 0197 "Content-Length: 0\r\n\r\n"), 0198 QStringLiteral("HTTP/1.1 200 OK\r\n" 0199 "CACHE-CONTROL: max-age=1800\r\n" 0200 "DATE: mar., 27 oct. 2015 21:03:35 G\x7F\r\n" 0201 "ST: urn:schemas-upnp-org:device:MediaServer:1\r\n" 0202 "USN: uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::urn:schemas-upnp-org:device:MediaServer:1\r\n" 0203 "EXT:\r\n" 0204 "SERVER: Debian DLNADOC/1.50 UPnP/1.0 MiniDLNA/1.1.4\r\n" 0205 "LOCATION: http://127.0.0.1:8200/rootDesc.xml\r\n" 0206 "Content-Length: 0\r\n\r\n"), 0207 QStringLiteral("HTTP/1.1 200 OK\r\n" 0208 "CACHE-CONTROL: max-age=1800\r\n" 0209 "DATE: mar., 27 oct. 2015 21:03:35 G\x7F\r\n" 0210 "ST: urn:schemas-upnp-org:service:ContentDirectory:1\r\n" 0211 "USN: uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::urn:schemas-upnp-org:service:ContentDirectory:1\r\n" 0212 "EXT:\r\n" 0213 "SERVER: Debian DLNADOC/1.50 UPnP/1.0 MiniDLNA/1.1.4\r\n" 0214 "LOCATION: http://127.0.0.1:8200/rootDesc.xml\r\n" 0215 "Content-Length: 0\r\n\r\n"), 0216 QStringLiteral("HTTP/1.1 200 OK\r\n" 0217 "CACHE-CONTROL: max-age=1800\r\n" 0218 "DATE: mar., 27 oct. 2015 21:03:35 G\x7F\r\n" 0219 "ST: urn:schemas-upnp-org:service:ConnectionManager:1\r\n" 0220 "USN: uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::urn:schemas-upnp-org:service:ConnectionManager:1\r\n" 0221 "EXT:\r\n" 0222 "SERVER: Debian DLNADOC/1.50 UPnP/1.0 MiniDLNA/1.1.4\r\n" 0223 "LOCATION: http://127.0.0.1:8200/rootDesc.xml\r\n" 0224 "Content-Length: 0\r\n\r\n") }) 0225 << QList<UpnpDiscoveryResult>({ UpnpDiscoveryResult(QStringLiteral("uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e"), 0226 QStringLiteral("uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e"), 0227 QStringLiteral("http://127.0.0.1:8200/rootDesc.xml"), 0228 UpnpSsdpEngine::NotificationSubType::Invalid, 0229 QStringLiteral("mar., 27 oct. 2015 21:03:35 G\x7F"), 0230 1800), 0231 UpnpDiscoveryResult(QStringLiteral("upnp:rootdevice"), 0232 QStringLiteral("uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::upnp:rootdevice"), 0233 QStringLiteral("http://127.0.0.1:8200/rootDesc.xml"), 0234 UpnpSsdpEngine::NotificationSubType::Invalid, 0235 QStringLiteral("mar., 27 oct. 2015 21:03:35 G\x7F"), 0236 1800), 0237 UpnpDiscoveryResult(QStringLiteral("urn:schemas-upnp-org:device:MediaServer:1"), 0238 QStringLiteral("uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::urn:schemas-upnp-org:device:MediaServer:1"), 0239 QStringLiteral("http://127.0.0.1:8200/rootDesc.xml"), 0240 UpnpSsdpEngine::NotificationSubType::Invalid, 0241 QStringLiteral("mar., 27 oct. 2015 21:03:35 G\x7F"), 0242 1800), 0243 UpnpDiscoveryResult(QStringLiteral("urn:schemas-upnp-org:service:ContentDirectory:1"), 0244 QStringLiteral("uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::urn:schemas-upnp-org:service:ContentDirectory:1"), 0245 QStringLiteral("http://127.0.0.1:8200/rootDesc.xml"), 0246 UpnpSsdpEngine::NotificationSubType::Invalid, 0247 QStringLiteral("mar., 27 oct. 2015 21:03:35 G\x7F"), 0248 1800), 0249 UpnpDiscoveryResult(QStringLiteral("urn:schemas-upnp-org:service:ConnectionManager:1"), 0250 QStringLiteral("uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::urn:schemas-upnp-org:service:ConnectionManager:1"), 0251 QStringLiteral("http://127.0.0.1:8200/rootDesc.xml"), 0252 UpnpSsdpEngine::NotificationSubType::Invalid, 0253 QStringLiteral("mar., 27 oct. 2015 21:03:35 G\x7F"), 0254 1800) }); 0255 0256 QTest::newRow("root device") << UpnpSsdpEngine::RootDevices 0257 << QString() 0258 << QByteArray("M-SEARCH * HTTP/1.1\r\n" 0259 "HOST: 239.255.255.250:11900\r\n" 0260 "MAN: \"ssdp:discover\"\r\n" 0261 "MX: 2\r\n" 0262 "ST: upnp:rootdevice\r\n\r\n") 0263 << QStringList({ QStringLiteral("HTTP/1.1 200 OK\r\n" 0264 "CACHE-CONTROL: max-age=1800\r\n" 0265 "DATE: mar., 27 oct. 2015 21:03:35 G\x7F\r\n" 0266 "ST: upnp:rootdevice\r\n" 0267 "USN: uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::upnp:rootdevice\r\n" 0268 "EXT:\r\n" 0269 "SERVER: Debian DLNADOC/1.50 UPnP/1.0 MiniDLNA/1.1.4\r\n" 0270 "LOCATION: http://127.0.0.1:8200/rootDesc.xml\r\n" 0271 "Content-Length: 0\r\n\r\n") }) 0272 << QList<UpnpDiscoveryResult>({ UpnpDiscoveryResult(QStringLiteral("upnp:rootdevice"), 0273 QStringLiteral("uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::upnp:rootdevice"), 0274 QStringLiteral("http://127.0.0.1:8200/rootDesc.xml"), 0275 UpnpSsdpEngine::NotificationSubType::Invalid, 0276 QStringLiteral("mar., 27 oct. 2015 21:03:35 G\x7F"), 0277 1800) }); 0278 0279 QTest::newRow("device by uuid") << UpnpSsdpEngine::DeviceByUUID 0280 << QStringLiteral("4d696e69-444c-164e-9d41-ecf4bb9c317e") 0281 << QByteArray("M-SEARCH * HTTP/1.1\r\n" 0282 "HOST: 239.255.255.250:11900\r\n" 0283 "MAN: \"ssdp:discover\"\r\n" 0284 "MX: 2\r\n" 0285 "ST: uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e\r\n\r\n") 0286 << QStringList({ 0287 QStringLiteral("HTTP/1.1 200 OK\r\n" 0288 "CACHE-CONTROL: max-age=1800\r\n" 0289 "DATE: mar., 27 oct. 2015 21:03:35 G\x7F\r\n" 0290 "ST: uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e\r\n" 0291 "USN: uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e\r\n" 0292 "EXT:\r\n" 0293 "SERVER: Debian DLNADOC/1.50 UPnP/1.0 MiniDLNA/1.1.4\r\n" 0294 "LOCATION: http://127.0.0.1:8200/rootDesc.xml\r\n" 0295 "Content-Length: 0\r\n\r\n"), 0296 }) 0297 << QList<UpnpDiscoveryResult>({ 0298 UpnpDiscoveryResult(QStringLiteral("uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e"), 0299 QStringLiteral("uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e"), 0300 QStringLiteral("http://127.0.0.1:8200/rootDesc.xml"), 0301 UpnpSsdpEngine::NotificationSubType::Invalid, 0302 QStringLiteral("mar., 27 oct. 2015 21:03:35 G\x7F"), 0303 1800), 0304 }); 0305 0306 QTest::newRow("device by type") << UpnpSsdpEngine::DeviceByType 0307 << QStringLiteral("schemas-upnp-org:device:MediaServer:1") 0308 << QByteArray("M-SEARCH * HTTP/1.1\r\n" 0309 "HOST: 239.255.255.250:11900\r\n" 0310 "MAN: \"ssdp:discover\"\r\n" 0311 "MX: 2\r\n" 0312 "ST: urn:schemas-upnp-org:device:MediaServer:1\r\n\r\n") 0313 << QStringList({ 0314 QStringLiteral("HTTP/1.1 200 OK\r\n" 0315 "CACHE-CONTROL: max-age=1800\r\n" 0316 "DATE: mar., 27 oct. 2015 21:03:35 G\x7F\r\n" 0317 "ST: urn:schemas-upnp-org:device:MediaServer:1\r\n" 0318 "USN: uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::urn:schemas-upnp-org:device:MediaServer:1\r\n" 0319 "EXT:\r\n" 0320 "SERVER: Debian DLNADOC/1.50 UPnP/1.0 MiniDLNA/1.1.4\r\n" 0321 "LOCATION: http://127.0.0.1:8200/rootDesc.xml\r\n" 0322 "Content-Length: 0\r\n\r\n"), 0323 }) 0324 << QList<UpnpDiscoveryResult>({ 0325 UpnpDiscoveryResult(QStringLiteral("urn:schemas-upnp-org:device:MediaServer:1"), 0326 QStringLiteral("uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::urn:schemas-upnp-org:device:MediaServer:1"), 0327 QStringLiteral("http://127.0.0.1:8200/rootDesc.xml"), 0328 UpnpSsdpEngine::NotificationSubType::Invalid, 0329 QStringLiteral("mar., 27 oct. 2015 21:03:35 G\x7F"), 0330 1800), 0331 }); 0332 0333 QTest::newRow("service by type") << UpnpSsdpEngine::ServiceByType 0334 << QStringLiteral("schemas-upnp-org:service:ConnectionManager:1") 0335 << QByteArray("M-SEARCH * HTTP/1.1\r\n" 0336 "HOST: 239.255.255.250:11900\r\n" 0337 "MAN: \"ssdp:discover\"\r\n" 0338 "MX: 2\r\n" 0339 "ST: urn:schemas-upnp-org:service:ConnectionManager:1\r\n\r\n") 0340 << QStringList({ QStringLiteral("HTTP/1.1 200 OK\r\n" 0341 "CACHE-CONTROL: max-age=1800\r\n" 0342 "DATE: mar., 27 oct. 2015 21:03:35 G\x7F\r\n" 0343 "ST: urn:schemas-upnp-org:service:ConnectionManager:1\r\n" 0344 "USN: uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::urn:schemas-upnp-org:service:ConnectionManager:1\r\n" 0345 "EXT:\r\n" 0346 "SERVER: Debian DLNADOC/1.50 UPnP/1.0 MiniDLNA/1.1.4\r\n" 0347 "LOCATION: http://127.0.0.1:8200/rootDesc.xml\r\n" 0348 "Content-Length: 0\r\n\r\n") }) 0349 << QList<UpnpDiscoveryResult>({ 0350 UpnpDiscoveryResult(QStringLiteral("urn:schemas-upnp-org:service:ConnectionManager:1"), 0351 QStringLiteral("uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::urn:schemas-upnp-org:service:ConnectionManager:1"), 0352 QStringLiteral("http://127.0.0.1:8200/rootDesc.xml"), 0353 UpnpSsdpEngine::NotificationSubType::Invalid, 0354 QStringLiteral("mar., 27 oct. 2015 21:03:35 G\x7F"), 0355 1800), 0356 }); 0357 } 0358 0359 void searchAll() 0360 { 0361 QFETCH(UpnpSsdpEngine::SEARCH_TYPE, searchType); 0362 QFETCH(QString, searchCriteria); 0363 QFETCH(QByteArray, ssdpRequest); 0364 QFETCH(QStringList, ssdpAnswers); 0365 QFETCH(QList<UpnpDiscoveryResult>, results); 0366 0367 QScopedPointer<MockSsdpClient> newClient(new MockSsdpClient(11900, ssdpRequest, ssdpAnswers, false)); 0368 newClient->listen(); 0369 0370 UpnpSsdpEngine newEngine; 0371 newEngine.setPort(11900); 0372 newEngine.initialize(); 0373 0374 QSignalSpy newServiceSignal(&newEngine, &UpnpSsdpEngine::newService); 0375 0376 newEngine.searchUpnp(searchType, searchCriteria, 2); 0377 0378 newServiceSignal.wait(20000); 0379 0380 QCOMPARE(newServiceSignal.size(), results.size()); 0381 0382 for (int i = 0; i < results.size(); ++i) { 0383 auto firstService = newServiceSignal[i][0].value<UpnpDiscoveryResult>(); 0384 QCOMPARE(firstService.announceDate(), results[i].announceDate()); 0385 QCOMPARE(firstService.cacheDuration(), results[i].cacheDuration()); 0386 QCOMPARE(firstService.location(), results[i].location()); 0387 QCOMPARE(firstService.nt(), results[i].nt()); 0388 QCOMPARE(firstService.nts(), results[i].nts()); 0389 QCOMPARE(firstService.usn(), results[i].usn()); 0390 } 0391 } 0392 0393 void searchDeviceWaitTimeout_data() 0394 { 0395 QTest::addColumn<UpnpSsdpEngine::SEARCH_TYPE>("searchType"); 0396 QTest::addColumn<QString>("searchCriteria"); 0397 QTest::addColumn<QByteArray>("ssdpRequest"); 0398 QTest::addColumn<QStringList>("ssdpAnswers"); 0399 QTest::addColumn<QList<UpnpDiscoveryResult>>("results"); 0400 0401 QTest::newRow("root device") << UpnpSsdpEngine::RootDevices 0402 << QString() 0403 << QByteArray("M-SEARCH * HTTP/1.1\r\n" 0404 "HOST: 239.255.255.250:11900\r\n" 0405 "MAN: \"ssdp:discover\"\r\n" 0406 "MX: 2\r\n" 0407 "ST: upnp:rootdevice\r\n\r\n") 0408 << QStringList({ QStringLiteral("HTTP/1.1 200 OK\r\n" 0409 "CACHE-CONTROL: max-age=3\r\n" 0410 "DATE: mar., 27 oct. 2015 21:03:35 G\x7F\r\n" 0411 "ST: upnp:rootdevice\r\n" 0412 "USN: uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::upnp:rootdevice\r\n" 0413 "EXT:\r\n" 0414 "SERVER: Debian DLNADOC/1.50 UPnP/1.0 MiniDLNA/1.1.4\r\n" 0415 "LOCATION: http://127.0.0.1:8200/rootDesc.xml\r\n" 0416 "Content-Length: 0\r\n\r\n") }) 0417 << QList<UpnpDiscoveryResult>({ UpnpDiscoveryResult(QStringLiteral("upnp:rootdevice"), 0418 QStringLiteral("uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::upnp:rootdevice"), 0419 QStringLiteral("http://127.0.0.1:8200/rootDesc.xml"), 0420 UpnpSsdpEngine::NotificationSubType::Invalid, 0421 QStringLiteral("mar., 27 oct. 2015 21:03:35 G\x7F"), 0422 3) }); 0423 } 0424 0425 void searchDeviceWaitTimeout() 0426 { 0427 QFETCH(UpnpSsdpEngine::SEARCH_TYPE, searchType); 0428 QFETCH(QString, searchCriteria); 0429 QFETCH(QByteArray, ssdpRequest); 0430 QFETCH(QStringList, ssdpAnswers); 0431 QFETCH(QList<UpnpDiscoveryResult>, results); 0432 0433 QScopedPointer<MockSsdpClient> newClient(new MockSsdpClient(11900, ssdpRequest, ssdpAnswers, false)); 0434 newClient->listen(); 0435 0436 QScopedPointer<UpnpSsdpEngine> newEngine(new UpnpSsdpEngine); 0437 newEngine->setPort(11900); 0438 newEngine->initialize(); 0439 0440 QSignalSpy newServiceSignal(newEngine.data(), &UpnpSsdpEngine::newService); 0441 QSignalSpy removedServiceSignal(newEngine.data(), &UpnpSsdpEngine::removedService); 0442 0443 newEngine->searchUpnp(searchType, searchCriteria, 2); 0444 0445 newServiceSignal.wait(20000); 0446 0447 QCOMPARE(newServiceSignal.size(), results.size()); 0448 0449 for (int i = 0; i < results.size(); ++i) { 0450 auto firstService = newServiceSignal[i][0].value<UpnpDiscoveryResult>(); 0451 QCOMPARE(firstService.announceDate(), results[i].announceDate()); 0452 QCOMPARE(firstService.cacheDuration(), results[i].cacheDuration()); 0453 QCOMPARE(firstService.location(), results[i].location()); 0454 QCOMPARE(firstService.nt(), results[i].nt()); 0455 QCOMPARE(firstService.nts(), results[i].nts()); 0456 QCOMPARE(firstService.usn(), results[i].usn()); 0457 } 0458 0459 removedServiceSignal.wait(); 0460 0461 QVERIFY(removedServiceSignal.count() > 0); 0462 } 0463 0464 void searchDeviceWaitRefreshBeforeTimeout_data() 0465 { 0466 QTest::addColumn<UpnpSsdpEngine::SEARCH_TYPE>("searchType"); 0467 QTest::addColumn<QString>("searchCriteria"); 0468 QTest::addColumn<QByteArray>("ssdpRequest"); 0469 QTest::addColumn<QStringList>("ssdpAnswers"); 0470 QTest::addColumn<QList<UpnpDiscoveryResult>>("results"); 0471 QTest::addColumn<bool>("needAutoRefresh"); 0472 QTest::addColumn<int>("refreshPeriod"); 0473 QTest::addColumn<QStringList>("refreshMessages"); 0474 0475 QTest::newRow("root device with refresh") << UpnpSsdpEngine::RootDevices 0476 << QString() 0477 << QByteArray("M-SEARCH * HTTP/1.1\r\n" 0478 "HOST: 239.255.255.250:11900\r\n" 0479 "MAN: \"ssdp:discover\"\r\n" 0480 "MX: 2\r\n" 0481 "ST: upnp:rootdevice\r\n\r\n") 0482 << QStringList({ QStringLiteral("HTTP/1.1 200 OK\r\n" 0483 "CACHE-CONTROL: max-age=4\r\n" 0484 "DATE: mar., 27 oct. 2015 21:03:35 G\x7F\r\n" 0485 "ST: upnp:rootdevice\r\n" 0486 "USN: uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::upnp:rootdevice\r\n" 0487 "EXT:\r\n" 0488 "SERVER: Debian DLNADOC/1.50 UPnP/1.0 MiniDLNA/1.1.4\r\n" 0489 "LOCATION: http://127.0.0.1:8200/rootDesc.xml\r\n" 0490 "Content-Length: 0\r\n\r\n") }) 0491 << QList<UpnpDiscoveryResult>({ UpnpDiscoveryResult(QStringLiteral("upnp:rootdevice"), 0492 QStringLiteral("uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::upnp:rootdevice"), 0493 QStringLiteral("http://127.0.0.1:8200/rootDesc.xml"), 0494 UpnpSsdpEngine::NotificationSubType::Invalid, 0495 QStringLiteral("mar., 27 oct. 2015 21:03:35 G\x7F"), 0496 4) }) 0497 << true 0498 << 3 0499 << QStringList({ QStringLiteral("NOTIFY * HTTP/1.1 200 OK\r\n" 0500 "CACHE-CONTROL: max-age=4\r\n" 0501 "HOST: 239.255.255.250:1900\r\n" 0502 "NT: upnp:rootdevice\r\n" 0503 "USN: uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::upnp:rootdevice\r\n" 0504 "NTS: ssdp:alive\r\n" 0505 "SERVER: Debian DLNADOC/1.50 UPnP/1.0 MiniDLNA/1.1.4\r\n" 0506 "LOCATION: http://127.0.0.1:8200/rootDesc.xml\r\n" 0507 "Content-Length: 0\r\n\r\n") }); 0508 0509 QTest::newRow("root device without refresh") << UpnpSsdpEngine::RootDevices 0510 << QString() 0511 << QByteArray("M-SEARCH * HTTP/1.1\r\n" 0512 "HOST: 239.255.255.250:11900\r\n" 0513 "MAN: \"ssdp:discover\"\r\n" 0514 "MX: 2\r\n" 0515 "ST: upnp:rootdevice\r\n\r\n") 0516 << QStringList({ QStringLiteral("HTTP/1.1 200 OK\r\n" 0517 "CACHE-CONTROL: max-age=4\r\n" 0518 "DATE: mar., 27 oct. 2015 21:03:35 G\x7F\r\n" 0519 "ST: upnp:rootdevice\r\n" 0520 "USN: uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::upnp:rootdevice\r\n" 0521 "EXT:\r\n" 0522 "SERVER: Debian DLNADOC/1.50 UPnP/1.0 MiniDLNA/1.1.4\r\n" 0523 "LOCATION: http://127.0.0.1:8200/rootDesc.xml\r\n" 0524 "Content-Length: 0\r\n\r\n") }) 0525 << QList<UpnpDiscoveryResult>({ UpnpDiscoveryResult(QStringLiteral("upnp:rootdevice"), 0526 QStringLiteral("uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::upnp:rootdevice"), 0527 QStringLiteral("http://127.0.0.1:8200/rootDesc.xml"), 0528 UpnpSsdpEngine::NotificationSubType::Invalid, 0529 QStringLiteral("mar., 27 oct. 2015 21:03:35 G\x7F"), 0530 4) }) 0531 << false 0532 << 3 0533 << QStringList({}); 0534 } 0535 0536 void searchDeviceWaitRefreshBeforeTimeout() 0537 { 0538 QFETCH(UpnpSsdpEngine::SEARCH_TYPE, searchType); 0539 QFETCH(QString, searchCriteria); 0540 QFETCH(QByteArray, ssdpRequest); 0541 QFETCH(QStringList, ssdpAnswers); 0542 QFETCH(QList<UpnpDiscoveryResult>, results); 0543 QFETCH(bool, needAutoRefresh); 0544 QFETCH(int, refreshPeriod); 0545 QFETCH(QStringList, refreshMessages); 0546 0547 MockSsdpClient newClient(11900, ssdpRequest, ssdpAnswers, needAutoRefresh, refreshPeriod, refreshMessages); 0548 newClient.listen(); 0549 0550 UpnpSsdpEngine newEngine; 0551 newEngine.setPort(11900); 0552 newEngine.initialize(); 0553 0554 QSignalSpy newServiceSignal(&newEngine, &UpnpSsdpEngine::newService); 0555 QSignalSpy removedServiceSignal(&newEngine, &UpnpSsdpEngine::removedService); 0556 0557 newEngine.searchUpnp(searchType, searchCriteria, 2); 0558 0559 newServiceSignal.wait(20000); 0560 0561 QCOMPARE(newServiceSignal.size(), results.size()); 0562 0563 for (int i = 0; i < results.size(); ++i) { 0564 auto firstService = newServiceSignal[i][0].value<UpnpDiscoveryResult>(); 0565 QCOMPARE(firstService.announceDate(), results[i].announceDate()); 0566 QCOMPARE(firstService.cacheDuration(), results[i].cacheDuration()); 0567 QCOMPARE(firstService.location(), results[i].location()); 0568 QCOMPARE(firstService.nt(), results[i].nt()); 0569 QCOMPARE(firstService.nts(), results[i].nts()); 0570 QCOMPARE(firstService.usn(), results[i].usn()); 0571 } 0572 0573 removedServiceSignal.wait(10000); 0574 0575 if (needAutoRefresh) { 0576 QCOMPARE(removedServiceSignal.count(), 0); 0577 } else { 0578 QVERIFY(removedServiceSignal.count() > 0); 0579 } 0580 } 0581 0582 void listenNotify_data() 0583 { 0584 QTest::addColumn<QList<UpnpDiscoveryResult>>("results"); 0585 QTest::addColumn<int>("refreshPeriod"); 0586 QTest::addColumn<QStringList>("refreshMessages"); 0587 0588 QTest::newRow("root device with notify") 0589 << QList<UpnpDiscoveryResult>({ UpnpDiscoveryResult(QStringLiteral("upnp:rootdevice"), 0590 QStringLiteral("uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::upnp:rootdevice"), 0591 QStringLiteral("http://127.0.0.1:8200/rootDesc.xml"), 0592 UpnpSsdpEngine::NotificationSubType::Alive, 0593 QStringLiteral("mar., 27 oct. 2015 21:03:35 G\x7F"), 0594 4) }) 0595 << 3 0596 << QStringList({ QStringLiteral("NOTIFY * HTTP/1.1 200 OK\r\n" 0597 "CACHE-CONTROL: max-age=4\r\n" 0598 "HOST: 239.255.255.250:1900\r\n" 0599 "NT: upnp:rootdevice\r\n" 0600 "USN: uuid:4d696e69-444c-164e-9d41-ecf4bb9c317e::upnp:rootdevice\r\n" 0601 "NTS: ssdp:alive\r\n" 0602 "SERVER: Debian DLNADOC/1.50 UPnP/1.0 MiniDLNA/1.1.4\r\n" 0603 "LOCATION: http://127.0.0.1:8200/rootDesc.xml\r\n" 0604 "Content-Length: 0\r\n\r\n") }); 0605 } 0606 0607 void listenNotify() 0608 { 0609 QFETCH(QList<UpnpDiscoveryResult>, results); 0610 QFETCH(int, refreshPeriod); 0611 QFETCH(QStringList, refreshMessages); 0612 0613 QScopedPointer<MockSsdpClient> newClient(new MockSsdpClient(11900, QByteArray(), QStringList({}), true, refreshPeriod, refreshMessages)); 0614 newClient->listen(); 0615 0616 QScopedPointer<UpnpSsdpEngine> newEngine(new UpnpSsdpEngine); 0617 newEngine->setPort(11900); 0618 newEngine->initialize(); 0619 0620 QSignalSpy newServiceSignal(newEngine.data(), &UpnpSsdpEngine::newService); 0621 QSignalSpy removedServiceSignal(newEngine.data(), &UpnpSsdpEngine::removedService); 0622 0623 newServiceSignal.wait(); 0624 0625 QVERIFY(newServiceSignal.size() == results.size()); 0626 0627 for (int i = 0; i < results.size(); ++i) { 0628 auto firstService = newServiceSignal[i][0].value<UpnpDiscoveryResult>(); 0629 QVERIFY(firstService.cacheDuration() == results[i].cacheDuration()); 0630 QVERIFY(firstService.location() == results[i].location()); 0631 QVERIFY(firstService.nt() == results[i].nt()); 0632 QVERIFY(firstService.nts() == results[i].nts()); 0633 QVERIFY(firstService.usn() == results[i].usn()); 0634 } 0635 0636 removedServiceSignal.wait(10000); 0637 0638 QCOMPARE(removedServiceSignal.count(), 0); 0639 } 0640 }; 0641 0642 QTEST_MAIN(SsdpTests) 0643 0644 #include "ssdptests.moc"