feat: Delay M-SEARCH response by a random value according to MX header (#844)

This commit is contained in:
Murat Seker 2020-06-28 23:19:06 +02:00 committed by GitHub
parent 458113f8f9
commit db8b872217
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 32 deletions

View File

@ -12,7 +12,7 @@ static const quint16 SSDP_PORT(1900);
static const QString UPNP_DISCOVER_MESSAGE = "M-SEARCH * HTTP/1.1\r\n" static const QString UPNP_DISCOVER_MESSAGE = "M-SEARCH * HTTP/1.1\r\n"
"HOST: 239.255.255.250:1900\r\n" "HOST: 239.255.255.250:1900\r\n"
"MAN: \"ssdp:discover\"\r\n" "MAN: \"ssdp:discover\"\r\n"
"MX: 1\r\n" "MX: 1\r\n"
"ST: %1\r\n" "ST: %1\r\n"
"\r\n"; "\r\n";
@ -49,7 +49,6 @@ const QString SSDPDiscover::getFirstService(const searchType& type, const QStrin
QByteArray datagram; QByteArray datagram;
while (_udpSocket->hasPendingDatagrams()) while (_udpSocket->hasPendingDatagrams())
{ {
datagram.resize(_udpSocket->pendingDatagramSize()); datagram.resize(_udpSocket->pendingDatagramSize());
QHostAddress sender; QHostAddress sender;
quint16 senderPort; quint16 senderPort;
@ -163,13 +162,15 @@ void SSDPDiscover::readPendingDatagrams()
if(entry.contains("HTTP/1.1")) if(entry.contains("HTTP/1.1"))
continue; continue;
// split into key:vale, be aware that value field may contain also a ":" // split into key:value, be aware that value field may contain also a ":"
entry = entry.simplified(); entry = entry.simplified();
int pos = entry.indexOf(":"); int pos = entry.indexOf(":");
if(pos == -1) if(pos == -1)
continue; continue;
headers[entry.left(pos).trimmed().toLower()] = entry.mid(pos+1).trimmed(); const QString key = entry.left(pos).trimmed().toLower();
const QString value = entry.mid(pos + 1).trimmed();
headers[key] = value;
} }
// verify ssdp spec // verify ssdp spec
@ -185,7 +186,7 @@ void SSDPDiscover::readPendingDatagrams()
_usnList << headers.value("usn"); _usnList << headers.value("usn");
//Debug(_log, "Received msearch response from '%s:%d'. Search target: %s",QSTRING_CSTR(sender.toString()), senderPort, QSTRING_CSTR(headers.value("st"))); //Debug(_log, "Received msearch response from '%s:%d'. Search target: %s",QSTRING_CSTR(sender.toString()), senderPort, QSTRING_CSTR(headers.value("st")));
QUrl url(headers.value("location")); QUrl url(headers.value("location"));
emit newService(url.host()+":"+QString::number(url.port())); emit newService(url.host() + ":" + QString::number(url.port()));
} }
} }
} }
@ -194,7 +195,5 @@ void SSDPDiscover::sendSearch(const QString& st)
{ {
const QString msg = UPNP_DISCOVER_MESSAGE.arg(st); const QString msg = UPNP_DISCOVER_MESSAGE.arg(st);
_udpSocket->writeDatagram(msg.toUtf8(), _udpSocket->writeDatagram(msg.toUtf8(), QHostAddress(SSDP_ADDR), SSDP_PORT);
QHostAddress(SSDP_ADDR),
SSDP_PORT);
} }

View File

@ -150,13 +150,28 @@ const QString SSDPHandler::getLocalAddress()
void SSDPHandler::handleMSearchRequest(const QString& target, const QString& mx, const QString address, const quint16 & port) void SSDPHandler::handleMSearchRequest(const QString& target, const QString& mx, const QString address, const quint16 & port)
{ {
// TODO Response delay according to MX field (sec) random between 0 and MX const auto respond = [=] () {
// when searched for all devices / root devices / basic device
if(target == "ssdp:all")
sendMSearchResponse(SSDP_HYPERION_ST, address, port);
else if(target == "upnp:rootdevice" || target == "urn:schemas-upnp-org:device:basic:1" || target == SSDP_HYPERION_ST)
sendMSearchResponse(target, address, port);
};
// when searched for all devices / root devices / basic device bool ok = false;
if(target == "ssdp:all") int maxDelay = mx.toInt(&ok);
sendMSearchResponse(SSDP_HYPERION_ST, address, port); if (ok)
else if(target == "upnp:rootdevice" || target == "urn:schemas-upnp-org:device:basic:1" || target == SSDP_HYPERION_ST) {
sendMSearchResponse(target, address, port); /* Pick a random delay between 0 and MX seconds */
int randomDelay = qrand() % (maxDelay * 1000);
QTimer::singleShot(randomDelay, respond);
}
else
{
/* MX Header is not valid.
* Send response without delay */
respond();
}
} }
const QString SSDPHandler::getDescAddress() const QString SSDPHandler::getDescAddress()

View File

@ -163,8 +163,8 @@ void SSDPServer::readPendingDatagrams()
if (headers.value("man") == "\"ssdp:discover\"") if (headers.value("man") == "\"ssdp:discover\"")
{ {
//Debug(_log, "Received msearch from '%s:%d'. Search target: %s",QSTRING_CSTR(sender.toString()), senderPort, QSTRING_CSTR(headers.value("st"))); //Debug(_log, "Received msearch from '%s:%d'. Search target: %s",QSTRING_CSTR(sender.toString()), senderPort, QSTRING_CSTR(headers.value("st")));
emit msearchRequestReceived(headers.value("st"), headers.value("mx"), sender.toString(), senderPort); emit msearchRequestReceived(headers.value("st"), headers.value("mx"), sender.toString(), senderPort);
} }
} }
} }
@ -181,9 +181,7 @@ void SSDPServer::sendMSearchResponse(const QString& st, const QString& senderIp,
, _jssPort , _jssPort
, _name ); , _name );
_udpSocket->writeDatagram(message.toUtf8(), _udpSocket->writeDatagram(message.toUtf8(), QHostAddress(senderIp), senderPort);
QHostAddress(senderIp),
senderPort);
} }
void SSDPServer::sendByeBye(const QString& st) void SSDPServer::sendByeBye(const QString& st)
@ -192,11 +190,8 @@ void SSDPServer::sendByeBye(const QString& st)
// we repeat 3 times // we repeat 3 times
quint8 rep = 0; quint8 rep = 0;
while(rep < 3) { while(rep++ < 3) {
_udpSocket->writeDatagram(message.toUtf8(), _udpSocket->writeDatagram(message.toUtf8(), QHostAddress(SSDP_ADDR), SSDP_PORT);
QHostAddress(SSDP_ADDR),
SSDP_PORT);
rep++;
} }
} }
@ -215,11 +210,8 @@ void SSDPServer::sendAlive(const QString& st)
// we repeat 3 times // we repeat 3 times
quint8 rep = 0; quint8 rep = 0;
while(rep < 3) { while(rep++ < 3) {
_udpSocket->writeDatagram(message.toUtf8(), _udpSocket->writeDatagram(message.toUtf8(), QHostAddress(SSDP_ADDR), SSDP_PORT);
QHostAddress(SSDP_ADDR),
SSDP_PORT);
rep++;
} }
} }
@ -229,7 +221,5 @@ void SSDPServer::sendUpdate(const QString& st)
, st , st
, _uuid+"::"+st ); , _uuid+"::"+st );
_udpSocket->writeDatagram(message.toUtf8(), _udpSocket->writeDatagram(message.toUtf8(), QHostAddress(SSDP_ADDR), SSDP_PORT);
QHostAddress(SSDP_ADDR),
SSDP_PORT);
} }