From 34b934d6aa4cb6f3515c1b01af9c83e832293ca7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= <sybren@stuvel.eu>
Date: Wed, 23 Aug 2017 13:37:40 +0200
Subject: [PATCH] Allow SSDP discovery msg sending to fail on almost all
 address families

Some machines cause a PermissionError when sending to IPv6, but if IPv4
still works fine we should just use that instead. This change counts the
number of failed address families, and only if all of them fail we stop
the discovery.
---
 CHANGELOG.md                     |  1 +
 flamenco_worker/ssdp_discover.py | 23 ++++++++++++++++++-----
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ed911e41..6310e266 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ changed functionality, fixed bugs).
 - Fixed parsing of `--config` CLI param on Python 3.5
 - Added `--debug` CLI parameter to easily enable debug logging without having
   to edit `flamenco-worker.cfg`.
+- Only fail UPnP/SSDP discovery when it fails to send on both IPv4 and IPv6.
 
 
 ## Version 2.0.7 (released 2017-07-04)
diff --git a/flamenco_worker/ssdp_discover.py b/flamenco_worker/ssdp_discover.py
index 7407d384..a8a6d862 100644
--- a/flamenco_worker/ssdp_discover.py
+++ b/flamenco_worker/ssdp_discover.py
@@ -57,6 +57,8 @@ def find_flamenco_manager(timeout=1, retries=5):
     families_and_addresses = list(unique(interface_addresses()))
 
     for _ in range(retries):
+        failed_families = 0
+
         for family, addr in families_and_addresses:
             try:
                 dest = DESTINATIONS[family]
@@ -64,17 +66,23 @@ def find_flamenco_manager(timeout=1, retries=5):
                 log.warning('Unknown address family %s, skipping', family)
                 continue
 
-            log.debug('Sending to %s %s, dest=%s' % (family, addr, dest))
+            log.debug('Sending to %s %s, dest=%s', family, addr, dest)
 
             sock = socket.socket(family, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
             sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
             sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
             sock.bind((addr, 0))
 
-            for _ in range(2):
-                # sending it more than once will
-                # decrease the probability of a timeout
-                sock.sendto(DISCOVERY_MSG, (dest, 1900))
+            try:
+                for _ in range(2):
+                    # sending it more than once will
+                    # decrease the probability of a timeout
+                    sock.sendto(DISCOVERY_MSG, (dest, 1900))
+            except PermissionError:
+                log.info('Failed sending UPnP/SSDP discovery message to %s %s, dest=%s',
+                         family, addr, dest)
+                failed_families += 1
+                continue
 
             try:
                 data = sock.recv(1024)
@@ -84,6 +92,11 @@ def find_flamenco_manager(timeout=1, retries=5):
                 response = Response(data)
                 return response.getheader('Location')
 
+        if failed_families >= len(families_and_addresses):
+            log.error('Failed to send UPnP/SSDP discovery message '
+                      'to every address family (IPv4/IPv6)')
+            break
+
     raise DiscoveryFailed('Unable to find Flamenco Manager after %i tries' % retries)
 
 
-- 
GitLab