[vlc-devel] [PATCH 6/7] mdns: Add basic ip address detection (Linux)

Roland Bewick roland.bewick at gmail.com
Wed Aug 7 07:55:26 CEST 2019


On 4/08/2019 7:51 PM, Marvin Scholz wrote:
>
>
> On 4 Aug 2019, at 7:55, Roland Bewick wrote:
>
>> On 2/08/2019 4:19 PM, Marvin Scholz wrote:
>>>
>>>
>>> On 2 Aug 2019, at 8:03, Thomas Guillem wrote:
>>>
>>>> On Wed, Jul 31, 2019, at 08:35, Roland Bewick wrote:
>>>>>
>>>>> On 27/07/2019 2:04 PM, Roland Bewick wrote:
>>>>>>
>>>>>> On 26/07/2019 1:07 AM, Rémi Denis-Courmont wrote:
>>>>>>> Le torstaina 25. heinäkuuta 2019, 20.51.09 EEST Roland Bewick a 
>>>>>>> écrit :
>>>>>>>> On Fri, 26 Jul 2019 at 12:15 AM, Rémi Denis-Courmont 
>>>>>>>> <remi at remlab.net>
>>>>>>>>
>>>>>>>> wrote:
>>>>>>>>> Le torstaina 25. heinäkuuta 2019, 8.39.11 EEST Roland Bewick a 
>>>>>>>>> écrit :
>>>>>>>>>> On 24/07/2019 11:18 PM, Rémi Denis-Courmont wrote:
>>>>>>>>>>> Le keskiviikkona 24. heinäkuuta 2019, 19.10.50 EEST Roland 
>>>>>>>>>>> Bewick a
>>>>>>>>> écrit
>>>>>>>>>
>>>>>>>>>>>> Hi Rémi,
>>>>>>>>>>>>
>>>>>>>>>>>> Thanks for the reply.
>>>>>>>>>>>>
>>>>>>>>>>>> On 24/07/2019 10:59 PM, Rémi Denis-Courmont wrote:
>>>>>>>>>>>>> Le keskiviikkona 24. heinäkuuta 2019, 18.43.49 EEST Roland
>>>>>>>>>>>>> Bewick a
>>>>>>>>>>>>> écrit
>>>>>>>>>>>>>
>>>>>>>>>>>>>> ---
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> modules/services_discovery/microdns.c | 62
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> +++++++++++++++++++++++++++++++++-- 1 file changed, 59
>>>>>>>>> insertions(+), 3
>>>>>>>>>
>>>>>>>>>>>>>> deletions(-)
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> diff --git a/modules/services_discovery/microdns.c
>>>>>>>>>>>>>> b/modules/services_discovery/microdns.c index
>>>>>>>>>>>>>> c460126b58..fa34ffa8d8
>>>>>>>>>>>>>> 100644
>>>>>>>>>>>>>> --- a/modules/services_discovery/microdns.c
>>>>>>>>>>>>>> +++ b/modules/services_discovery/microdns.c
>>>>>>>>>>>>>> @@ -28,6 +28,12 @@
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>     #include <stdatomic.h>
>>>>>>>>>>>>>>     #include <assert.h>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> +#if defined( _WIN32 )
>>>>>>>>>>>>>> +
>>>>>>>>>>>>>> +#else
>>>>>>>>>>>>>> +    #include <ifaddrs.h>
>>>>>>>>>>>>>> +#endif
>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>     #include <vlc_common.h>
>>>>>>>>>>>>>>     #include <vlc_plugin.h>
>>>>>>>>>>>>>>     #include <vlc_modules.h>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> @@ -868,9 +874,59 @@ CloseRD( vlc_object_t *p_this )
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>         CleanDiscoveryCommon( p_sys );
>>>>>>>>>>>>>>         }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> -static char * detect_ip_address()
>>>>>>>>>>>>>> +static char * detect_ip_address( vlc_object_t *p_obj )
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>     {
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> -    return strdup("127.0.0.1"); /* TODO: actually detect ip
>>>>>>>>> address */
>>>>>>>>>
>>>>>>>>>>>>>> +    char result[16] = "127.0.0.1";
>>>>>>>>>>>>>> +    bool found = false;
>>>>>>>>>>>>>> +#if defined( _WIN32 )
>>>>>>>>>>>>>> +
>>>>>>>>>>>>>> +#else
>>>>>>>>>>>>>> +    struct ifaddrs *id;
>>>>>>>>>>>>>> +    if( getifaddrs( &id ) == 0 )
>>>>>>>>>>>>>> +    {
>>>>>>>>>>>>>> +        int selected_priority = 0;
>>>>>>>>>>>>>> +
>>>>>>>>>>>>>> +        for( ; id != NULL; id = id->ifa_next )
>>>>>>>>>>>>>> +        {
>>>>>>>>>>>>>> +            if( id->ifa_addr->sa_family == AF_INET )
>>>>>>>>>>>>>> +            {
>>>>>>>>>>>>>> +                struct sockaddr_in *addr_in = (struct
>>>>>>>>>>>>>> sockaddr_in
>>>>>>>>>>>>>> *)id->ifa_addr; +
>>>>>>>>>>>>>> +                char *ip_address = inet_ntoa(
>>>>>>>>>>>>>> addr_in->sin_addr );
>>>>>>>>>>>>>> +
>>>>>>>>>>>>>> +                /* TODO: smarter priority function. */
>>>>>>>>>>>>>> +                int priority = 0;
>>>>>>>>>>>>>> +                if( strncmp( "eth0", id->ifa_name, strlen(
>>>>>>>>>>>>>> "eth0"
>>>>>>>>> ) )
>>>>>>>>>
>>>>>>>>>>>>>> ==
>>>>>>>>>>>>>> 0
>>>>>>>>>>>>>> ) +                {
>>>>>>>>>>>>>> +                    priority = 1000;
>>>>>>>>>>>>>> +                }
>>>>>>>>>>>>>> +                else if( strncmp( "wifi0", id->ifa_name, 
>>>>>>>>>>>>>> strlen(
>>>>>>>>>>>>>> "wifi0"
>>>>>>>>>>>>>> )
>>>>>>>>>>>>>> ) == 0 ) +                {
>>>>>>>>>>>>>> +                    priority = 2000;
>>>>>>>>>>>>>> +                }
>>>>>>>>>>>>>> +
>>>>>>>>>>>>>> +                msg_Dbg( p_obj, "Assigned interface %s 
>>>>>>>>>>>>>> priority
>>>>>>>>> %d",
>>>>>>>>>
>>>>>>>>>>>>>> + id->ifa_name, priority);
>>>>>>>>>>>>>> +
>>>>>>>>>>>>>> +                if( priority > selected_priority )
>>>>>>>>>>>>>> +                {
>>>>>>>>>>>>>> +                    strcpy( result, ip_address );
>>>>>>>>>>>>>> +                    selected_priority = priority;
>>>>>>>>>>>>>> +                    found = true;
>>>>>>>>>>>>>> +                }
>>>>>>>>>>>>>> +            }
>>>>>>>>>>>>>> +        }
>>>>>>>>>>>>>> +    }
>>>>>>>>>>>>>> +    else
>>>>>>>>>>>>>> +    {
>>>>>>>>>>>>>> +        msg_Err( p_obj, "Couldn't get interface 
>>>>>>>>>>>>>> addresses");
>>>>>>>>>>>>>> +    }
>>>>>>>>>>>>> That could have worked in the nineties. Machines, especially
>>>>>>>>>>>>> laptops,
>>>>>>>>>>>>> change IP addresses and have multiple addresses routinely
>>>>>>>>>>>>> nowadays,
>>>>>>>>> and
>>>>>>>>>
>>>>>>>>>>>>> Linux desktops interfaces are not always called eth0 or 
>>>>>>>>>>>>> wifi0.
>>>>>>>>>>>> I will take Alexandre's suggestion.
>>>>>>>>>>>>
>>>>>>>>>>>>> Besides, you need to respond with the correct IP address 
>>>>>>>>>>>>> for the
>>>>>>>>>>>>> interface
>>>>>>>>>>>>> on which the request came, usually with 
>>>>>>>>>>>>> IP_PKTINFO/IP6_PKTINFO if
>>>>>>>>>>>>> you
>>>>>>>>>>>>> use
>>>>>>>>>>>>> UDP.
>>>>>>>>>>>> Respond to what? I don't understand.
>>>>>>>>>>> Typically, discovery protocols wait for inbound client 
>>>>>>>>>>> requests.
>>>>>>>>>> Oh - so I don't even have to do the detection myself. Great!
>>>>>>>>> You should never do detection.
>>>>>>>>>
>>>>>>>>> For unsolicited announcements, you should either enumerate all
>>>>>>>>> eligible
>>>>>>>>> interfaces and spam all of them, or leave the IP stack routing
>>>>>>>>> table to
>>>>>>>>> pick
>>>>>>>>> the correct one at a given time.
>>>>>>>>>
>>>>>>>>> For responses to unicast, you should copy the destination IP 
>>>>>>>>> of the
>>>>>>>>> request as
>>>>>>>>> the source IP of the response.
>>>>>>>>>
>>>>>>>>> And for responses to multicast, you should again let the IP stack
>>>>>>>>> routing
>>>>>>>>> table pick the correct source address for the inbound interface.
>>>>>>>>>
>>>>>>>>> In any case, that can only work with packet info ancillary data.
>>>>>>>>> There are
>>>>>>>>> no
>>>>>>>>> reason to write OS-specific code here.
>>>>>>>> In this case we are responding to multicast (works currently as 
>>>>>>>> you
>>>>>>>> mentioned above I think) BUT also we are providing a unicast ip
>>>>>>>> address in
>>>>>>>> the A/AAAA record in the response packet.
>>>>>>>> The relationship between the unicast address and the multicast
>>>>>>>> response is
>>>>>>>> that they share the same interface. Right?
>>>>>>> Multicast addresses do not have an interface; you can have the same
>>>>>>> multicast
>>>>>>> addresses on different interfaces referring to the same or to
>>>>>>> different actual
>>>>>>> group(s). AFAIK, you have to get the correct interface index 
>>>>>>> from the
>>>>>>> incoming
>>>>>>> packet ancillary data.
>>>>>> Ok, thanks for the information.
>>>>>>
>>>>>> libmicrodns scans all interface addresses on initialisation and for
>>>>>> each valid one opens a socket.
>>>>>>
>>>>>> Each socket and interface [address (linux) / index (Windows)] are
>>>>>> paired so when we get an incoming packet we know what interface 
>>>>>> it is.
>>>>>> Therefore, I don't think we have to deal with packet ancillary data?
>>>>>>
>>>>>> The problem though is getting the unicast address for that interface
>>>>>> so we can put it in the response body (A/AAAA record).
>>>>>>
>>>>>> If I'm correct, this needs to be calculated on Windows which will
>>>>>> require OS-specific code. Then I will update libmicrodns to pass the
>>>>>> IP address string to the callback so VLC can use it to populate the
>>>>>> A/AAAA record.
>>>>>>
>>>>>> Does this sound like a valid approach?
>>>>>>
>>>>>> Thanks,
>>>>>>
>>>>>> Roland
>>>>>
>>>>>
>>>>> Hi,
>>>>>
>>>>> I've made the necessary changes to libmicrodns. My pull request is
>>>>> here:
>>>>> https://github.com/videolabs/libmicrodns/pull/20/commits/fb58b2fffdce80be6381431845fc8e743920e054 
>>>>>
>>>>
>>>> Hello, I will do the review on libmicrodns.
>> Thanks Thomas
>>>>
>>>> I have one question though. Will it be possible to do the same with 
>>>> avahi (used by default on linux Desktop) and bonjour (used by macOS) ?
>>>>
>>>
>>> On macOS/iOS you would do something like:
>>>
>>>     NSNetService *service = [[NSNetService alloc] 
>>> initWithDomain:@"local."
>>> type:@"_http._tcp."
>>> name:@"VLC media player something"
>>> port:8080];
>>>     [service publish];
>>>
>>> (We probably want to use CFNetServices instead as that is pure C, 
>>> but it works really similar)
>>>
>>> It seems to work similar for avahi, see
>>> https://www.avahi.org/doxygen/html/publish_8h.html#acb05a7d3d23a3b825ca77cb1c7d00ce4 
>>>
>>> When passing NULL for host, the daemon will use the local host name, 
>>> just like what
>>> happens in the above snippet for macOS/iOS.
>>>
>>> So we do not have to worry about which exact addresses to announce 
>>> at all there.

Thanks for the info. It looks like we can still choose a custom domain 
name for the service (vlc.local) if we want it to be consistent across 
iOS/Linux/Windows?

>>
>>
>> libmicrodns is our cross-platform solution for mDNS discovery / 
>> advertisement. Why do we need to write specific code for Avahi / 
>> Bonjour implementations?
>>
>> I've tested service discovery on Linux and Windows and it works. I 
>> have no access to macOS.
>>
>
> It can not work if another mDNS daemon like avahi or bonjour is 
> running as that is already
> bound to the port. See https://github.com/videolabs/libmicrodns/issues/9

It worked for me in Linux (Docker) with the avahi-daemon service running.

>
>>
>>>
>>>>>
>>>>> Please have a look and let me know if it's a viable solution.
>>>>>
>>>>> Thanks,
>>>>>
>>>>> Roland
>>>>>
>>>>> _______________________________________________
>>>>> 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
>> _______________________________________________
>> 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