[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