ssdp: fix M-SEARCH replies on non-linux OS and drop broadcast receiving due no read

On Darwin & *BSD binding to mcast address may force NITIFY packet send from
 this mcast address, not from primary interface address. Therefore subsequent
 NOTIFY packets might be ignored by some clients, including Samsung Smart TV
 and they will stop & disconnect after initial max-age timeout.

 SO_BROADCAST on notify packets is not needed, because there's no broadcasted
 M-SEARCH packets and notify socket queue is never read.
This commit is contained in:
Vladislav Grishenko 2017-05-22 22:17:03 +05:00 committed by Justin Maggard
parent d9f033aa43
commit b0cd672abf

View File

@ -113,11 +113,18 @@ OpenAndConfSSDPReceiveSocket(void)
memset(&sockname, 0, sizeof(struct sockaddr_in));
sockname.sin_family = AF_INET;
sockname.sin_port = htons(SSDP_PORT);
#ifdef __linux__
/* NOTE: Binding a socket to a UDP multicast address means, that we just want
* to receive datagramms send to this multicast address.
* To specify the local nics we want to use we have to use setsockopt,
* see AddMulticastMembership(...). */
sockname.sin_addr.s_addr = inet_addr(SSDP_MCAST_ADDR);
#else
/* NOTE: Binding to SSDP_MCAST_ADDR on Darwin & *BSD causes NOTIFY replies are
* sent from SSDP_MCAST_ADDR what forces some clients to ignore subsequent
* unsolicited NOTIFY packets from the real interface address. */
sockname.sin_addr.s_addr = htonl(INADDR_ANY);
#endif
if (bind(s, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)) < 0)
{
@ -136,7 +143,6 @@ OpenAndConfSSDPNotifySocket(struct lan_addr_s *iface)
{
int s;
unsigned char loopchar = 0;
int bcast = 1;
uint8_t ttl = 4;
struct in_addr mc_if;
struct sockaddr_in sockname;
@ -166,13 +172,6 @@ OpenAndConfSSDPNotifySocket(struct lan_addr_s *iface)
setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof(bcast)) < 0)
{
DPRINTF(E_ERROR, L_SSDP, "setsockopt(udp_notify, SO_BROADCAST): %s\n", strerror(errno));
close(s);
return -1;
}
memset(&sockname, 0, sizeof(struct sockaddr_in));
sockname.sin_family = AF_INET;
sockname.sin_addr.s_addr = iface->addr.s_addr;