[vlc-devel] [PATCH] upnp: lookup the best interface to use libupnp with

Steve Lhomme robux4 at videolabs.io
Wed Jun 15 20:17:12 CEST 2016


libupnp cannot handle more than one interface/IP at a time, so we need to make
sure we use an appropriate one.
---
 modules/services_discovery/upnp.cpp | 68 +++++++++++++++++++++++++++++++++++--
 1 file changed, 66 insertions(+), 2 deletions(-)

diff --git a/modules/services_discovery/upnp.cpp b/modules/services_discovery/upnp.cpp
index ff86868..f8b240a 100644
--- a/modules/services_discovery/upnp.cpp
+++ b/modules/services_discovery/upnp.cpp
@@ -32,6 +32,7 @@
 #include <vlc_plugin.h>
 #include <vlc_interrupt.h>
 #include <vlc_services_discovery.h>
+#include <vlc_charset.h>
 
 #include <assert.h>
 #include <limits.h>
@@ -1253,6 +1254,67 @@ UpnpInstanceWrapper::~UpnpInstanceWrapper()
     UpnpFinish();
 }
 
+static char *getIpv4ForMulticast()
+{
+# ifdef _WIN32
+#  if !VLC_WINSTORE_APP || _WIN32_WINNT >= 0x0A00
+    ULONG addrSize = 32 * sizeof(IP_ADAPTER_ADDRESSES);
+    IP_ADAPTER_ADDRESSES *addresses = (IP_ADAPTER_ADDRESSES*) malloc(addrSize);
+    if (addresses == NULL)
+        return NULL;
+
+    unsigned long i_broadcast_ip = inet_addr("239.255.255.250");
+    ULONG erraddr = GetAdaptersAddresses( AF_INET,
+                                          GAA_FLAG_INCLUDE_GATEWAYS|GAA_FLAG_SKIP_ANYCAST|GAA_FLAG_SKIP_DNS_SERVER|GAA_FLAG_SKIP_FRIENDLY_NAME,
+                                          NULL, addresses, &addrSize );
+    if (erraddr != ERROR_SUCCESS)
+        goto err;
+
+    IP_ADAPTER_ADDRESSES *p_adapter = addresses;
+    while(p_adapter != NULL)
+    {
+        if(p_adapter->OperStatus == IfOperStatusUp && p_adapter->FirstGatewayAddress && p_adapter->Ipv4Enabled)
+        {
+            /* make sure it supports 239.255.255.250 */
+            IP_ADAPTER_MULTICAST_ADDRESS *p_multicast = p_adapter->FirstMulticastAddress;
+            while (p_multicast != NULL)
+            {
+                if (p_multicast->Address.lpSockaddr->sa_family == AF_INET)
+                {
+                    if (((struct sockaddr_in *)p_multicast->Address.lpSockaddr)->sin_addr.S_un.S_addr == i_broadcast_ip)
+                        break;
+                }
+                p_multicast = p_multicast->Next;
+            }
+            if (p_multicast != NULL)
+            {
+                /* get an IPv4 address */
+                IP_ADAPTER_UNICAST_ADDRESS *p_unicast = p_adapter->FirstUnicastAddress;
+                while (p_unicast != NULL)
+                {
+                    if (p_unicast->Address.lpSockaddr->sa_family == AF_INET )
+                    {
+                        wchar_t psz_uri[1026];
+                        DWORD strSize = sizeof( psz_uri ) / sizeof( wchar_t );
+                        if( WSAAddressToString( p_unicast->Address.lpSockaddr,
+                                                p_unicast->Address.iSockaddrLength,
+                                                NULL, psz_uri, &strSize ) == 0 )
+                            return FromWide( psz_uri );
+                    }
+                    p_unicast = p_unicast->Next;
+                }
+            }
+        }
+        p_adapter = p_adapter->Next;
+    }
+
+err:
+    free(addresses);
+#  endif /* GetAdaptersAddresses available */
+# endif /* _WIN32 */
+    return NULL;
+}
+
 UpnpInstanceWrapper *UpnpInstanceWrapper::get(vlc_object_t *p_obj, services_discovery_t *p_sd)
 {
     SD::MediaServerList *p_server_list = NULL;
@@ -1280,8 +1342,10 @@ UpnpInstanceWrapper *UpnpInstanceWrapper::get(vlc_object_t *p_obj, services_disc
         free( psz_miface );
     #else
         /* If UpnpInit2 isnt available, initialize on first IPv4-capable interface */
-        int i_res = UpnpInit( 0, 0 );
-    #endif
+        char *psz_hostip = getIpv4ForMulticast();
+        int i_res = UpnpInit( psz_hostip, 0 );
+        free(psz_hostip);
+    #endif /* UPNP_ENABLE_IPV6 */
         if( i_res != UPNP_E_SUCCESS )
         {
             msg_Err( p_obj, "Initialization failed: %s", UpnpGetErrorMessage( i_res ) );
-- 
2.8.2



More information about the vlc-devel mailing list