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

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


On 5/08/2019 2:16 PM, Thomas Guillem wrote:
>
> On Sun, Aug 4, 2019, at 07:56, 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.
>>
>> libmicrodns is our cross-platform solution for mDNS discovery /
>> advertisement. Why do we need to write specific code for Avahi / Bonjour
>> implementations?
> No, libmicrodns is only used on mobile ports and windows.
> Avahi is used on Linux, bonjour is used on macOS.
>
> Therefore, Videolan doesn't package libmicrodns for macOS builds, and Linux distributions should not include both avahi and libmicrodns plugins.

Thanks for letting me know.

In that case, for now I will just focus on the libmicrodns 
implementation if that's OK?

>
>> I've tested service discovery on Linux and Windows and it works. I have
>> no access to macOS.
>>
>>
>>>>> 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