[vlc-devel] [PATCH 2/3] upnp: move UpnpInstanceWrapper to upnp-wrapper
Shaleen Jain
shaleen at jain.sh
Wed Jun 27 13:30:33 CEST 2018
On Wed, 2018-06-27 at 04:26 -0700, Hugo Beauzée-Luyssen wrote:
> On Wed, Jun 27, 2018, at 4:23 AM, Shaleen Jain wrote:
> > On Wed, 2018-06-27 at 04:15 -0700, Hugo Beauzée-Luyssen wrote:
> > > On Wed, Jun 27, 2018, at 3:50 AM, Hugo Beauzée-Luyssen wrote:
> > > >
> > > >
> > > > On Mon, Jun 25, 2018, at 6:49 AM, Shaleen Jain wrote:
> > > > > Move out UpnpInstanceWrapper into its own file
> > > > > since it no longer has any dependencies on existing
> > > > > modules and allow other modules to get references to it.
> > > > > Move as well as the various helper functions that are
> > > > > directly required by the UpnpInstanceWrapper class
> > > > > and inline them for a small performance gain.
> > > > >
> > > > > ---
> > > > > modules/services_discovery/Makefile.am | 4 +-
> > > > > modules/services_discovery/upnp-wrapper.cpp | 156 ++++++++
> > > > > modules/services_discovery/upnp-wrapper.hpp | 349
> > > > > ++++++++++++++++++
> > > > > modules/services_discovery/upnp.cpp | 378 ----------
> > > > > ----
> > > > > ------
> > > > > modules/services_discovery/upnp.hpp | 66 +---
> > > > > 5 files changed, 509 insertions(+), 444 deletions(-)
> > > > > create mode 100644 modules/services_discovery/upnp-
> > > > > wrapper.cpp
> > > > > create mode 100644 modules/services_discovery/upnp-
> > > > > wrapper.hpp
> > > > >
> > > > > diff --git a/modules/services_discovery/Makefile.am
> > > > > b/modules/
> > > > > services_discovery/Makefile.am
> > > > > index 41c7871a29..f63df23b32 100644
> > > > > --- a/modules/services_discovery/Makefile.am
> > > > > +++ b/modules/services_discovery/Makefile.am
> > > > > @@ -26,7 +26,9 @@ libmtp_plugin_la_LIBADD = $(MTP_LIBS)
> > > > > EXTRA_LTLIBRARIES += libmtp_plugin.la
> > > > > sd_LTLIBRARIES += $(LTLIBmtp)
> > > > >
> > > > > -libupnp_plugin_la_SOURCES = services_discovery/upnp.cpp
> > > > > services_discovery/upnp.hpp
> > > > > +libupnp_plugin_la_SOURCES = services_discovery/upnp.cpp
> > > > > services_discovery/upnp.hpp \
> > > > > + services_discovery/upnp-
> > > > > wrapper.hpp
> > > > > \
> > > > > + services_discovery/upnp-
> > > > > wrapper.cpp
> > > > > libupnp_plugin_la_CXXFLAGS = $(AM_CXXFLAGS) $(UPNP_CFLAGS)
> > > > > libupnp_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(sddir)'
> > > > > libupnp_plugin_la_LIBADD = $(UPNP_LIBS)
> > > > > diff --git a/modules/services_discovery/upnp-wrapper.cpp
> > > > > b/modules/
> > > > > services_discovery/upnp-wrapper.cpp
> > > > > new file mode 100644
> > > > > index 0000000000..e1f167a5a7
> > > > > --- /dev/null
> > > > > +++ b/modules/services_discovery/upnp-wrapper.cpp
> > > > > @@ -0,0 +1,156 @@
> > > > > +/
> > > > > *************************************************************
> > > > > ****
> > > > > ************
> > > > > + * upnp-wrapper.cpp : UPnP Instance Wrapper class
> > > > > +
> > > > > *************************************************************
> > > > > ****
> > > > > ************
> > > > > + * Copyright © 2004-2018 VLC authors and VideoLAN
> > > > > + * $Id$
> > > > > + *
> > > > > + * Authors: Rémi Denis-Courmont <rem # videolan.org>
> > > > > (original
> > > > > plugin)
> > > > > + * Christian Henz <henz # c-lab.de>
> > > > > + * Mirsal Ennaime <mirsal dot ennaime at gmail dot
> > > > > com>
> > > > > + * Hugo Beauzée-Luyssen <hugo at beauzee.fr>
> > > > > + * Shaleen Jain <shaleen at jain.sh>
> > > > > + *
> > > > > + * This program is free software; you can redistribute it
> > > > > and/or
> > > > > modify
> > > > > it
> > > > > + * under the terms of the GNU Lesser General Public License
> > > > > as
> > > > > published by
> > > > > + * the Free Software Foundation; either version 2.1 of the
> > > > > License, or
> > > > > + * (at your option) any later version.
> > > > > + *
> > > > > + * This program is distributed in the hope that it will be
> > > > > useful,
> > > > > + * but WITHOUT ANY WARRANTY; without even the implied
> > > > > warranty
> > > > > of
> > > > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
> > > > > the
> > > > > + * GNU Lesser General Public License for more details.
> > > > > + *
> > > > > + * You should have received a copy of the GNU Lesser General
> > > > > Public
> > > > > License
> > > > > + * along with this program; if not, write to the Free
> > > > > Software
> > > > > Foundation,
> > > > > + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-
> > > > > 1301,
> > > > > USA.
> > > > > +
> > > > > *************************************************************
> > > > > ****
> > > > > ************/
> > > > > +
> > > > > +#include "upnp-wrapper.hpp"
> > > > > +
> > > > > +UpnpInstanceWrapper* UpnpInstanceWrapper::s_instance;
> > > > > +UpnpInstanceWrapper::Listeners
> > > > > UpnpInstanceWrapper::s_listeners;
> > > > > +vlc_mutex_t UpnpInstanceWrapper::s_lock = VLC_STATIC_MUTEX;
> > > > > +
> > > > > +UpnpInstanceWrapper::UpnpInstanceWrapper()
> > > > > + : m_handle( -1 )
> > > > > + , m_refcount( 0 )
> > > > > +{
> > > > > +}
> > > > > +
> > > > > +UpnpInstanceWrapper::~UpnpInstanceWrapper()
> > > > > +{
> > > > > + UpnpUnRegisterClient( m_handle );
> > > > > + UpnpFinish();
> > > > > +}
> > > > > +
> > > > > +UpnpInstanceWrapper *UpnpInstanceWrapper::get(vlc_object_t
> > > > > *p_obj)
> > > > > +{
> > > > > + vlc_mutex_locker lock( &s_lock );
> > > > > + if ( s_instance == NULL )
> > > > > + {
> > > > > + UpnpInstanceWrapper* instance = new(std::nothrow)
> > > > > UpnpInstanceWrapper;
> > > > > + if ( unlikely( !instance ) )
> > > > > + {
> > > > > + return NULL;
> > > > > + }
> > > > > +
> > > > > + #ifdef UPNP_ENABLE_IPV6
> > > > > + char* psz_miface = var_InheritString( p_obj,
> > > > > "miface" );
> > > > > + if (psz_miface == NULL)
> > > > > + psz_miface = getPreferedAdapter();
> > > > > + msg_Info( p_obj, "Initializing libupnp on '%s'
> > > > > interface",
> > > > > psz_miface ? psz_miface : "default" );
> > > > > + int i_res = UpnpInit2( psz_miface, 0 );
> > > > > + free( psz_miface );
> > > > > + #else
> > > > > + /* If UpnpInit2 isnt available, initialize on first
> > > > > IPv4-
> > > > > capable interface */
> > > > > + 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 ) );
> > > > > + delete instance;
> > > > > + return NULL;
> > > > > + }
> > > > > +
> > > > > + ixmlRelaxParser( 1 );
> > > > > +
> > > > > + /* Register a control point */
> > > > > + i_res = UpnpRegisterClient( Callback, instance,
> > > > > &instance-
> > > > > > m_handle );
> > > > >
> > > > > + if( i_res != UPNP_E_SUCCESS )
> > > > > + {
> > > > > + msg_Err( p_obj, "Client registration failed:
> > > > > %s",
> > > > > UpnpGetErrorMessage( i_res ) );
> > > > > + delete instance;
> > > > > + return NULL;
> > > > > + }
> > > > > +
> > > > > + /* libupnp does not treat a maximum content length
> > > > > of 0
> > > > > as
> > > > > unlimited
> > > > > + * until 64dedf (~ pupnp v1.6.7) and provides no
> > > > > sane
> > > > > way to
> > > > > discriminate
> > > > > + * between versions */
> > > > > + if( (i_res = UpnpSetMaxContentLength( INT_MAX )) !=
> > > > > UPNP_E_SUCCESS )
> > > > > + {
> > > > > + msg_Err( p_obj, "Failed to set maximum content
> > > > > length: %s",
> > > > > + UpnpGetErrorMessage( i_res ));
> > > > > + delete instance;
> > > > > + return NULL;
> > > > > + }
> > > > > + s_instance = instance;
> > > > > + }
> > > > > + s_instance->m_refcount++;
> > > > > + return s_instance;
> > > > > +}
> > > > > +
> > > > > +void UpnpInstanceWrapper::release()
> > > > > +{
> > > > > + UpnpInstanceWrapper *p_delete = NULL;
> > > > > + vlc_mutex_lock( &s_lock );
> > > > > + if (--s_instance->m_refcount == 0)
> > > > > + {
> > > > > + p_delete = s_instance;
> > > > > + s_instance = NULL;
> > > > > + }
> > > > > + vlc_mutex_unlock( &s_lock );
> > > > > + delete p_delete;
> > > > > +}
> > > > > +
> > > > > +UpnpClient_Handle UpnpInstanceWrapper::handle() const
> > > > > +{
> > > > > + return m_handle;
> > > > > +}
> > > > > +
> > > > > +int UpnpInstanceWrapper::Callback(Upnp_EventType
> > > > > event_type,
> > > > > UpnpEventPtr p_event, void *p_user_data)
> > > > > +{
> > > > > + for (Listeners::iterator iter = s_listeners.begin();
> > > > > iter
> > > > > !=
> > > > > s_listeners.end(); ++iter)
> > > > > + {
> > > > > + (*iter)->onEvent(event_type, p_event, p_user_data);
> > > > > + }
> > > > > +
> > > > > + return 0;
> > > > > +}
> > > > > +
> > > > > +void UpnpInstanceWrapper::addListener(ListenerPtr listener)
> > > > > +{
> > > > > + vlc_mutex_lock( &s_lock );
> > > > > + if ( std::find( s_listeners.begin(), s_listeners.end(),
> > > > > listener) !
> > > > > = s_listeners.end() )
> > > > > + {
> > > > > + vlc_mutex_unlock( &s_lock );
> > > > > + return;
> > > > > + }
> > > > > + s_listeners.push_back( std::move(listener) );
> > > > > + vlc_mutex_unlock( &s_lock );
> > > > > +}
> > > > > +
> > > > > +void UpnpInstanceWrapper::removeListener(ListenerPtr
> > > > > listener)
> > > > > +{
> > > > > + vlc_mutex_lock( &s_lock );
> > > > > + Listeners::iterator iter = std::find(
> > > > > s_listeners.begin(),
> > > > > s_listeners.end(), listener );
> > > > > + if ( iter == s_listeners.end() )
> > > > > + {
> > > > > + vlc_mutex_unlock( &s_lock );
> > > > > + return;
> > > > > + }
> > > > > +
> > > > > + s_listeners.erase( iter );
> > > > > + vlc_mutex_unlock( &s_lock );
> > > > > +}
> > > > > diff --git a/modules/services_discovery/upnp-wrapper.hpp
> > > > > b/modules/
> > > > > services_discovery/upnp-wrapper.hpp
> > > > > new file mode 100644
> > > > > index 0000000000..e8952a152a
> > > > > --- /dev/null
> > > > > +++ b/modules/services_discovery/upnp-wrapper.hpp
> > > > > @@ -0,0 +1,349 @@
> > > > > +/
> > > > > *************************************************************
> > > > > ****
> > > > > ************
> > > > > + * upnp-wrapper.cpp : UPnP Instance Wrapper class header
> > > >
> > > > Copy paste mistake :)
> > > >
> > > > > +
> > > > > *************************************************************
> > > > > ****
> > > > > ************
> > > > > + * Copyright © 2004-2018 VLC authors and VideoLAN
> > > > > + * $Id$
> > > >
> > > > Feel free to remove the $Id$ svn relicate
> > > >
> > > > > + *
> > > > > + * Authors: Rémi Denis-Courmont <rem # videolan.org>
> > > > > (original
> > > > > plugin)
> > > > > + * Christian Henz <henz # c-lab.de>
> > > > > + * Mirsal Ennaime <mirsal dot ennaime at gmail dot
> > > > > com>
> > > > > + * Hugo Beauzée-Luyssen <hugo at beauzee.fr>
> > > > > + * Shaleen Jain <shaleen at jain.sh>
> > > > > + *
> > > > > + * This program is free software; you can redistribute it
> > > > > and/or
> > > > > modify
> > > > > it
> > > > > + * under the terms of the GNU Lesser General Public License
> > > > > as
> > > > > published by
> > > > > + * the Free Software Foundation; either version 2.1 of the
> > > > > License, or
> > > > > + * (at your option) any later version.
> > > > > + *
> > > > > + * This program is distributed in the hope that it will be
> > > > > useful,
> > > > > + * but WITHOUT ANY WARRANTY; without even the implied
> > > > > warranty
> > > > > of
> > > > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
> > > > > the
> > > > > + * GNU Lesser General Public License for more details.
> > > > > + *
> > > > > + * You should have received a copy of the GNU Lesser General
> > > > > Public
> > > > > License
> > > > > + * along with this program; if not, write to the Free
> > > > > Software
> > > > > Foundation,
> > > > > + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-
> > > > > 1301,
> > > > > USA.
> > > > > +
> > > > > *************************************************************
> > > > > ****
> > > > > ************/
> > > > > +
> > > > > +#ifdef HAVE_CONFIG_H
> > > > > +# include "config.h"
> > > > > +#endif
> > > >
> > > > Although it was previously included from upnp.h, config.h
> > > > should
> > > > be
> > > > included from the source rather than the header.
> > > >
> > > > It's also fine to fix this in a separated commit though, since
> > > > you're
> > > > just moving code around in this one
> > > >
> > > > > +
> > > > > +#include <memory>
> > > > > +#include <vector>
> > > > > +#include <algorithm>
> > > > > +#include <assert.h>
> > > > > +
> > > > > +#include <upnp/upnp.h>
> > > > > +#include <upnp/upnptools.h>
> > > > > +
> > > > > +#include <vlc_common.h>
> > > > > +
> > > > > +#if UPNP_VERSION < 10800
> > > > > +typedef void* UpnpEventPtr;
> > > > > +#else
> > > > > +typedef const void* UpnpEventPtr;
> > > > > +#endif
> > > > > +
> > > > > +/**
> > > > > + * libUpnp allows only one instance per process, so we
> > > > > create a
> > > > > wrapper
> > > > > + * class around it that acts and behaves as a singleton.
> > > > > Letting
> > > > > us get
> > > > > + * multiple references to it but only ever having a single
> > > > > instance in
> > > > > memory.
> > > > > + * At the same time we let any module wishing to get a
> > > > > callback
> > > > > from
> > > > > the library
> > > > > + * to register a UpnpInstanceWrapper::Listener to get the
> > > > > Listener#onEvent()
> > > > > + * callback without having any hard dependencies.
> > > > > + */
> > > > > +class UpnpInstanceWrapper
> > > > > +{
> > > > > +public:
> > > > > + class Listener
> > > > > + {
> > > > > + public:
> > > > > + virtual ~Listener() {}
> > > > > + virtual int onEvent( Upnp_EventType event_type,
> > > > > + UpnpEventPtr p_event,
> > > > > + void* p_user_data ) = 0;
> > > > > + };
> > > > > +
> > > > > +private:
> > > > > + static UpnpInstanceWrapper* s_instance;
> > > > > + static vlc_mutex_t s_lock;
> > > > > + UpnpClient_Handle m_handle;
> > > > > + int m_refcount;
> > > > > + typedef std::shared_ptr<Listener> ListenerPtr;
> > > > > + typedef std::vector<ListenerPtr> Listeners;
> > > > > + static Listeners s_listeners;
> > > > > +
> > > > > +public:
> > > > > + // This increases the refcount before returning the
> > > > > instance
> > > > > + static UpnpInstanceWrapper* get( vlc_object_t* p_obj );
> > > > > + void release();
> > > > > + UpnpClient_Handle handle() const;
> > > > > + void addListener(ListenerPtr listener);
> > > > > + void removeListener(ListenerPtr listener);
> > > > > +
> > > > > +private:
> > > > > + static int Callback( Upnp_EventType event_type,
> > > > > UpnpEventPtr
> > > > > p_event, void* p_user_data );
> > > > > +
> > > > > + UpnpInstanceWrapper();
> > > > > + ~UpnpInstanceWrapper();
> > > > > +};
> > > > > +
> > > > > +// **************************
> > > > > +// Helper functions
> > > > > +// **************************
> > > > > +
> > > > > +#if UPNP_VERSION < 10623
> > > > > +/*
> > > > > + * Compat functions and typedefs for libupnp prior to 1.8
> > > > > + */
> > > > > +
> > > > > +typedef Upnp_Discovery UpnpDiscovery;
> > > > > +typedef Upnp_Action_Complete UpnpActionComplete;
> > > > > +
> > > > > +inline const char* UpnpDiscovery_get_Location_cstr( const
> > > > > UpnpDiscovery* p_discovery )
> > > > > +{
> > > > > + return p_discovery->Location;
> > > > > +}
> > > > > +
> > > > > +inline const char* UpnpDiscovery_get_DeviceID_cstr( const
> > > > > UpnpDiscovery* p_discovery )
> > > > > +{
> > > > > + return p_discovery->DeviceId;
> > > > > +}
> > > > > +
> > > > > +inline static IXML_Document*
> > > > > UpnpActionComplete_get_ActionResult( const
> > > > > UpnpActionComplete* p_result )
> > > > > +{
> > > > > + return p_result->ActionResult;
> > > > > +}
> > > > > +#endif
> > > > > +
> > > > > +/*
> > > > > + * Returns the value of a child element, or NULL on error
> > > > > + */
> > > > > +inline const char* xml_getChildElementValue( IXML_Element*
> > > > > p_parent,
> > > > > + const
> > > > > char* psz_tag_name
> > > > > )
> > > > > +{
> > > > > + assert( p_parent );
> > > > > + assert( psz_tag_name );
> > > > > +
> > > > > + IXML_NodeList* p_node_list;
> > > > > + p_node_list = ixmlElement_getElementsByTagName(
> > > > > p_parent,
> > > > > psz_tag_name );
> > > > > + if ( !p_node_list ) return NULL;
> > > > > +
> > > > > + IXML_Node* p_element = ixmlNodeList_item( p_node_list, 0
> > > > > );
> > > > > + ixmlNodeList_free( p_node_list );
> > > > > + if ( !p_element ) return NULL;
> > > > > +
> > > > > + IXML_Node* p_text_node = ixmlNode_getFirstChild(
> > > > > p_element
> > > > > );
> > > > > + if ( !p_text_node ) return NULL;
> > > > > +
> > > > > + return ixmlNode_getNodeValue( p_text_node );
> > > > > +}
> > > > > +
> > > > > +#ifdef _WIN32
> > > > > +
> > > > > +inline IP_ADAPTER_MULTICAST_ADDRESS*
> > > > > getMulticastAddress(IP_ADAPTER_ADDRESSES* p_adapter)
> > > > > +{
> > > > > + const unsigned long i_broadcast_ip =
> > > > > inet_addr("239.255.255.250");
> > > > > +
> > > > > + IP_ADAPTER_MULTICAST_ADDRESS *p_multicast = p_adapter-
> > > > > > FirstMulticastAddress;
> > > > >
> > > > > + while (p_multicast != NULL)
> > > > > + {
> > > > > + if (((struct sockaddr_in *)p_multicast-
> > > > > > Address.lpSockaddr)-
> > > > > > sin_addr.S_un.S_addr == i_broadcast_ip)
> > > > >
> > > > > + return p_multicast;
> > > > > + p_multicast = p_multicast->Next;
> > > > > + }
> > > > > + return NULL;
> > > > > +}
> > > > > +
> > > > > +inline bool isAdapterSuitable(IP_ADAPTER_ADDRESSES*
> > > > > p_adapter,
> > > > > bool
> > > > > ipv6)
> > > > > +{
> > > > > + if ( p_adapter->OperStatus != IfOperStatusUp )
> > > > > + return false;
> > > > > + if (p_adapter->Length ==
> > > > > sizeof(IP_ADAPTER_ADDRESSES_XP))
> > > > > + {
> > > > > + IP_ADAPTER_ADDRESSES_XP* p_adapter_xp =
> > > > > reinterpret_cast<IP_ADAPTER_ADDRESSES_XP*>( p_adapter );
> > > > > + // On Windows Server 2003 and Windows XP, this
> > > > > member is
> > > > > zero
> > > > > if IPv4 is not available on the interface.
> > > > > + if (ipv6)
> > > > > + return p_adapter_xp->Ipv6IfIndex != 0;
> > > > > + return p_adapter_xp->IfIndex != 0;
> > > > > + }
> > > > > + IP_ADAPTER_ADDRESSES_LH* p_adapter_lh =
> > > > > reinterpret_cast<IP_ADAPTER_ADDRESSES_LH*>( p_adapter );
> > > > > + if (p_adapter_lh->FirstGatewayAddress == NULL)
> > > > > + return false;
> > > > > + if (ipv6)
> > > > > + return p_adapter_lh->Ipv6Enabled;
> > > > > + return p_adapter_lh->Ipv4Enabled;
> > > > > +}
> > > > > +
> > > > > +inline IP_ADAPTER_ADDRESSES* ListAdapters()
> > > > > +{
> > > > > + ULONG addrSize;
> > > > > + const ULONG queryFlags = GAA_FLAG_INCLUDE_GATEWAYS|
> > > > > GAA_FLAG_SKIP_ANYCAST|GAA_FLAG_SKIP_DNS_SERVER;
> > > > > + IP_ADAPTER_ADDRESSES* addresses = NULL;
> > > > > + HRESULT hr;
> > > > > +
> > > > > + /**
> > > > > + * https://msdn.microsoft.com/en-us/library/aa365915.asp
> > > > > x
> > > > > + *
> > > > > + * The recommended method of calling the
> > > > > GetAdaptersAddresses
> > > > > function is to pre-allocate a
> > > > > + * 15KB working buffer pointed to by the
> > > > > AdapterAddresses
> > > > > parameter. On typical computers,
> > > > > + * this dramatically reduces the chances that the
> > > > > GetAdaptersAddresses function returns
> > > > > + * ERROR_BUFFER_OVERFLOW, which would require calling
> > > > > GetAdaptersAddresses function multiple
> > > > > + * times. The example code illustrates this method of
> > > > > use.
> > > > > + */
> > > > > + addrSize = 15 * 1024;
> > > > > + do
> > > > > + {
> > > > > + free(addresses);
> > > > > + addresses = (IP_ADAPTER_ADDRESSES*)malloc( addrSize
> > > > > );
> > > > > + if (addresses == NULL)
> > > > > + return NULL;
> > > > > + hr = GetAdaptersAddresses(AF_UNSPEC, queryFlags,
> > > > > NULL,
> > > > > addresses, &addrSize);
> > > > > + } while (hr == ERROR_BUFFER_OVERFLOW);
> > > > > + if (hr != NO_ERROR) {
> > > > > + free(addresses);
> > > > > + return NULL;
> > > > > + }
> > > > > + return addresses;
> > > > > +}
> > > > > +
> > > > > +#ifdef UPNP_ENABLE_IPV6
> > > > > +
> > > > > +inline char* getPreferedAdapter()
> > > > > +{
> > > > > + IP_ADAPTER_ADDRESSES *p_adapter, *addresses;
> > > > > +
> > > > > + addresses = ListAdapters();
> > > > > + if (addresses == NULL)
> > > > > + return NULL;
> > > > > +
> > > > > + /* find one with multicast capabilities */
> > > > > + p_adapter = addresses;
> > > > > + while (p_adapter != NULL)
> > > > > + {
> > > > > + if (isAdapterSuitable( p_adapter, true ))
> > > > > + {
> > > > > + /* make sure it supports 239.255.255.250 */
> > > > > + IP_ADAPTER_MULTICAST_ADDRESS *p_multicast =
> > > > > getMulticastAddress( p_adapter );
> > > > > + if (p_multicast != NULL)
> > > > > + {
> > > > > + char* res = FromWide( p_adapter-
> > > > > >FriendlyName );
> > > > > + free( addresses );
> > > > > + return res;
> > > > > + }
> > > > > + }
> > > > > + p_adapter = p_adapter->Next;
> > > > > + }
> > > > > + free(addresses);
> > > > > + return NULL;
> > > > > +}
> > > > > +
> > > > > +#else
> > > > > +
> > > > > +inline char *getIpv4ForMulticast()
> > > > > +{
> > > > > + IP_ADAPTER_UNICAST_ADDRESS *p_best_ip = NULL;
> > > > > + wchar_t psz_uri[32];
> > > > > + DWORD strSize;
> > > > > + IP_ADAPTER_ADDRESSES *p_adapter, *addresses;
> > > > > +
> > > > > + addresses = ListAdapters();
> > > > > + if (addresses == NULL)
> > > > > + return NULL;
> > > > > +
> > > > > + /* find one with multicast capabilities */
> > > > > + p_adapter = addresses;
> > > > > + while (p_adapter != NULL)
> > > > > + {
> > > > > + if (isAdapterSuitable( p_adapter, false ))
> > > > > + {
> > > > > + /* make sure it supports 239.255.255.250 */
> > > > > + IP_ADAPTER_MULTICAST_ADDRESS *p_multicast =
> > > > > getMulticastAddress( p_adapter );
> > > > > + if (p_multicast != NULL)
> > > > > + {
> > > > > + /* get an IPv4 address */
> > > > > + IP_ADAPTER_UNICAST_ADDRESS *p_unicast =
> > > > > p_adapter-
> > > > > > FirstUnicastAddress;
> > > > >
> > > > > + while (p_unicast != NULL)
> > > > > + {
> > > > > + strSize = sizeof( psz_uri ) / sizeof(
> > > > > wchar_t );
> > > > > + if( WSAAddressToString( p_unicast-
> > > > > > Address.lpSockaddr,
> > > > >
> > > > > + p_unicast-
> > > > > > Address.iSockaddrLength,
> > > > >
> > > > > + NULL, psz_uri,
> > > > > &strSize )
> > > > > == 0 )
> > > > > + {
> > > > > + if ( p_best_ip == NULL ||
> > > > > + p_best_ip->ValidLifetime >
> > > > > p_unicast-
> > > > > > ValidLifetime )
> > > > >
> > > > > + {
> > > > > + p_best_ip = p_unicast;
> > > > > + }
> > > > > + }
> > > > > + p_unicast = p_unicast->Next;
> > > > > + }
> > > > > + }
> > > > > + }
> > > > > + p_adapter = p_adapter->Next;
> > > > > + }
> > > > > +
> > > > > + if ( p_best_ip != NULL )
> > > > > + goto done;
> > > > > +
> > > > > + /* find any with IPv4 */
> > > > > + p_adapter = addresses;
> > > > > + while (p_adapter != NULL)
> > > > > + {
> > > > > + if (isAdapterSuitable(p_adapter, false))
> > > > > + {
> > > > > + /* get an IPv4 address */
> > > > > + IP_ADAPTER_UNICAST_ADDRESS *p_unicast =
> > > > > p_adapter-
> > > > > > FirstUnicastAddress;
> > > > >
> > > > > + while (p_unicast != NULL)
> > > > > + {
> > > > > + strSize = sizeof( psz_uri ) / sizeof(
> > > > > wchar_t );
> > > > > + if( WSAAddressToString( p_unicast-
> > > > > > Address.lpSockaddr,
> > > > >
> > > > > + p_unicast-
> > > > > > Address.iSockaddrLength,
> > > > >
> > > > > + NULL, psz_uri,
> > > > > &strSize
> > > > > ) ==
> > > > > 0 )
> > > > > + {
> > > > > + if ( p_best_ip == NULL ||
> > > > > + p_best_ip->ValidLifetime >
> > > > > p_unicast-
> > > > > > ValidLifetime )
> > > > >
> > > > > + {
> > > > > + p_best_ip = p_unicast;
> > > > > + }
> > > > > + }
> > > > > + p_unicast = p_unicast->Next;
> > > > > + }
> > > > > + }
> > > > > + p_adapter = p_adapter->Next;
> > > > > + }
> > > > > +
> > > > > +done:
> > > > > + if (p_best_ip != NULL)
> > > > > + {
> > > > > + strSize = sizeof( psz_uri ) / sizeof( wchar_t );
> > > > > + WSAAddressToString( p_best_ip->Address.lpSockaddr,
> > > > > + p_best_ip-
> > > > > >Address.iSockaddrLength,
> > > > > + NULL, psz_uri, &strSize );
> > > > > + free(addresses);
> > > > > + return FromWide( psz_uri );
> > > > > + }
> > > > > + free(addresses);
> > > > > + return NULL;
> > > > > +}
> > > > > +#endif /* UPNP_ENABLE_IPV6 */
> > > > > +#else /* _WIN32 */
> > > > > +
> > > > > +#ifdef UPNP_ENABLE_IPV6
> > > > > +
> > > > > +inline char *getPreferedAdapter()
> > > > > +{
> > > > > + return NULL;
> > > > > +}
> > > > > +
> > > > > +#else
> > > > > +
> > > > > +inline char *getIpv4ForMulticast()
> > > > > +{
> > > > > + return NULL;
> > > > > +}
> > > > > +
> > > > > +#endif
> > > > > +
> > > > > +#endif /* _WIN32 */
> > > > > diff --git a/modules/services_discovery/upnp.cpp b/modules/
> > > > > services_discovery/upnp.cpp
> > > > > index fc81a847a2..26d9206b5f 100644
> > > > > --- a/modules/services_discovery/upnp.cpp
> > > > > +++ b/modules/services_discovery/upnp.cpp
> > > > > @@ -39,30 +39,6 @@
> > > > > #include <set>
> > > > > #include <string>
> > > > >
> > > > > -#if UPNP_VERSION < 10623
> > > > > -/*
> > > > > - * Compat functions and typedefs for libupnp prior to 1.8
> > > > > - */
> > > > > -
> > > > > -typedef Upnp_Discovery UpnpDiscovery;
> > > > > -typedef Upnp_Action_Complete UpnpActionComplete;
> > > > > -
> > > > > -static const char* UpnpDiscovery_get_Location_cstr( const
> > > > > UpnpDiscovery* p_discovery )
> > > > > -{
> > > > > - return p_discovery->Location;
> > > > > -}
> > > > > -
> > > > > -static const char* UpnpDiscovery_get_DeviceID_cstr( const
> > > > > UpnpDiscovery* p_discovery )
> > > > > -{
> > > > > - return p_discovery->DeviceId;
> > > > > -}
> > > > > -
> > > > > -static IXML_Document* UpnpActionComplete_get_ActionResult(
> > > > > const
> > > > > UpnpActionComplete* p_result )
> > > > > -{
> > > > > - return p_result->ActionResult;
> > > > > -}
> > > > > -#endif
> > > > > -
> > > > > /*
> > > > > * Constants
> > > > > */
> > > > > @@ -94,10 +70,6 @@ struct access_sys_t
> > > > > UpnpInstanceWrapper* p_upnp;
> > > > > };
> > > > >
> > > > > -UpnpInstanceWrapper* UpnpInstanceWrapper::s_instance;
> > > > > -UpnpInstanceWrapper::Listeners
> > > > > UpnpInstanceWrapper::s_listeners;
> > > > > -vlc_mutex_t UpnpInstanceWrapper::s_lock = VLC_STATIC_MUTEX;
> > > > > -
> > > > > /*
> > > > > * VLC callback prototypes
> > > > > */
> > > > > @@ -141,30 +113,6 @@ vlc_module_begin()
> > > > > VLC_SD_PROBE_SUBMODULE
> > > > > vlc_module_end()
> > > > >
> > > > > -
> > > > > -/*
> > > > > - * Returns the value of a child element, or NULL on error
> > > > > - */
> > > > > -const char* xml_getChildElementValue( IXML_Element*
> > > > > p_parent,
> > > > > - const
> > > > > char* psz_tag_name
> > > > > )
> > > > > -{
> > > > > - assert( p_parent );
> > > > > - assert( psz_tag_name );
> > > > > -
> > > > > - IXML_NodeList* p_node_list;
> > > > > - p_node_list = ixmlElement_getElementsByTagName(
> > > > > p_parent,
> > > > > psz_tag_name );
> > > > > - if ( !p_node_list ) return NULL;
> > > > > -
> > > > > - IXML_Node* p_element = ixmlNodeList_item( p_node_list, 0
> > > > > );
> > > > > - ixmlNodeList_free( p_node_list );
> > > > > - if ( !p_element ) return NULL;
> > > > > -
> > > > > - IXML_Node* p_text_node = ixmlNode_getFirstChild(
> > > > > p_element
> > > > > );
> > > > > - if ( !p_text_node ) return NULL;
> > > > > -
> > > > > - return ixmlNode_getNodeValue( p_text_node );
> > > > > -}
> > > > > -
> > > > > /*
> > > > > * Extracts the result document from a SOAP response
> > > > > */
> > > > > @@ -1309,329 +1257,3 @@ static void Close( vlc_object_t*
> > > > > p_this )
> > > > > }
> > > > >
> > > > > }
> > > > > -
> > > > > -UpnpInstanceWrapper::UpnpInstanceWrapper()
> > > > > - : m_handle( -1 )
> > > > > - , m_refcount( 0 )
> > > > > -{
> > > > > -}
> > > > > -
> > > > > -UpnpInstanceWrapper::~UpnpInstanceWrapper()
> > > > > -{
> > > > > - UpnpUnRegisterClient( m_handle );
> > > > > - UpnpFinish();
> > > > > -}
> > > > > -
> > > > > -#ifdef _WIN32
> > > > > -
> > > > > -static IP_ADAPTER_MULTICAST_ADDRESS*
> > > > > getMulticastAddress(IP_ADAPTER_ADDRESSES* p_adapter)
> > > > > -{
> > > > > - const unsigned long i_broadcast_ip =
> > > > > inet_addr("239.255.255.250");
> > > > > -
> > > > > - IP_ADAPTER_MULTICAST_ADDRESS *p_multicast = p_adapter-
> > > > > > FirstMulticastAddress;
> > > > >
> > > > > - while (p_multicast != NULL)
> > > > > - {
> > > > > - if (((struct sockaddr_in *)p_multicast-
> > > > > > Address.lpSockaddr)-
> > > > > > sin_addr.S_un.S_addr == i_broadcast_ip)
> > > > >
> > > > > - return p_multicast;
> > > > > - p_multicast = p_multicast->Next;
> > > > > - }
> > > > > - return NULL;
> > > > > -}
> > > > > -
> > > > > -static bool isAdapterSuitable(IP_ADAPTER_ADDRESSES*
> > > > > p_adapter,
> > > > > bool
> > > > > ipv6)
> > > > > -{
> > > > > - if ( p_adapter->OperStatus != IfOperStatusUp )
> > > > > - return false;
> > > > > - if (p_adapter->Length ==
> > > > > sizeof(IP_ADAPTER_ADDRESSES_XP))
> > > > > - {
> > > > > - IP_ADAPTER_ADDRESSES_XP* p_adapter_xp =
> > > > > reinterpret_cast<IP_ADAPTER_ADDRESSES_XP*>( p_adapter );
> > > > > - // On Windows Server 2003 and Windows XP, this
> > > > > member is
> > > > > zero
> > > > > if IPv4 is not available on the interface.
> > > > > - if (ipv6)
> > > > > - return p_adapter_xp->Ipv6IfIndex != 0;
> > > > > - return p_adapter_xp->IfIndex != 0;
> > > > > - }
> > > > > - IP_ADAPTER_ADDRESSES_LH* p_adapter_lh =
> > > > > reinterpret_cast<IP_ADAPTER_ADDRESSES_LH*>( p_adapter );
> > > > > - if (p_adapter_lh->FirstGatewayAddress == NULL)
> > > > > - return false;
> > > > > - if (ipv6)
> > > > > - return p_adapter_lh->Ipv6Enabled;
> > > > > - return p_adapter_lh->Ipv4Enabled;
> > > > > -}
> > > > > -
> > > > > -static IP_ADAPTER_ADDRESSES* ListAdapters()
> > > > > -{
> > > > > - ULONG addrSize;
> > > > > - const ULONG queryFlags = GAA_FLAG_INCLUDE_GATEWAYS|
> > > > > GAA_FLAG_SKIP_ANYCAST|GAA_FLAG_SKIP_DNS_SERVER;
> > > > > - IP_ADAPTER_ADDRESSES* addresses = NULL;
> > > > > - HRESULT hr;
> > > > > -
> > > > > - /**
> > > > > - * https://msdn.microsoft.com/en-us/library/aa365915.asp
> > > > > x
> > > > > - *
> > > > > - * The recommended method of calling the
> > > > > GetAdaptersAddresses
> > > > > function is to pre-allocate a
> > > > > - * 15KB working buffer pointed to by the
> > > > > AdapterAddresses
> > > > > parameter. On typical computers,
> > > > > - * this dramatically reduces the chances that the
> > > > > GetAdaptersAddresses function returns
> > > > > - * ERROR_BUFFER_OVERFLOW, which would require calling
> > > > > GetAdaptersAddresses function multiple
> > > > > - * times. The example code illustrates this method of
> > > > > use.
> > > > > - */
> > > > > - addrSize = 15 * 1024;
> > > > > - do
> > > > > - {
> > > > > - free(addresses);
> > > > > - addresses = (IP_ADAPTER_ADDRESSES*)malloc( addrSize
> > > > > );
> > > > > - if (addresses == NULL)
> > > > > - return NULL;
> > > > > - hr = GetAdaptersAddresses(AF_UNSPEC, queryFlags,
> > > > > NULL,
> > > > > addresses, &addrSize);
> > > > > - } while (hr == ERROR_BUFFER_OVERFLOW);
> > > > > - if (hr != NO_ERROR) {
> > > > > - free(addresses);
> > > > > - return NULL;
> > > > > - }
> > > > > - return addresses;
> > > > > -}
> > > > > -
> > > > > -#ifdef UPNP_ENABLE_IPV6
> > > > > -
> > > > > -static char* getPreferedAdapter()
> > > > > -{
> > > > > - IP_ADAPTER_ADDRESSES *p_adapter, *addresses;
> > > > > -
> > > > > - addresses = ListAdapters();
> > > > > - if (addresses == NULL)
> > > > > - return NULL;
> > > > > -
> > > > > - /* find one with multicast capabilities */
> > > > > - p_adapter = addresses;
> > > > > - while (p_adapter != NULL)
> > > > > - {
> > > > > - if (isAdapterSuitable( p_adapter, true ))
> > > > > - {
> > > > > - /* make sure it supports 239.255.255.250 */
> > > > > - IP_ADAPTER_MULTICAST_ADDRESS *p_multicast =
> > > > > getMulticastAddress( p_adapter );
> > > > > - if (p_multicast != NULL)
> > > > > - {
> > > > > - char* res = FromWide( p_adapter-
> > > > > >FriendlyName );
> > > > > - free( addresses );
> > > > > - return res;
> > > > > - }
> > > > > - }
> > > > > - p_adapter = p_adapter->Next;
> > > > > - }
> > > > > - free(addresses);
> > > > > - return NULL;
> > > > > -}
> > > > > -
> > > > > -#else
> > > > > -
> > > > > -static char *getIpv4ForMulticast()
> > > > > -{
> > > > > - IP_ADAPTER_UNICAST_ADDRESS *p_best_ip = NULL;
> > > > > - wchar_t psz_uri[32];
> > > > > - DWORD strSize;
> > > > > - IP_ADAPTER_ADDRESSES *p_adapter, *addresses;
> > > > > -
> > > > > - addresses = ListAdapters();
> > > > > - if (addresses == NULL)
> > > > > - return NULL;
> > > > > -
> > > > > - /* find one with multicast capabilities */
> > > > > - p_adapter = addresses;
> > > > > - while (p_adapter != NULL)
> > > > > - {
> > > > > - if (isAdapterSuitable( p_adapter, false ))
> > > > > - {
> > > > > - /* make sure it supports 239.255.255.250 */
> > > > > - IP_ADAPTER_MULTICAST_ADDRESS *p_multicast =
> > > > > getMulticastAddress( p_adapter );
> > > > > - if (p_multicast != NULL)
> > > > > - {
> > > > > - /* get an IPv4 address */
> > > > > - IP_ADAPTER_UNICAST_ADDRESS *p_unicast =
> > > > > p_adapter-
> > > > > > FirstUnicastAddress;
> > > > >
> > > > > - while (p_unicast != NULL)
> > > > > - {
> > > > > - strSize = sizeof( psz_uri ) / sizeof(
> > > > > wchar_t );
> > > > > - if( WSAAddressToString( p_unicast-
> > > > > > Address.lpSockaddr,
> > > > >
> > > > > - p_unicast-
> > > > > > Address.iSockaddrLength,
> > > > >
> > > > > - NULL, psz_uri,
> > > > > &strSize )
> > > > > == 0 )
> > > > > - {
> > > > > - if ( p_best_ip == NULL ||
> > > > > - p_best_ip->ValidLifetime >
> > > > > p_unicast-
> > > > > > ValidLifetime )
> > > > >
> > > > > - {
> > > > > - p_best_ip = p_unicast;
> > > > > - }
> > > > > - }
> > > > > - p_unicast = p_unicast->Next;
> > > > > - }
> > > > > - }
> > > > > - }
> > > > > - p_adapter = p_adapter->Next;
> > > > > - }
> > > > > -
> > > > > - if ( p_best_ip != NULL )
> > > > > - goto done;
> > > > > -
> > > > > - /* find any with IPv4 */
> > > > > - p_adapter = addresses;
> > > > > - while (p_adapter != NULL)
> > > > > - {
> > > > > - if (isAdapterSuitable(p_adapter, false))
> > > > > - {
> > > > > - /* get an IPv4 address */
> > > > > - IP_ADAPTER_UNICAST_ADDRESS *p_unicast =
> > > > > p_adapter-
> > > > > > FirstUnicastAddress;
> > > > >
> > > > > - while (p_unicast != NULL)
> > > > > - {
> > > > > - strSize = sizeof( psz_uri ) / sizeof(
> > > > > wchar_t );
> > > > > - if( WSAAddressToString( p_unicast-
> > > > > > Address.lpSockaddr,
> > > > >
> > > > > - p_unicast-
> > > > > > Address.iSockaddrLength,
> > > > >
> > > > > - NULL, psz_uri,
> > > > > &strSize
> > > > > ) ==
> > > > > 0 )
> > > > > - {
> > > > > - if ( p_best_ip == NULL ||
> > > > > - p_best_ip->ValidLifetime >
> > > > > p_unicast-
> > > > > > ValidLifetime )
> > > > >
> > > > > - {
> > > > > - p_best_ip = p_unicast;
> > > > > - }
> > > > > - }
> > > > > - p_unicast = p_unicast->Next;
> > > > > - }
> > > > > - }
> > > > > - p_adapter = p_adapter->Next;
> > > > > - }
> > > > > -
> > > > > -done:
> > > > > - if (p_best_ip != NULL)
> > > > > - {
> > > > > - strSize = sizeof( psz_uri ) / sizeof( wchar_t );
> > > > > - WSAAddressToString( p_best_ip->Address.lpSockaddr,
> > > > > - p_best_ip-
> > > > > >Address.iSockaddrLength,
> > > > > - NULL, psz_uri, &strSize );
> > > > > - free(addresses);
> > > > > - return FromWide( psz_uri );
> > > > > - }
> > > > > - free(addresses);
> > > > > - return NULL;
> > > > > -}
> > > > > -#endif /* UPNP_ENABLE_IPV6 */
> > > > > -#else /* _WIN32 */
> > > > > -
> > > > > -#ifdef UPNP_ENABLE_IPV6
> > > > > -
> > > > > -static char *getPreferedAdapter()
> > > > > -{
> > > > > - return NULL;
> > > > > -}
> > > > > -
> > > > > -#else
> > > > > -
> > > > > -static char *getIpv4ForMulticast()
> > > > > -{
> > > > > - return NULL;
> > > > > -}
> > > > > -
> > > > > -#endif
> > > > > -
> > > > > -#endif /* _WIN32 */
> > > > > -
> > > > > -UpnpInstanceWrapper *UpnpInstanceWrapper::get(vlc_object_t
> > > > > *p_obj)
> > > > > -{
> > > > > - vlc_mutex_locker lock( &s_lock );
> > > > > - if ( s_instance == NULL )
> > > > > - {
> > > > > - UpnpInstanceWrapper* instance = new(std::nothrow)
> > > > > UpnpInstanceWrapper;
> > > > > - if ( unlikely( !instance ) )
> > > > > - {
> > > > > - return NULL;
> > > > > - }
> > > > > -
> > > > > - #ifdef UPNP_ENABLE_IPV6
> > > > > - char* psz_miface = var_InheritString( p_obj,
> > > > > "miface" );
> > > > > - if (psz_miface == NULL)
> > > > > - psz_miface = getPreferedAdapter();
> > > > > - msg_Info( p_obj, "Initializing libupnp on '%s'
> > > > > interface",
> > > > > psz_miface ? psz_miface : "default" );
> > > > > - int i_res = UpnpInit2( psz_miface, 0 );
> > > > > - free( psz_miface );
> > > > > - #else
> > > > > - /* If UpnpInit2 isnt available, initialize on first
> > > > > IPv4-
> > > > > capable interface */
> > > > > - 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 ) );
> > > > > - delete instance;
> > > > > - return NULL;
> > > > > - }
> > > > > -
> > > > > - ixmlRelaxParser( 1 );
> > > > > -
> > > > > - /* Register a control point */
> > > > > - i_res = UpnpRegisterClient( Callback, instance,
> > > > > &instance-
> > > > > > m_handle );
> > > > >
> > > > > - if( i_res != UPNP_E_SUCCESS )
> > > > > - {
> > > > > - msg_Err( p_obj, "Client registration failed:
> > > > > %s",
> > > > > UpnpGetErrorMessage( i_res ) );
> > > > > - delete instance;
> > > > > - return NULL;
> > > > > - }
> > > > > -
> > > > > - /* libupnp does not treat a maximum content length
> > > > > of 0
> > > > > as
> > > > > unlimited
> > > > > - * until 64dedf (~ pupnp v1.6.7) and provides no
> > > > > sane
> > > > > way to
> > > > > discriminate
> > > > > - * between versions */
> > > > > - if( (i_res = UpnpSetMaxContentLength( INT_MAX )) !=
> > > > > UPNP_E_SUCCESS )
> > > > > - {
> > > > > - msg_Err( p_obj, "Failed to set maximum content
> > > > > length: %s",
> > > > > - UpnpGetErrorMessage( i_res ));
> > > > > - delete instance;
> > > > > - return NULL;
> > > > > - }
> > > > > - s_instance = instance;
> > > > > - }
> > > > > - s_instance->m_refcount++;
> > > > > - return s_instance;
> > > > > -}
> > > > > -
> > > > > -void UpnpInstanceWrapper::release()
> > > > > -{
> > > > > - UpnpInstanceWrapper *p_delete = NULL;
> > > > > - vlc_mutex_lock( &s_lock );
> > > > > - if (--s_instance->m_refcount == 0)
> > > > > - {
> > > > > - p_delete = s_instance;
> > > > > - s_instance = NULL;
> > > > > - }
> > > > > - vlc_mutex_unlock( &s_lock );
> > > > > - delete p_delete;
> > > > > -}
> > > > > -
> > > > > -UpnpClient_Handle UpnpInstanceWrapper::handle() const
> > > > > -{
> > > > > - return m_handle;
> > > > > -}
> > > > > -
> > > > > -int UpnpInstanceWrapper::Callback(Upnp_EventType
> > > > > event_type,
> > > > > UpnpEventPtr p_event, void *p_user_data)
> > > > > -{
> > > > > - for (Listeners::iterator iter = s_listeners.begin();
> > > > > iter
> > > > > !=
> > > > > s_listeners.end(); ++iter)
> > > > > - {
> > > > > - (*iter)->onEvent(event_type, p_event, p_user_data);
> > > > > - }
> > > > > -
> > > > > - return 0;
> > > > > -}
> > > > > -
> > > > > -void UpnpInstanceWrapper::addListener(ListenerPtr listener)
> > > > > -{
> > > > > - vlc_mutex_lock( &s_lock );
> > > > > - if ( std::find( s_listeners.begin(), s_listeners.end(),
> > > > > listener) !
> > > > > = s_listeners.end() )
> > > > > - return;
> > > > > - s_listeners.push_back( std::move(listener) );
> > > > > - vlc_mutex_unlock( &s_lock );
> > > > > -}
> > > > > -
> > > > > -void UpnpInstanceWrapper::removeListener(ListenerPtr
> > > > > listener)
> > > > > -{
> > > > > - vlc_mutex_lock( &s_lock );
> > > > > - Listeners::iterator iter = std::find(
> > > > > s_listeners.begin(),
> > > > > s_listeners.end(), listener );
> > > > > - if ( iter == s_listeners.end() )
> > > > > - return;
> > > > > -
> > > > > - s_listeners.erase( iter );
> > > > > - vlc_mutex_unlock( &s_lock );
> > > > > -}
> > > > > diff --git a/modules/services_discovery/upnp.hpp b/modules/
> > > > > services_discovery/upnp.hpp
> > > > > index 8c13265fc8..164b1cbc69 100644
> > > > > --- a/modules/services_discovery/upnp.hpp
> > > > > +++ b/modules/services_discovery/upnp.hpp
> > > > > @@ -24,82 +24,18 @@
> > > > > * along with this program; if not, write to the Free
> > > > > Software
> > > > > Foundation,
> > > > > * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-
> > > > > 1301,
> > > > > USA.
> > > > >
> > > > > *************************************************************
> > > > > ****
> > > > > ************/
> > > > > -
> > > > > -#ifdef HAVE_CONFIG_H
> > > > > -# include "config.h"
> > > > > -#endif
> > > > > +#include "upnp-wrapper.hpp"
> > > > >
> > > > > #include <vector>
> > > > > #include <string>
> > > > > -#include <memory>
> > > > >
> > > > > #ifdef _WIN32
> > > > > #include <windows.h>
> > > > > #include <wincrypt.h>
> > > > > #endif
> > > > > -#include <upnp/upnp.h>
> > > > > -#include <upnp/upnptools.h>
> > > > >
> > > > > -#include <vlc_common.h>
> > > > > #include <vlc_url.h>
> > > > >
> > > > > -#if UPNP_VERSION < 10800
> > > > > -typedef void* UpnpEventPtr;
> > > > > -#else
> > > > > -typedef const void* UpnpEventPtr;
> > > > > -#endif
> > > > > -
> > > > > -namespace SD
> > > > > -{
> > > > > - class MediaServerList;
> > > > > -}
> > > > > -
> > > > > -/*
> > > > > - * libUpnp allows only one instance per process, so we have
> > > > > to
> > > > > share
> > > > > one for
> > > > > - * both SD & Access module
> > > > > - * Since the callback is bound to the UpnpClient_Handle, we
> > > > > have
> > > > > to
> > > > > register
> > > > > - * a wrapper callback, in order for the access module to be
> > > > > able
> > > > > to
> > > > > initialize
> > > > > - * libUpnp first.
> > > > > - * When a SD wishes to use libUpnp, it will provide its own
> > > > > callback,
> > > > > that the
> > > > > - * wrapper will forward.
> > > > > - * This way, we always have a register callback & a client
> > > > > handle.
> > > > > - */
> > > > > -class UpnpInstanceWrapper
> > > > > -{
> > > > > -public:
> > > > > - class Listener
> > > > > - {
> > > > > - public:
> > > > > - virtual ~Listener() {}
> > > > > - virtual int onEvent( Upnp_EventType event_type,
> > > > > - UpnpEventPtr p_event,
> > > > > - void* p_user_data ) = 0;
> > > > > - };
> > > > > -
> > > > > -private:
> > > > > - static UpnpInstanceWrapper* s_instance;
> > > > > - static vlc_mutex_t s_lock;
> > > > > - UpnpClient_Handle m_handle;
> > > > > - int m_refcount;
> > > > > - typedef std::shared_ptr<Listener> ListenerPtr;
> > > > > - typedef std::vector<ListenerPtr> Listeners;
> > > > > - static Listeners s_listeners;
> > > > > -
> > > > > -public:
> > > > > - // This increases the refcount before returning the
> > > > > instance
> > > > > - static UpnpInstanceWrapper* get( vlc_object_t* p_obj );
> > > > > - void release();
> > > > > - UpnpClient_Handle handle() const;
> > > > > - void addListener(ListenerPtr listener);
> > > > > - void removeListener(ListenerPtr listener);
> > > > > -
> > > > > -private:
> > > > > - static int Callback( Upnp_EventType event_type,
> > > > > UpnpEventPtr
> > > > > p_event, void* p_user_data );
> > > > > -
> > > > > - UpnpInstanceWrapper();
> > > > > - ~UpnpInstanceWrapper();
> > > > > -};
> > > > > -
> > > > > namespace SD
> > > > > {
> > > > >
> > > > > --
> > > > > 2.18.0
> > > > > _______________________________________________
> > > > > vlc-devel mailing list
> > > > > To unsubscribe or modify your subscription options:
> > > > > https://mailman.videolan.org/listinfo/vlc-devel
> > > >
> > > > Nitpick aside, LGTM
> > > >
> > > > --
> > > > Hugo Beauzée-Luyssen
> > > > hugo at beauzee.fr
> > > >
> > > > _______________________________________________
> > > > vlc-devel mailing list
> > > > To unsubscribe or modify your subscription options:
> > > > https://mailman.videolan.org/listinfo/vlc-devel
> > >
> > >
> > > Actually no, you're missing an include to vlc_charset.h it seems.
> >
> > It compiles fine without vlc_charset.h on my system. Also it wasn't
> > included before as well. Why do you think it's needed?
> > >
>
> Try compiling for win32 then :)
> AFAICS it's included from upnp.cpp, but is now required from upnp-
> wrapper.h
Okay, included in upnp-wrapper.h now.
>
--
Regards,
Shaleen Jain
More information about the vlc-devel
mailing list