<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Great comments.  Thank you.  I’ll get on it.  And next time I’ll try to squash all three files atm.c, amt.h and Makefile.am into a single patch since they need to be applied together.<div class="">Wayne.<br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Jan 18, 2019, at 12:34 PM, Tristan Matthews <<a href="mailto:tmatth@videolan.org" class="">tmatth@videolan.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">Hi,</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">On Thu, Jan 17, 2019 at 6:41 AM Wayne Brassem <</span><a href="mailto:wbrassem@rogers.com" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">wbrassem@rogers.com</a><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">> wrote:</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br class="">Addressing items raised in <a href="https://mailman.videolan.org/pipermail/vlc-devel/2018-November/121776.html" class="">https://mailman.videolan.org/pipermail/vlc-devel/2018-November/121776.html</a> and added FQDN support to the AMT code.<br class="">AMT stands for Automatic Multicast Tunnelling and allow the user to receive multicast streams over an non-multicast enabled network by tunnelling through an AMT relay.<br class=""><br class="">From 91ef0bbc4b43eceaa3aea6cb2710232370a67ec8 Mon Sep 17 00:00:00 2001<br class="">From: Wayne Brassem <<a href="mailto:wbrassem@rogers.com" class="">wbrassem@rogers.com</a>><br class="">Date: Mon, 14 Jan 2019 18:25:02 -0500<br class="">Subject: [PATCH 1/3] Addressed items in original AMT code submission and added<br class="">FQDN support<br class=""><br class="">---<br class="">modules/access/Makefile.am | 4 ++++<br class="">1 file changed, 4 insertions(+)<br class=""><br class="">diff --git a/modules/access/Makefile.am b/modules/access/Makefile.am<br class="">index c56cb8fe3a..792c6efb04 100644<br class="">--- a/modules/access/Makefile.am<br class="">+++ b/modules/access/Makefile.am<br class="">@@ -373,6 +373,10 @@ libudp_plugin_la_SOURCES = access/udp.c<br class="">libudp_plugin_la_LIBADD = $(SOCKET_LIBS)<br class="">access_LTLIBRARIES += <a href="http://libudp_plugin.la" class="">libudp_plugin.la</a><br class=""><br class="">+libamt_plugin_la_SOURCES = access/amt.c access/amt.h<br class="">+libamt_plugin_la_LIBADD = $(SOCKET_LIBS)<br class="">+access_LTLIBRARIES += <a href="http://libamt_plugin.la" class="">libamt_plugin.la</a><br class="">+<br class="">libunc_plugin_la_SOURCES = access/unc.c access/smb_common.h<br class="">libunc_plugin_la_LIBADD = -lmpr -lnetapi32<br class="">if HAVE_WIN32<br class="">--<br class="">2.17.2 (Apple Git-113)<br class=""><br class="">From 91c757f47445095ac8de8574a8b216cca3043898 Mon Sep 17 00:00:00 2001<br class="">From: Wayne Brassem <<a href="mailto:wbrassem@rogers.com" class="">wbrassem@rogers.com</a>><br class="">Date: Mon, 14 Jan 2019 18:47:06 -0500<br class="">Subject: [PATCH 2/3] Addressed concerns in first submissions and added support<br class="">for FQDN<br class=""><br class="">---<br class="">modules/access/amt.c | 1208 ++++++++++++++++++++++++++++++++++++++++++<br class="">1 file changed, 1208 insertions(+)<br class="">create mode 100644 modules/access/amt.c<br class=""><br class="">diff --git a/modules/access/amt.c b/modules/access/amt.c<br class="">new file mode 100644<br class="">index 0000000000..df023be9dc<br class="">--- /dev/null<br class="">+++ b/modules/access/amt.c<br class="">@@ -0,0 +1,1208 @@<br class="">+/**<br class="">+ * @file amt.c<br class="">+ * @brief Automatic Multicast Tunneling Protocol (AMT) file for VLC media player<br class="">+ * Allows multicast streaming when not in a multicast-enabled network<br class="">+ * Currently IPv4 is supported, but IPv6 is not yet.<br class="">+ *<br class="">+ * Copyright (C) 2018 VLC authors and VideoLAN<br class="">+ * Copyright (c) Juniper Networks, Inc., 2018. All rights reserved.<br class="">+ *<br class="">+ * Authors: Christophe Massiot <<a href="mailto:massiot@via.ecp.fr" class="">massiot@via.ecp.fr</a>>         - original UDP code<br class="">+ *          Tristan Leteurtre <<a href="mailto:tooney@via.ecp.fr" class="">tooney@via.ecp.fr</a>>           - original UDP code<br class="">+ *          Laurent Aimar <<a href="mailto:fenrir@via.ecp.fr" class="">fenrir@via.ecp.fr</a>>               - original UDP code<br class="">+ *          Jean-Paul Saman <jpsaman #_at_# m2x dot nl>     - original UDP code<br class="">+ *          Remi Denis-Courmont                             - original UDP code<br class="">+ *          Natalie Landsberg <a href="mailto:natalie.landsberg97@gmail.com" class="">natalie.landsberg97@gmail.com</a> - AMT support<br class="">+ *          Wayne Brassem <<a href="mailto:wbrassem@rogers.com" class="">wbrassem@rogers.com</a>>             - Added FQDN support<br class="">+ *<br class="">+ * This code is licensed to you under the GNU Lesser General Public License<br class="">+ * version 2.1 or later. You may not use this code except in compliance with<br class="">+ * the GNU Lesser General Public License.<br class="">+ * This code is not an official Juniper product.<br class="">+ *<br class="">+ * This library is free software; you can redistribute it and/or<br class="">+ * modify it under the terms of the GNU Lesser General Public License<br class="">+ * as published by the Free Software Foundation; either version 2.1<br class="">+ * of the License, or (at your option) any later version.<br class="">+ *<br class="">+ * This library is distributed in the hope that it will be useful,<br class="">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of<br class="">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br class="">+ * GNU Lesser General Public License for more details.<br class="">+ *<br class="">+ * You should have received a copy of the GNU Lesser General Public<br class="">+ * License along with this library; if not, write to the Free Software<br class="">+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA<br class="">+ ****************************************************************************/<br class="">+#ifdef HAVE_CONFIG_H<br class="">+# include "config.h"<br class="">+#endif<br class="">+<br class="">+#include <errno.h><br class="">+#include <ctype.h><br class="">+#ifdef HAVE_ARPA_INET_H<br class="">+# include <arpa/inet.h><br class="">+#endif<br class="">+<br class="">+#ifdef HAVE_SYS_SELECT_H<br class="">+# include <sys/select.h><br class="">+#endif<br class="">+<br class="">+#ifdef HAVE_SYS_SOCKET_H<br class="">+# include <sys/socket.h><br class="">+#endif<br class="">+<br class="">+#include <vlc_common.h><br class="">+#include <vlc_demux.h><br class="">+#include <vlc_plugin.h><br class="">+#include <vlc_access.h><br class="">+#include <vlc_network.h><br class="">+#include <vlc_block.h><br class="">+#include <vlc_interrupt.h><br class="">+#include <vlc_url.h><br class="">+<br class="">+#include "amt.h"<br class="">+<br class="">+#ifdef HAVE_POLL<br class="">+ #include <poll.h><br class="">+#endif<br class="">+#ifdef HAVE_SYS_UIO_H<br class="">+ #include <sys/uio.h><br class="">+#endif<br class="">+<br class="">+#define BUFFER_TEXT N_("Receive buffer")<br class="">+#define BUFFER_LONGTEXT N_("AMT receive buffer size (bytes)" )<br class="">+#define TIMEOUT_TEXT N_("Native multicast timeout (sec)")<br class="">+#define AMT_TIMEOUT_TEXT N_("AMT timeout (sec)")<br class="">+#define AMT_RELAY_ADDRESS N_("AMT relay (IP address or FQDN)")<br class="">+#define AMT_RELAY_ADDR_LONG N_("AMT relay anycast address, or specify the relay you want by address or fully qualified domain name")<br class="">+#define AMT_DEFAULT_RELAY N_("<a href="http://amt-relay.m2icast.net" class="">amt-relay.m2icast.net</a>")<br class="">+<br class="">+static int  Open (vlc_object_t *);<br class="">+static void Close (vlc_object_t *);<br class="">+<br class="">+/* memory leak and packet counters */<br class="">+static int mem_alloc, packet;<br class=""></blockquote><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">This information should be stored in the access_sys_t struct instead</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">of static globals, or just deleted since it seems to be for debugging</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">only.</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">+<br class="">+vlc_module_begin ()<br class="">+    set_shortname( N_("AMT" ) )<br class="">+    set_description( N_("AMT input") )<br class="">+    set_category( CAT_INPUT )<br class="">+    set_subcategory( SUBCAT_INPUT_ACCESS )<br class="">+<br class="">+    add_integer( "amt-timeout", 5, AMT_TIMEOUT_TEXT, NULL, true )<br class="">+    add_integer( "amt-native-timeout", 3, TIMEOUT_TEXT, NULL, true )<br class="">+    add_string( "amt-relay", AMT_DEFAULT_RELAY, AMT_RELAY_ADDRESS, AMT_RELAY_ADDR_LONG, true )<br class="">+<br class="">+    set_capability( "access", 0 )<br class="">+    add_shortcut( "amt" )<br class="">+<br class="">+    set_callbacks( Open, Close )<br class="">+vlc_module_end ()<br class="">+<br class="">+/*****************************************************************************<br class="">+ * Control:<br class="">+ *****************************************************************************/<br class="">+static int Control( stream_t *p_access, int i_query, va_list args )<br class="">+{<br class="">+    bool    *pb_bool;<br class="">+<br class="">+/*    msg_Dbg( p_access, "Control: mem_alloc = %d", mem_alloc); */<br class=""></blockquote><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">This can be deleted.</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">+<br class="">+    switch( i_query )<br class="">+    {<br class="">+        case STREAM_CAN_SEEK:<br class="">+        case STREAM_CAN_FASTSEEK:<br class="">+        case STREAM_CAN_PAUSE:<br class="">+        case STREAM_CAN_CONTROL_PACE:<br class="">+            pb_bool = va_arg( args, bool * );<br class="">+            *pb_bool = false;<br class="">+            break;<br class="">+<br class="">+        case STREAM_GET_PTS_DELAY:<br class="">+            *va_arg( args, vlc_tick_t * ) =<br class="">+                VLC_TICK_FROM_MS(var_InheritInteger( p_access, "network-caching" ));<br class="">+        break;<br class="">+<br class="">+        default:<br class="">+            return VLC_EGENERIC;<br class="">+    }<br class="">+    return VLC_SUCCESS;<br class="">+}<br class="">+<br class="">+/*****************************************************************************<br class="">+ * BlockUDP:<br class="">+ *****************************************************************************/<br class="">+static block_t *BlockUDP(stream_t *p_access, bool *restrict eof)<br class="">+{<br class="">+    access_sys_t *sys = p_access->p_sys;<br class="">+    ssize_t len;<br class="">+<br class="">+    block_t *pkt = block_Alloc(sys->mtu);<br class="">+    char *amtpkt = malloc( DEFAULT_MTU );<br class="">+<br class="">+    packet++;<br class="">+    mem_alloc++;   /* do not include *pkt in memory alloc count because it gets freed by caller */<br class="">+<br class="">+/*    msg_Dbg( p_access, "BlockUDP Enter: packet = %d, mem_alloc = %d, pkt = %016x, amtpkt = %016x", packet, mem_alloc, (int) pkt, (int) amtpkt); */<br class="">+<br class="">+    if (unlikely(pkt == NULL))<br class="">+    {   /* OOM - dequeue and discard one packet */<br class="">+        char dummy;<br class="">+        recv(sys->fd, &dummy, 1, 0);<br class="">+        return NULL;<br class="">+    }<br class="">+<br class="">+    if (unlikely(amtpkt == NULL))<br class="">+    goto error;<br class="">+<br class="">+    struct iovec iov = {<br class="">+        .iov_base = pkt->p_buffer,<br class="">+        .iov_len  = sys->mtu,<br class="">+    };<br class="">+    struct msghdr msg = {<br class="">+        .msg_iov = &iov,<br class="">+        .msg_iovlen = 1,<br class="">+#ifdef __linux__<br class="">+        .msg_flags = MSG_TRUNC,<br class="">+#endif<br class="">+    };<br class="">+<br class="">+    struct pollfd ufd[1];<br class="">+<br class="">+    if( sys->tryAMT )<br class="">+        ufd[0].fd = sys->sAMT;<br class="">+    else<br class="">+        ufd[0].fd = sys->fd;<br class="">+    ufd[0].events = POLLIN;<br class="">+<br class="">+    switch (vlc_poll_i11e(ufd, 1, sys->timeout))<br class="">+    {<br class="">+        case 0:<br class="">+            msg_Err(p_access, "native multicast receive time-out, packet = %d", packet);<br class="">+            net_Close( sys->fd );<br class="">+            if( !sys->tryAMT )<br class="">+            {<br class="">+                if( open_amt_tunnel( p_access ) == false )<br class=""></blockquote><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">You can just do if (!open_amt_tunnel( p_access ))</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">+                    goto error;<br class="">+                break;<br class="">+            }<br class="">+            else<br class="">+            {<br class="">+                msg_Err(p_access, "AMT receive time-out");<br class="">+                *eof = true;<br class="">+            }<br class="">+            /* fall through */<br class="">+        case -1:<br class="">+/*            msg_Dbg(p_access, "Exiting vlc_poll switch, packet = %d", packet); */<br class="">+            goto error;<br class="">+    }<br class="">+<br class="">+    if( sys->tryAMT )<br class="">+    {<br class="">+        len = recv( sys->sAMT, amtpkt, DEFAULT_MTU, 0 );<br class="">+<br class="">+        if( len < 0 || amtpkt[0] != AMT_MULT_DATA )<br class="">+            goto error;<br class="">+<br class="">+        ssize_t shift = IP_HDR_LEN + UDP_HDR_LEN + AMT_HDR_LEN;<br class="">+<br class="">+        if( len < shift )<br class="">+        {<br class="">+            msg_Err(p_access, "%zd bytes packet truncated (MTU was %zu)",<br class="">+                len, sys->mtu);<br class="">+            pkt->i_flags |= BLOCK_FLAG_CORRUPTED;<br class="">+            sys->mtu = len;<br class="">+        } else {<br class="">+            len -= shift;<br class="">+        }<br class="">+<br class="">+        memcpy( pkt->p_buffer, &amtpkt[shift], len );<br class="">+    }<br class="">+    else<br class="">+        len = recvmsg(sys->fd, &msg, 0);<br class="">+<br class="">+#ifdef MSG_TRUNC<br class="">+    if (msg.msg_flags & MSG_TRUNC)<br class="">+    {<br class="">+        msg_Err(p_access, "%zd bytes packet truncated (MTU was %zu)",<br class="">+                len, sys->mtu);<br class="">+        pkt->i_flags |= BLOCK_FLAG_CORRUPTED;<br class="">+        sys->mtu = len;<br class="">+    }<br class="">+    else<br class="">+#endif<br class="">+        pkt->i_buffer = len;<br class="">+<br class="">+    free( amtpkt );<br class="">+    mem_alloc--;<br class="">+<br class="">+/*    msg_Dbg( p_access, "BlockUDP: Main Exit: mem_alloc = %d, packet = %d", mem_alloc, packet); */<br class=""></blockquote><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">This can be deleted.</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">+<br class="">+    return pkt;<br class="">+<br class="">+error:<br class="">+    free( amtpkt );<br class="">+    mem_alloc--;<br class="">+<br class="">+/*    msg_Dbg( p_access, "BlockUDP: Error Exit: mem_alloc = %d, packet = %d", mem_alloc, packet); */<br class="">+<br class="">+    return NULL;<br class="">+}<br class="">+<br class="">+/*****************************************************************************<br class="">+ * Open: open the socket<br class="">+ *****************************************************************************/<br class="">+static int Open( vlc_object_t *p_this )<br class="">+{<br class="">+    stream_t            *p_access = (stream_t*) p_this;<br class="">+    access_sys_t        *sys = NULL;<br class="">+    struct addrinfo      hints, *serverinfo = NULL;<br class="">+    struct sockaddr_in  *server_addr;<br class="">+    char                *psz_name = NULL, *saveptr, ip_buffer[INET_ADDRSTRLEN];<br class="">+    int                  i_bind_port = 1234, i_server_port = 0, VLC_ret = VLC_SUCCESS, res;<br class="">+    vlc_url_t            url;<br class="">+<br class="">+    mem_alloc = 0; packet = 0;<br class="">+/*    msg_Dbg( p_access, "Open: Enter: mem_alloc = %d", mem_alloc);<br class=""></blockquote><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">This can be deleted.</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">+<br class="">+    if( p_access->b_preparsing )<br class="">+    {<br class="">+        VLC_ret = VLC_EGENERIC;<br class="">+        goto cleanup;<br class="">+    }<br class="">+<br class="">+    sys = vlc_obj_malloc( p_this, sizeof( *sys ) );<br class="">+    mem_alloc++;<br class="">+<br class="">+    if( unlikely( sys == NULL ) )<br class="">+    {<br class="">+        VLC_ret = VLC_ENOMEM;<br class="">+        goto cleanup;<br class="">+    }<br class="">+    else<br class="">+        memset( sys, 0, sizeof( *sys ));<br class="">+<br class="">+    p_access->p_sys = sys;<br class="">+<br class="">+    /* Set up p_access */<br class="">+    ACCESS_SET_CALLBACKS( NULL, BlockUDP, Control, NULL );<br class="">+<br class="">+    if( !p_access->psz_location )<br class="">+    {<br class="">+        VLC_ret = VLC_EGENERIC;<br class="">+        goto cleanup;<br class="">+    }<br class="">+<br class="">+    psz_name = strdup( p_access->psz_location );<br class="">+    mem_alloc++;<br class="">+    if ( unlikely( psz_name == NULL ) )<br class="">+    {<br class="">+        VLC_ret = VLC_ENOMEM;<br class="">+        goto cleanup;<br class="">+    }<br class="">+<br class="">+    /* Parse psz_name syntax :<br class="">+     * [serveraddr[:serverport]][@[bindaddr]:[bindport]] */<br class="">+    if( vlc_UrlParse( &url, p_access->psz_url ) != 0 )<br class="">+    {<br class="">+        msg_Err( p_access, "Invalid URL" );<br class="">+        VLC_ret = VLC_EGENERIC;<br class="">+        goto cleanup;<br class="">+    }<br class="">+    mem_alloc++;<br class="">+<br class="">+    if( url.i_port > 0 )<br class="">+        i_bind_port = url.i_port;<br class="">+<br class="">+    msg_Dbg( p_access, "opening multicast: %s:%d local=%s:%d",<br class="">+             url.psz_host, i_server_port, url.psz_path, i_bind_port );<br class="">+<br class="">+    if( ( url.psz_host == NULL ) || ( strlen( url.psz_host ) == 0 ) )<br class="">+    {<br class="">+        msg_Err( p_access, "Please enter a group and/or source address." );<br class="">+        VLC_ret = VLC_EGENERIC;<br class="">+        goto cleanup;<br class="">+    }<br class="">+<br class="">+    memset( &hints, 0, sizeof( hints ));<br class="">+    hints.ai_family = AF_INET;  /* Setting to AF_UNSPEC accepts both IPv4 and IPv6 */<br class="">+    hints.ai_socktype = SOCK_DGRAM;<br class="">+<br class="">+    /* retrieve list of multicast addresses matching the multicast group identifier */<br class="">+    res = vlc_getaddrinfo( url.psz_host, AMT_PORT, &hints, &serverinfo );<br class="">+    mem_alloc++;<br class="">+<br class="">+    if( res )<br class="">+    {<br class="">+        msg_Err( p_access, "Could not find multicast group %s, reason: %s", url.psz_host, gai_strerror(res) );<br class="">+        VLC_ret = VLC_EGENERIC;<br class="">+        goto cleanup;<br class="">+    }<br class="">+<br class="">+    /* Convert binary socket address to string */<br class="">+    server_addr = (struct sockaddr_in *) serverinfo->ai_addr;<br class="">+    inet_ntop(AF_INET, &(server_addr->sin_addr), ip_buffer, INET_ADDRSTRLEN);<br class="">+<br class="">+    /* release the allocated memory */<br class="">+    freeaddrinfo(serverinfo);<br class="">+    serverinfo = NULL;<br class="">+    mem_alloc--;<br class="">+<br class="">+    msg_Dbg( p_access, "Setting multicast group address to %s", ip_buffer);<br class="">+<br class="">+    sys->mcastGroup = strdup( ip_buffer );<br class="">+    mem_alloc++;<br class="">+    if( unlikely( sys->mcastGroup == NULL ) )<br class="">+    {<br class="">+        VLC_ret = VLC_ENOMEM;<br class="">+        goto cleanup;<br class="">+    }<br class="">+<br class="">+    /* The following uses strtok_r() because strtok() is not thread safe */<br class="">+    sys->srcAddr = strdup( strtok_r( psz_name, "@", &saveptr ) );<br class=""></blockquote><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">You may want to do this in 2 steps to check that strok_r worked as expected.</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">+    mem_alloc++;<br class="">+<br class="">+    if( unlikely( sys->srcAddr == NULL ) )<br class="">+    {<br class="">+        VLC_ret = VLC_ENOMEM;<br class="">+        goto cleanup;<br class="">+    }<br class="">+<br class="">+    /* if strings are equal then no multicast source has been specified */<br class="">+    if( strcmp( url.psz_host, sys->srcAddr ) == 0 )<br class="">+ {<br class="">+        strcpy(sys->srcAddr, "0.0.0.0");<br class="">+        msg_Dbg( p_access, "No multicast source address specified, trying ASM...");<br class="">+    }<br class="">+<br class="">+    /* retrieve list of source addresses matching the multicast source identifier */<br class="">+    res = vlc_getaddrinfo( sys->srcAddr, AMT_PORT, &hints, &serverinfo );<br class="">+    mem_alloc++;<br class="">+<br class="">+    if( res )<br class="">+    {<br class="">+        msg_Err( p_access, "Could not find multicast source %s, reason: %s", sys->srcAddr, gai_strerror(res) );<br class="">+        VLC_ret = VLC_EGENERIC;<br class="">+        goto cleanup;<br class="">+    }<br class="">+<br class="">+    /* Convert binary socket address to string */<br class="">+    server_addr = (struct sockaddr_in *) serverinfo->ai_addr;<br class="">+    inet_ntop(AF_INET, &(server_addr->sin_addr), ip_buffer, INET_ADDRSTRLEN);<br class="">+<br class="">+    msg_Dbg( p_access, "Setting multicast source address to %s", ip_buffer);<br class="">+<br class="">+    /* free the original source address buffer (IP or FQDN) and assign it just the IP address */<br class="">+    free(sys->srcAddr);<br class="">+    sys->srcAddr = strdup( ip_buffer );<br class="">+<br class="">+    if( unlikely( sys->srcAddr == NULL ) )<br class="">+    {<br class="">+        VLC_ret = VLC_ENOMEM;<br class="">+        goto cleanup;<br class="">+    }<br class="">+<br class="">+    if( strcmp( url.psz_host, sys->srcAddr ) == 0 )<br class="">+        strcpy(sys->srcAddr, "0.0.0.0");<br class="">+<br class="">+    sys->relayAddr = var_InheritString( p_access, "amt-relay" );<br class="">+<br class="">+    if( unlikely(sys->relayAddr == NULL ) )<br class="">+    {<br class="">+        msg_Err( p_access, "No relay anycast or unicast address specified." );<br class="">+        VLC_ret = VLC_EGENERIC;<br class="">+        goto cleanup;<br class="">+    }<br class="">+<br class="">+    msg_Dbg( p_access, "Addresses: mcastGroup: %s srcAddr: %s relayAddr: %s", \<br class="">+             sys->mcastGroup, sys->srcAddr, sys->relayAddr);<br class="">+<br class="">+    sys->fd = net_OpenDgram( p_access, sys->mcastGroup, i_bind_port,<br class="">+                             sys->srcAddr, i_server_port, IPPROTO_UDP );<br class="">+    if( sys->fd == -1 )<br class="">+    {<br class="">+        msg_Err( p_access, "cannot open socket" );<br class="">+        VLC_ret = VLC_EGENERIC;<br class="">+        goto cleanup;<br class="">+    }<br class="">+<br class="">+    sys->mtu = 7 * 188;<br class="">+<br class="">+    sys->timeout = var_InheritInteger( p_access, "amt-native-timeout");<br class="">+    if( sys->timeout > 0)<br class="">+        sys->timeout *= 1000;<br class="">+<br class="">+    sys->amtTimeout = var_InheritInteger( p_access, "amt-timeout" );<br class="">+    if( sys->amtTimeout > 0)<br class="">+        sys->amtTimeout *= 1000;<br class="">+<br class="">+    sys->tryAMT = false;<br class="">+    sys->threadReady = false;<br class="">+<br class="">+cleanup: /* fall through */<br class="">+<br class="">+    /* release the allocated memory */<br class="">+    free( psz_name );<br class="">+    vlc_UrlClean( &url );<br class="">+    freeaddrinfo( serverinfo );<br class="">+<br class="">+    mem_alloc-=3;<br class="">+<br class="">+    /* if an error occurred free the memory */<br class="">+    if ( VLC_ret != VLC_SUCCESS )<br class="">+    {<br class="">+        free( sys->mcastGroup );<br class="">+        free( sys->srcAddr );<br class="">+        vlc_obj_free( p_this, sys );<br class="">+        mem_alloc -= 3;<br class="">+    }<br class="">+<br class="">+/*    msg_Dbg( p_access, "Open: Exit: mem_alloc = %d", mem_alloc); */<br class="">+<br class="">+    return VLC_ret;<br class="">+}<br class="">+<br class="">+/*****************************************************************************<br class="">+ * Close: free unused data structures<br class="">+ *****************************************************************************/<br class="">+static void Close( vlc_object_t *p_this )<br class="">+{<br class="">+    char         relay_ip[INET_ADDRSTRLEN];<br class="">+    stream_t     *p_access = (stream_t*)p_this;<br class="">+    access_sys_t *sys = p_access->p_sys;<br class="">+<br class="">+    inet_ntop(AF_INET, &(sys->relayAddrDisco.sin_addr), relay_ip, INET_ADDRSTRLEN);<br class="">+<br class="">+    if( strcmp(sys->srcAddr, "0.0.0.0") == 0 )<br class="">+        amt_leaveASM_group( p_access );<br class="">+    else<br class="">+        amt_leaveSSM_group( p_access );<br class="">+    amt_send_mem_update( p_access, relay_ip, true );<br class="">+<br class="">+    if( sys->threadReady )<br class="">+    {<br class="">+        sys->threadReady = false;<br class="">+        vlc_cancel( sys->updateThread );<br class="">+        vlc_join( sys->updateThread, NULL );<br class="">+    }<br class="">+<br class="">+    free( sys->mcastGroup );<br class="">+    free( sys->srcAddr );<br class="">+    vlc_obj_free( p_this, sys );<br class="">+<br class="">+    mem_alloc -= 3;<br class="">+    if (mem_alloc)<br class="">+        msg_Err( p_access, "Closing AMT plugin, mem_alloc = %d", mem_alloc);<br class="">+    else<br class="">+        msg_Dbg( p_access, "Closing AMT plugin, mem_alloc = %d", mem_alloc);<br class="">+<br class="">+    net_Close( sys->fd );<br class="">+    net_Close( sys->sAMT );<br class="">+    net_Close( sys->sQuery );<br class="">+}<br class="">+<br class="">+<br class="">+bool open_amt_tunnel( stream_t *p_access )<br class="">+{<br class="">+    struct addrinfo hints, *serverinfo, *server;<br class="">+    access_sys_t *sys = p_access->p_sys;<br class="">+<br class="">+    memset( &hints, 0, sizeof( hints ));<br class="">+    hints.ai_family = AF_INET;  /* Setting to AF_UNSPEC accepts both IPv4 and IPv6 */<br class="">+    hints.ai_socktype = SOCK_DGRAM;<br class="">+<br class="">+/*    msg_Dbg( p_access, "open_amt_tunnel: Enter: mem_alloc = %d", mem_alloc); */<br class="">+<br class="">+    msg_Dbg( p_access, "Attempting AMT to %s...", sys->relayAddr);<br class="">+    sys->tryAMT = true;<br class="">+<br class="">+    /* retrieve list of addresses matching the AMT relay */<br class="">+    int res = vlc_getaddrinfo( sys->relayAddr, AMT_PORT, &hints, &serverinfo );<br class="">+    mem_alloc++;<br class="">+<br class="">+    if( res )<br class="">+    {<br class="">+        msg_Err( p_access, "Could not find relay %s, reason: %s", sys->relayAddr, gai_strerror(res) );<br class="">+        goto error;<br class="">+    }<br class="">+<br class="">+    /* iterate through the list of sockets to find one the works */<br class="">+    for (server = serverinfo; server != NULL; server = server->ai_next)<br class="">+    {<br class="">+        struct sockaddr_in *server_addr = (struct sockaddr_in *) server->ai_addr;<br class="">+        char relay_ip[INET_ADDRSTRLEN];<br class="">+<br class="">+        inet_ntop(AF_INET, &(server_addr->sin_addr), relay_ip, INET_ADDRSTRLEN);<br class="">+<br class="">+        msg_Dbg( p_access, "Trying AMT Server: %s", relay_ip);<br class="">+<br class="">+        sys->relayAddrDisco.sin_addr = server_addr->sin_addr;<br class="">+<br class="">+        /* if can't open socket try any others in list */<br class="">+        if( amt_sockets_init( p_access ) != 0 )<br class="">+            msg_Err( p_access, "Error initializing socket to %s", relay_ip );<br class="">+<br class="">+        /* Otherwise negotiate with AMT relay and confirm you can pull a UDP packet  */<br class="">+        else<br class="">+        {<br class="">+            amt_send_relay_discovery_msg( p_access, relay_ip );<br class="">+            msg_Dbg( p_access, "Sent relay AMT discovery message to %s", relay_ip );<br class="">+<br class="">+            if( !amt_rcv_relay_adv( p_access ) )<br class="">+            {<br class="">+                msg_Err( p_access, "Error receiving AMT relay advertisement msg from %s, skipping", relay_ip );<br class="">+                goto error;<br class="">+            }<br class="">+            msg_Dbg( p_access, "Received AMT relay advertisement from %s", relay_ip );<br class="">+<br class="">+            amt_send_relay_request( p_access, relay_ip );<br class="">+            msg_Dbg( p_access, "Sent AMT relay request message to %s", relay_ip );<br class="">+<br class="">+            if( !amt_rcv_relay_mem_query( p_access ) )<br class="">+            {<br class="">+                msg_Err( p_access, "Could not receive AMT relay membership query from %s, reason: %s", relay_ip, vlc_strerror(errno));<br class="">+                goto error;<br class="">+            }<br class="">+            msg_Dbg( p_access, "Received AMT relay membership query from %s", relay_ip );<br class="">+<br class="">+            if( strcmp(sys->srcAddr, "") == 0 )<br class="">+            {<br class="">+                if( amt_joinASM_group( p_access ) != 0 )<br class="">+                {<br class="">+                    msg_Err( p_access, "Error joining ASM %s", vlc_strerror(errno) );<br class="">+                    goto error;<br class="">+                }<br class="">+                msg_Dbg( p_access, "Joined ASM group: %s", sys->mcastGroup );<br class="">+            }<br class="">+            else {<br class="">+                if( amt_joinSSM_group( p_access ) != 0 )<br class="">+                {<br class="">+                    msg_Err( p_access, "Error joining SSM %s", vlc_strerror(errno) );<br class="">+                    goto error;<br class="">+                }<br class="">+                msg_Dbg( p_access, "Joined SSM src: %s group: %s", sys->srcAddr, sys->mcastGroup );<br class="">+            }<br class="">+<br class="">+            bool eof=false;<br class="">+            block_t *pkt;<br class="">+<br class="">+            /* Confirm that you can pull a UDP packet from the socket */<br class="">+            if ( (pkt = BlockUDP( p_access, &eof )) == false )<br class=""></blockquote><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">A ! here would be sufficient, checking that a pointer == false is not</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">really idiomatic.</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">+                msg_Dbg( p_access, "Unable to receive UDP packet from AMT relay %s for multicast group %s, skipping...", relay_ip, sys->mcastGroup );<br class="">+            else<br class="">+            {<br class="">+                block_Release(pkt);  /* don't decrement mem_alloc since pkt not included in count */<br class="">+                msg_Dbg( p_access, "Got UDP packet from multicast group %s via AMT relay %s, continuing...", sys->mcastGroup, relay_ip );<br class="">+                break;   /* found an active server sending UDP packets, so exit loop */<br class="">+           }<br class="">+        }<br class="">+    }<br class="">+<br class="">+    /* if server is NULL then no AMT relay is responding */<br class="">+    if (server == NULL)<br class="">+    {<br class="">+        msg_Err( p_access, "No AMT servers responding" );<br class="">+        goto error;<br class="">+    }<br class="">+<br class="">+    sys->queryTime = vlc_tick_now() / CLOCK_FREQ;<br class="">+<br class="">+    /* release the allocated memory */<br class="">+    freeaddrinfo(serverinfo);<br class="">+    mem_alloc--;<br class="">+<br class="">+/*    msg_Dbg( p_access, "open_amt_tunnel: Exit: mem_alloc = %d", mem_alloc); */<br class=""></blockquote><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">This can be deleted.</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">+<br class="">+    return true;<br class="">+<br class="">+error:<br class="">+    /* release the allocated memory */<br class="">+    freeaddrinfo(serverinfo);<br class="">+    mem_alloc--;<br class="">+<br class="">+/*    msg_Dbg( p_access, "open_amt_tunnel: Exit: mem_alloc = %d", mem_alloc); */<br class=""></blockquote><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">This can be deleted.</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">+<br class="">+    sys->threadReady = false;<br class="">+    return false;<br class="">+}<br class="">+/**<br class="">+ * Calculate checksum<br class="">+ * */<br class="">+unsigned short getChecksum( unsigned short *buffer, int nLen )<br class="">+{<br class="">+    int nleft = nLen;<br class="">+    int sum = 0;<br class="">+    unsigned short *w = buffer;<br class="">+    unsigned short answer = 0;<br class="">+<br class="">+    while (nleft > 1)<br class="">+    {<br class="">+        sum += *w++;<br class="">+        nleft -= 2;<br class="">+    }<br class="">+    if (nleft == 1)<br class="">+    {<br class="">+        *(unsigned char*)(&answer) = *(unsigned char*)w;<br class="">+        sum += answer;<br class="">+    }<br class="">+    sum = (sum >> 16) + (sum & 0xffff);<br class="">+    answer = ~sum;<br class="">+    return (answer);<br class="">+}<br class="">+<br class="">+/**<br class="">+ * Make IGMP Membership report<br class="">+ * */<br class="">+void makeReport( amt_igmpv3_membership_report_t *mr )<br class="">+{<br class="">+    mr->type = AMT_IGMPV3_MEMBERSHIP_REPORT_TYPEID;<br class="">+    mr->resv = 0;<br class="">+    mr->checksum = 0;<br class="">+    mr->resv2 = 0;<br class="">+    mr->nGroupRecord = htons(1);<br class="">+}<br class="">+<br class="">+/**<br class="">+ * Make IP header<br class="">+ * */<br class="">+void makeIPHeader( amt_ip_alert_t *p_ipHead )<br class="">+{<br class="">+    p_ipHead->ver_ihl = 0x46;<br class="">+    p_ipHead->tos = 0xc0;<br class="">+    p_ipHead->tot_len = htons( IP_HDR_IGMP_LEN + IGMP_REPORT_LEN );<br class="">+    p_ipHead->id = 0x00;<br class="">+    p_ipHead->frag_off = 0x0000;<br class="">+    p_ipHead->ttl = 0x01;<br class="">+    p_ipHead->protocol = 0x02;<br class="">+    p_ipHead->check = 0;<br class="">+    p_ipHead->srcAddr = INADDR_ANY;<br class="">+    p_ipHead->options = 0x0000;<br class="">+}<br class="">+<br class="">+/** Create relay discovery socket, query socket, UDP socket and<br class="">+ * fills in relay anycast address for discovery<br class="">+ * return 0 if successful, -1 if not<br class="">+ */<br class="">+int amt_sockets_init( stream_t *p_access )<br class="">+{<br class="">+    struct sockaddr_in rcvAddr;<br class="">+    access_sys_t *sys = p_access->p_sys;<br class="">+    memset( &rcvAddr, 0, sizeof(struct sockaddr_in) );<br class="">+    int enable = 0, res = 0;<br class="">+<br class="">+    /* Relay anycast address for discovery */<br class="">+    sys->relayAddrDisco.sin_family = AF_INET;<br class="">+    sys->relayAddrDisco.sin_port = htons( AMT_PORT );<br class="">+<br class="">+    /* create UDP socket */<br class="">+    sys->sAMT = vlc_socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP, true );<br class="">+    if( sys->sAMT == -1 )<br class="">+    {<br class="">+        msg_Err( p_access, "Failed to create UDP socket" );<br class="">+        goto error;<br class="">+    }<br class="">+<br class="">+    res = setsockopt(sys->sAMT, IPPROTO_IP, IP_PKTINFO, &enable, sizeof(enable));<br class="">+    if(res < 0)<br class="">+    {<br class="">+        msg_Err( p_access, "Couldn't set socket options for IPPROTO_IP, IP_PKTINFO\n %s", vlc_strerror(errno));<br class="">+        goto error;<br class="">+    }<br class="">+<br class="">+    res = setsockopt(sys->sAMT, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));<br class="">+    if(res < 0)<br class="">+    {<br class="">+        msg_Err( p_access, "Couldn't make socket reusable");<br class="">+        goto error;<br class="">+    }<br class="">+<br class="">+    rcvAddr.sin_family      = AF_INET;<br class="">+    rcvAddr.sin_port        = htons( 0 );<br class="">+    rcvAddr.sin_addr.s_addr = INADDR_ANY;<br class="">+<br class="">+    if( bind(sys->sAMT, (struct sockaddr *)&rcvAddr, sizeof(rcvAddr) ) != 0 )<br class="">+    {<br class="">+        msg_Err( p_access, "Failed to bind UDP socket error: %s", vlc_strerror(errno) );<br class="">+        goto error;<br class="">+    }<br class="">+<br class="">+    sys->sQuery = vlc_socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP, true );<br class="">+    if( sys->sQuery == -1 )<br class="">+    {<br class="">+        msg_Err( p_access, "Failed to create query socket" );<br class="">+        goto error;<br class="">+    }<br class="">+<br class="">+    /* bind socket to local address */<br class="">+    sys->stLocalAddr.sin_family      = AF_INET;<br class="">+    sys->stLocalAddr.sin_port        = htons( 0 );<br class="">+    sys->stLocalAddr.sin_addr.s_addr = INADDR_ANY;<br class="">+<br class="">+    if( bind(sys->sQuery, (struct sockaddr *)&sys->stLocalAddr, sizeof(struct sockaddr) ) != 0 )<br class="">+    {<br class="">+        msg_Err( p_access, "Failed to bind query socket" );<br class="">+        goto error;<br class="">+    }<br class="">+<br class="">+    sys->stSvrAddr.sin_family        = AF_INET;<br class="">+    sys->stSvrAddr.sin_port          = htons( 9124 );<br class="">+    res = inet_pton( AF_INET, "127.0.0.1", &sys->stSvrAddr.sin_addr );<br class="">+    if( res == 0 )<br class="">+    {<br class="">+        msg_Err( p_access, "Could not convert loopback address" );<br class="">+        goto error;<br class="">+    }<br class="">+<br class="">+    return 0;<br class="">+<br class="">+error:<br class="">+    net_Close( sys->sAMT );<br class="">+    net_Close( sys->sQuery );<br class="">+    return -1;<br class="">+}<br class="">+<br class="">+/**<br class="">+ * Send a relay discovery message, before 3-way handshake<br class="">+ * */<br class="">+void amt_send_relay_discovery_msg( stream_t *p_access, char *relay_ip )<br class="">+{<br class="">+    char          chaSendBuffer[AMT_DISCO_MSG_LEN];<br class="">+    unsigned int  ulNonce;<br class="">+    int           nRet;<br class="">+    access_sys_t *sys = p_access->p_sys;<br class="">+<br class="">+    /* initialize variables */<br class="">+    memset( chaSendBuffer, 0, sizeof(chaSendBuffer) );<br class="">+    ulNonce = 0;<br class="">+    nRet = 0;<br class="">+<br class="">+    /*<br class="">+     * create AMT discovery message format<br class="">+     * +---------------------------------------------------+<br class="">+     * | Msg Type(1Byte)| Reserved (3 byte)| nonce (4byte) |<br class="">+     * +---------------------------------------------------+<br class="">+     */<br class="">+<br class="">+    chaSendBuffer[0] = AMT_RELAY_DISCO;<br class="">+    chaSendBuffer[1] = 0;<br class="">+    chaSendBuffer[2] = 0;<br class="">+    chaSendBuffer[3] = 0;<br class="">+<br class="">+    /* create nonce and copy into send buffer */<br class="">+    srand( (unsigned int)time(NULL) );<br class="">+    ulNonce = htonl( rand() );<br class="">+    memcpy( (void*)&chaSendBuffer[4], (void*)&ulNonce, sizeof(ulNonce) );<br class="">+    sys->glob_ulNonce = ulNonce;<br class="">+<br class="">+    /* send it */<br class="">+    nRet = sendto( sys->sAMT, chaSendBuffer, sizeof(chaSendBuffer), 0,\<br class="">+            (struct sockaddr *)&sys->relayAddrDisco, sizeof(struct sockaddr) );<br class="">+<br class="">+    if( nRet < 0)<br class="">+        msg_Err( p_access, "Sendto failed to %s with error %d.", relay_ip, errno);<br class="">+}<br class="">+<br class="">+/**<br class="">+ * Send relay request message, stage 2 of handshake<br class="">+ * */<br class="">+void amt_send_relay_request( stream_t *p_access, char *relay_ip )<br class="">+{<br class="">+    char         chaSendBuffer[AMT_REQUEST_MSG_LEN];<br class="">+    uint32_t     ulNonce;<br class="">+    int          nRet;<br class="">+    int          nRetry;<br class="">+    access_sys_t *sys = p_access->p_sys;<br class="">+<br class="">+    memset( chaSendBuffer, 0, sizeof(chaSendBuffer) );<br class="">+<br class="">+    ulNonce = 0;<br class="">+    nRet = 0;<br class="">+    nRetry = 0;<br class="">+<br class="">+    /*<br class="">+     * create AMT request message format<br class="">+     * +-----------------------------------------------------------------+<br class="">+     * | Msg Type(1Byte)| Reserved(1byte)|P flag(1byte)|Reserved (2 byte)|<br class="">+     * +-----------------------------------------------------------------+<br class="">+     * |             nonce (4byte)                                       |<br class="">+     * +-----------------------------------------------------------------+<br class="">+     *<br class="">+     * The P flag is set to indicate which group membership protocol the<br class="">+     * gateway wishes the relay to use in the Membership Query response:<br class="">+<br class="">+     * Value Meaning<br class="">+<br class="">+     *  0    The relay MUST respond with a Membership Query message that<br class="">+     *       contains an IPv4 packet carrying an IGMPv3 General Query<br class="">+     *       message.<br class="">+     *  1    The relay MUST respond with a Membership Query message that<br class="">+     *       contains an IPv6 packet carrying an MLDv2 General Query<br class="">+     *       message.<br class="">+     *<br class="">+     */<br class="">+<br class="">+    chaSendBuffer[0] = AMT_REQUEST;<br class="">+    chaSendBuffer[1] = 0;<br class="">+    chaSendBuffer[2] = 0;<br class="">+    chaSendBuffer[3] = 0;<br class="">+<br class="">+    ulNonce = sys->glob_ulNonce;<br class="">+    memcpy( (void*)&chaSendBuffer[4], (void*)&ulNonce, sizeof(uint32_t) );<br class="">+<br class="">+    nRet = send( sys->sAMT, chaSendBuffer, sizeof(chaSendBuffer), 0 );<br class="">+<br class="">+    if( nRet < 0 )<br class="">+        msg_Err(p_access, "Error sending relay request to %s error: %s", relay_ip, vlc_strerror(errno) );<br class="">+}<br class="">+<br class="">+/*<br class="">+* create AMT request message format<br class="">+* +----------------------------------------------------------------------------------+<br class="">+* | Msg Type(1 byte)| Reserved (1 byte)| MAC (6 byte)| nonce (4 byte) | IGMP packet  |<br class="">+* +----------------------------------------------------------------------------------+<br class="">+*/<br class="">+void amt_send_mem_update( stream_t *p_access, char *relay_ip, bool leave)<br class="">+{<br class="">+    int           sendBufSize = IP_HDR_IGMP_LEN + MAC_LEN + NONCE_LEN + AMT_HDR_LEN;<br class="">+    char          pSendBuffer[ sendBufSize + IGMP_REPORT_LEN ];<br class="">+    uint32_t      ulNonce = 0;<br class="">+    access_sys_t *sys = p_access->p_sys;<br class="">+<br class="">+    memset( &pSendBuffer, 0, sizeof(pSendBuffer) );<br class="">+<br class="">+    pSendBuffer[0] = AMT_MEM_UPD;<br class="">+<br class="">+    /* copy relay MAC response */<br class="">+    memcpy( (void*)&pSendBuffer[2], (void*)sys->relay_mem_query_msg.uchaMAC, MAC_LEN );<br class="">+<br class="">+    /* copy nonce */<br class="">+    ulNonce = ntohl(sys->glob_ulNonce);<br class="">+    memcpy( (void*)&pSendBuffer[8], (void*)&ulNonce, NONCE_LEN );<br class="">+<br class="">+    /* make IP header for IGMP packet */<br class="">+    amt_ip_alert_t p_ipHead;<br class="">+    memset( &p_ipHead, 0, IP_HDR_IGMP_LEN );<br class="">+    makeIPHeader( &p_ipHead );<br class="">+<br class="">+    struct sockaddr_in temp;<br class="">+    inet_pton( AF_INET, MCAST_ALLHOSTS, &(temp.sin_addr) );<br class="">+    p_ipHead.destAddr = temp.sin_addr.s_addr;<br class="">+    p_ipHead.check = getChecksum( (unsigned short*)&p_ipHead, IP_HDR_IGMP_LEN );<br class="">+<br class="">+    amt_igmpv3_groupRecord_t groupRcd;<br class="">+    groupRcd.auxDatalen = 0;<br class="">+    inet_pton( AF_INET, sys->mcastGroup, &(temp.sin_addr) );<br class="">+    groupRcd.ssm = temp.sin_addr.s_addr;<br class="">+<br class="">+    if( strcmp(sys->srcAddr, "0.0.0.0") != 0 )<br class="">+    {<br class="">+        groupRcd.type = leave ? AMT_IGMP_BLOCK:AMT_IGMP_INCLUDE;<br class="">+        groupRcd.nSrc = htons(1);<br class="">+<br class="">+        inet_pton( AF_INET, sys->srcAddr, &(temp.sin_addr) );<br class="">+        groupRcd.srcIP[0] = temp.sin_addr.s_addr;<br class="">+<br class="">+    } else {<br class="">+        groupRcd.type = leave ? AMT_IGMP_INCLUDE_CHANGE:AMT_IGMP_EXCLUDE_CHANGE;<br class="">+        groupRcd.nSrc = htons(0);<br class="">+    }<br class="">+<br class="">+    /* make IGMP membership report */<br class="">+    amt_igmpv3_membership_report_t p_igmpMemRep;<br class="">+    makeReport( &p_igmpMemRep );<br class="">+<br class="">+    memcpy((void *)&p_igmpMemRep.grp[0], (void *)&groupRcd, (int)sizeof(groupRcd) );<br class="">+    p_igmpMemRep.checksum = getChecksum( (unsigned short*)&p_igmpMemRep, IGMP_REPORT_LEN );<br class="">+<br class="">+    amt_membership_update_msg_t memUpdateMsg;<br class="">+    memset((void*)&memUpdateMsg, 0, sizeof(memUpdateMsg));<br class="">+    memcpy((void*)&memUpdateMsg.ipHead, (void*)&p_ipHead, sizeof(p_ipHead) );<br class="">+    memcpy((void*)&memUpdateMsg.memReport, (void*)&p_igmpMemRep, sizeof(p_igmpMemRep) );<br class="">+<br class="">+    memcpy( (void*)&pSendBuffer[12], (void*)&memUpdateMsg, sizeof(memUpdateMsg) );<br class="">+<br class="">+    send( sys->sAMT, pSendBuffer, sizeof(pSendBuffer), 0 );<br class="">+<br class="">+    msg_Dbg( p_access, "AMT relay membership report sent to %s", relay_ip );<br class="">+}<br class="">+<br class="">+/**<br class="">+ * Receive relay advertisement message<br class="">+ *<br class="">+ *<br class="">+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class="">+ *  |  V=0  |Type=2 |                   Reserved                    |<br class="">+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class="">+ *  |                        Discovery Nonce                        |<br class="">+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class="">+ *  |                                                               |<br class="">+ *  ~                  Relay Address (IPv4 or IPv6)                 ~<br class="">+ *  |                                                               |<br class="">+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class="">+ * */<br class="">+bool amt_rcv_relay_adv( stream_t *p_access )<br class="">+{<br class="">+    char pkt[RELAY_ADV_MSG_LEN];<br class="">+    access_sys_t *sys = p_access->p_sys;<br class="">+<br class="">+    memset( &pkt, 0, RELAY_ADV_MSG_LEN );<br class="">+<br class="">+    struct pollfd ufd[1];<br class="">+<br class="">+    ufd[0].fd = sys->sAMT;<br class="">+    ufd[0].events = POLLIN;<br class="">+<br class="">+    switch( vlc_poll_i11e(ufd, 1, sys->timeout) )<br class="">+    {<br class="">+        case 0:<br class="">+            msg_Err(p_access, "AMT relay advertisement receive time-out");<br class="">+            /* fall through */<br class="">+        case -1:<br class="">+            return false;<br class="">+    }<br class="">+<br class="">+    struct sockaddr temp;<br class="">+    uint32_t temp_size = sizeof( struct sockaddr );<br class="">+    ssize_t len = recvfrom( sys->sAMT, &pkt, RELAY_ADV_MSG_LEN, 0, &temp, &temp_size );<br class="">+<br class="">+    if (len < 0)<br class="">+    {<br class="">+        msg_Err(p_access, "Received message length less than zero");<br class="">+        return false;<br class="">+    }<br class="">+<br class="">+    memcpy( (void*)&sys->relay_adv_msg.type, &pkt[0], MSG_TYPE_LEN );<br class="">+    if( sys->relay_adv_msg.type != AMT_RELAY_ADV )<br class="">+    {<br class="">+        msg_Err( p_access, "Received message not an AMT relay advertisement, ignoring. ");<br class="">+        return false;<br class="">+    }<br class="">+<br class="">+    memcpy( (void*)&sys->relay_adv_msg.ulRcvNonce, &pkt[NONCE_LEN], NONCE_LEN );<br class="">+    if( sys->glob_ulNonce != sys->relay_adv_msg.ulRcvNonce )<br class="">+    {<br class="">+        msg_Err( p_access, "Discovery nonces differ! currNonce:%x rcvd%x", sys->glob_ulNonce, ntohl(sys->relay_adv_msg.ulRcvNonce) );<br class="">+        return false;<br class="">+    }<br class="">+<br class="">+    memcpy( (void*)&sys->relay_adv_msg.ipAddr, &pkt[8], 4 );<br class="">+<br class="">+    memset( &sys->relayAddress, 0, sizeof(sys->relayAddress) );<br class="">+    sys->relayAddress.sin_family       = AF_INET;<br class="">+    sys->relayAddress.sin_addr.s_addr  = sys->relay_adv_msg.ipAddr;<br class="">+    sys->relayAddress.sin_port         = htons( AMT_PORT );<br class="">+<br class="">+    int nRet = connect( sys->sAMT, (struct sockaddr *)&sys->relayAddress, sizeof(sys->relayAddress) );<br class="">+    if( nRet < 0 )<br class="">+    {<br class="">+        msg_Err( p_access, "Error connecting AMT UDP socket: %s", vlc_strerror(errno) );<br class="">+        return false;<br class="">+    }<br class="">+<br class="">+    return true;<br class="">+}<br class="">+<br class="">+/**<br class="">+ * Receive relay membership query message<br class="">+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class="">+   |  V=0  |Type=4 | Reserved  |L|G|         Response MAC          |<br class="">+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +<br class="">+   |                                                               |<br class="">+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class="">+   |                         Request Nonce                         |<br class="">+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class="">+   |                                                               |<br class="">+   |               Encapsulated General Query Message              |<br class="">+   ~                 IPv4:IGMPv3(Membership Query)                 ~<br class="">+   |                  IPv6:MLDv2(Listener Query)                   |<br class="">+   |                                                               |<br class="">+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class="">+   |     Gateway Port Number       |                               |<br class="">+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +<br class="">+   |                                                               |<br class="">+   +                                                               +<br class="">+   |                Gateway IP Address (IPv4 or IPv6)              |<br class="">+   +                                                               +<br class="">+   |                                                               |<br class="">+   +                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class="">+   |                               |<br class="">+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class="">+ */<br class="">+bool amt_rcv_relay_mem_query( stream_t *p_access )<br class="">+{<br class="">+    char pkt[RELAY_QUERY_MSG_LEN];<br class="">+    memset( &pkt, 0, RELAY_QUERY_MSG_LEN );<br class="">+    struct pollfd ufd[1];<br class="">+    access_sys_t *sys = p_access->p_sys;<br class="">+<br class="">+    ufd[0].fd = sys->sAMT;<br class="">+    ufd[0].events = POLLIN;<br class="">+<br class="">+    switch( vlc_poll_i11e(ufd, 1, sys->timeout) )<br class="">+    {<br class="">+        case 0:<br class="">+            msg_Err(p_access, "AMT relay membership query receive time-out");<br class="">+            /* fall through */<br class="">+        case -1:<br class="">+            return false;<br class="">+    }<br class="">+<br class="">+    ssize_t len = recv( sys->sAMT, &pkt, RELAY_QUERY_MSG_LEN, 0 );<br class="">+<br class="">+    if (len < 0)<br class="">+    {<br class="">+        msg_Err(p_access, "length less than zero");<br class="">+        return false;<br class="">+    }<br class="">+<br class="">+    memcpy( (void*)&sys->relay_mem_query_msg.type, &pkt[0], MSG_TYPE_LEN );<br class="">+    /* pkt[1] is reserved  */<br class="">+    memcpy( (void*)&sys->relay_mem_query_msg.uchaMAC[0], &pkt[AMT_HDR_LEN], MAC_LEN );<br class="">+    memcpy( (void*)&sys->relay_mem_query_msg.ulRcvedNonce, &pkt[AMT_HDR_LEN + MAC_LEN], NONCE_LEN );<br class="">+    if( sys->relay_mem_query_msg.ulRcvedNonce != sys->glob_ulNonce )<br class="">+    {<br class="">+        msg_Warn( p_access, "Nonces are different rcvd: %x glob: %x", sys->relay_mem_query_msg.ulRcvedNonce, sys->glob_ulNonce );<br class="">+        return false;<br class="">+    }<br class="">+<br class="">+    sys->glob_ulNonce = ntohl(sys->relay_mem_query_msg.ulRcvedNonce);<br class="">+<br class="">+    int shift = AMT_HDR_LEN + MAC_LEN + NONCE_LEN;<br class="">+    memcpy( (void*)&sys->relay_ip_hdr, (void*)&pkt[shift], IP_HDR_IGMP_LEN );<br class="">+<br class="">+    shift += IP_HDR_IGMP_LEN;<br class="">+    sys->relay_igmp_query.type = pkt[shift];<br class="">+    shift++;<br class="">+    sys->relay_igmp_query.max_resp_code = pkt[shift];<br class="">+    shift++;<br class="">+    memcpy( (void*)&sys->relay_igmp_query.checksum, &pkt[shift], 2 );<br class="">+    shift += 2;<br class="">+    memcpy( (void*)&sys->relay_igmp_query.ssmIP, &pkt[shift], 4 );<br class="">+    shift += 4;<br class="">+    sys->relay_igmp_query.s_qrv = pkt[shift];<br class="">+    shift++;<br class="">+    if( (int)pkt[shift] == 0 )<br class="">+        sys->relay_igmp_query.qqic = 125;<br class="">+    else if( (int)pkt[shift] < 128 )<br class="">+        sys->relay_igmp_query.qqic = pkt[shift];<br class="">+    else {<br class="">+        int qqic;<br class="">+        qqic = ((pkt[shift]&0x0f) + 0x10) << (((pkt[shift] >> 4)&0x07) + 3);<br class="">+        sys->relay_igmp_query.qqic = qqic;<br class="">+    }<br class="">+<br class="">+    shift++;<br class="">+    memcpy( (void*)&sys->relay_igmp_query.nSrc, &pkt[shift], 2 );<br class="">+    if( sys->relay_igmp_query.nSrc != 0 )<br class="">+    {<br class="">+        shift += 2;<br class="">+        memcpy( (void*)&sys->relay_igmp_query.srcIP, &pkt[shift], 4 );<br class="">+    }<br class="">+<br class="">+    /* if a membership thread exists cancel it */<br class="">+    if( sys->threadReady )<br class="">+    {<br class="">+        msg_Dbg( p_access, "Cancelling existing AMT relay membership update thread");<br class="">+<br class="">+        sys->threadReady = false;<br class="">+        vlc_cancel( sys->updateThread );<br class="">+        vlc_join( sys->updateThread, NULL );<br class="">+    }<br class="">+<br class="">+    msg_Dbg( p_access, "Spawning AMT relay membership update thread");<br class="">+<br class="">+    if( vlc_clone( &sys->updateThread, amt_mem_upd, p_access, VLC_THREAD_PRIORITY_LOW) )<br class="">+    {<br class="">+        msg_Err( p_access, "Could not create AMT relay membership update thread" );<br class="">+        return false;<br class="">+    }<br class="">+<br class="">+    /* set theadReady to true, thread will send periodic membership updates until false */<br class="">+    sys->threadReady = true;<br class="">+    return true;<br class="">+}<br class="">+<br class="">+/**<br class="">+ * Join SSM group based on input addresses, or use the defaults<br class="">+ * */<br class="">+int amt_joinSSM_group( stream_t *p_access )<br class="">+{<br class="">+    struct ip_mreq_source imr;<br class="">+    struct sockaddr_in temp;<br class="">+    access_sys_t *sys = p_access->p_sys;<br class="">+<br class="">+    inet_pton( AF_INET, sys->mcastGroup, &(temp.sin_addr.s_addr) );<br class="">+    imr.imr_multiaddr.s_addr = temp.sin_addr.s_addr;<br class="">+<br class="">+    inet_pton( AF_INET, sys->srcAddr, &(temp.sin_addr.s_addr) );<br class="">+    imr.imr_sourceaddr.s_addr = temp.sin_addr.s_addr;<br class="">+    imr.imr_interface.s_addr = INADDR_ANY;<br class="">+<br class="">+    return setsockopt( sys->sAMT, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, (char *)&imr, sizeof(imr) );<br class="">+}<br class="">+<br class="">+int amt_joinASM_group( stream_t *p_access )<br class="">+{<br class="">+    struct ip_mreq imr;<br class="">+    struct sockaddr_in temp;<br class="">+    access_sys_t *sys = p_access->p_sys;<br class="">+<br class="">+    inet_pton( AF_INET, sys->mcastGroup, &(temp.sin_addr.s_addr) );<br class="">+    imr.imr_multiaddr.s_addr = temp.sin_addr.s_addr;<br class="">+    imr.imr_interface.s_addr = INADDR_ANY;<br class="">+<br class="">+    return setsockopt( sys->sAMT, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&imr, sizeof(imr) );<br class="">+}<br class="">+<br class="">+/**<br class="">+ * Leave SSM group that was joined earlier.<br class="">+ * */<br class="">+int amt_leaveSSM_group( stream_t *p_access )<br class="">+{<br class="">+    struct ip_mreq_source imr;<br class="">+    struct sockaddr_in temp;<br class="">+    access_sys_t *sys = p_access->p_sys;<br class="">+<br class="">+    inet_pton( AF_INET, sys->mcastGroup, &(temp.sin_addr.s_addr) );<br class="">+    imr.imr_multiaddr.s_addr = temp.sin_addr.s_addr;<br class="">+<br class="">+    inet_pton( AF_INET, sys->srcAddr, &(temp.sin_addr.s_addr) );<br class="">+    imr.imr_sourceaddr.s_addr = temp.sin_addr.s_addr;<br class="">+    imr.imr_interface.s_addr = INADDR_ANY;<br class="">+<br class="">+    return setsockopt( sys->sAMT, IPPROTO_IP, IP_DROP_SOURCE_MEMBERSHIP, (char *)&imr, sizeof(imr) );<br class="">+}<br class="">+<br class="">+int amt_leaveASM_group( stream_t *p_access )<br class="">+{<br class="">+    struct ip_mreq imr;<br class="">+    struct sockaddr_in temp;<br class="">+    access_sys_t *sys = p_access->p_sys;<br class="">+<br class="">+    inet_pton( AF_INET, sys->mcastGroup, &(temp.sin_addr.s_addr) );<br class="">+    imr.imr_multiaddr.s_addr = temp.sin_addr.s_addr;<br class="">+    imr.imr_interface.s_addr = INADDR_ANY;<br class="">+<br class="">+    return setsockopt( sys->sAMT, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *)&imr, sizeof(imr) );<br class="">+}<br class="">+<br class="">+void *amt_mem_upd( void *data )<br class="">+{<br class="">+    char          relay_ip[INET_ADDRSTRLEN];<br class="">+    stream_t     *p_access = (stream_t*) data;<br class="">+    access_sys_t *sys = p_access->p_sys;<br class="">+<br class="">+    msg_Dbg( p_access, "AMT relay membership update thread started" );<br class="">+<br class="">+    inet_ntop(AF_INET, &(sys->relayAddrDisco.sin_addr), relay_ip, INET_ADDRSTRLEN);<br class="">+<br class="">+    /* thread sends periodic AMT membership updates until Close() which clears sys->threadReady and terminates thread */<br class="">+    while ( sys->threadReady  )<br class="">+    {<br class="">+        amt_send_mem_update( p_access, relay_ip, false );<br class="">+        vlc_tick_sleep( (vlc_tick_t)sys->relay_igmp_query.qqic * CLOCK_FREQ );<br class="">+    }<br class="">+<br class="">+    return NULL;<br class="">+}<br class="">--<br class="">2.17.2 (Apple Git-113)<br class=""><br class="">From 72ea76afdb7679f11e19b0ac2cba6c81ec1aed33 Mon Sep 17 00:00:00 2001<br class="">From: Wayne Brassem <<a href="mailto:wbrassem@rogers.com" class="">wbrassem@rogers.com</a>><br class="">Date: Mon, 14 Jan 2019 18:48:17 -0500<br class="">Subject: [PATCH 3/3] Modifed function declarations<br class=""><br class="">---<br class="">modules/access/amt.h | 220 +++++++++++++++++++++++++++++++++++++++++++<br class="">1 file changed, 220 insertions(+)<br class="">create mode 100644 modules/access/amt.h<br class=""><br class="">diff --git a/modules/access/amt.h b/modules/access/amt.h<br class="">new file mode 100644<br class="">index 0000000000..7c14365cff<br class="">--- /dev/null<br class="">+++ b/modules/access/amt.h<br class="">@@ -0,0 +1,220 @@<br class="">+/*****************************************************************************<br class="">+ * @file amt.h<br class="">+ * @brief AMT access module structs<br class="">+ *<br class="">+ * Some of this code was pulled from or based off Cisco's open-source<br class="">+ * SSMAMTtools repo.<br class="">+ * Copyright (c) Juniper Networks, Inc., 2018 - 2018. All rights reserved.<br class="">+ *<br class="">+ * This code is licensed to you under the GNU Lesser General Public License<br class="">+ * version 2.1 or later. You may not use this code except in compliance with<br class="">+ * the GNU Lesser General Public License.<br class="">+ * This code is not an official Juniper product.<br class="">+ *<br class="">+ * Authors: Natalie Landsberg <<a href="mailto:nlandsberg@juniper.net" class="">nlandsberg@juniper.net</a>><br class="">+ *          Wayne Brassem <<a href="mailto:wbrassem@rogers.com" class="">wbrassem@rogers.com</a>><br class="">+ *<br class="">+ * This library is free software; you can redistribute it and/or<br class="">+ * modify it under the terms of the GNU Lesser General Public License<br class="">+ * as published by the Free Software Foundation; either version 2.1<br class="">+ * of the License, or (at your option) any later version.<br class="">+ *<br class="">+ * This library is distributed in the hope that it will be useful,<br class="">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of<br class="">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br class="">+ * GNU Lesser General Public License for more details.<br class="">+ *<br class="">+ * You should have received a copy of the GNU Lesser General Public<br class="">+ * License along with this library; if not, write to the Free Software<br class="">+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA<br class="">+ ****************************************************************************/<br class="">+<br class="">+/*****************************************************************************<br class="">+ * Various Lengths of Msgs or Hdrs<br class="">+ *****************************************************************************/<br class="">+#define MAC_LEN 6                /* length of generated MAC in bytes */<br class="">+#define NONCE_LEN 4              /* length of nonce in bytes */<br class="">+<br class="">+#define MSG_TYPE_LEN 1           /* length of msg type */<br class="">+#define RELAY_QUERY_MSG_LEN 48   /* total length of relay query */<br class="">+#define RELAY_ADV_MSG_LEN 12     /* length of relay advertisement message */<br class="">+#define IGMP_QUERY_LEN 24        /* length of encapsulated IGMP query message */<br class="">+#define IGMP_REPORT_LEN 20<br class="">+#define AMT_HDR_LEN 2            /* length of AMT header on a packet */<br class="">+#define IP_HDR_LEN 20            /* length of standard IP header */<br class="">+#define IP_HDR_IGMP_LEN 24       /* length of IP header with an IGMP report */<br class="">+#define UDP_HDR_LEN 8            /* length of standard UDP header */<br class="">+#define AMT_REQUEST_MSG_LEN 9<br class="">+#define AMT_DISCO_MSG_LEN 8<br class="">+<br class="">+/*****************************************************************************<br class="">+ * Different AMT Message Types<br class="">+ *****************************************************************************/<br class="">+#define AMT_RELAY_DISCO 1       /* relay discovery */<br class="">+#define AMT_RELAY_ADV 2         /* relay advertisement */<br class="">+#define AMT_REQUEST 3           /* request */<br class="">+#define AMT_MEM_QUERY 4         /* membership query */<br class="">+#define AMT_MEM_UPD 5           /* membership update */<br class="">+#define AMT_MULT_DATA 6         /* multicast data */<br class="">+#define AMT_TEARDOWN 7          /* teardown (not currently supported) */<br class="">+<br class="">+/*****************************************************************************<br class="">+ * Different IGMP Message Types<br class="">+ *****************************************************************************/<br class="">+#define AMT_IGMPV3_MEMBERSHIP_QUERY_TYPEID 0x11<br class="">+#define AMT_IGMPV3_MEMBERSHIP_REPORT_TYPEID 0x22<br class="">+/* IGMPv2, interoperability  */<br class="">+#define AMT_IGMPV1_MEMBERSHIP_REPORT_TYPEID 0x12<br class="">+#define AMT_IGMPV2_MEMBERSHIP_REPORT_TYPEID 0x16<br class="">+#define AMT_IGMPV2_MEMBERSHIP_LEAVE_TYPEID 0x17<br class="">+<br class="">+#define AMT_IGMP_INCLUDE 0x01<br class="">+#define AMT_IGMP_EXCLUDE 0x02<br class="">+#define AMT_IGMP_INCLUDE_CHANGE 0x03<br class="">+#define AMT_IGMP_EXCLUDE_CHANGE 0x04<br class="">+#define AMT_IGMP_ALLOW 0x05<br class="">+#define AMT_IGMP_BLOCK 0x06<br class="">+<br class="">+#define MCAST_ALLHOSTS "224.0.0.22"<br class="">+#define AMT_PORT 2268<br class="">+<br class="">+#define DEFAULT_MTU (1500u - (20 + 8))<br class="">+<br class="">+typedef struct access_sys_t access_sys_t;<br class="">+<br class="">+typedef struct _amt_ip {<br class="">+    uint8_t  ver_ihl;<br class="">+    uint8_t  tos;<br class="">+    uint16_t tot_len;<br class="">+    uint16_t id;<br class="">+    uint16_t frag_off;<br class="">+    uint8_t  ttl;<br class="">+    uint8_t  protocol;<br class="">+    uint16_t check;<br class="">+    uint32_t srcAddr;<br class="">+    uint32_t destAddr;<br class="">+} amt_ip_t;<br class="">+<br class="">+typedef struct _amt_ip_alert {<br class="">+    uint8_t  ver_ihl;<br class="">+    uint8_t   tos;<br class="">+    uint16_t tot_len;<br class="">+    uint16_t id;<br class="">+    uint16_t frag_off;<br class="">+    uint8_t  ttl;<br class="">+    uint8_t  protocol;<br class="">+    uint16_t check;<br class="">+    uint32_t srcAddr;<br class="">+    uint32_t destAddr;<br class="">+    uint32_t options;<br class="">+} amt_ip_alert_t;<br class="">+<br class="">+typedef struct _amt_igmpv3_groupRecord {<br class="">+    uint8_t type;<br class="">+    uint8_t auxDatalen;<br class="">+    uint16_t nSrc;<br class="">+    uint32_t ssm;<br class="">+    uint32_t srcIP[1];<br class="">+} amt_igmpv3_groupRecord_t;<br class="">+<br class="">+typedef struct _amt_igmpv3_membership_report {<br class="">+    uint8_t  type;<br class="">+    uint8_t  resv;<br class="">+    uint16_t checksum;<br class="">+    uint16_t resv2;<br class="">+    uint16_t nGroupRecord;<br class="">+    amt_igmpv3_groupRecord_t grp[1];<br class="">+} amt_igmpv3_membership_report_t;<br class="">+<br class="">+typedef struct _amt_igmpv3_membership_query {<br class="">+    uint8_t  type;<br class="">+    uint8_t  max_resp_code;  /* in 100ms, Max Resp Time = (mant | 0x10) << (exp + 3) */<br class="">+    uint32_t checksum;<br class="">+    uint32_t   ssmIP;<br class="">+    uint8_t  s_qrv;<br class="">+    uint8_t  qqic;           /* in second, query Time = (mant | 0x10) << (exp + 3) */<br class="">+    uint16_t nSrc;<br class="">+    uint32_t srcIP[1];<br class="">+} amt_igmpv3_membership_query_t;<br class="">+<br class="">+typedef struct _amt_membership_update_msg {<br class="">+    amt_ip_alert_t ipHead;<br class="">+    amt_igmpv3_membership_report_t memReport;<br class="">+} amt_membership_update_msg_t;<br class="">+<br class="">+typedef struct _amt_udpHdr {<br class="">+    uint16_t srcPort;<br class="">+    uint16_t dstPort;<br class="">+    uint16_t len;<br class="">+    uint16_t check;<br class="">+} amt_udpHdr_t;<br class="">+<br class="">+typedef struct _amt_multicast_data {<br class="">+    uint8_t   type;<br class="">+    uint8_t   resv;<br class="">+    amt_ip_t        ip;<br class="">+    amt_udpHdr_t    udp;<br class="">+    uint8_t   *buf;<br class="">+} amt_multicast_data_t;<br class="">+<br class="">+/* AMT Functions */<br class="">+int amt_sockets_init( stream_t *p_access );<br class="">+void amt_send_relay_discovery_msg( stream_t *p_access, char *relay_ip );<br class="">+void amt_send_relay_request( stream_t *p_access, char *relay_ip );<br class="">+int amt_joinSSM_group( stream_t *p_access );<br class="">+int amt_joinASM_group( stream_t *p_access );<br class="">+int amt_leaveASM_group( stream_t *p_access );<br class="">+int amt_leaveSSM_group( stream_t *p_access );<br class="">+bool amt_rcv_relay_adv( stream_t *p_access );<br class="">+bool amt_rcv_relay_mem_query( stream_t *p_access );<br class="">+void amt_send_mem_update( stream_t *p_access, char *relay_ip, bool leave );<br class="">+bool open_amt_tunnel( stream_t *p_access );<br class="">+void *amt_mem_upd( void *data );<br class="">+<br class="">+/* Utility functions */<br class="">+unsigned short getChecksum( unsigned short *buffer, int nLen );<br class="">+void makeReport( amt_igmpv3_membership_report_t *mr );<br class="">+void makeIPHeader( amt_ip_alert_t *p_ipHead );<br class=""></blockquote><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">These should be static and only in amt.c if they are not used outside</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">of that file. Also we tend to use snake case rather than camel case.</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">+<br class="">+struct access_sys_t<br class="">+{<br class="">+    int fd;<br class="">+    int sAMT;<br class="">+    int sQuery;<br class="">+    int timeout;<br class="">+    int amtTimeout;<br class="">+    size_t mtu;<br class="">+    bool tryAMT;<br class="">+    bool threadReady;<br class="">+<br class="">+    vlc_thread_t updateThread;<br class="">+    vlc_tick_t queryTime;<br class="">+<br class="">+    char *mcastGroup;<br class="">+    char *srcAddr;<br class="">+    char *relayAddr;<br class="">+<br class="">+    struct sockaddr_in relayAddrDisco;<br class="">+    struct sockaddr_in relayAddress;<br class="">+    struct sockaddr_in stLocalAddr;<br class="">+    struct sockaddr_in stSvrAddr;<br class="">+<br class="">+    uint32_t glob_ulNonce;<br class="">+    uint32_t ulRelayNonce;<br class="">+<br class="">+    struct relay_mem_query_msg_t {<br class="">+        uint8_t type;<br class="">+        uint32_t  ulRcvedNonce;<br class="">+        uint8_t uchaMAC[MAC_LEN];<br class="">+        uint8_t uchaIGMP[IGMP_QUERY_LEN];<br class="">+    } relay_mem_query_msg;<br class="">+<br class="">+    struct relay_adv_msg_t {<br class="">+        uint8_t type;<br class="">+        uint32_t ulRcvNonce;<br class="">+        uint32_t ipAddr;<br class="">+    } relay_adv_msg;<br class="">+<br class="">+    amt_ip_t relay_ip_hdr;<br class="">+    amt_igmpv3_membership_query_t relay_igmp_query;<br class="">+};<br class=""></blockquote><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">You may want to reorder this:<span class="Apple-converted-space"> </span></span><a href="http://www.catb.org/esr/structure-packing/" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">http://www.catb.org/esr/structure-packing/</a><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">--<br class="">2.17.2 (Apple Git-113)<br class="">_______________________________________________<br class="">vlc-devel mailing list<br class="">To unsubscribe or modify your subscription options:<br class=""><a href="https://mailman.videolan.org/listinfo/vlc-devel" class="">https://mailman.videolan.org/listinfo/vlc-devel</a><br class=""></blockquote><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">_______________________________________________</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">vlc-devel mailing list</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">To unsubscribe or modify your subscription options:</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><a href="https://mailman.videolan.org/listinfo/vlc-devel" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">https://mailman.videolan.org/listinfo/vlc-devel</a></div></blockquote></div><br class=""></div></body></html>