Skip to content

Commit 36f21e9

Browse files
committed
[SSDP] Send M-Search response appropriate for the network
M-Search responses should be sent with a LOCATION header which specifies an address that is reachable on the interface upon which the request was received. Prior to this change we were sending a response for each and every ip address on the system, which is not correct. Refs MythTV#341
1 parent 6bd517b commit 36f21e9

File tree

1 file changed

+51
-40
lines changed

1 file changed

+51
-40
lines changed

mythtv/libs/libmythupnp/upnptasksearch.cpp

Lines changed: 51 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <QDateTime>
1818
#include <QFile>
1919
#include <QStringList>
20+
#include <QNetworkInterface>
2021
#include <utility>
2122

2223
#include "upnp.h"
@@ -25,6 +26,7 @@
2526
#include "compat.h"
2627
#include "mythmiscutil.h"
2728
#include "mythdate.h"
29+
#include "mythlogging.h"
2830

2931
static QPair<QHostAddress, int> kLinkLocal6 =
3032
QHostAddress::parseSubnet("fe80::/10");
@@ -96,47 +98,56 @@ void UPnpSearchTask::SendMsg( MSocketDevice *pSocket,
9698
.arg(m_peerAddress.toString()) .arg(m_nPeerPort));
9799
#endif
98100

99-
for (const auto & addr : qAsConst(m_addressList))
101+
// TODO: When we add dynamic handling of interfaces the information
102+
// for each address on the system should be available from the
103+
// "central" location on request.
104+
//
105+
// loop through all available interfaces
106+
QList<QNetworkInterface> IFs = QNetworkInterface::allInterfaces();
107+
for (const auto & qni : qAsConst(IFs))
100108
{
101-
QString ipaddress;
102-
103-
// Avoid announcing the localhost address
104-
if (addr == QHostAddress::LocalHost ||
105-
addr == QHostAddress::LocalHostIPv6 ||
106-
addr == QHostAddress::AnyIPv4 ||
107-
addr == QHostAddress::AnyIPv6)
108-
continue;
109-
110-
QHostAddress ip = addr;
111-
// Descope the Link Local address. The scope is only valid
112-
// on the server sending the announcement, not the clients
113-
// that receive it
114-
ip.setScopeId(QString());
115-
116-
// If this looks like an IPv6 address, then enclose it in []'s
117-
if (ip.protocol() == QAbstractSocket::IPv6Protocol)
118-
ipaddress = "[" + ip.toString() + "]";
119-
else
120-
ipaddress = ip.toString();
121-
122-
QString sHeader = QString ( "HTTP/1.1 200 OK\r\n"
123-
"LOCATION: http://%1:%2/getDeviceDesc\r\n" )
124-
.arg( ipaddress )
125-
.arg( m_nServicePort);
126-
127-
128-
QString sPacket = sHeader + sData;
129-
QByteArray scPacket = sPacket.toUtf8();
130-
131-
// ------------------------------------------------------------------
132-
// Send Packet to UDP Socket (Send same packet twice)
133-
// ------------------------------------------------------------------
134-
135-
pSocket->writeBlock( scPacket, scPacket.length(), m_peerAddress,
136-
m_nPeerPort );
137-
std::this_thread::sleep_for( std::chrono::milliseconds( MythRandom() % 250 ));
138-
pSocket->writeBlock( scPacket, scPacket.length(), m_peerAddress,
139-
m_nPeerPort );
109+
QList<QNetworkAddressEntry> netAddressList = qni.addressEntries();
110+
for (const auto & netAddr : qAsConst(netAddressList))
111+
{
112+
QString ip_subnet = QString("%1/%2").arg(netAddr.ip().toString()).arg(netAddr.prefixLength());
113+
QPair<QHostAddress, int> subnet = QHostAddress::parseSubnet(ip_subnet);
114+
if (m_peerAddress.isInSubnet(subnet)) {
115+
LOG(VB_UPNP, LOG_DEBUG, QString("UPnpSearchTask::SendMsg : IP: [%1], Found network [%2], relevant to peer [%3]")
116+
.arg(netAddr.ip().toString()).arg(subnet.first.toString()).arg(m_peerAddress.toString()));
117+
118+
QString ipaddress;
119+
QHostAddress ip = netAddr.ip();
120+
// Descope the Link Local address. The scope is only valid
121+
// on the server sending the announcement, not the clients
122+
// that receive it
123+
ip.setScopeId(QString());
124+
125+
// If this looks like an IPv6 address, then enclose it in []'s
126+
if (ip.protocol() == QAbstractSocket::IPv6Protocol)
127+
ipaddress = "[" + ip.toString() + "]";
128+
else
129+
ipaddress = ip.toString();
130+
131+
QString sHeader = QString ( "HTTP/1.1 200 OK\r\n"
132+
"LOCATION: http://%1:%2/getDeviceDesc\r\n" )
133+
.arg( ipaddress )
134+
.arg( m_nServicePort);
135+
136+
137+
QString sPacket = sHeader + sData;
138+
QByteArray scPacket = sPacket.toUtf8();
139+
140+
// ------------------------------------------------------------------
141+
// Send Packet to UDP Socket (Send same packet twice)
142+
// ------------------------------------------------------------------
143+
144+
pSocket->writeBlock( scPacket, scPacket.length(), m_peerAddress,
145+
m_nPeerPort );
146+
std::this_thread::sleep_for( std::chrono::milliseconds( MythRandom() % 250 ));
147+
pSocket->writeBlock( scPacket, scPacket.length(), m_peerAddress,
148+
m_nPeerPort );
149+
}
150+
}
140151
}
141152
}
142153

0 commit comments

Comments
 (0)