[vlc-devel] [PATCH] [RESEND] Add support for AMT multicast tunneling over non-multicast enabled networks
Rémi Denis-Courmont
remi at remlab.net
Wed May 15 19:17:41 CEST 2019
Le maanantaina 13. toukokuuta 2019, 17.51.21 EEST Wayne Brassem a écrit :
> Resend of submission sent on May 6th.
>
> ----------------------------------------------
>
> Updated submission. The last one was on April 29.
>
> Changes in this version based on the two previous code reviews:
> 1. Eliminated a redundant malloc() and strcpy() operation per call to
> BlockUDP(). 2. Upon inspection it was indeed obvious that there was
> considerable and inefficient usage of ntop and pton for IP address format
> conversion throughout. This issue has been addressed and kept to a
> minimum, however because both the string and binary IP address formats are
> used regularly both are retained in the data structures. 3. All IP address
> comparisons are done using numeric form except for a single strcmp()
> occurrence where it is necessary. 4. The protective buffer approach was
> imported from upd.c to address the potential to receive maximal IPv4 UDP
> frames. The alternative of allocating a pathologically large buffer for
> each packet received when not required is inefficient. 5. The usage of
> strtok_r() was added based on the code review comments on an much earlier
> version of this module which used strtok() because it was not thread safe.
> It’s probably safer this way, but if strtok is preferred that’s easy to
> change.
>
> As always, additional comments and suggestions are welcome.
> Wayne.
>
> ---
> modules/access/Makefile.am | 4 +
> modules/access/amt.c | 1226 ++++++++++++++++++++++++++++++++++++
> modules/access/amt.h | 220 +++++++
> 3 files changed, 1450 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 9cdf98e0a1..fec9c32005 100644
> --- a/modules/access/Makefile.am
> +++ b/modules/access/Makefile.am
> @@ -373,6 +373,10 @@ libudp_plugin_la_SOURCES = access/udp.c
> libudp_plugin_la_LIBADD = $(SOCKET_LIBS)
> access_LTLIBRARIES += libudp_plugin.la <http://libudp_plugin.la/>
>
> +libamt_plugin_la_SOURCES = access/amt.c access/amt.h
> +libamt_plugin_la_LIBADD = $(SOCKET_LIBS)
> +access_LTLIBRARIES += libamt_plugin.la <http://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..e1e5e61158
> --- /dev/null
> +++ b/modules/access/amt.c
> @@ -0,0 +1,1226 @@
> +/**
> + * @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
> <mailto:massiot at via.ecp.fr>> - original UDP code + *
> Tristan Leteurtre <tooney at via.ecp.fr <mailto:tooney at via.ecp.fr>>
> - original UDP code + * Laurent Aimar <fenrir at via.ecp.fr
> <mailto: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
> <mailto:natalie.landsberg97 at gmail.com>> - AMT support + * Wayne
> Brassem <wbrassem at rogers.com <mailto:wbrassem at rogers.com>> -
> Added FQDN 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 (IP address or FQDN)")
> +#define AMT_RELAY_ADDR_LONG N_("AMT relay anycast address, or specify the
> relay you want by address or fully qualified domain name") +#define
> AMT_DEFAULT_RELAY N_("amt-relay.m2icast.net
> <http://amt-relay.m2icast.net/>") +
> +static int Open (vlc_object_t *);
> +static void Close (vlc_object_t *);
Reorder the code to avoid forward declarations. Same below.
> +
> +/* Utility functions */
> +static unsigned short get_checksum( unsigned short *buffer, int nLen );
> +static void make_report( amt_igmpv3_membership_report_t *mr );
> +static void make_ip_header( amt_ip_alert_t *p_ipHead );
> +
> +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_DEFAULT_RELAY, AMT_RELAY_ADDRESS,
> AMT_RELAY_ADDR_LONG, true ) +
> + set_capability( "access", 0 )
> + add_shortcut( "amt" )
> +
> + set_callbacks( Open, Close )
> +vlc_module_end ()
> +
> +/**************************************************************************
> *** + * Local prototypes
> +
> ***************************************************************************
> **/ +static block_t *BlockUDP( stream_t *, bool * );
> +static int Control( stream_t *, int, va_list );
> +
> +/**************************************************************************
> *** + * Open: Open a connection to the multicast feed
> +
> ***************************************************************************
> **/ +static int Open( vlc_object_t *p_this )
> +{
> + stream_t *p_access = (stream_t*) p_this;
> + access_sys_t *sys = NULL;
> + struct addrinfo hints, *serverinfo = NULL;
> + struct sockaddr_in *server_addr;
> + char *psz_name = NULL, *saveptr, *psz_strtok_r,
> ip_buffer[INET_ADDRSTRLEN];
> + int i_bind_port = 1234, i_server_port = 0, VLC_ret =
VLC_SUCCESS, res;
> + vlc_url_t url;
> +
> + if( p_access->b_preparsing )
> + return VLC_EGENERIC;
> +
> + /* Allocate the structure for holding AMT info and zeroize it */
> + sys = vlc_obj_calloc( p_this, 1, sizeof( *sys ) );
> + if( unlikely( sys == NULL ) )
> + return VLC_ENOMEM;
> +
> + /* The standard MPEG-2 transport is 188 bytes. 7 packets fit into a
> standard 1500 byte Ethernet frame */ + sys->mtu = 7 * 188;
> +
> + /* Protective packet overflow buffer designed to accommodate maximum
> IPv4 UDP payload minus the anticapated MTU */
Typo.
> + sys->overflow_block =
> block_Alloc(MAX_IPV4_UDP - sys->mtu);
> + if( unlikely( sys->overflow_block == NULL ) )
> + return VLC_ENOMEM;
> +
> + p_access->p_sys = sys;
> +
> + /* Set up p_access */
> + ACCESS_SET_CALLBACKS( NULL, BlockUDP, Control, NULL );
> +
> + if( !p_access->psz_location )
> + return VLC_EGENERIC;
> +
> + psz_name = strdup( p_access->psz_location );
> + if ( unlikely( psz_name == NULL ) )
> + return VLC_ENOMEM;
> +
> + /* Parse psz_name syntax :
> + * [serveraddr[:serverport]][@[bindaddr]:[bindport]] */
> + if( vlc_UrlParse( &url, p_access->psz_url ) != 0 )
> + {
> + msg_Err( p_access, "Invalid URL: %s", p_access->psz_url );
> + VLC_ret = VLC_EGENERIC;
> + goto cleanup;
> + }
> +
> + /* Determining the multicast source and group depends on the URL
> provided */ + /*
> */ + /* The address(es) in the URL can be in the form of
> IP address or FQDN */ + /* By calling vlc_getaaddrinfo() you get it
> in IP form either way */ + /*
> */ + /* Case 1:
> amt://<source-ip-address>@<multicast-group-ip-address> */ + /*
> */ +
> /* sys->mcastSrc = <source-ip-address>
> */ + /* sys->mcastSrcAddr = inet_pton( sys->mcastSrc )
> */ + /*
> */ + /* sys->mcastGroup =
> <multicast-group-ip-address> */ + /*
> sys->mcastGroupAddr = inet_pton( sys->mcastGroup ) */ + /*
> */ +
> /* Case 2: amt://<multicast-group-ip-address>
> */ + /*
> */ + /* sys->mcastSrc = MCAST_ANYCAST = "0.0.0.0"
> */ + /* sys->mcastSrcAddr = inet_pton( sys->mcastSrc
> ) = 0 */ + /*
> */ + /* sys->mcastGroup =
> <multicast-group-ip-address> */ + /*
> sys->mcastGroupAddr = inet_pton( sys->mcastGroup ) */ + /*
> */ +
> + /* If UDP port provided then assign port to stream */
> + if( url.i_port > 0 )
> + i_bind_port = url.i_port;
> +
> + msg_Dbg( p_access, "Opening multicast: %s:%d local=%s:%d",
> url.psz_host, i_server_port, url.psz_path, i_bind_port );
> +
> + /* Initialize hints prior to call to vlc_getaddrinfo with either IP
> address or FQDN */
> + memset( &hints, 0, sizeof( hints ));
> + hints.ai_family = AF_INET; /* Setting to AF_UNSPEC accepts both IPv4
> and IPv6 */
> + hints.ai_socktype = SOCK_DGRAM;
> +
> + /* Retrieve list of multicast addresses matching the multicast group
> identifier */ + res = vlc_getaddrinfo( url.psz_host, AMT_PORT, &hints,
> &serverinfo );
DNS-resolving a multicast group is veeeery weird.
> +
> + /* If an error returned print reason and exit */
> + if( res )
> + {
> + msg_Err( p_access, "Could not find multicast group %s, reason: %s",
> url.psz_host, gai_strerror(res) );
> + VLC_ret = VLC_EGENERIC;
> + goto cleanup;
> + }
> +
> + /* Convert binary socket address to string */
> + server_addr = (struct sockaddr_in *) serverinfo->ai_addr;
> + inet_ntop(AF_INET, &(server_addr->sin_addr), ip_buffer,
> INET_ADDRSTRLEN); +
> + /* Store the binary socket representation of multicast group address */
> + sys->mcastGroupAddr = *server_addr;
> +
> + /* Release the allocated memory */
> + freeaddrinfo( serverinfo );
> + serverinfo = NULL;
> +
> + /* Store string representation */
> + sys->mcastGroup = strdup( ip_buffer );
As I said before, this is completely useless and not the only occurrence.
--
レミ・デニ-クールモン
http://www.remlab.net/
More information about the vlc-devel
mailing list