[vlc-devel] [PATCH] access: amt: allow users to view multicast streams when not in multicast network

Tristan Matthews tmatth at videolan.org
Thu Nov 1 17:02:47 CET 2018


On Thu, Nov 1, 2018 at 11:40 AM Tristan Matthews <tmatth at videolan.org> wrote:
>
> Hi,
>
> On Thu, Nov 1, 2018 at 10:36 AM Natalie Landsberg
> <natalie.landsberg97 at gmail.com> wrote:
> >
> > AMT = Automatic Multicast Tunneling
> >
> > Re-sending patch as no further comments were made previously.
> > I got busy and forgot to ping the devel list again, so I created a
> > new patch instead of dragging up an old one.
> >
> > This module aims to provide access to multicast streams from a
> > non-multicast enabled network. So, if you have a stream coming
> > from Internet2, you should be able to access it from outside of
> > Internet2 using this module. For example, some universities have
> > livestreams of ocean explorations that are on 24/7. Normally, you
> > would not be able to access these streams without being within the
> > university network. Now, for public ones, you can view them from
> > almost anywhere.
> >
> > Essentially it creates a tunnel for you to have access to the stream.
>
> This sounds like a cool feature.
>
> >
> > It works similarly to udp native multicast streaming:
> > -provide server address
> > -provide multicast group address
> > -(optional) provide AMT relay address
> >
> > There exists a relay which can be used to test the stream. Can be
> > provided upon request.
> >
> > Modified code according to comments from VLC developers, listed below
> >
> > -Reordered code to avoid forward declarations (but please verify again)
> > -Removed unnecessary code
> > -Made sure to use standard ISO C types
> > -Moved opening AMT tunnel to its own function outside of BlockUDP for cleaner read
> > -Changed timer to use vlc_tick_now
> > -Changed stack allocated array to dynamic in BlockUDP
> > -Changed URI parsers to use vlc_UrlParseFixup()
> > -Added private thread for update timer and fixed typo in Makefile.
> >
> > Now supports both ASM and SSM. Fixed minor style issues and some error handling.
> >
> > Changed instance of int, short, etc to uint*_t for wire format messages,
> > to guarantee a fixed-size. Tested and works on 64-bit MacOS, but needs
> > to be tested on 32-bit.
> >
> > Can still change the fixed-size integers if needed.
> >
> > Fixed what I think are all memory leaks. Needs verification. Added more error handling.
> > ---
> >  modules/access/Makefile.am |   4 +
> >  modules/access/amt.c       | 971 +++++++++++++++++++++++++++++++++++++++++++++
> >  modules/access/amt.h       | 220 ++++++++++
> >  3 files changed, 1195 insertions(+)
> >  create mode 100644 modules/access/amt.c
> >  create mode 100644 modules/access/amt.h
> >
> > diff --git a/modules/access/Makefile.am b/modules/access/Makefile.am
> > index 5abe3a1a5f..445bf262f6 100644
> > --- a/modules/access/Makefile.am
> > +++ b/modules/access/Makefile.am
> > @@ -371,6 +371,10 @@ libudp_plugin_la_SOURCES = access/udp.c
> >  libudp_plugin_la_LIBADD = $(SOCKET_LIBS)
> >  access_LTLIBRARIES += libudp_plugin.la
> >
> > +libamt_plugin_la_SOURCES = access/amt.c access/amt.h
> > +libamt_plugin_la_LIBADD = $(SOCKET_LIBS)
> > +access_LTLIBRARIES += libamt_plugin.la
> > +
> >  libunc_plugin_la_SOURCES = access/unc.c access/smb_common.h
> >  libunc_plugin_la_LIBADD = -lmpr -lnetapi32
> >  if HAVE_WIN32
> > diff --git a/modules/access/amt.c b/modules/access/amt.c
> > new file mode 100644
> > index 0000000000..188a4875b4
> > --- /dev/null
> > +++ b/modules/access/amt.c
> > @@ -0,0 +1,971 @@
> > +/**
> > + * @file amt.c
> > + * @brief Automatic Multicast Tunneling Protocol (AMT) file for VLC media player
> > + * Allows multicast streaming when not in a multicast-enabled network
> > + * Currently IPv4 is supported, but IPv6 is not yet.
> > + *
> > + * Copyright (C) 2018 VLC authors and VideoLAN
> > + * Copyright (c) Juniper Networks, Inc., 2018. All rights reserved.
> > + *
> > + * Authors: Christophe Massiot <massiot at via.ecp.fr>     - original UDP code
> > + *          Tristan Leteurtre <tooney at via.ecp.fr>       - original UDP code
> > + *          Laurent Aimar <fenrir at via.ecp.fr>           - original UDP code
> > + *          Jean-Paul Saman <jpsaman #_at_# m2x dot nl> - original UDP code
> > + *          Remi Denis-Courmont                         - original UDP code
> > + *          Natalie Landsberg natalie.landsberg97 at gmail.com - AMT support
> > + *
> > + * This code is licensed to you under the GNU Lesser General Public License
> > + * version 2.1 or later. You may not use this code except in compliance with
> > + * the GNU Lesser General Public License.
> > + * This code is not an official Juniper product.
> > + *
> > + * This library 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 library 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 library; if not, write to the Free Software
> > + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
> > + ****************************************************************************/
> > +#ifdef HAVE_CONFIG_H
> > +# include "config.h"
> > +#endif
> > +
> > +#include <errno.h>
> > +#include <ctype.h>
> > +#ifdef HAVE_ARPA_INET_H
> > +# include <arpa/inet.h>
> > +#endif
> > +
> > +#ifdef HAVE_SYS_SELECT_H
> > +# include <sys/select.h>
> > +#endif
> > +
> > +#ifdef HAVE_SYS_SOCKET_H
> > +# include <sys/socket.h>
> > +#endif
> > +
> > +#include <vlc_common.h>
> > +#include <vlc_demux.h>
> > +#include <vlc_plugin.h>
> > +#include <vlc_access.h>
> > +#include <vlc_network.h>
> > +#include <vlc_block.h>
> > +#include <vlc_interrupt.h>
> > +#include <vlc_url.h>
> > +
> > +#include "amt.h"
> > +
> > +#ifdef HAVE_POLL
> > + #include <poll.h>
> > +#endif
> > +#ifdef HAVE_SYS_UIO_H
> > + #include <sys/uio.h>
> > +#endif
> > +
> > +#define BUFFER_TEXT N_("Receive buffer")
> > +#define BUFFER_LONGTEXT N_("AMT receive buffer size (bytes)" )
> > +#define TIMEOUT_TEXT N_("Native multicast timeout (sec)")
> > +#define AMT_TIMEOUT_TEXT N_("AMT timeout (sec)")
> > +#define AMT_RELAY_ADDRESS N_("AMT relay address")
> > +#define AMT_RELAY_ADDR_LONG N_("AMT relay anycast address, or specify the relay you want")
> > +
> > +static int  Open (vlc_object_t *);
> > +static void Close (vlc_object_t *);
> > +
> > +vlc_module_begin ()
> > +    set_shortname( N_("AMT" ) )
> > +    set_description( N_("AMT input") )
> > +    set_category( CAT_INPUT )
> > +    set_subcategory( SUBCAT_INPUT_ACCESS )
> > +
> > +    add_integer( "amt-timeout", 5, AMT_TIMEOUT_TEXT, NULL, true )
> > +    add_integer( "amt-native-timeout", 3, TIMEOUT_TEXT, NULL, true )
> > +    add_string( "amt-relay", "", AMT_RELAY_ADDRESS, AMT_RELAY_ADDR_LONG, true )
> > +
> > +    set_capability( "access", 0 )
> > +    add_shortcut( "amt" )
> > +
> > +    set_callbacks( Open, Close )
> > +vlc_module_end ()
> > +
> > +/*****************************************************************************
> > + * Control:
> > + *****************************************************************************/
> > +static int Control( stream_t *p_access, int i_query, va_list args )
> > +{
> > +    bool    *pb_bool;
> > +
> > +    switch( i_query )
> > +    {
> > +        case STREAM_CAN_SEEK:
> > +        case STREAM_CAN_FASTSEEK:
> > +        case STREAM_CAN_PAUSE:
> > +        case STREAM_CAN_CONTROL_PACE:
> > +            pb_bool = va_arg( args, bool * );
> > +            *pb_bool = false;
> > +            break;
> > +
> > +        case STREAM_GET_PTS_DELAY:
> > +            *va_arg( args, vlc_tick_t * ) =
> > +                VLC_TICK_FROM_MS(var_InheritInteger( p_access, "network-caching" ));
> > +        break;
> > +
> > +        default:
> > +            return VLC_EGENERIC;
> > +    }
> > +    return VLC_SUCCESS;
> > +}
> > +
> > +/*****************************************************************************
> > + * BlockUDP:
> > + *****************************************************************************/
> > +static block_t *BlockUDP(stream_t *access, bool *restrict eof)
> > +{
> > +    access_sys_t *sys = access->p_sys;
> > +
> > +    block_t *pkt = block_Alloc(sys->mtu);
> > +    char *amtpkt = malloc( DEFAULT_MTU );
>
> You'll want to check that amtpkt was allocated as well.
>
> > +
> > +    if (unlikely(pkt == NULL))
> > +    {   /* OOM - dequeue and discard one packet */
> > +        char dummy;
> > +        recv(sys->fd, &dummy, 1, 0);
> > +        return NULL;
> > +    }
> > +
> > +    struct iovec iov = {
> > +        .iov_base = pkt->p_buffer,
> > +        .iov_len  = sys->mtu,
> > +    };
> > +    struct msghdr msg = {
> > +        .msg_iov = &iov,
> > +        .msg_iovlen = 1,
> > +#ifdef __linux__
> > +        .msg_flags = MSG_TRUNC,
> > +#endif
> > +    };
> > +
> > +    struct pollfd ufd[1];
> > +
> > +    if( sys->tryAMT )
> > +        ufd[0].fd = sys->sAMT;
> > +    else
> > +        ufd[0].fd = sys->fd;
> > +    ufd[0].events = POLLIN;
> > +
> > +    switch (vlc_poll_i11e(ufd, 1, sys->timeout))
> > +    {
> > +        case 0:
> > +            msg_Err(access, "native multicast receive time-out");
> > +            net_Close( sys->fd );
> > +            if( !sys->tryAMT )
> > +            {
> > +                if( !open_amt_tunnel( sys, access ) )
> > +                    goto error;
> > +            }
> > +            else
> > +            {
> > +                msg_Err(access, "AMT receive time-out");
> > +                *eof = true;
> > +            }
> > +            /* fall through */
> > +        case -1:
> > +            goto error;
> > +    }
> > +
> > +    ssize_t len;
> > +    if( sys->tryAMT )
> > +    {
> > +        len = recv( sys->sAMT, amtpkt, DEFAULT_MTU, 0 );
> > +
> > +        if( len < 0 || amtpkt[0] != AMT_MULT_DATA )
> > +            goto error;
> > +
> > +        ssize_t shift = IP_HDR_LEN + UDP_HDR_LEN + AMT_HDR_LEN;
> > +
> > +        if( len < shift )
> > +        {
> > +            msg_Err(access, "%zd bytes packet truncated (MTU was %zu)",
> > +                len, sys->mtu);
> > +            pkt->i_flags |= BLOCK_FLAG_CORRUPTED;
> > +            sys->mtu = len;
> > +        } else {
> > +            len -= shift;
> > +        }
> > +
> > +        memcpy( pkt->p_buffer, &amtpkt[shift], len );
> > +        free( amtpkt );
> > +    }
> > +    else
> > +        len = recvmsg(sys->fd, &msg, 0);
> > +
> > +#ifdef MSG_TRUNC
> > +    if (msg.msg_flags & MSG_TRUNC)
> > +    {
> > +        msg_Err(access, "%zd bytes packet truncated (MTU was %zu)",
> > +                len, sys->mtu);
> > +        pkt->i_flags |= BLOCK_FLAG_CORRUPTED;
> > +        sys->mtu = len;
> > +    }
> > +    else
> > +#endif
> > +        pkt->i_buffer = len;
> > +
> > +    return pkt;
> > +
> > +error:
> > +    free( amtpkt );
> > +    block_Release(pkt);
> > +    return NULL;
> > +}
> > +
> > +/*****************************************************************************
> > + * Open: open the socket
> > + *****************************************************************************/
> > +static int Open( vlc_object_t *p_this )
> > +{
> > +    stream_t     *p_access = (stream_t*)p_this;
> > +    access_sys_t *sys;
> > +
> > +    if( p_access->b_preparsing )
> > +        return VLC_EGENERIC;
> > +
> > +    sys = vlc_obj_malloc( p_this, sizeof( *sys ) );
> > +    if( unlikely( sys == NULL ) )
> > +    {
> > +        free( sys );

No need for this free.

Best,
-t


More information about the vlc-devel mailing list