[vlc-devel] [PATCH 3/3] Add microdns services_advertisement submodule

Roland Bewick roland.bewick at gmail.com
Tue Sep 3 16:30:31 CEST 2019


On 2/09/2019 11:34 PM, Thomas Guillem wrote:
> One other concern:
>
> SA modules should not annonce anything by default but the core should ask for it.
>
> I propose the following changes:
>   - The sa module initialize from Open but doesn't annonce anything, it just registers an annonce callback.
>   - Add vlc_sa_annonce( libvlc, const char *name, const char *type, unsigned port ), that will call the annonce callback of the main SA.
>
> That way, any interface or control modules will be able to announce themself using the vlc_sa_annonce() call.

The user has to currently enable it with the command line argument.

If a module can announce itself, we might still want to have the user 
enable it some way, through the command line or UI?

I'm happy with the idea though, it's more flexible.

>
>
> On Mon, Sep 2, 2019, at 14:14, Thomas Guillem wrote:
>>
>> On Mon, Sep 2, 2019, at 07:25, Roland Bewick wrote:
>>> ---
>>>   modules/services_discovery/microdns.c | 318 +++++++++++++++++++++-----
>>>   1 file changed, 261 insertions(+), 57 deletions(-)
>>>
>>> diff --git a/modules/services_discovery/microdns.c
>>> b/modules/services_discovery/microdns.c
>>> index ad0d2691f7..d5dc5bda94 100644
>>> --- a/modules/services_discovery/microdns.c
>>> +++ b/modules/services_discovery/microdns.c
>>> @@ -33,6 +33,7 @@
>>>   #include <vlc_modules.h>
>>>   #include <vlc_services_discovery.h>
>>>   #include <vlc_renderer_discovery.h>
>>> +#include <vlc_services_advertisement.h>
>>>   
>>>   #include <microdns/microdns.h>
>>>   
>>> @@ -40,6 +41,8 @@ static int OpenSD( vlc_object_t * );
>>>   static void CloseSD( vlc_object_t * );
>>>   static int OpenRD( vlc_object_t * );
>>>   static void CloseRD( vlc_object_t * );
>>> +static int OpenSA( vlc_object_t * );
>>> +static void CloseSA( vlc_object_t * );
>>>   
>>>   VLC_SD_PROBE_HELPER( "microdns", N_("mDNS Network Discovery"), SD_CAT_LAN )
>>>   VLC_RD_PROBE_HELPER( "microdns_renderer", "mDNS renderer Discovery" )
>>> @@ -69,6 +72,14 @@ vlc_module_begin()
>>>           set_callbacks( OpenRD, CloseRD )
>>>           add_shortcut( "mdns_renderer", "microdns_renderer" )
>>>           VLC_RD_PROBE_SUBMODULE
>>> +    add_submodule() \
>>> +        set_description( N_( "mDNS Services Advertisement" ) )
>>> +        set_category( CAT_ADVANCED )
>>> +        set_subcategory( SUBCAT_ADVANCED_NETWORK )
>>> +        set_capability( "services_advertisement", 0 )
>>> +        set_callbacks( OpenSA, CloseSA )
>>> +        add_shortcut( "mdns", "microdns" )
>>> +        VLC_RD_PROBE_SUBMODULE
>>>   vlc_module_end ()
>>>   
>>>   static const struct
>>> @@ -87,16 +98,37 @@ static const struct
>>>   };
>>>   #define NB_PROTOCOLS (sizeof(protocols) / sizeof(*protocols))
>>>   
>>> +/*
>>> + * Services advertisement configuration
>>> + */
>>> +char sa_domain_name[] = "vlc.local"; /* Announce our service on this
>>> domain name*/
>>> +char sa_service_type[] = "_vlc._tcp.local"; /* respond to PTR query of
>>> this type */
>>> +char sa_service_type_link[] = "vlc VLC._vlc._tcp.local"; /* link
>>> service type to domain */
>> These 3 char * should be const and static.
>>
>>> +
>>>   struct discovery_sys
>>>   {
>>> -    vlc_thread_t        thread;
>>> -    atomic_bool         stop;
>>> -    struct mdns_ctx *   p_microdns;
>>>       const char *        ppsz_service_names[NB_PROTOCOLS];
>>>       unsigned int        i_nb_service_names;
>>>       vlc_array_t         items;
>>>   };
>>>   
>>> +struct advertisement_sys
>>> +{
>>> +    int i_http_port;
>>> +};
>>> +
>>> +struct microdns_sys
>>> +{
>>> +    vlc_thread_t        thread;
>>> +    atomic_bool         stop;
>>> +    struct mdns_ctx *   p_microdns;
>>> +    union
>>> +    {
>>> +        struct discovery_sys discovery_sys;
>>> +        struct advertisement_sys advertisement_sys;
>>> +    };
>>> +};
>>> +
>>>   struct item
>>>   {
>>>       char *              psz_uri;
>>> @@ -383,7 +415,7 @@ static void
>>>   new_entries_sd_cb( void *p_this, int i_status, const struct rr_entry
>>> *p_entries )
>>>   {
>>>       services_discovery_t *p_sd = (services_discovery_t *)p_this;
>>> -    struct discovery_sys *p_sys = p_sd->p_sys;
>>> +    struct microdns_sys *p_sys = p_sd->p_sys;
>> If you do
>>
>> struct microdns_sys *p_mdns_sys = p_sd->p_sys;
>> struct discovery_sys *p_sys = p_mdns_sys->p_sys;
>>
>> You won't have to modify every access of discovery_sys. The diff will
>> be smaller and easier to read.
>>
>>
>>>       if( i_status < 0 )
>>>       {
>>>           print_error( VLC_OBJECT( p_sd ), "entry callback", i_status );
>>> @@ -408,12 +440,12 @@ new_entries_sd_cb( void *p_this, int i_status,
>>> const struct rr_entry *p_entries
>>>           if( psz_uri == NULL )
>>>               break;
>>>   
>>> -        if( items_exists( p_sys, psz_uri ) )
>>> +        if( items_exists( &p_sys->discovery_sys, psz_uri ) )
>>>           {
>>>               free( psz_uri );
>>>               continue;
>>>           }
>>> -        items_add_input( p_sys, p_sd, psz_uri, p_srv->psz_device_name
>>> );
>>> +        items_add_input( &p_sys->discovery_sys, p_sd, psz_uri,
>>> p_srv->psz_device_name );
>>>       }
>>>   
>>>       for( unsigned int i = 0; i < i_nb_srv; ++i )
>>> @@ -426,13 +458,13 @@ static bool
>>>   stop_sd_cb( void *p_this )
>>>   {
>>>       services_discovery_t *p_sd = ( services_discovery_t* )p_this;
>>> -    struct discovery_sys *p_sys = p_sd->p_sys;
>>> +    struct microdns_sys *p_sys = p_sd->p_sys;
>>>   
>>>       if( atomic_load( &p_sys->stop ) )
>>>           return true;
>>>       else
>>>       {
>>> -        items_timeout( p_sys, p_sd, NULL );
>>> +        items_timeout( &p_sys->discovery_sys, p_sd, NULL );
>>>           return false;
>>>       }
>>>   }
>>> @@ -441,11 +473,11 @@ static void *
>>>   RunSD( void *p_this )
>>>   {
>>>       services_discovery_t *p_sd = ( services_discovery_t* )p_this;
>>> -    struct discovery_sys *p_sys = p_sd->p_sys;
>>> +    struct microdns_sys *p_sys = p_sd->p_sys;
>>>   
>>>       int i_status = mdns_listen( p_sys->p_microdns,
>>> -                                p_sys->ppsz_service_names,
>>> -                                p_sys->i_nb_service_names,
>>> +                                p_sys->discovery_sys.ppsz_service_names,
>>> +                                p_sys->discovery_sys.i_nb_service_names,
>>>                                   RR_PTR, SEC_FROM_VLC_TICK(LISTEN_INTERVAL),
>>>                                   stop_sd_cb, new_entries_sd_cb, p_sd );
>>>   
>>> @@ -459,7 +491,7 @@ static void
>>>   new_entries_rd_cb( void *p_this, int i_status, const struct rr_entry
>>> *p_entries )
>>>   {
>>>       vlc_renderer_discovery_t *p_rd = (vlc_renderer_discovery_t
>>> *)p_this;
>>> -    struct discovery_sys *p_sys = p_rd->p_sys;
>>> +    struct microdns_sys *p_sys = p_rd->p_sys;
>>>       if( i_status < 0 )
>>>       {
>>>           print_error( VLC_OBJECT( p_rd ), "entry callback", i_status );
>>> @@ -506,7 +538,7 @@ new_entries_rd_cb( void *p_this, int i_status,
>>> const struct rr_entry *p_entries
>>>           if( psz_uri == NULL )
>>>               break;
>>>   
>>> -        if( items_exists( p_sys, psz_uri ) )
>>> +        if( items_exists( &p_sys->discovery_sys, psz_uri ) )
>>>           {
>>>               free( psz_uri );
>>>               continue;
>>> @@ -523,8 +555,8 @@ new_entries_rd_cb( void *p_this, int i_status,
>>> const struct rr_entry *p_entries
>>>           if( strcmp( p_srv->psz_protocol, "chromecast" ) == 0)
>>>               psz_demux_filter = "cc_demux";
>>>   
>>> -        items_add_renderer( p_sys, p_rd, p_srv->psz_device_name,
>>> psz_uri,
>>> -                            psz_demux_filter, psz_icon_uri,
>>> +        items_add_renderer( &p_sys->discovery_sys, p_rd,
>>> p_srv->psz_device_name,
>>> +                            psz_uri, psz_demux_filter, psz_icon_uri,
>>>                               p_srv->i_renderer_flags );
>>>           free(psz_icon_uri);
>>>       }
>>> @@ -538,13 +570,13 @@ static bool
>>>   stop_rd_cb( void *p_this )
>>>   {
>>>       vlc_renderer_discovery_t *p_rd = p_this;
>>> -    struct discovery_sys *p_sys = p_rd->p_sys;
>>> +    struct microdns_sys *p_sys = p_rd->p_sys;
>>>   
>>>       if( atomic_load( &p_sys->stop ) )
>>>           return true;
>>>       else
>>>       {
>>> -        items_timeout( p_sys, NULL, p_rd );
>>> +        items_timeout( &p_sys->discovery_sys, NULL, p_rd );
>>>           return false;
>>>       }
>>>   }
>>> @@ -553,11 +585,11 @@ static void *
>>>   RunRD( void *p_this )
>>>   {
>>>       vlc_renderer_discovery_t *p_rd = p_this;
>>> -    struct discovery_sys *p_sys = p_rd->p_sys;
>>> +    struct microdns_sys *p_sys = p_rd->p_sys;
>>>   
>>>       int i_status = mdns_listen( p_sys->p_microdns,
>>> -                                p_sys->ppsz_service_names,
>>> -                                p_sys->i_nb_service_names,
>>> +                                p_sys->discovery_sys.ppsz_service_names,
>>> +                                p_sys->discovery_sys.i_nb_service_names,
>>>                                   RR_PTR, SEC_FROM_VLC_TICK(LISTEN_INTERVAL),
>>>                                   stop_rd_cb, new_entries_rd_cb, p_rd );
>>>   
>>> @@ -567,62 +599,195 @@ RunRD( void *p_this )
>>>       return NULL;
>>>   }
>>>   
>>> -static int
>>> -OpenCommon( vlc_object_t *p_obj, struct discovery_sys *p_sys, bool b_renderer )
>>> +static void
>>> +request_sa_callback(void *cbarg, int r, const struct mdns_ip *mdns_ip,
>>> +                    const struct rr_entry *entry)
>>>   {
>>> -    int i_ret = VLC_EGENERIC;
>>> -    atomic_init( &p_sys->stop, false );
>>> -    vlc_array_init( &p_sys->items );
>>> +    VLC_UNUSED( r );  /* result code from mdns_recv */
>>>   
>>> -    /* Listen to protocols that are handled by VLC */
>>> -    for( unsigned int i = 0; i < NB_PROTOCOLS; ++i )
>>> +    services_advertisement_t *p_sa = ( services_advertisement_t*
>>> )cbarg;
>>> +    struct microdns_sys *p_sys = p_sa->p_sys;
>>> +    struct mdns_ctx *ctx = p_sys->p_microdns;
>>> +    struct mdns_hdr hdr = {0};  /* response header */
>>> +
>>> +    if( entry->type != RR_PTR || entry->rr_class != RR_IN )
>>>       {
>>> -        if( protocols[i].b_renderer == b_renderer )
>>> -            p_sys->ppsz_service_names[p_sys->i_nb_service_names++] =
>>> -                protocols[i].psz_service_name;
>>> +        msg_Dbg( VLC_OBJECT( p_sa ),
>>> +                 "mDNS-SA: Skipped unsupported request type: %d class:
>>> %d\n",
>>> +                 entry->type,
>>> +                 entry->rr_class );
>>> +        return;
>>> +    }
>>> +
>>> +    /*
>>> +     * When we receive a PTR record (question) from an mDNS client we
>>> need to
>>> +     * answer with four record types that will allow our domain name
>>> (vlc.local)
>>> +     * to resolve the IP address and port we are hosting the VLC
>>> interface on.
>>> +     *
>>> +     * PTR: point service type (_vlc._tcp._local) to local domain
>>> +     * TXT: provide additional information (HTTP server root directory
>>> etc.)
>>> +     * SRV: provide server information (port number etc.)
>>> +     * A: link local domain to IP address
>>> +     */
>>> +
>>> +    struct rr_entry answers[4] = {0};  /* PTR, TXT, SRV, A */
>>> +
>>> +    hdr.flags |= FLAG_QR;
>>> +    hdr.flags |= FLAG_AA;
>>> +
>>> +    hdr.num_ans_rr = sizeof( answers ) / sizeof( answers[0] );
>>> +
>>> +    for( int i = 0; i < hdr.num_ans_rr; i++ )
>>> +    {
>>> +            answers[i].rr_class = RR_IN;
>>> +            answers[i].ttl      = 120;
>>> +
>>> +            if (i + 1 < hdr.num_ans_rr)
>>> +                    answers[i].next = &answers[i + 1];
>>>       }
>>>   
>>> -    if( p_sys->i_nb_service_names == 0 )
>>> +    // RR_PTR: point service type to local domain and instance name
>>> (VLC)
>>> +    answers[0].type     = RR_PTR;
>>> +    answers[0].name     = sa_service_type;
>>> +    answers[0].data.PTR.domain = sa_service_type_link;
>>> +
>>> +    // RR_TXT: provide additional information (HTTP server root
>>> directory etc.)
>>> +    answers[1].type     = RR_TXT;
>>> +    answers[1].name     = sa_service_type_link;
>>> +
>>> +    // RR_SRV: provide info about the service we're announcing (port
>>> no, etc.)
>>> +    answers[2].type     = RR_SRV;
>>> +    answers[2].name     = sa_service_type_link;
>>> +    answers[2].data.SRV.port = p_sys->advertisement_sys.i_http_port;
>>> +    answers[2].data.SRV.priority = 0;
>>> +    answers[2].data.SRV.weight = 0;
>>> +    answers[2].data.SRV.target = sa_domain_name;
>>> +
>>> +    // RR_A/AAAA: link .local domain to IP address
>>> +    answers[3].name     = sa_domain_name;
>>> +    if (mdns_ip->family == AF_INET)
>>>       {
>>> -        msg_Err( p_obj, "no services found" );
>>> -        goto error;
>>> +            answers[3].type     = RR_A;
>>> +            memcpy(&answers[3].data.A.addr, &mdns_ip->ipv4,
>>> +                    sizeof(answers[3].data.A.addr));
>>>       }
>>> -    for( unsigned int i = 0; i < p_sys->i_nb_service_names; ++i )
>>> -        msg_Dbg( p_obj, "mDNS: listening to %s %s",
>>> p_sys->ppsz_service_names[i],
>>> -                 b_renderer ? "renderer" : "service" );
>>> +    else
>>> +    {
>>> +            answers[3].type     = RR_AAAA;
>>> +            memcpy(&answers[3].data.AAAA.addr, &mdns_ip->ipv6,
>>> +                    sizeof(answers[3].data.AAAA.addr));
>>> +    }
>>> +
>>> +    mdns_entries_send(ctx, &hdr, answers);
>>> +}
>>> +
>>> +static bool
>>> +stop_sa_cb( void *cbarg )
>>> +{
>>> +    services_advertisement_t *p_sa = ( services_advertisement_t*
>>> )cbarg;
>>> +    struct microdns_sys *p_sys = p_sa->p_sys;
>>> +
>>> +    return atomic_load( &p_sys->stop );
>>> +}
>>> +
>>> +static void *
>>> +RunSA( void *p_this )
>>> +{
>>> +    services_advertisement_t *p_sa = ( services_advertisement_t*
>>> )p_this;
>>> +    struct microdns_sys *p_sys = p_sa->p_sys;
>>>   
>>>       int i_status;
>>> -    if( ( i_status = mdns_init( &p_sys->p_microdns, MDNS_ADDR_IPV4,
>>> +
>>> +    i_status = mdns_announce( p_sys->p_microdns,
>>> +                              sa_service_type,
>>> +                              RR_PTR,
>>> +                              request_sa_callback,
>>> +                              p_sa);
>>> +
>>> +    if( i_status < 0 )
>>> +        print_error( VLC_OBJECT( p_sa ), "announce", i_status );
>>> +
>>> +    i_status = mdns_serve(p_sys->p_microdns, stop_sa_cb, p_sa);
>>> +
>>> +    return NULL;
>>> +}
>>> +
>>> +static void
>>> +CleanCommon( struct microdns_sys *p_sys )
>>> +{
>>> +    if ( p_sys->p_microdns )
>>> +        mdns_destroy( p_sys->p_microdns );
>>> +    free( p_sys );
>>> +}
>>> +
>>> +static void
>>> +CleanDiscoveryCommon( struct microdns_sys *p_sys )
>>> +{
>>> +    items_clear( &p_sys->discovery_sys );
>>> +    CleanCommon( p_sys );
>>> +}
>>> +
>>> +
>>> +static void CloseCommon( struct microdns_sys *p_sys )
>>> +{
>>> +    atomic_store( &p_sys->stop, true );
>>> +    vlc_join( p_sys->thread, NULL );
>>> +}
>>> +
>>> +static int
>>> +OpenCommon( vlc_object_t *p_obj, struct microdns_sys *p_sys,
>>> +            const char *mdns_addr, void *(*entry)(void *) )
>>> +{
>>> +    int i_ret = VLC_EGENERIC;
>>> +    atomic_init( &p_sys->stop, false );
>>> +
>>> +    int i_status;
>>> +    if( ( i_status = mdns_init( &p_sys->p_microdns, mdns_addr,
>>>                                   MDNS_PORT ) ) < 0 )
>>>       {
>>>           print_error( p_obj, "init", i_status );
>>>           goto error;
>>>       }
>>>   
>>> -    if( vlc_clone( &p_sys->thread, b_renderer ? RunRD : RunSD, p_obj,
>>> -                   VLC_THREAD_PRIORITY_LOW) )
>>> +    if( vlc_clone( &p_sys->thread, entry, p_obj, VLC_THREAD_PRIORITY_LOW) )
>>>       {
>>> -        msg_Err( p_obj, "Can't run the lookup thread" );
>>> +        msg_Err( p_obj, "Can't run the mdns thread");
>>>           goto error;
>>>       }
>>>   
>>>       return VLC_SUCCESS;
>>>   error:
>>> -    if( p_sys->p_microdns != NULL )
>>> -        mdns_destroy( p_sys->p_microdns );
>>> -    free( p_sys );
>>> +    CleanCommon( p_sys );
>>>       return i_ret;
>>>   }
>>>   
>>> -static void
>>> -CleanCommon( struct discovery_sys *p_sys )
>>> +static int OpenDiscoveryCommon( vlc_object_t *p_obj, struct
>>> microdns_sys *p_sys,
>>> +                               bool b_renderer, void *(*entry)(void *)
>>> )
>>>   {
>>> -    atomic_store( &p_sys->stop, true );
>>> -    vlc_join( p_sys->thread, NULL );
>>> +    int i_ret = VLC_EGENERIC;
>>> +    struct discovery_sys *discovery_sys = &p_sys->discovery_sys;
>>>   
>>> -    items_clear( p_sys );
>>> -    mdns_destroy( p_sys->p_microdns );
>>> -    free( p_sys );
>>> +    vlc_array_init( &discovery_sys->items );
>>> +    /* Listen to protocols that are handled by VLC */
>>> +    for( unsigned int i = 0; i < NB_PROTOCOLS; ++i )
>>> +    {
>>> +        if( protocols[i].b_renderer == b_renderer )
>>> +
>>> discovery_sys->ppsz_service_names[discovery_sys->i_nb_service_names++] =
>>> +                protocols[i].psz_service_name;
>>> +    }
>>> +    if( discovery_sys->i_nb_service_names == 0 )
>>> +    {
>>> +        msg_Err( p_obj, "no services found" );
>>> +        goto error;
>>> +    }
>>> +    for( unsigned int i = 0; i < discovery_sys->i_nb_service_names;
>>> ++i )
>>> +        msg_Dbg( p_obj, "mDNS: listening to %s %s",
>>> discovery_sys->ppsz_service_names[i],
>>> +                b_renderer ? "renderer" : "service" );
>>> +
>>> +    return OpenCommon( p_obj, p_sys, MDNS_ADDR_IPV4, entry );
>>> +error:
>>> +    CleanCommon( p_sys );
>>> +    return i_ret;
>>>   }
>>>   
>>>   static int
>>> @@ -630,7 +795,7 @@ OpenSD( vlc_object_t *p_obj )
>>>   {
>>>       services_discovery_t *p_sd = (services_discovery_t *)p_obj;
>>>   
>>> -    struct discovery_sys *p_sys = calloc( 1, sizeof(struct discovery_sys) );
>>> +    struct microdns_sys *p_sys = calloc( 1, sizeof(struct microdns_sys) );
>>>       if( !p_sys )
>>>           return VLC_ENOMEM;
>>>       p_sd->p_sys = p_sys;
>>> @@ -638,16 +803,17 @@ OpenSD( vlc_object_t *p_obj )
>>>       p_sd->description = _("mDNS Network Discovery");
>>>       config_ChainParse( p_sd, CFG_PREFIX, ppsz_options, p_sd->p_cfg );
>>>   
>>> -    return OpenCommon( p_obj, p_sys, false );
>>> +    return OpenDiscoveryCommon( p_obj, p_sys, false, RunSD );
>>>   }
>>>   
>>>   static void
>>>   CloseSD( vlc_object_t *p_this )
>>>   {
>>>       services_discovery_t *p_sd = (services_discovery_t *) p_this;
>>> -    struct discovery_sys *p_sys = p_sd->p_sys;
>>> +    struct microdns_sys *p_sys = p_sd->p_sys;
>>>   
>>> -    CleanCommon( p_sys );
>>> +    CloseCommon( p_sys );
>>> +    CleanDiscoveryCommon( p_sys );
>>>   }
>>>   
>>>   static int
>>> @@ -655,21 +821,59 @@ OpenRD( vlc_object_t *p_obj )
>>>   {
>>>       vlc_renderer_discovery_t *p_rd = (vlc_renderer_discovery_t *)p_obj;
>>>   
>>> -    struct discovery_sys *p_sys = calloc( 1, sizeof(struct discovery_sys) );
>>> +    struct microdns_sys *p_sys = calloc( 1, sizeof(struct microdns_sys) );
>>>       if( !p_sys )
>>>           return VLC_ENOMEM;
>>>       p_rd->p_sys = p_sys;
>>>   
>>>       config_ChainParse( p_rd, CFG_PREFIX, ppsz_options, p_rd->p_cfg );
>>>   
>>> -    return OpenCommon( p_obj, p_sys, true );
>>> +    return OpenDiscoveryCommon( p_obj, p_sys, true, RunRD );
>>>   }
>>>   
>>>   static void
>>>   CloseRD( vlc_object_t *p_this )
>>>   {
>>>       vlc_renderer_discovery_t *p_rd = (vlc_renderer_discovery_t *) p_this;
>>> -    struct discovery_sys *p_sys = p_rd->p_sys;
>>> +    struct microdns_sys *p_sys = p_rd->p_sys;
>>> +
>>> +    CloseCommon( p_sys );
>>> +    CleanDiscoveryCommon( p_sys );
>>> +}
>>> +
>>> +static int
>>> +OpenSA( vlc_object_t *p_obj )
>>> +{
>>> +    services_advertisement_t *p_sa = (services_advertisement_t *)p_obj;
>>> +
>>> +    struct microdns_sys *p_sys = calloc( 1, sizeof(struct microdns_sys) );
>>> +    if( !p_sys )
>>> +        return VLC_ENOMEM;
>>> +
>>> +    p_sa->p_sys = p_sys;
>>> +    config_ChainParse( p_sa, CFG_PREFIX, ppsz_options, p_sa->p_cfg );
>>> +
>>> +    p_sys->advertisement_sys.i_http_port = var_InheritInteger(
>>> +        p_obj, "http-port" ); /* 8080 if unset */
>>> +    char *psz_address_family = var_InheritString(
>>> +        p_obj, "services-advertisement-address-family" ); /* v6 if unset */
>>> +
>>> +
>>> +    p_sa->description = _("mDNS Network Advertisement");
>>> +
>>> +    const char *mdns_addr = MDNS_ADDR_IPV6;
>>> +    if( strcmp( psz_address_family, "v4" ) == 0 )
>>> +        mdns_addr = MDNS_ADDR_IPV4;
>>> +
>>> +    return OpenCommon( p_obj, p_sys, mdns_addr, RunSA );
>> YOu should free (psz_address_family).
>>
>>> +}
>>> +
>>> +static void
>>> +CloseSA( vlc_object_t *p_this )
>>> +{
>>> +    services_advertisement_t *p_sa = (services_advertisement_t *) p_this;
>>> +    struct microdns_sys *p_sys = p_sa->p_sys;
>>>   
>>> +    CloseCommon( p_sys );
>>>       CleanCommon( p_sys );
>>>   }
>>> -- 
>>> 2.17.1
>>>
>>> _______________________________________________
>>> vlc-devel mailing list
>>> To unsubscribe or modify your subscription options:
>>> https://mailman.videolan.org/listinfo/vlc-devel
>> _______________________________________________
>> vlc-devel mailing list
>> To unsubscribe or modify your subscription options:
>> https://mailman.videolan.org/listinfo/vlc-devel
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel


More information about the vlc-devel mailing list