From b0cd672abf134443ff6424d92fd5b2738dca896a Mon Sep 17 00:00:00 2001 From: Vladislav Grishenko Date: Mon, 22 May 2017 22:17:03 +0500 Subject: [PATCH] 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. --- minissdp.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/minissdp.c b/minissdp.c index 7789076..545087a 100644 --- a/minissdp.c +++ b/minissdp.c @@ -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; @@ -165,13 +171,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;