[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