Merge "chan_sip: option 'notifyringing' change and doc fix"
authorMark Michelson <mmichelson@digium.com>
Thu, 21 Jan 2016 21:22:53 +0000 (15:22 -0600)
committerGerrit Code Review <gerrit2@gerrit.digium.api>
Thu, 21 Jan 2016 21:22:53 +0000 (15:22 -0600)
140 files changed:
CHANGES
Makefile.moddir_rules
UPGRADE.txt
apps/app_amd.c
apps/app_bridgeaddchan.c [new file with mode: 0644]
apps/app_dial.c
apps/app_meetme.c
apps/app_queue.c
apps/app_statsd.c
apps/app_voicemail.c
cel/cel_radius.c
channels/chan_iax2.c
channels/chan_pjsip.c
channels/chan_sip.c
channels/chan_skinny.c
channels/sip/config_parser.c
codecs/codec_resample.c
configs/samples/amd.conf.sample
configs/samples/features.conf.sample
configs/samples/pjsip.conf.sample
configure
configure.ac
contrib/ast-db-manage/config/versions/136885b81223_add_regcontext_to_pj.py [new file with mode: 0644]
contrib/ast-db-manage/config/versions/189a235b3fd7_add_keep_alive_interval.py [new file with mode: 0644]
contrib/ast-db-manage/config/versions/26d7f3bf0fa5_add_bind_rtp_to_media_address_to_pjsip.py [new file with mode: 0644]
contrib/ast-db-manage/config/versions/2d078ec071b7_increaes_contact_column_size.py [new file with mode: 0644]
contrib/ast-db-manage/config/versions/423f34ad36e2_fix_pjsip_qualify_ti.py [new file with mode: 0644]
contrib/scripts/autosupport [changed mode: 0644->0755]
contrib/scripts/sipp-sendfax.xml [new file with mode: 0644]
contrib/scripts/spandspflow2pcap.log [new file with mode: 0644]
contrib/scripts/spandspflow2pcap.py [new file with mode: 0755]
funcs/func_cdr.c
funcs/func_channel.c
include/asterisk/_private.h
include/asterisk/app.h
include/asterisk/astmm.h
include/asterisk/autoconfig.h.in
include/asterisk/bridge.h
include/asterisk/compat.h
include/asterisk/features_config.h
include/asterisk/http_websocket.h
include/asterisk/module.h
include/asterisk/res_pjproject.h [new file with mode: 0644]
include/asterisk/res_pjsip.h
include/asterisk/stasis_cache_pattern.h
include/asterisk/statsd.h
include/asterisk/taskprocessor.h
include/asterisk/term.h
include/asterisk/time.h
include/asterisk/translate.h
include/asterisk/utils.h
main/aoc.c
main/app.c
main/asterisk.c
main/astmm.c
main/audiohook.c
main/bridge.c
main/bridge_basic.c
main/bridge_channel.c
main/ccss.c
main/cdr.c
main/channel.c
main/cli.c
main/config.c
main/devicestate.c
main/dns.c
main/dns_system_resolver.c
main/endpoints.c
main/features_config.c
main/format_cap.c
main/loader.c
main/logger.c
main/manager.c
main/pbx.c
main/pbx_app.c [new file with mode: 0644]
main/pbx_builtins.c [new file with mode: 0644]
main/pbx_functions.c [new file with mode: 0644]
main/pbx_hangup_handler.c [new file with mode: 0644]
main/pbx_private.h [new file with mode: 0644]
main/pbx_switch.c [new file with mode: 0644]
main/pbx_timing.c [new file with mode: 0644]
main/pbx_variables.c [new file with mode: 0644]
main/rtp_engine.c
main/sched.c
main/sorcery.c
main/stasis.c
main/stasis_cache_pattern.c
main/stasis_channels.c
main/stdtime/localtime.c
main/taskprocessor.c
main/term.c
main/translate.c
main/utils.c
pbx/pbx_dundi.c
res/res_agi.c
res/res_calendar.c
res/res_chan_stats.c
res/res_crypto.c
res/res_endpoint_stats.c [new file with mode: 0644]
res/res_fax.c
res/res_format_attr_h264.c
res/res_format_attr_opus.c
res/res_format_attr_vp8.c [new file with mode: 0644]
res/res_http_websocket.c
res/res_jabber.exports.in [deleted file]
res/res_musiconhold.c
res/res_mwi_external.c
res/res_pjproject.c [new file with mode: 0644]
res/res_pjproject.exports.in [new file with mode: 0644]
res/res_pjsip.c
res/res_pjsip/config_global.c
res/res_pjsip/config_transport.c
res/res_pjsip/location.c
res/res_pjsip/pjsip_configuration.c
res/res_pjsip/pjsip_distributor.c
res/res_pjsip/pjsip_options.c
res/res_pjsip_endpoint_identifier_ip.c
res/res_pjsip_history.c [new file with mode: 0644]
res/res_pjsip_log_forwarder.c [deleted file]
res/res_pjsip_messaging.c
res/res_pjsip_notify.c
res/res_pjsip_outbound_registration.c
res/res_pjsip_pubsub.c
res/res_pjsip_refer.c
res/res_pjsip_registrar.c
res/res_pjsip_sdp_rtp.c
res/res_pjsip_session.c
res/res_pjsip_t38.c
res/res_pjsip_transport_websocket.c
res/res_rtp_asterisk.c
res/res_sorcery_memory_cache.c
res/res_sorcery_realtime.c
res/res_stasis.c
res/res_stasis_playback.c
res/res_stasis_recording.c
res/res_statsd.c
res/stasis/app.c
tests/test_sorcery_realtime.c
tests/test_stasis_endpoints.c
tests/test_threadpool.c

diff --git a/CHANGES b/CHANGES
index d6fea74..173a411 100644 (file)
--- a/CHANGES
+++ b/CHANGES
 Applications
 ------------------
 
+BridgeAdd
+------------------
+ * A new application in Asterisk, this will join the calling channel
+   to an existing bridge containing the named channel prefix.
+
 ConfBridge
 ------------------
  * Added the ability to pass options to MixMonitor when recording is used with
@@ -197,9 +202,70 @@ Queue
    the queue member was paused.
 
 ------------------------------------------------------------------------------
+--- Functionality changes from Asterisk 13.7.0 to Asterisk 13.8.0 ------------
+------------------------------------------------------------------------------
+
+res_pjproject
+------------------
+ * This module is the successor of res_pjsip_log_forwarder.  As well as
+   handling the log forwarding (which now displays as 'pjproject:0' instead
+   of 'pjsip:0'), it also adds a 'pjproject show buildopts' command to the CLI.
+   This displays the compiled-in options of the pjproject installation
+   Asterisk is currently running against.
+
+res_pjsip
+------------------
+
+ * Added new global option (regcontext) to pjsip. When set, Asterisk will
+   dynamically create and destroy a NoOp priority 1 extension
+   for a given endpoint who registers or unregisters with us.
+
+res_pjsip_history
+------------------
+ * A new module, res_pjsip_history, has been added that provides SIP history
+   viewing/filtering from the CLI. The module is intended to be used on systems
+   with busy SIP traffic, where existing forms of viewing SIP messages - such
+   as the res_pjsip_logger - may be inadequate. The module provides two new
+   CLI commands:
+   - 'pjsip set history {on|off|clear}' - this enables/disables SIP history
+     capturing, as well as clears an existing history capture. Note that SIP
+     packets captured are stored in memory until cleared. As a result, the
+     history capture should only be used for debugging/viewing purposes, and
+     should *NOT* be left permanently enabled on a system.
+   - 'pjsip show history' - displays the captured SIP history. When invoked
+     with no options, the entire captured history is displayed. Two options
+     are available:
+     -- 'entry <num>' - display a detailed view of a single SIP message in
+        the history
+     -- 'where ...' - filter the history based on some expression. For more
+        information on filtering, view the current CLI help for the
+        'pjsip show history' command.
+
+Voicemail
+------------------
+ * app_voicemail and res_mwi_external can now be built together.  The default
+   remains to build app_voicemail and not res_mwi_external but if they are
+   both built, the load order will cause res_mwi_external to load first and
+   app_voicemail will be skipped.  Use 'preload=app_voicemail.so' in
+   modules.conf to force app_voicemail to be the voicemail provider.
+
+res_pjsip_sdp_rtp
+------------------
+ * A new option (bind_rtp_to_media_address) has been added to endpoint which
+   will cause res_pjsip_sdp_rtp to actually bind the RTP instance to the
+   media_address as well as using it in the SDP.  If set, RTP packets will now
+   originate from the media address instead of the operating system's "primary"
+   ip address.
+
+------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 13.6.0 to Asterisk 13.7.0 ------------
 ------------------------------------------------------------------------------
 
+Codecs
+------------------
+ * Added format attribute negotiation for the VP8 video codec. Format attribute
+   negotiation is provided by the res_format_attr_vp8 module.
+
 ConfBridge
 ------------------
  * A new "timeout" user profile option has been added. This configures the number
@@ -222,12 +288,38 @@ Dialplan Functions
    the 'hold' raised by a channel to be intercepted and converted into an
    event instead.
 
+res_pjsip_outbound_registration
+-------------------------------
+ * If res_statsd is loaded and a StatsD server is configured, basic statistics
+   regarding the state of outbound registrations will now be emitted. This
+   includes:
+   - A GAUGE statistic for the overall number of outbound registrations, i.e.:
+       PJSIP.registrations.count
+   - A GAUGE statistic for the overall number of outbound registrations in a
+     particular state, e.g.:
+       PJSIP.registrations.state.Registered
 
 res_pjsip
 ------------------
  * The ability to use "like" has been added to the pjsip list and show
    CLI commands.  For instance: CLI> pjsip list endpoints like abc
 
+ * If res_statsd is loaded and a StatsD server is configured, basic statistics
+   regarding the state of PJSIP contacts will now be emitted. This includes:
+   - A GAUGE statistic for the overall number of contacts in a particular
+     state, e.g.:
+       PJSIP.contacts.states.Reachable
+   - A TIMER statistic for the RTT time for each qualified contact, e.g.:
+       PJSIP.contacts.alice@@127.0.0.1:5061.rtt
+
+res_sorcery_memory_cache
+------------------------
+ * A new caching strategy, full_backend_cache, has been added which caches
+   all stored objects in the backend. When enabled all objects will be
+   expired or go stale according to the configuration. As well when enabled
+   all retrieval operations will be performed against the cache instead of
+   the backend.
+
 func_callerid
 -------------------
  * CALLERID(pres) is now documented as a valid alternative to setting both
@@ -238,6 +330,18 @@ func_callerid
    The same applies to CONNECTEDLINE(pres), REDIRECTING(orig-pres),
    REDIRECTING(to-pres) and REDIRECTING(from-pres).
 
+res_endpoint_stats
+-------------------
+ * A new module that emits StatsD statistics regarding Asterisk endpoints.
+   This includes a total count of the number of endpoints, the count of the
+   number of endpoints in the technology agnostic state of the endpoint -
+   online or offline - as well as the number of channels associated with each
+   endpoint. These are recorded as three different GAUGE statistics:
+    - endpoints.count
+    - endpoints.state.{unknown|offline|online}
+    - endpoints.{tech}.{resource}.channels
+
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 13.5.0 to Asterisk 13.6.0 ------------
 ------------------------------------------------------------------------------
index df715d9..a92b0d8 100644 (file)
@@ -77,7 +77,7 @@ $$(subst $(3),$(5),$(2)): _ASTCFLAGS+=$$(call MOD_ASTCFLAGS,$(1))
 clean:: clean-$(1)$(3)
 
 clean-$(1)$(3):
-       rm -f $$(subst $(3),$(5),$(2)) $$(subst $(3),$(4),$(2))
+       rm -f $$(subst $(3),$(4),$(2)) $$(subst $(3),$(5),$(2)) $$(subst $(3),$(6),$(2)) $$(subst $(3),$(7),$(2))
 
 endef
 
index 91d9edc..6fb82c4 100644 (file)
@@ -64,5 +64,15 @@ AMI:
    Commands that fail to execute (no such command, invalid syntax etc.) now
    return an Error response instead of Success.
 
+app_amd:
+ - The 'maximum_number_of_words' configuration option and parameter to the AMD
+   application previously did not match the documented functionality + variable
+   name.  In Asterisk 13, a value of '3' would mean that if '3' words were detected,
+   the result would be detection as a 'MACHINE'.  As of this version, the value
+   reflects the maximum words that if EXCEEDED (rather than reached), would
+   result in detection as a machine.  This means that you should update this
+   value to be one higher than your previos value, if your previous value
+   was working well for you.
+
 ===========================================================
 ===========================================================
index ee421b6..83da533 100644 (file)
@@ -62,19 +62,19 @@ ASTERISK_REGISTER_FILE()
                <syntax>
                        <parameter name="initialSilence" required="false">
                                <para>Is maximum initial silence duration before greeting.</para>
-                               <para>If this is exceeded set as MACHINE</para>
+                               <para>If this is exceeded, the result is detection as a MACHINE</para>
                        </parameter>
                        <parameter name="greeting" required="false">
                                <para>is the maximum length of a greeting.</para>
-                               <para>If this is exceeded set as MACHINE</para>
+                               <para>If this is exceeded, the result is detection as a MACHINE</para>
                        </parameter>
                        <parameter name="afterGreetingSilence" required="false">
                                <para>Is the silence after detecting a greeting.</para>
-                               <para>If this is exceeded set as HUMAN</para>
+                               <para>If this is exceeded, the result is detection as a HUMAN</para>
                        </parameter>
                        <parameter name="totalAnalysis Time" required="false">
                                <para>Is the maximum time allowed for the algorithm</para>
-                               <para>to decide HUMAN or MACHINE</para>
+                               <para>to decide on whether the audio represents a HUMAN, or a MACHINE</para>
                        </parameter>
                        <parameter name="miniumWordLength" required="false">
                                <para>Is the minimum duration of Voice considered to be a word</para>
@@ -85,14 +85,14 @@ ASTERISK_REGISTER_FILE()
                        </parameter>
                        <parameter name="maximumNumberOfWords" required="false">
                                <para>Is the maximum number of words in a greeting</para>
-                               <para>If this is exceeded set as MACHINE</para>
+                               <para>If this is exceeded, then the result is detection as a MACHINE</para>
                        </parameter>
                        <parameter name="silenceThreshold" required="false">
-                               <para>How long do we consider silence</para>
+                               <para>What is the average level of noise from 0 to 32767 which if not exceeded, should be considered silence?</para>
                        </parameter>
                        <parameter name="maximumWordLength" required="false">
                                <para>Is the maximum duration of a word to accept.</para>
-                               <para>If exceeded set as MACHINE</para>
+                               <para>If exceeded, then the result is detection as a MACHINE</para>
                        </parameter>
                </syntax>
                <description>
@@ -130,7 +130,7 @@ ASTERISK_REGISTER_FILE()
                                        </value>
                                        <value name="MAXWORDS">
                                                Word Count - maximum number of words.
-                                       </value>        
+                                       </value>
                                </variable>
                        </variablelist>
                </description>
@@ -154,7 +154,7 @@ static int dfltAfterGreetingSilence = 800;
 static int dfltTotalAnalysisTime    = 5000;
 static int dfltMinimumWordLength    = 100;
 static int dfltBetweenWordsSilence  = 50;
-static int dfltMaximumNumberOfWords = 3;
+static int dfltMaximumNumberOfWords = 2;
 static int dfltSilenceThreshold     = 256;
 static int dfltMaximumWordLength    = 5000; /* Setting this to a large default so it is not used unless specify it in the configs or command line */
 
@@ -367,7 +367,7 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
                                        sprintf(amdCause , "MAXWORDLENGTH-%d", consecutiveVoiceDuration);
                                        break;
                                }
-                               if (iWordsCount >= maximumNumberOfWords) {
+                               if (iWordsCount > maximumNumberOfWords) {
                                        ast_verb(3, "AMD: Channel [%s]. ANSWERING MACHINE: iWordsCount:%d\n", ast_channel_name(chan), iWordsCount);
                                        ast_frfree(f);
                                        strcpy(amdStatus , "MACHINE");
diff --git a/apps/app_bridgeaddchan.c b/apps/app_bridgeaddchan.c
new file mode 100644 (file)
index 0000000..fda6ca5
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2015, Digium, Inc.
+ *
+ * Alec Davis <sivad.a@paradise.net.nz>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Application to place the channel into an existing Bridge
+ *
+ * \author Alec Davis
+ *
+ * \ingroup applications
+ */
+
+/*** MODULEINFO
+       <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_REGISTER_FILE()
+
+#include "asterisk/file.h"
+#include "asterisk/module.h"
+#include "asterisk/channel.h"
+#include "asterisk/bridge.h"
+#include "asterisk/features.h"
+
+/*** DOCUMENTATION
+       <application name="BridgeAdd" language="en_US">
+               <synopsis>
+                       Join a bridge that contains the specified channel.
+               </synopsis>
+               <syntax>
+                       <parameter name="name">
+                               <para>Name of the channel in an existing bridge
+                               </para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application places the incoming channel into
+                       the bridge containing the specified channel. The specified
+                       channel only needs to be the prefix of a full channel name
+                       IE. 'SIP/cisco0001'.
+                       </para>
+               </description>
+       </application>
+ ***/
+
+static const char app[] = "BridgeAdd";
+
+static int bridgeadd_exec(struct ast_channel *chan, const char *data)
+{
+       struct ast_channel *c_ref;
+       struct ast_bridge_features chan_features;
+       struct ast_bridge *bridge;
+       char *c_name;
+
+       /* Answer the channel if needed */
+       if (ast_channel_state(chan) != AST_STATE_UP) {
+               ast_answer(chan);
+       }
+
+       if (!(c_ref = ast_channel_get_by_name_prefix(data, strlen(data)))) {
+               ast_log(LOG_WARNING, "Channel %s not found\n", data);
+               return -1;
+       }
+
+       c_name = ast_strdupa(ast_channel_name(c_ref));
+
+       ast_channel_lock(c_ref);
+       bridge = ast_channel_get_bridge(c_ref);
+       ast_channel_unlock(c_ref);
+
+       ast_channel_unref(c_ref);
+
+       if (!bridge) {
+               ast_log(LOG_WARNING, "Channel %s is not in a bridge\n", c_name);
+               return -1;
+       }
+
+       ast_verb(3, "%s is joining %s in bridge %s\n", ast_channel_name(chan),
+               c_name, bridge->uniqueid);
+
+       if (ast_bridge_features_init(&chan_features)
+               || ast_bridge_join(bridge, chan, NULL, &chan_features, NULL, 0)) {
+
+               ast_log(LOG_WARNING, "%s failed to join %s in bridge %s\n", ast_channel_name(chan),
+                        c_name, bridge->uniqueid);
+
+               ast_bridge_features_cleanup(&chan_features);
+               ao2_cleanup(bridge);
+               return -1;
+       }
+
+       ast_bridge_features_cleanup(&chan_features);
+       ao2_cleanup(bridge);
+       return 0;
+}
+
+static int unload_module(void)
+{
+       return ast_unregister_application(app);
+}
+
+static int load_module(void)
+{
+       return ast_register_application_xml(app, bridgeadd_exec);
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Bridge Add Channel Application");
index 540f662..11591bd 100644 (file)
@@ -2151,6 +2151,24 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
                return -1;
        }
 
+       if (ast_check_hangup_locked(chan)) {
+               /*
+                * Caller hung up before we could dial.  If dial is executed
+                * within an AGI then the AGI has likely eaten all queued
+                * frames before executing the dial in DeadAGI mode.  With
+                * the caller hung up and no pending frames from the caller's
+                * read queue, dial would not know that the call has hung up
+                * until a called channel answers.  It is rather annoying to
+                * whoever just answered the non-existent call.
+                *
+                * Dial should not continue execution in DeadAGI mode, hangup
+                * handlers, or the h exten.
+                */
+               ast_verb(3, "Caller hung up before dial.\n");
+               pbx_builtin_setvar_helper(chan, "DIALSTATUS", "CANCEL");
+               return -1;
+       }
+
        parse = ast_strdupa(data);
 
        AST_STANDARD_APP_ARGS(args, parse);
index 0c339d6..ab6b94f 100644 (file)
@@ -5774,6 +5774,9 @@ static void meetme_set_defaults(void)
 
        /*  Logging of participants defaults to ON for compatibility reasons */
        rt_log_members = 1;
+
+       /* Set default number of buffers to be allocated. */
+       audio_buffers = DEFAULT_AUDIO_BUFFERS;
 }
 
 static void load_config_meetme(int reload)
index 234543f..c4025d2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Asterisk -- An open source telephony toolkit.
  *
- * Copyright (C) 1999 - 2006, Digium, Inc.
+ * Copyright (C) 1999 - 2015, Digium, Inc.
  *
  * Mark Spencer <markster@digium.com>
  *
@@ -1023,6 +1023,13 @@ ASTERISK_REGISTER_FILE()
                                <parameter name="LastCall">
                                        <para>The time this member last took a call, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
                                </parameter>
+                               <parameter name="InCall">
+                                       <para>Set to 1 if member is in call. Set to 0 after LastCall time is updated.</para>
+                                       <enumlist>
+                                               <enum name="0"/>
+                                               <enum name="1"/>
+                                       </enumlist>
+                               </parameter>
                                <parameter name="Status">
                                        <para>The numeric device state status of the queue member.</para>
                                        <enumlist>
@@ -1540,6 +1547,7 @@ struct member {
        char reason_paused[80];              /*!< Reason of paused if member is paused */
        int queuepos;                        /*!< In what order (pertains to certain strategies) should this member be called? */
        time_t lastcall;                     /*!< When last successful call was hungup */
+       unsigned int in_call:1;              /*!< True if member is still in call. (so lastcall is not actual) */
        struct call_queue *lastqueue;        /*!< Last queue we received a call */
        unsigned int dead:1;                 /*!< Used to detect members deleted in realtime */
        unsigned int delme:1;                /*!< Flag to delete entry on reload */
@@ -2177,7 +2185,7 @@ static void queue_publish_member_blob(struct stasis_message_type *type, struct a
 
 static struct ast_json *queue_member_blob_create(struct call_queue *q, struct member *mem)
 {
-       return ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: i, s: i, s: i, s: i, s: i, s: s, s: i}",
+       return ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: i, s: i, s: i, s: i, s: i, s: i, s: s, s: i}",
                "Queue", q->name,
                "MemberName", mem->membername,
                "Interface", mem->interface,
@@ -2186,6 +2194,7 @@ static struct ast_json *queue_member_blob_create(struct call_queue *q, struct me
                "Penalty", mem->penalty,
                "CallsTaken", mem->calls,
                "LastCall", (int)mem->lastcall,
+               "InCall", mem->in_call,
                "Status", mem->status,
                "Paused", mem->paused,
                "PausedReason", mem->reason_paused,
@@ -2249,6 +2258,10 @@ static int get_member_status(struct call_queue *q, int max_penalty, int min_pena
                        if (member->paused && (conditions & QUEUE_EMPTY_PAUSED)) {
                                ast_debug(4, "%s is unavailable because he is paused'\n", member->membername);
                                break;
+                       } else if ((conditions & QUEUE_EMPTY_WRAPUP) && member->in_call && q->wrapuptime) {
+                               ast_debug(4, "%s is unavailable because still in call, so we can`t check "
+                                       "wrapuptime (%d)\n", member->membername, q->wrapuptime);
+                               break;
                        } else if ((conditions & QUEUE_EMPTY_WRAPUP) && member->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < member->lastcall)) {
                                ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n", member->membername, (int) (time(NULL) - member->lastcall), q->wrapuptime);
                                break;
@@ -2316,6 +2329,9 @@ static int is_member_available(struct call_queue *q, struct member *mem)
        }
 
        /* Let wrapuptimes override device state availability */
+       if (q->wrapuptime && mem->in_call) {
+               available = 0; /* member is still in call, cant check wrapuptime to lastcall time */
+       }
        if (mem->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < mem->lastcall)) {
                available = 0;
        }
@@ -2668,6 +2684,7 @@ static void clear_queue(struct call_queue *q)
                while ((mem = ao2_iterator_next(&mem_iter))) {
                        mem->calls = 0;
                        mem->lastcall = 0;
+                       mem->in_call = 0;
                        ao2_ref(mem, -1);
                }
                ao2_iterator_destroy(&mem_iter);
@@ -4165,6 +4182,12 @@ static int can_ring_entry(struct queue_ent *qe, struct callattempt *call)
                return 0;
        }
 
+       if (call->member->in_call && call->lastqueue->wrapuptime) {
+               ast_debug(1, "%s is in call, so not available (wrapuptime %d)\n",
+                       call->interface, call->lastqueue->wrapuptime);
+               return 0;
+       }
+
        if ((call->lastqueue && call->lastqueue->wrapuptime && (time(NULL) - call->lastcall < call->lastqueue->wrapuptime))
                || (!call->lastqueue && qe->parent->wrapuptime && (time(NULL) - call->lastcall < qe->parent->wrapuptime))) {
                ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
@@ -5214,6 +5237,11 @@ static int is_our_turn(struct queue_ent *qe)
                res = 0;
        }
 
+       /* Update realtime members if this is the first call and number of avalable members is 0 */
+       if (avl == 0 && qe->pos == 1) {
+               update_realtime_members(qe->parent);
+       }
+
        return res;
 }
 
@@ -5382,6 +5410,9 @@ static int update_queue(struct call_queue *q, struct member *member, int callcom
                                time(&mem->lastcall);
                                mem->calls++;
                                mem->lastqueue = q;
+                               mem->in_call = 0;
+                               ast_debug(4, "Marked member %s as NOT in_call. Lastcall time: %ld \n",
+                                       mem->membername, (long)mem->lastcall);
                                ao2_ref(mem, -1);
                        }
                        ao2_unlock(qtmp);
@@ -5393,6 +5424,9 @@ static int update_queue(struct call_queue *q, struct member *member, int callcom
                time(&member->lastcall);
                member->calls++;
                member->lastqueue = q;
+               member->in_call = 0;
+               ast_debug(4, "Marked member %s as NOT in_call. Lastcall time: %ld \n",
+                       member->membername, (long)member->lastcall);
                ao2_unlock(q);
        }
        ao2_lock(q);
@@ -6371,6 +6405,9 @@ static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_a
        int callcompletedinsl;
        struct ao2_iterator memi;
        struct queue_end_bridge *queue_end_bridge = NULL;
+       struct ao2_iterator queue_iter; /* to iterate through all queues (for shared_lastcall)*/
+       struct member *mem;
+       struct call_queue *queuetmp;
 
        memset(&bridge_config, 0, sizeof(bridge_config));
        tmpid[0] = 0;
@@ -6796,6 +6833,28 @@ static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_a
                        }
                }
                qe->handled++;
+
+               /** mark member as "in_call" in all queues */
+               if (shared_lastcall) {
+                       queue_iter = ao2_iterator_init(queues, 0);
+                       while ((queuetmp = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
+                               ao2_lock(queuetmp);
+                               if ((mem = ao2_find(queuetmp->members, member, OBJ_POINTER))) {
+                                       mem->in_call = 1;
+                                       ast_debug(4, "Marked member %s as in_call \n", mem->membername);
+                                       ao2_ref(mem, -1);
+                               }
+                               ao2_unlock(queuetmp);
+                               queue_t_unref(queuetmp, "Done with iterator");
+                       }
+                       ao2_iterator_destroy(&queue_iter);
+               } else {
+                       ao2_lock(qe->parent);
+                       member->in_call = 1;
+                       ast_debug(4, "Marked member %s as in_call \n", member->membername);
+                       ao2_unlock(qe->parent);
+               }
+
                ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "CONNECT", "%ld|%s|%ld", (long) (time(NULL) - qe->start), ast_channel_uniqueid(peer),
                                                                                                        (long)(orig - to > 0 ? (orig - to) / 1000 : 0));
 
@@ -9250,10 +9309,21 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char *
 
                                ast_str_append(&out, 0, " (ringinuse %s)", mem->ringinuse ? "enabled" : "disabled");
 
-                               ast_str_append(&out, 0, "%s%s%s%s%s%s%s%s%s (%s%s%s)",
+                               ast_str_append(&out, 0, "%s%s%s%s%s%s%s%s%s",
                                        mem->dynamic ? ast_term_color(COLOR_CYAN, COLOR_BLACK) : "", mem->dynamic ? " (dynamic)" : "", ast_term_reset(),
                                        mem->realtime ? ast_term_color(COLOR_MAGENTA, COLOR_BLACK) : "", mem->realtime ? " (realtime)" : "", ast_term_reset(),
-                                       mem->paused ? ast_term_color(COLOR_BROWN, COLOR_BLACK) : "", mem->paused ? " (paused)" : "", ast_term_reset(),
+                                       mem->in_call ? ast_term_color(COLOR_BROWN, COLOR_BLACK) : "", mem->in_call ? " (in call)" : "", ast_term_reset());
+                               if (mem->paused) {
+                                       if (ast_strlen_zero(mem->reason_paused)) {
+                                               ast_str_append(&out, 0, " %s(paused)%s",
+                                                       ast_term_color(COLOR_BROWN, COLOR_BLACK), ast_term_reset());
+                                       } else {
+                                               ast_str_append(&out, 0, " %s(paused:%s)%s", ast_term_color(COLOR_BROWN, COLOR_BLACK),
+                                                       mem->reason_paused, ast_term_reset());
+                                       }
+                               }
+
+                               ast_str_append(&out, 0, " (%s%s%s)",
                                        ast_term_color(
                                                mem->status == AST_DEVICE_UNAVAILABLE || mem->status == AST_DEVICE_UNKNOWN ?
                                                        COLOR_RED : COLOR_GREEN, COLOR_BLACK),
@@ -9621,13 +9691,15 @@ static int manager_queues_status(struct mansession *s, const struct message *m)
                                                "Penalty: %d\r\n"
                                                "CallsTaken: %d\r\n"
                                                "LastCall: %d\r\n"
+                                               "InCall: %d\r\n"
                                                "Status: %d\r\n"
                                                "Paused: %d\r\n"
                                                "PausedReason: %s\r\n"
                                                "%s"
                                                "\r\n",
                                                q->name, mem->membername, mem->interface, mem->state_interface, mem->dynamic ? "dynamic" : "static",
-                                               mem->penalty, mem->calls, (int)mem->lastcall, mem->status, mem->paused, mem->reason_paused, idText);
+                                               mem->penalty, mem->calls, (int)mem->lastcall, mem->in_call, mem->status,
+                                               mem->paused, mem->reason_paused, idText);
                                        ++q_items;
                                }
                                ao2_ref(mem, -1);
index 176796f..e87aac6 100644 (file)
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2015, Digium, Inc.
- *
- * Tyler Cambron <tcambron@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
- /*** MODULEINFO
-       <depend>res_statsd</depend>
-       <defaultenabled>no</defaultenabled>
-       <support_level>extended</support_level>
- ***/
-
-#include "asterisk.h"
-
-ASTERISK_REGISTER_FILE()
-
-#include <math.h>
-
-#include "asterisk/module.h"
-#include "asterisk/logger.h"
-#include "asterisk/app.h"
-#include "asterisk/pbx.h"
-#include "asterisk/strings.h"
-#include "asterisk/statsd.h"
-
-/*** DOCUMENTATION
-       <application name="StatsD" language="en_US">
-               <synopsis>
-                       Allow statistics to be passed to the StatsD server from the dialplan.
-               </synopsis>
-               <syntax>
-                       <parameter name="metric_type" required="true">
-                               <para>The metric type to be sent to StatsD.</para>
-                       </parameter>
-                       <parameter name="statistic_name" required="true">
-                               <para>The name of the variable to be sent to StatsD.</para>
-                       </parameter>
-                       <parameter name="value" required="true">
-                               <para>The value of the variable to be sent to StatsD.</para>
-                       </parameter>
-               </syntax>
-               <description>
-                       <para>This dialplan application sends statistics to the StatsD
-                       server specified inside of <literal>statsd.conf</literal>.</para>
-               </description>
-       </application>
- ***/
-
-static const char app[] = "StatsD";
-
-/*!
- * \brief Check to ensure the value is within the allowed range.
- *
- * \param value The value of the statistic to be sent to StatsD.
- * \param metric The metric type to be sent to StatsD.
- *
- * This function checks to see if the value given to the StatsD daialplan
- * application is within the allowed range as specified by StatsD. A counter
- * is the only metric type allowed to be initialized as a negative number.
- *
- * \retval zero on success.
- * \retval 1 on error.
- */
-static int value_in_range(const char *value, const char *metric)
-{
-       double numerical_value = strtod(value, NULL);
-
-       if (!strcmp(metric, "c")) {
-               if (numerical_value < pow(-2, 63) || numerical_value > pow(2, 63)) {
-                       ast_log(AST_LOG_WARNING, "Value %lf out of range!\n", numerical_value);
-                       return 1;
-               }
-       } else {
-               if (numerical_value < 0 || numerical_value > pow(2, 64)) {
-                       ast_log(AST_LOG_WARNING, "Value %lf out of range!\n", numerical_value);
-                       return 1;
-               }
-       }
-
-       return 0;
-}
-
-/*!
- * \brief Check to ensure the metric type is a valid metric type.
- *
- * \param metric The metric type to be sent to StatsD.
- *
- * This function checks to see if the metric type given to the StatsD dialplan
- * is a valid metric type. Metric types are determined by StatsD.
- *
- * \retval zero on success.
- * \retval 1 on error.
- */
-static int validate_metric(const char *metric)
-{
-       const char *valid_metrics[] = {"g","s","ms","c"};
-       int i;
-
-       if (ast_strlen_zero(metric)) {
-               ast_log(AST_LOG_ERROR, "Missing metric type argument.\n");
-               return 1;
-       }
-
-       for (i = 0; i < ARRAY_LEN(valid_metrics); i++) {
-               if (!strcmp(valid_metrics[i], metric)) {
-                       return 0;
-               }
-       }
-
-       ast_log(AST_LOG_ERROR, "Invalid metric type %s.\n", metric);
-
-       return 1;
-}
-
-/*!
- * \brief Check to ensure the statistic name is valid.
- *
- * \param name The variable name to be sent to StatsD.
- *
- * This function checks to see if the statistic name given to the StatsD
- * dialplan application is valid by ensuring that the name does not have any
- * invalid characters.
- *
- * \retval zero on success.
- * \retval 1 on error.
- */
-static int validate_name(const char *name)
-{
-       if (ast_strlen_zero(name) || (strstr(name, "|") != NULL)) {
-               ast_log(AST_LOG_ERROR, "Statistic name %s is missing or contains a pipe (|)"
-                       " character.\n", name);
-               return 1;
-       }
-
-       return 0;
-}
-
-/*!
- * \brief Check to ensure the value is valid.
- *
- * \param value The value of the statistic to be sent to StatsD.
- * \param metric The metric type to be sent to StatsD.
- *
- * This function checks to see if the value given to the StatsD daialplan
- * application is valid by testing if it is numeric. A plus or minus is only
- * allowed at the beginning of the value if it is a counter or a gauge.
- *
- * \retval zero on success.
- * \retval 1 on error.
- */
-static int validate_value(const char *value, const char *metric)
-{
-       const char *actual_value;
-
-       if (ast_strlen_zero(value)) {
-               ast_log(AST_LOG_ERROR, "Missing value argument.\n");
-               return 1;
-       }
-
-       if (!strcmp(metric, "g") || !strcmp(metric, "c")) {
-               if ((value[0] == '+') || (value[0] == '-')) {
-                       actual_value = &value[1];
-                       if (ast_strlen_zero(actual_value)) {
-                               ast_log(AST_LOG_ERROR, "Value argument %s only contains a sign"
-                                       " operator.\n", value);
-                               return 1;
-                       }
-               } else {
-                       actual_value = &value[0];
-               }
-       } else {
-               actual_value = &value[0];
-       }
-
-       if (!isdigit(*actual_value)) {
-               ast_log(AST_LOG_ERROR, "Value of %s is not a valid number!\n", actual_value);
-               return 1;
-       }
-
-       if (value_in_range(actual_value, metric)) {
-               return 1;
-       }
-
-       return 0;
-}
-
-static int statsd_exec(struct ast_channel *chan, const char *data)
-{
-       char *stats;
-       double numerical_value;
-
-       AST_DECLARE_APP_ARGS(args,
-                       AST_APP_ARG(metric_type);
-                       AST_APP_ARG(statistic_name);
-                       AST_APP_ARG(value);
-       );
-
-       if (!data) {
-               ast_log(AST_LOG_ERROR, "No parameters were provided. Correct format is "
-                       "StatsD(metric_type,statistic_name,value). All parameters are required.\n");
-               return 1;
-       }
-
-       stats = ast_strdupa(data);
-       AST_STANDARD_APP_ARGS(args, stats);
-
-       /* If any of the validations fail, emit a warning message. */
-       if (validate_metric(args.metric_type) || validate_name(args.statistic_name)
-               || validate_value(args.value, args.metric_type)) {
-               ast_log(AST_LOG_WARNING, "Invalid parameters provided. Correct format is "
-                       "StatsD(metric_type,statistic_name,value). All parameters are required.\n");
-
-               return 1;
-       }
-
-       /*
-        * Conversion to a double is safe here since the value would have been validated as a
-        * number in validate_value().
-        */
-       numerical_value = strtod(args.value, NULL);
-       ast_statsd_log(args.statistic_name, args.metric_type, numerical_value);
-
-       return 0;
-}
-
-static int unload_module(void)
-{
-       return ast_unregister_application(app);
-}
-
-static int load_module(void)
-{
-       return ast_register_application_xml(app, statsd_exec);
-}
-
-AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "StatsD Dialplan Application");
+/*\r
+ * Asterisk -- An open source telephony toolkit.\r
+ *\r
+ * Copyright (C) 2015, Digium, Inc.\r
+ *\r
+ * Tyler Cambron <tcambron@digium.com>\r
+ *\r
+ * See http://www.asterisk.org for more information about\r
+ * the Asterisk project. Please do not directly contact\r
+ * any of the maintainers of this project for assistance;\r
+ * the project provides a web site, mailing lists and IRC\r
+ * channels for your use.\r
+ *\r
+ * This program is free software, distributed under the terms of\r
+ * the GNU General Public License Version 2. See the LICENSE file\r
+ * at the top of the source tree.\r
+ */\r
+\r
+ /*** MODULEINFO\r
+       <depend>res_statsd</depend>\r
+       <defaultenabled>no</defaultenabled>\r
+       <support_level>extended</support_level>\r
+ ***/\r
+\r
+#include "asterisk.h"\r
+\r
+ASTERISK_REGISTER_FILE()\r
+\r
+#include <math.h>\r
+\r
+#include "asterisk/module.h"\r
+#include "asterisk/logger.h"\r
+#include "asterisk/app.h"\r
+#include "asterisk/pbx.h"\r
+#include "asterisk/strings.h"\r
+#include "asterisk/statsd.h"\r
+\r
+/*** DOCUMENTATION\r
+       <application name="StatsD" language="en_US">\r
+               <synopsis>\r
+                       Allow statistics to be passed to the StatsD server from the dialplan.\r
+               </synopsis>\r
+               <syntax>\r
+                       <parameter name="metric_type" required="true">\r
+                               <para>The metric type to be sent to StatsD. Valid metric types\r
+                               are 'g' for gauge, 'c' for counter, 'ms' for timer, and 's' for\r
+                               sets.</para>\r
+                       </parameter>\r
+                       <parameter name="statistic_name" required="true">\r
+                               <para>The name of the variable to be sent to StatsD. Statistic\r
+                               names cannot contain the pipe (|) character.</para>\r
+                       </parameter>\r
+                       <parameter name="value" required="true">\r
+                               <para>The value of the variable to be sent to StatsD. Values\r
+                               must be numeric. Values for gauge and counter metrics can be\r
+                               sent with a '+' or '-' to update a value after the value has\r
+                               been initialized. Only counters can be initialized as negative.\r
+                               Sets can send a string as the value parameter, but the string\r
+                               cannot contain the pipe character.</para>\r
+                       </parameter>\r
+                       <parameter name="sample_rate">\r
+                               <para>The value of the sample rate to be sent to StatsD. Sample\r
+                               rates less than or equal to 0 will never be sent and sample rates\r
+                               greater than or equal to 1 will always be sent. Any rate\r
+                               between 1 and 0 will be compared to a randomly generated value,\r
+                               and if it is greater than the random value, it will be sent.</para>\r
+                       </parameter>\r
+               </syntax>\r
+               <description>\r
+                       <para>This dialplan application sends statistics to the StatsD\r
+                       server specified inside of <literal>statsd.conf</literal>.</para>\r
+               </description>\r
+       </application>\r
+ ***/\r
+\r
+static const char app[] = "StatsD";\r
+\r
+/*!\r
+ * \brief Check to ensure the value is within the allowed range.\r
+ *\r
+ * \param value The value of the statistic to be sent to StatsD.\r
+ *\r
+ * This function checks to see if the value given to the StatsD daialplan\r
+ * application is within the allowed range of [-2^63, 2^63] as specified by StatsD.\r
+ *\r
+ * \retval zero on success.\r
+ * \retval 1 on error.\r
+ */\r
+static int value_in_range(const char *value) {\r
+       double numerical_value = strtod(value, NULL);\r
+\r
+       if (numerical_value < pow(-2, 63) || numerical_value > pow(2, 63)) {\r
+               ast_log(AST_LOG_WARNING, "Value %lf out of range!\n", numerical_value);\r
+               return 1;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+/*!\r
+ * \brief Check to ensure the value is within the allowed range.\r
+ *\r
+ * \param value The value of the statistic to be sent to StatsD.\r
+ *\r
+ * This function checks to see if the value given to the StatsD daialplan\r
+ * application is within the allowed range of [0, 2^64] as specified by StatsD.\r
+ *\r
+ * \retval zero on success.\r
+ * \retval 1 on error.\r
+ */\r
+static int non_neg_value_range(const char *value) {\r
+       double numerical_value = strtod(value, NULL);\r
+\r
+       if (numerical_value < 0 || numerical_value > pow(2, 64)) {\r
+               ast_log(AST_LOG_WARNING, "Value %lf out of range!\n", numerical_value);\r
+               return 1;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+/*!\r
+ * \brief Check to ensure the metric type is a valid metric type.\r
+ *\r
+ * \param metric The metric type to be sent to StatsD.\r
+ *\r
+ * This function checks to see if the metric type given to the StatsD dialplan\r
+ * is a valid metric type. Metric types are determined by StatsD.\r
+ *\r
+ * \retval zero on success.\r
+ * \retval 1 on error.\r
+ */\r
+static int validate_metric(const char *metric)\r
+{\r
+       const char *valid_metrics[] = {"g","s","ms","c"};\r
+       int i;\r
+\r
+       if (ast_strlen_zero(metric)) {\r
+               ast_log(AST_LOG_ERROR, "Missing metric type argument.\n");\r
+               return 1;\r
+       }\r
+\r
+       for (i = 0; i < ARRAY_LEN(valid_metrics); i++) {\r
+               if (!strcmp(valid_metrics[i], metric)) {\r
+                       return 0;\r
+               }\r
+       }\r
+\r
+       ast_log(AST_LOG_ERROR, "Invalid metric type %s.\n", metric);\r
+\r
+       return 1;\r
+}\r
+\r
+/*!\r
+ * \brief Check to ensure that a numeric value is valid.\r
+ *\r
+ * \param numeric_value The numeric value to be sent to StatsD.\r
+ *\r
+ * This function checks to see if a number to be sent to StatsD is actually\r
+ * a valid number. One decimal is allowed.\r
+ *\r
+ * \retval zero on success.\r
+ * \retval 1 on error.\r
+ */\r
+static int validate_numeric(const char *numeric_value) {\r
+       const char *num;\r
+       int decimal_counter = 0;\r
+\r
+       num = numeric_value;\r
+       while (*num) {\r
+               if (!isdigit(*num++)) {\r
+                       if (strstr(numeric_value, ".") != NULL && decimal_counter == 0) {\r
+                               decimal_counter++;\r
+                               continue;\r
+                       }\r
+                       ast_log(AST_LOG_ERROR, "%s is not a number!\n", numeric_value);\r
+                       return 1;\r
+               }\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+/*!\r
+ * \brief Determines the actual value of a number by looking for a leading + or -.\r
+ *\r
+ * \param raw_value The entire numeric string to be sent to StatsD.\r
+ *\r
+ * This function checks to see if the numeric string contains valid characters\r
+ * and then isolates the actual number to be sent for validation. Returns the\r
+ * result of the numeric validation.\r
+ *\r
+ * \retval zero on success.\r
+ * \retval 1 on error.\r
+ */\r
+static int determine_actual_value(const char *raw_value) {\r
+       const char *actual_value;\r
+\r
+       if ((raw_value[0] == '+') || (raw_value[0] == '-')) {\r
+               actual_value = &raw_value[1];\r
+               if (ast_strlen_zero(actual_value)) {\r
+                       ast_log(AST_LOG_ERROR, "Value argument %s only contains a sign"\r
+                               " operator.\n", raw_value);\r
+                       return 1;\r
+               }\r
+       } else {\r
+               actual_value = &raw_value[0];\r
+       }\r
+\r
+       return validate_numeric(actual_value);\r
+}\r
+\r
+/*!\r
+ * \brief Check to ensure the statistic name is valid.\r
+ *\r
+ * \param name The variable name to be sent to StatsD.\r
+ *\r
+ * This function checks to see if the statistic name given to the StatsD\r
+ * dialplan application is valid by ensuring that the name does not have any\r
+ * invalid characters.\r
+ *\r
+ * \retval zero on success.\r
+ * \retval 1 on error.\r
+ */\r
+static int validate_name(const char *name)\r
+{\r
+       if (ast_strlen_zero(name) || (strstr(name, "|") != NULL)) {\r
+               ast_log(AST_LOG_ERROR, "Statistic name %s is missing or contains a pipe (|)"\r
+                       " character.\n", name);\r
+               return 1;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+\r
+/*!\r
+ * \brief Calls the appropriate functions to validate a gauge metric.\r
+ *\r
+ * \param statistic_name The statistic name to be sent to StatsD.\r
+ * \param value The value to be sent to StatsD.\r
+ *\r
+ * This function calls other validating functions to correctly validate each\r
+ * input based on allowable input for a gauge metric.\r
+ *\r
+ * \retval zero on success.\r
+ * \retval 1 on error.\r
+ */\r
+static int validate_metric_type_gauge(const char *statistic_name, const char *value) {\r
+\r
+       if (ast_strlen_zero(value)) {\r
+               ast_log(AST_LOG_ERROR, "Missing value argument.\n");\r
+               return 1;\r
+       }\r
+\r
+       if (validate_name(statistic_name) || determine_actual_value(value)\r
+               || value_in_range(value)) {\r
+               return 1;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+/*!\r
+ * \brief Calls the appropriate functions to validate a counter metric.\r
+ *\r
+ * \param statistic_name The statistic name to be sent to StatsD.\r
+ * \param value The value to be sent to StatsD.\r
+ *\r
+ * This function calls other validating functions to correctly validate each\r
+ * input based on allowable input for a counter metric.\r
+ *\r
+ * \retval zero on success.\r
+ * \retval 1 on error.\r
+ */\r
+static int validate_metric_type_counter(const char *statistic_name, const char *value) {\r
+\r
+       if (ast_strlen_zero(value)) {\r
+               ast_log(AST_LOG_ERROR, "Missing value argument.\n");\r
+               return 1;\r
+       }\r
+\r
+       if (validate_name(statistic_name) || determine_actual_value(value)\r
+               || value_in_range(value)) {\r
+               return 1;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+/*!\r
+ * \brief Calls the appropriate functions to validate a timer metric.\r
+ *\r
+ * \param statistic_name The statistic name to be sent to StatsD.\r
+ * \param value The value to be sent to StatsD.\r
+ *\r
+ * This function calls other validating functions to correctly validate each\r
+ * input based on allowable input for a timer metric.\r
+ *\r
+ * \retval zero on success.\r
+ * \retval 1 on error.\r
+ */\r
+static int validate_metric_type_timer(const char *statistic_name, const char *value) {\r
+\r
+       if (ast_strlen_zero(value)) {\r
+               ast_log(AST_LOG_ERROR, "Missing value argument.\n");\r
+               return 1;\r
+       }\r
+\r
+       if (validate_name(statistic_name) || validate_numeric(value)\r
+               || non_neg_value_range(value)) {\r
+               return 1;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+/*!\r
+ * \brief Calls the appropriate functions to validate a set metric.\r
+ *\r
+ * \param statistic_name The statistic name to be sent to StatsD.\r
+ * \param value The value to be sent to StatsD.\r
+ *\r
+ * This function calls other validating functions to correctly validate each\r
+ * input based on allowable input for a set metric.\r
+ *\r
+ * \retval zero on success.\r
+ * \retval 1 on error.\r
+ */\r
+static int validate_metric_type_set(const char *statistic_name, const char *value) {\r
+       if (ast_strlen_zero(value)) {\r
+               ast_log(AST_LOG_ERROR, "Missing value argument.\n");\r
+               return 1;\r
+       }\r
+\r
+       if (validate_name(statistic_name)) {\r
+               return 1;\r
+       }\r
+\r
+       if (strstr(value, "|") != NULL) {\r
+               ast_log(AST_LOG_ERROR, "Pipe (|) character is not allowed for value %s"\r
+                       " in a set metric.\n", value);\r
+               return 1;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+static int statsd_exec(struct ast_channel *chan, const char *data)\r
+{\r
+       char *stats;\r
+       double numerical_rate = 1.0;\r
+\r
+       AST_DECLARE_APP_ARGS(args,\r
+                       AST_APP_ARG(metric_type);\r
+                       AST_APP_ARG(statistic_name);\r
+                       AST_APP_ARG(value);\r
+                       AST_APP_ARG(sample_rate);\r
+       );\r
+\r
+       if (!data) {\r
+               ast_log(AST_LOG_ERROR, "No parameters were provided. Correct format is "\r
+                       "StatsD(metric_type,statistic_name,value[,sample_rate]). Sample rate is the "\r
+                       "only optional parameter.\n");\r
+               return 1;\r
+       }\r
+\r
+       stats = ast_strdupa(data);\r
+       AST_STANDARD_APP_ARGS(args, stats);\r
+\r
+       if (validate_metric(args.metric_type)) {\r
+               return 1;\r
+       }\r
+\r
+       if (!strcmp(args.metric_type, "g")) {\r
+               if (validate_metric_type_gauge(args.statistic_name, args.value)) {\r
+                       ast_log(AST_LOG_ERROR, "Invalid input for a gauge metric.\n");\r
+                       return 1;\r
+               }\r
+       }\r
+       else if (!strcmp(args.metric_type, "c")) {\r
+               if (validate_metric_type_counter(args.statistic_name, args.value)) {\r
+                       ast_log(AST_LOG_ERROR, "Invalid input for a counter metric.\n");\r
+                       return 1;\r
+               }\r
+       }\r
+       else if (!strcmp(args.metric_type, "ms")) {\r
+               if (validate_metric_type_timer(args.statistic_name, args.value)) {\r
+                       ast_log(AST_LOG_ERROR, "Invalid input for a timer metric.\n");\r
+                       return 1;\r
+               }\r
+       }\r
+       else if (!strcmp(args.metric_type, "s")) {\r
+               if (validate_metric_type_set(args.statistic_name, args.value)) {\r
+                       ast_log(AST_LOG_ERROR, "Invalid input for a set metric.\n");\r
+                       return 1;\r
+               }\r
+       }\r
+\r
+       if (args.sample_rate) {\r
+\r
+               if (validate_numeric(args.sample_rate)) {\r
+                       return 1;\r
+               }\r
+\r
+               numerical_rate = strtod(args.sample_rate, NULL);\r
+       }\r
+\r
+       ast_statsd_log_string(args.statistic_name, args.metric_type, args.value,\r
+               numerical_rate);\r
+\r
+       return 0;\r
+}\r
+\r
+static int unload_module(void)\r
+{\r
+       return ast_unregister_application(app);\r
+}\r
+\r
+static int load_module(void)\r
+{\r
+       return ast_register_application_xml(app, statsd_exec);\r
+}\r
+\r
+AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "StatsD Dialplan Application");\r
index f2f7bad..cd55254 100644 (file)
@@ -48,7 +48,6 @@
 
 /*** MODULEINFO
        <defaultenabled>yes</defaultenabled>
-       <conflict>res_mwi_external</conflict>
        <use type="module">res_adsi</use>
        <use type="module">res_smdi</use>
        <support_level>core</support_level>
@@ -14702,10 +14701,14 @@ static int unload_module(void)
  *
  * Module loading including tests for configuration or dependencies.
  * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
- * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
- * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the 
- * configuration file or other non-critical problem return 
- * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
+ * or AST_MODULE_LOAD_SUCCESS.
+ *
+ * If a dependency, allocation or environment variable fails tests, return AST_MODULE_LOAD_FAILURE.
+ *
+ * If the module can't load the configuration file, can't register as a provider or
+ * has another issue not fatal to Asterisk itself, return AST_MODULE_LOAD_DECLINE.
+ *
+ * On success return AST_MODULE_LOAD_SUCCESS.
  */
 static int load_module(void)
 {
@@ -14714,7 +14717,7 @@ static int load_module(void)
        umask(my_umask);
 
        if (!(inprocess_container = ao2_container_alloc(573, inprocess_hash_fn, inprocess_cmp_fn))) {
-               return AST_MODULE_LOAD_DECLINE;
+               return AST_MODULE_LOAD_FAILURE;
        }
 
        /* compute the location of the voicemail spool directory */
@@ -14724,8 +14727,10 @@ static int load_module(void)
                ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
        }
 
-       if ((res = load_config(0)))
-               return res;
+       if ((res = load_config(0))) {
+               unload_module();
+               return AST_MODULE_LOAD_DECLINE;
+       }
 
        res = ast_register_application_xml(app, vm_exec);
        res |= ast_register_application_xml(app2, vm_execmain);
@@ -14746,10 +14751,26 @@ static int load_module(void)
        res |= AST_TEST_REGISTER(test_voicemail_vm_info);
 #endif
 
-       res |= ast_vm_register(&vm_table);
-       res |= ast_vm_greeter_register(&vm_greeter_table);
        if (res) {
-               return res;
+               ast_log(LOG_ERROR, "Failure registering applications, functions or tests\n");
+               unload_module();
+               return AST_MODULE_LOAD_DECLINE;
+       }
+
+       /* ast_vm_register may return DECLINE if another module registered for vm */
+       res = ast_vm_register(&vm_table);
+       if (res) {
+               ast_log(LOG_ERROR, "Failure registering as a voicemail provider\n");
+               unload_module();
+               return AST_MODULE_LOAD_DECLINE;
+       }
+
+       /* ast_vm_greeter_register may return DECLINE if another module registered as a greeter */
+       res = ast_vm_greeter_register(&vm_greeter_table);
+       if (res) {
+               ast_log(LOG_ERROR, "Failure registering as a greeter provider\n");
+               unload_module();
+               return AST_MODULE_LOAD_DECLINE;
        }
 
        ast_cli_register_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
@@ -14762,7 +14783,7 @@ static int load_module(void)
        ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
        ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
 
-       return res;
+       return AST_MODULE_LOAD_SUCCESS;
 }
 
 static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context) 
index 617ca66..3c20e97 100644 (file)
@@ -95,7 +95,7 @@ static rc_handle *rh = NULL;
 
 #define RADIUS_BACKEND_NAME "CEL Radius Logging"
 
-#define ADD_VENDOR_CODE(x,y) (rc_avpair_add(rh, send, x, &y, strlen(y), VENDOR_CODE))
+#define ADD_VENDOR_CODE(x,y) (rc_avpair_add(rh, send, x, (void *)y, strlen(y), VENDOR_CODE))
 
 static int build_radius_record(VALUE_PAIR **send, struct ast_cel_event_record *record)
 {
@@ -176,7 +176,7 @@ static int build_radius_record(VALUE_PAIR **send, struct ast_cel_event_record *r
        /* Setting Acct-Session-Id & User-Name attributes for proper generation
           of Acct-Unique-Session-Id on server side */
        /* Channel */
-       if (!rc_avpair_add(rh, send, PW_USER_NAME, &record->channel_name,
+       if (!rc_avpair_add(rh, send, PW_USER_NAME, (void *)record->channel_name,
                        strlen(record->channel_name), 0)) {
                return -1;
        }
index 42ccbd5..af44de9 100644 (file)
@@ -2236,6 +2236,14 @@ static struct chan_iax2_pvt *new_iax(struct ast_sockaddr *addr, const char *host
                return NULL;
        }
 
+       tmp->pingid = -1;
+       tmp->lagid = -1;
+       tmp->autoid = -1;
+       tmp->authid = -1;
+       tmp->initid = -1;
+       tmp->keyrotateid = -1;
+       tmp->jbid = -1;
+
        if (ast_string_field_init(tmp, 32)) {
                ao2_ref(tmp, -1);
                tmp = NULL;
@@ -2243,18 +2251,11 @@ static struct chan_iax2_pvt *new_iax(struct ast_sockaddr *addr, const char *host
        }
 
        tmp->prefs = prefs_global;
-       tmp->pingid = -1;
-       tmp->lagid = -1;
-       tmp->autoid = -1;
-       tmp->authid = -1;
-       tmp->initid = -1;
-       tmp->keyrotateid = -1;
 
        ast_string_field_set(tmp,exten, "s");
        ast_string_field_set(tmp,host, host);
 
        tmp->jb = jb_new();
-       tmp->jbid = -1;
        jbconf.max_jitterbuf = maxjitterbuffer;
        jbconf.resync_threshold = resyncthreshold;
        jbconf.max_contig_interp = maxjitterinterps;
index c98be35..32291e5 100644 (file)
@@ -162,11 +162,18 @@ static enum ast_rtp_glue_result chan_pjsip_get_rtp_peer(struct ast_channel *chan
        struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
        struct chan_pjsip_pvt *pvt;
        struct ast_sip_endpoint *endpoint;
+       struct ast_datastore *datastore;
 
        if (!channel || !channel->session || !(pvt = channel->pvt) || !pvt->media[SIP_MEDIA_AUDIO]->rtp) {
                return AST_RTP_GLUE_RESULT_FORBID;
        }
 
+       datastore = ast_sip_session_get_datastore(channel->session, "t38");
+       if (datastore) {
+               ao2_ref(datastore, -1);
+               return AST_RTP_GLUE_RESULT_FORBID;
+       }
+
        endpoint = channel->session->endpoint;
 
        *instance = pvt->media[SIP_MEDIA_AUDIO]->rtp;
index fa4b864..9e87027 100644 (file)
@@ -997,9 +997,9 @@ static struct ao2_container *threadt;
 static struct ao2_container *peers;
 static struct ao2_container *peers_by_ip;
 
-/*! \brief  A bogus peer, to be used when authentication should fail */
-static struct sip_peer *bogus_peer;
-/*! \brief  We can recognise the bogus peer by this invalid MD5 hash */
+/*! \brief A bogus peer, to be used when authentication should fail */
+static AO2_GLOBAL_OBJ_STATIC(g_bogus_peer);
+/*! \brief We can recognize the bogus peer by this invalid MD5 hash */
 #define BOGUS_PEER_MD5SECRET "intentionally_invalid_md5_string"
 
 /*! \brief  The register list: Other SIP proxies we register with and receive calls from */
@@ -1399,6 +1399,7 @@ static char *remove_uri_parameters(char *uri);
 static int get_refer_info(struct sip_pvt *transferer, struct sip_request *outgoing_req);
 static int get_also_info(struct sip_pvt *p, struct sip_request *oreq);
 static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req);
+static int use_reason_header(struct sip_pvt *pvt, struct sip_request *req);
 static int set_address_from_contact(struct sip_pvt *pvt);
 static void check_via(struct sip_pvt *p, const struct sip_request *req);
 static int get_rpid(struct sip_pvt *p, struct sip_request *oreq);
@@ -1709,6 +1710,7 @@ static int publish_expire(const void *data)
        ast_assert(esc != NULL);
 
        ao2_unlink(esc->compositor, esc_entry);
+       esc_entry->sched_id = -1;
        ao2_ref(esc_entry, -1);
        return 0;
 }
@@ -1741,6 +1743,11 @@ static struct sip_esc_entry *create_esc_entry(struct event_state_compositor *esc
        /* Bump refcount for scheduler */
        ao2_ref(esc_entry, +1);
        esc_entry->sched_id = ast_sched_add(sched, expires_ms, publish_expire, esc_entry);
+       if (esc_entry->sched_id == -1) {
+               ao2_ref(esc_entry, -1);
+               ao2_ref(esc_entry, -1);
+               return NULL;
+       }
 
        /* Note: This links the esc_entry into the ESC properly */
        create_new_sip_etag(esc_entry, 0);
@@ -4750,6 +4757,11 @@ static int sip_queryoption(struct ast_channel *chan, int option, void *data, int
        struct sip_pvt *p = (struct sip_pvt *) ast_channel_tech_pvt(chan);
        char *cp;
 
+       if (!p) {
+               ast_debug(1, "Attempt to Ref a null pointer. Sip private structure is gone!\n");
+               return -1;
+       }
+
        sip_pvt_lock(p);
 
        switch (option) {
@@ -9358,6 +9370,9 @@ static int sip_register(const char *value, int lineno)
                return -1;
        }
 
+       reg->expire = -1;
+       reg->timeout = -1;
+
        if (ast_string_field_init(reg, 256)) {
                ao2_t_ref(reg, -1, "failed to string_field_init, drop reg");
                return -1;
@@ -9431,6 +9446,8 @@ static int sip_subscribe_mwi(const char *value, int lineno)
                return -1;
        }
 
+       mwi->resub = -1;
+
        if (ast_string_field_init(mwi, 256)) {
                ao2_t_ref(mwi, -1, "failed to string_field_init, drop mwi");
                return -1;
@@ -9445,7 +9462,6 @@ static int sip_subscribe_mwi(const char *value, int lineno)
        }
        ast_string_field_set(mwi, hostname, hostname);
        ast_string_field_set(mwi, mailbox, mailbox);
-       mwi->resub = -1;
        mwi->portno = portnum;
        mwi->transport = transport;
 
@@ -10618,7 +10634,11 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
        /* Setup audio address and port */
        if (p->rtp) {
                if (sa && portno > 0) {
-                       start_ice(p->rtp, (req->method != SIP_RESPONSE) ? 0 : 1);
+                       /* Start ICE negotiation here, only when it is response, and setting that we are conrolling agent,
+                          as we are offerer */
+                       if (req->method == SIP_RESPONSE) {
+                               start_ice(p->rtp, 1);
+                       }
                        ast_sockaddr_set_port(sa, portno);
                        ast_rtp_instance_set_remote_address(p->rtp, sa);
                        if (debug) {
@@ -13392,6 +13412,11 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
                if (!doing_directmedia) {
                        if (ast_test_flag(&p->flags[2], SIP_PAGE3_ICE_SUPPORT)) {
                                add_ice_to_sdp(p->rtp, &a_audio);
+                               /* Start ICE negotiation, and setting that we are controlled agent,
+                                  as this is response to offer */
+                               if (resp->method == SIP_RESPONSE) {
+                                       start_ice(p->rtp, 0);
+                               }
                        }
 
                        add_dtls_to_sdp(p->rtp, &a_audio);
@@ -16111,6 +16136,49 @@ static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req)
        return TRUE;
 }
 
+/*!
+ * \brief Parses SIP reason header according to RFC3326 and sets channel's hangupcause if configured so
+ *  and header present
+ *
+ * \note This is used in BYE and CANCEL request and SIP response, but according to RFC3326 it could
+ *       appear in any request, but makes not a lot of sense in others than BYE or CANCEL.
+ *       Currently only implemented for Q.850 status codes.
+ * \retval 0 success
+ * \retval -1 on failure or if not configured
+ */
+static int use_reason_header(struct sip_pvt *pvt, struct sip_request *req)
+{
+       int ret, cause;
+       const char *rp, *rh;
+
+       if (!pvt->owner) {
+               return -1;
+       }
+
+       if (!ast_test_flag(&pvt->flags[1], SIP_PAGE2_Q850_REASON) ||
+               !(rh = sip_get_header(req, "Reason"))) {
+               return -1;
+       }
+
+       rh = ast_skip_blanks(rh);
+       if (strncasecmp(rh, "Q.850", 5)) {
+               return -1;
+       }
+
+       ret = -1;
+       cause = ast_channel_hangupcause(pvt->owner);
+       rp = strstr(rh, "cause=");
+       if (rp && sscanf(rp + 6, "%3d", &cause) == 1) {
+               ret = 0;
+               ast_channel_hangupcause_set(pvt->owner, cause & 0x7f);
+               if (req->debug) {
+                       ast_verbose("Using Reason header for cause code: %d\n",
+                                               ast_channel_hangupcause(pvt->owner));
+               }
+       }
+       return ret;
+}
+
 /*! \brief parse uri in a way that allows semicolon stripping if legacy mode is enabled
  *
  * \note This calls parse_uri which has the unexpected property that passing more
@@ -17174,8 +17242,7 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct ast_sock
        /* If we don't want username disclosure, use the bogus_peer when a user
         * is not found. */
        if (!peer && sip_cfg.alwaysauthreject && sip_cfg.autocreatepeer == AUTOPEERS_DISABLED) {
-               peer = bogus_peer;
-               sip_ref_peer(peer, "register_verify: ref the bogus_peer");
+               peer = ao2_t_global_obj_ref(g_bogus_peer, "register_verify: Get the bogus peer.");
        }
 
        if (!(peer && ast_apply_acl(peer->acl, addr, "SIP Peer ACL: "))) {
@@ -18428,6 +18495,7 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
        enum check_auth_result res;
        int debug = sip_debug_test_addr(addr);
        struct sip_peer *peer;
+       struct sip_peer *bogus_peer;
 
        if (sipmethod == SIP_SUBSCRIBE) {
                /* For subscribes, match on device name only; for other methods,
@@ -18467,8 +18535,13 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
                /* If you do mind, we use a peer that will never authenticate.
                 * This ensures that we follow the same code path as regular
                 * auth: less chance for username disclosure. */
-               peer = bogus_peer;
-               sip_ref_peer(peer, "sip_ref_peer: check_peer_ok: must ref bogus_peer so unreffing it does not fail");
+               peer = ao2_t_global_obj_ref(g_bogus_peer, "check_peer_ok: Get the bogus peer.");
+               if (!peer) {
+                       return AUTH_DONT_KNOW;
+               }
+               bogus_peer = peer;
+       } else {
+               bogus_peer = NULL;
        }
 
        /*  build_peer, called through sip_find_peer, is not able to check the
@@ -24097,27 +24170,13 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
                msg = "";
 
        sipmethod = find_sip_method(msg);
-
        owner = p->owner;
        if (owner) {
-               const char *rp = NULL, *rh = NULL;
-
                ast_channel_hangupcause_set(owner, 0);
-               if (ast_test_flag(&p->flags[1], SIP_PAGE2_Q850_REASON) && (rh = sip_get_header(req, "Reason"))) {
-                       rh = ast_skip_blanks(rh);
-                       if (!strncasecmp(rh, "Q.850", 5)) {
-                               int cause = ast_channel_hangupcause(owner);
-                               rp = strstr(rh, "cause=");
-                               if (rp && sscanf(rp + 6, "%30d", &cause) == 1) {
-                                       ast_channel_hangupcause_set(owner, cause & 0x7f);
-                                       if (req->debug)
-                                               ast_verbose("Using Reason header for cause code: %d\n", ast_channel_hangupcause(owner));
-                               }
-                       }
-               }
-
-               if (!ast_channel_hangupcause(owner))
+               if (use_reason_header(p, req)) {
+                       /* Use the SIP cause */
                        ast_channel_hangupcause_set(owner, hangup_sip2cause(resp));
+               }
        }
 
        if (p->socket.type == AST_TRANSPORT_UDP) {
@@ -26409,6 +26468,8 @@ static int handle_request_cancel(struct sip_pvt *p, struct sip_request *req)
                return 0;
        }
 
+       use_reason_header(p, req);
+
        /* At this point, we could have cancelled the invite at the same time
           as the other side sends a CANCEL. Our final reply with error code
           might not have been received by the other side before the CANCEL
@@ -26425,7 +26486,7 @@ static int handle_request_cancel(struct sip_pvt *p, struct sip_request *req)
 
        stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */
        if (p->owner) {
-               sip_queue_hangup_cause(p, 0);
+               sip_queue_hangup_cause(p, ast_channel_hangupcause(p->owner));
        } else {
                sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
        }
@@ -26604,6 +26665,7 @@ static int handle_request_bye(struct sip_pvt *p, struct sip_request *req)
                stop_session_timer(p); /* Stop Session-Timer */
        }
 
+       use_reason_header(p, req);
        if (!ast_strlen_zero(sip_get_header(req, "Also"))) {
                ast_log(LOG_NOTICE, "Client '%s' using deprecated BYE/Also transfer method.  Ask vendor to support REFER instead\n",
                        ast_sockaddr_stringify(&p->recv));
@@ -26644,7 +26706,7 @@ static int handle_request_bye(struct sip_pvt *p, struct sip_request *req)
                                ast_queue_hangup_with_cause(p->owner, AST_CAUSE_PROTOCOL_ERROR);
                }
        } else if (p->owner) {
-               sip_queue_hangup_cause(p, 0);
+               sip_queue_hangup_cause(p, ast_channel_hangupcause(p->owner));
                sip_scheddestroy_final(p, DEFAULT_TRANS_TIMEOUT);
                ast_debug(3, "Received bye, issuing owner hangup\n");
        } else {
@@ -31448,6 +31510,8 @@ static int reload_config(enum channelreloadreason reason)
        sip_cfg.peer_rtupdate = TRUE;
        global_dynamic_exclude_static = 0;      /* Exclude static peers */
        sip_cfg.tcp_enabled = FALSE;
+       sip_cfg.websocket_enabled = TRUE;
+       sip_cfg.websocket_write_timeout = AST_DEFAULT_WEBSOCKET_WRITE_TIMEOUT;
 
        /* Session-Timers */
        global_st_mode = SESSION_TIMER_MODE_ACCEPT;
@@ -32231,6 +32295,12 @@ static int reload_config(enum channelreloadreason reason)
                ast_log(LOG_ERROR, "SIP TCP Server start failed. Not listening on TCP socket.\n");
        } else {
                ast_debug(2, "SIP TCP server started\n");
+               if (sip_tcp_desc.accept_fd >= 0) {
+                       int flags = 1;
+                       if (setsockopt(sip_tcp_desc.accept_fd, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof(flags))) {
+                               ast_log(LOG_ERROR, "Error enabling TCP keep-alive on sip socket: %s\n", strerror(errno));
+                       }
+               }
        }
 
        /* Start TLS server if needed */
@@ -32251,6 +32321,13 @@ static int reload_config(enum channelreloadreason reason)
                        ast_log(LOG_ERROR, "TLS Server start failed. Not listening on TLS socket.\n");
                        sip_tls_desc.tls_cfg = NULL;
                }
+               if (sip_tls_desc.accept_fd >= 0) {
+                       int flags = 1;
+                       if (setsockopt(sip_tls_desc.accept_fd, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof(flags))) {
+                               ast_log(LOG_ERROR, "Error enabling TCP keep-alive on sip socket: %s\n", strerror(errno));
+                               sip_tls_desc.tls_cfg = NULL;
+                       }
+               }
        } else if (sip_tls_desc.tls_cfg->enabled) {
                sip_tls_desc.tls_cfg = NULL;
                ast_log(LOG_WARNING, "SIP TLS server did not load because of errors.\n");
@@ -33155,7 +33232,7 @@ static int sip_do_reload(enum channelreloadreason reason)
 /*! \brief Force reload of module from cli */
 static char *sip_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       static struct sip_peer *tmp_peer, *new_peer;
+       static struct sip_peer *new_peer;
 
        switch (cmd) {
        case CLI_INIT:
@@ -33178,13 +33255,13 @@ static char *sip_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a
        ast_mutex_unlock(&sip_reload_lock);
        restart_monitor();
 
-       tmp_peer = bogus_peer;
        /* Create new bogus peer possibly with new global settings. */
        if ((new_peer = temp_peer("(bogus_peer)"))) {
                ast_string_field_set(new_peer, md5secret, BOGUS_PEER_MD5SECRET);
                ast_clear_flag(&new_peer->flags[0], SIP_INSECURE);
-               bogus_peer = new_peer;
-               ao2_t_ref(tmp_peer, -1, "unref the old bogus_peer during reload");
+               ao2_t_global_obj_replace_unref(g_bogus_peer, new_peer,
+                       "Replacing the old bogus peer during reload.");
+               ao2_t_ref(new_peer, -1, "done with new_peer");
        } else {
                ast_log(LOG_ERROR, "Could not update the fake authentication peer.\n");
                /* You probably have bigger (memory?) issues to worry about though.. */
@@ -34435,6 +34512,8 @@ static int unload_module(void);
  */
 static int load_module(void)
 {
+       struct sip_peer *bogus_peer;
+
        ast_verbose("SIP channel loading...\n");
 
        if (STASIS_MESSAGE_TYPE_INIT(session_timeout_type)) {
@@ -34506,6 +34585,8 @@ static int load_module(void)
        /* Make sure the auth will always fail. */
        ast_string_field_set(bogus_peer, md5secret, BOGUS_PEER_MD5SECRET);
        ast_clear_flag(&bogus_peer->flags[0], SIP_INSECURE);
+       ao2_t_global_obj_replace_unref(g_bogus_peer, bogus_peer, "Set the initial bogus peer.");
+       ao2_t_ref(bogus_peer, -1, "Module load is done with the bogus peer.");
 
        /* Prepare the version that does not require DTMF BEGIN frames.
         * We need to use tricks such as memcpy and casts because the variable
@@ -34790,7 +34871,7 @@ static int unload_module(void)
                ast_debug(2, "TCP/TLS thread container did not become empty :(\n");
        }
 
-       ao2_t_cleanup(bogus_peer, "unref the bogus_peer");
+       ao2_t_global_obj_release(g_bogus_peer, "Release the bogus peer.");
 
        ao2_t_cleanup(peers, "unref the peers table");
        ao2_t_cleanup(peers_by_ip, "unref the peers_by_ip table");
index 6f56f73..da156fc 100644 (file)
@@ -1364,6 +1364,12 @@ static int gendigittimeout = 8000;
 /* How long to wait for an extra digit, if there is an ambiguous match */
 static int matchdigittimeout = 3000;
 
+/*!
+ * To apease the stupid compiler option on ast_sched_del()
+ * since we don't care about the return value.
+ */
+static int not_used;
+
 #define SUBSTATE_UNSET 0
 #define SUBSTATE_OFFHOOK 1
 #define SUBSTATE_ONHOOK 2
@@ -2262,10 +2268,10 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s)
        int instance;
        int res = -1;
 
-       if (s->auth_timeout_sched && ast_sched_del(sched, s->auth_timeout_sched)) {
-               return 0;
+       if (-1 < s->auth_timeout_sched) {
+               not_used = ast_sched_del(sched, s->auth_timeout_sched);
+               s->auth_timeout_sched = -1;
        }
-       s->auth_timeout_sched = 0;
 
        AST_LIST_LOCK(&devices);
        AST_LIST_TRAVERSE(&devices, d, list){
@@ -5548,12 +5554,12 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
 
        skinny_locksub(sub);
 
-       if (sub->dialer_sched) {
+       if (-1 < sub->dialer_sched) {
                skinny_sched_del(sub->dialer_sched, sub);
                sub->dialer_sched = -1;
        }
 
-       if (state != SUBSTATE_RINGIN && sub->aa_sched) {
+       if (state != SUBSTATE_RINGIN && -1 < sub->aa_sched) {
                skinny_sched_del(sub->aa_sched, sub);
                sub->aa_sched = -1;
                sub->aa_beep = 0;
@@ -5571,6 +5577,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
                        sub->cfwd_sched = -1;
                } else if (state == SUBSTATE_ONHOOK) {
                        skinny_sched_del(sub->cfwd_sched, sub);
+                       sub->cfwd_sched = -1;
                }
        }
 
@@ -6170,9 +6177,7 @@ static int handle_ip_port_message(struct skinny_req *req, struct skinnysession *
 
 static void handle_keepalive_message(struct skinny_req *req, struct skinnysession *s)
 {
-       if (ast_sched_del(sched, s->keepalive_timeout_sched)) {
-               return;
-       }
+       not_used = ast_sched_del(sched, s->keepalive_timeout_sched);
 
 #ifdef AST_DEVMODE
        {
@@ -6238,7 +6243,7 @@ static int handle_keypad_button_message(struct skinny_req *req, struct skinnyses
        }
 
        if ((sub->owner && ast_channel_state(sub->owner) <  AST_STATE_UP)) {
-               if (sub->dialer_sched && !skinny_sched_del(sub->dialer_sched, sub)) {
+               if (-1 < sub->dialer_sched && !skinny_sched_del(sub->dialer_sched, sub)) {
                        SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %u - Got a digit and not timed out, so try dialing\n", sub->callid);
                        sub->dialer_sched = -1;
                        len = strlen(sub->exten);
@@ -7075,7 +7080,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
        case SOFTKEY_BKSPC:
                SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_BKSPC from %s, inst %d, callref %d\n",
                        d->name, instance, callreference);
-               if (sub->dialer_sched && !skinny_sched_del(sub->dialer_sched, sub)) {
+               if (-1 < sub->dialer_sched && !skinny_sched_del(sub->dialer_sched, sub)) {
                        size_t len;
                        sub->dialer_sched = -1;
                        len = strlen(sub->exten);
@@ -7415,7 +7420,7 @@ static int skinny_noauth_cb(const void *data)
 {
        struct skinnysession *s = (struct skinnysession *)data;
        ast_log(LOG_WARNING, "Skinny Client failed to authenticate in %d seconds (SCHED %d)\n", auth_timeout, s->auth_timeout_sched);
-       s->auth_timeout_sched = 0;
+       s->auth_timeout_sched = -1;
        end_session(s);
        return 0;
 }
@@ -7424,7 +7429,7 @@ static int skinny_nokeepalive_cb(const void *data)
 {
        struct skinnysession *s = (struct skinnysession *)data;
        ast_log(LOG_WARNING, "Skinny Client failed to send keepalive in last %d seconds (SCHED %d)\n", keep_alive*3, s->keepalive_timeout_sched);
-       s->keepalive_timeout_sched = 0;
+       s->keepalive_timeout_sched = -1;
        end_session(s);
        return 0;
 }
@@ -7442,11 +7447,13 @@ static void skinny_session_cleanup(void *data)
                ast_mutex_unlock(&s->lock);
        }
 
-       if (s->auth_timeout_sched && !ast_sched_del(sched, s->auth_timeout_sched)) {
-               s->auth_timeout_sched = 0;
+       if (-1 < s->auth_timeout_sched) {
+               not_used = ast_sched_del(sched, s->auth_timeout_sched);
+               s->auth_timeout_sched = -1;
        }
-       if (s->keepalive_timeout_sched && !ast_sched_del(sched, s->keepalive_timeout_sched)) {
-               s->keepalive_timeout_sched = 0;
+       if (-1 < s->keepalive_timeout_sched) {
+               not_used = ast_sched_del(sched, s->keepalive_timeout_sched);
+               s->keepalive_timeout_sched = -1;
        }
 
        if (d) {
@@ -7651,6 +7658,8 @@ static void *accept_thread(void *ignore)
                ast_mutex_init(&s->lock);
                memcpy(&s->sin, &sin, sizeof(sin));
                s->fd = as;
+               s->auth_timeout_sched = -1;
+               s->keepalive_timeout_sched = -1;
 
                if (ast_pthread_create(&s->t, NULL, skinny_session, s)) {
                        destroy_session(s);
index a3964b0..56d04b2 100644 (file)
@@ -79,13 +79,17 @@ int sip_parse_register_line(struct sip_registry *reg, int default_expiry, const
                AST_APP_ARG(port);
        );
 
-       if (!value) {
+       if (!reg) {
                return -1;
        }
 
-       if (!reg) {
+       reg->expire = -1;
+       reg->timeout = -1;
+
+       if (!value) {
                return -1;
        }
+
        ast_copy_string(buf, value, sizeof(buf));
 
        /*! register => [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry]
@@ -261,7 +265,6 @@ int sip_parse_register_line(struct sip_registry *reg, int default_expiry, const
        ast_string_field_set(reg, regdomain, ast_strip_quoted(S_OR(user2.domain, ""), "\"", "\""));
 
        reg->transport = transport;
-       reg->timeout = reg->expire = -1;
        reg->portno = portnum;
        reg->regdomainport = domainport;
        reg->callid_valid = FALSE;
index 67e9ce2..1c73bf3 100644 (file)
@@ -38,7 +38,7 @@ ASTERISK_REGISTER_FILE()
 #include "asterisk/translate.h"
 #include "asterisk/slin.h"
 
-#define OUTBUF_SIZE   8096
+#define OUTBUF_SAMPLES   11520
 
 static struct ast_translator *translators;
 static int trans_size;
@@ -114,7 +114,7 @@ static void resamp_destroy(struct ast_trans_pvt *pvt)
 static int resamp_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
 {
        SpeexResamplerState *resamp_pvt = pvt->pvt;
-       unsigned int out_samples = (OUTBUF_SIZE / sizeof(int16_t)) - pvt->samples;
+       unsigned int out_samples = OUTBUF_SAMPLES - pvt->samples;
        unsigned int in_samples;
 
        if (!f->datalen) {
@@ -167,8 +167,8 @@ static int load_module(void)
                        translators[idx].destroy = resamp_destroy;
                        translators[idx].framein = resamp_framein;
                        translators[idx].desc_size = 0;
-                       translators[idx].buffer_samples = (OUTBUF_SIZE / sizeof(int16_t));
-                       translators[idx].buf_size = OUTBUF_SIZE;
+                       translators[idx].buffer_samples = OUTBUF_SAMPLES;
+                       translators[idx].buf_size = (OUTBUF_SAMPLES * sizeof(int16_t));
                        memcpy(&translators[idx].src_codec, &codec_list[x], sizeof(struct ast_codec));
                        memcpy(&translators[idx].dst_codec, &codec_list[y], sizeof(struct ast_codec));
                        snprintf(translators[idx].name, sizeof(translators[idx].name), "slin %ukhz -> %ukhz",
index d7323ec..d1764b5 100644 (file)
@@ -3,17 +3,25 @@
 ;
 
 [general]
+total_analysis_time = 5000     ; Maximum time allowed for the algorithm to decide
+                               ; on whether the audio represents a HUMAN, or a MACHINE
+silence_threshold = 256                ; If the average level of noise in a sample does not reach
+                               ; this value, from a scale of 0 to 32767, then we will consider
+                               ; it to be silence.
+
+; Greeting ;
 initial_silence = 2500         ; Maximum silence duration before the greeting.
-                               ; If exceeded then MACHINE.
-greeting = 1500                        ; Maximum length of a greeting. If exceeded then MACHINE.
+                               ; If exceeded, then the result is detection as a MACHINE.
 after_greeting_silence = 800   ; Silence after detecting a greeting.
-                               ; If exceeded then HUMAN
-total_analysis_time = 5000     ; Maximum time allowed for the algorithm to decide
-                               ; on a HUMAN or MACHINE
+                               ; If exceeded, then the result is detection as a HUMAN
+greeting = 1500                        ; Maximum length of a greeting. If exceeded, then the
+                               ; result is detection as a MACHINE.
+
+; Word detection ;
 min_word_length = 100          ; Minimum duration of Voice to considered as a word
+maximum_word_length = 5000     ; Maximum duration of a single Voice utterance allowed.
 between_words_silence = 50     ; Minimum duration of silence after a word to consider
                                ; the audio what follows as a new word
-maximum_number_of_words = 3    ; Maximum number of words in the greeting.
-                               ; If exceeded then MACHINE
-maximum_word_length = 5000      ; Maximum duration of a single Voice utterance allowed.
-silence_threshold = 256
+
+maximum_number_of_words = 2    ; Maximum number of words in the greeting
+                               ; If exceeded, then the result is detection as a MACHINE
index aeb25c0..223d693 100644 (file)
@@ -2,7 +2,7 @@
 ; Sample Call Features (transfer, monitor/mixmonitor, etc) configuration
 ;
 
-; Asterisk 12 Note - All parking lot configuration is now done in res_parking.conf
+; Note: From Asterisk 12 - All parking lot configuration is now done in res_parking.conf
 
 [general]
 ;transferdigittimeout => 3      ; Number of seconds to wait between digits when transferring a call
index 9302fb2..363ef85 100644 (file)
 ;disallow=      ; Media Codec s to disallow (default: "")
 ;dtmf_mode=rfc4733      ; DTMF mode (default: "rfc4733")
 ;media_address=         ; IP address used in SDP for media handling (default: "")
+;bind_rtp_to_media_address=     ; Bind the RTP session to the media_address.
+                                ; This causes all RTP packets to be sent from
+                                ; the specified address. (default: "no")
 ;force_rport=yes        ; Force use of return port (default: "yes")
 ;ice_support=no ; Enable the ICE mechanism to help traverse NAT (default: "no")
 ;identify_by=username   ; Way s for Endpoint to be identified (default:
                             ; startup that qualifies should be attempted on all
                             ; contacts.  If greater than the qualify_frequency
                             ; for an aor, qualify_frequency will be used instead.
+; If regcontext is specified, Asterisk will dynamically create and destroy a
+; NoOp priority 1 extension for a given endpoint who registers or unregisters
+; with us. The extension added is the name of the endpoint.
+;regcontext=sipregistrations
 
 ; MODULE PROVIDING BELOW SECTION(S): res_pjsip_acl
 ;==========================ACL SECTION OPTIONS=========================
index 509e29f..bc51839 100755 (executable)
--- a/configure
+++ b/configure
@@ -13653,7 +13653,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
@@ -13699,7 +13699,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
@@ -13723,7 +13723,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
@@ -13768,7 +13768,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
@@ -13792,7 +13792,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
index 7f69430..021d0d1 100644 (file)
@@ -218,17 +218,13 @@ if test ! x"${UNAME}" = xNo; then
 fi
 AC_SUBST(PBX_OSREV)
 
-AH_TOP(
-#ifndef ASTERISK_AUTOCONFIG_H
+AH_TOP([#ifndef ASTERISK_AUTOCONFIG_H
 #define ASTERISK_AUTOCONFIG_H
+/* IWYU pragma: private, include "asterisk.h" */
 
-#include "asterisk/buildopts.h"
+#include "asterisk/buildopts.h" /* IWYU pragma: export */])
 
-)
-
-AH_BOTTOM(
-#endif
-)
+AH_BOTTOM([#endif      /* ASTERISK_AUTOCONFIG_H */])
 
 # cross-compile checks
 if test "${cross_compiling}" = "yes";
diff --git a/contrib/ast-db-manage/config/versions/136885b81223_add_regcontext_to_pj.py b/contrib/ast-db-manage/config/versions/136885b81223_add_regcontext_to_pj.py
new file mode 100644 (file)
index 0000000..724a5e5
--- /dev/null
@@ -0,0 +1,20 @@
+"""add regcontext to pjsip
+
+Revision ID: 136885b81223
+Revises: 26d7f3bf0fa5
+Create Date: 2016-01-11 22:32:45.470522
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '136885b81223'
+down_revision = '26d7f3bf0fa5'
+
+from alembic import op
+import sqlalchemy as sa
+
+def upgrade():
+    op.add_column('ps_globals', sa.Column('regcontext', sa.String(80)))
+
+def downgrade():
+    op.drop_column('ps_globals', 'regcontext')
diff --git a/contrib/ast-db-manage/config/versions/189a235b3fd7_add_keep_alive_interval.py b/contrib/ast-db-manage/config/versions/189a235b3fd7_add_keep_alive_interval.py
new file mode 100644 (file)
index 0000000..ba972b6
--- /dev/null
@@ -0,0 +1,22 @@
+"""add_keep_alive_interval
+
+Revision ID: 189a235b3fd7
+Revises: 28ce1e718f05
+Create Date: 2015-12-16 11:23:16.994523
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '189a235b3fd7'
+down_revision = '339a3bdf53fc'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+    op.add_column('ps_globals', sa.Column('keep_alive_interval', sa.Integer))
+
+
+def downgrade():
+    op.drop_column('ps_globals', 'keep_alive_interval')
diff --git a/contrib/ast-db-manage/config/versions/26d7f3bf0fa5_add_bind_rtp_to_media_address_to_pjsip.py b/contrib/ast-db-manage/config/versions/26d7f3bf0fa5_add_bind_rtp_to_media_address_to_pjsip.py
new file mode 100644 (file)
index 0000000..e7c11da
--- /dev/null
@@ -0,0 +1,31 @@
+"""add bind_rtp_to_media_address to pjsip
+
+Revision ID: 26d7f3bf0fa5
+Revises: 2d078ec071b7
+Create Date: 2016-01-07 12:23:42.894400
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '26d7f3bf0fa5'
+down_revision = '2d078ec071b7'
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects.postgresql import ENUM
+
+YESNO_NAME = 'yesno_values'
+YESNO_VALUES = ['yes', 'no']
+
+def upgrade():
+    ############################# Enums ##############################
+
+    # yesno_values have already been created, so use postgres enum object
+    # type to get around "already created" issue - works okay with mysql
+    yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False)
+
+    op.add_column('ps_endpoints', sa.Column('bind_rtp_to_media_address', yesno_values))
+
+
+def downgrade():
+    op.drop_column('ps_endpoints', 'bind_rtp_to_media_address')
diff --git a/contrib/ast-db-manage/config/versions/2d078ec071b7_increaes_contact_column_size.py b/contrib/ast-db-manage/config/versions/2d078ec071b7_increaes_contact_column_size.py
new file mode 100644 (file)
index 0000000..2ade86f
--- /dev/null
@@ -0,0 +1,22 @@
+"""increaes_contact_column_size
+
+Revision ID: 2d078ec071b7
+Revises: 189a235b3fd7
+Create Date: 2015-12-16 11:26:54.218985
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '2d078ec071b7'
+down_revision = '189a235b3fd7'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+    op.alter_column('ps_aors', 'contact', type_=sa.String(255))
+
+
+def downgrade():
+    op.alter_column('ps_aors', 'contact', type_=sa.String(40))
diff --git a/contrib/ast-db-manage/config/versions/423f34ad36e2_fix_pjsip_qualify_ti.py b/contrib/ast-db-manage/config/versions/423f34ad36e2_fix_pjsip_qualify_ti.py
new file mode 100644 (file)
index 0000000..594f1eb
--- /dev/null
@@ -0,0 +1,26 @@
+"""fix pjsip qualify timeout
+
+Revision ID: 423f34ad36e2
+Revises: 136885b81223
+Create Date: 2016-01-13 21:49:21.557734
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '423f34ad36e2'
+down_revision = '136885b81223'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+    op.alter_column('ps_aors', 'qualify_timeout', type_=sa.Decimal)
+    op.alter_column('ps_contacts', 'qualify_timeout', type_=sa.Decimal)
+    pass
+
+
+def downgrade():
+    op.alter_column('ps_aors', 'qualify_timeout', type_=sa.Integer)
+    op.alter_column('ps_contacts', 'qualify_timeout', type_=sa.Integer)
+    pass
old mode 100644 (file)
new mode 100755 (executable)
index e41215f..3e0213a
@@ -3,7 +3,7 @@
 # Autosupport Version 2.1.0
 # Collect support information
 #
-# Copyright (C) 2005-2013, Digium, Inc.
+# Copyright (C) 2005-2016, Digium, Inc.
 #
 # Written by John Bigelow (support@digium.com)
 #            Charles Moye (cmoye@digium.com)
@@ -38,7 +38,7 @@ then
   -h | --help)
     echo
     echo "Digium autosupport script"
-    echo "Copyright (C) 2005-2013, Digium, Inc."
+    echo "Copyright (C) 2005-2016, Digium, Inc."
     echo "Licensed under the terms of the GNU General Public License"
     echo
     echo "usage: autosupport [prefix]"
@@ -186,7 +186,9 @@ asterisk -V >> $OUTPUT;
 echo >> $OUTPUT;
 # Add check to see if asterisk is running.
 if [ -e /var/run/asterisk.ctl ] || [ -e /var/run/asterisk/asterisk.ctl ]; then
-  for command in "core show version" "pri show version" "dahdi show version" "core show translation" \
+  for command in "core show version" "pri show version" "dahdi show version" \
+      "pjsip show version" "pjsip show buildopts" \
+      "core show translation" \
       "core show uptime" "core show settings" "core show sysinfo" "core show channels" \
       "pri show spans" "dahdi show status" "dahdi show channels" "dahdi show channel 1" \
       "pjsip show endpoints" "pjsip show registrations" "pjsip list channels" \
@@ -194,9 +196,9 @@ if [ -e /var/run/asterisk.ctl ] || [ -e /var/run/asterisk/asterisk.ctl ]; then
       "show g729" "g729 show version" "g729 show licenses" "g729 show hostid" \
       "digium_phones show version" "digium_phones show alerts" "digium_phones show applications" \
       "digium_phones show firmwares" "digium_phones show lines" "digium_phones show networks" \
-                       "digium_phones show phones" "digium_phones show sessions" "digium_phones show settings" \
+      "digium_phones show phones" "digium_phones show sessions" "digium_phones show settings" \
       "digium_phones show translations" ;
-       do
+  do
     echo "asterisk -rx \"$command\"" >> $OUTPUT;
     asterisk -rx "$command" >> $OUTPUT;
     echo >> $OUTPUT;
diff --git a/contrib/scripts/sipp-sendfax.xml b/contrib/scripts/sipp-sendfax.xml
new file mode 100644 (file)
index 0000000..a249808
--- /dev/null
@@ -0,0 +1,331 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE scenario SYSTEM "sipp.dtd">
+<scenario name="INVITE (optional auth), re-INVITE to T38 and send a Fax, Walter Doekes 2012-2013">
+
+  <!--
+
+  NOTE: Creating a sipp-sendfax.pcap is as easy as:
+  - receive a fax with asterisk
+  - get the incoming side of the spansdp.log (use 'fax set debug on',
+    check your logger.conf)
+  - feed it to spandspflow2pcap.py
+
+  NOTE: sipp-sendfax.xml requires image pcap play support in SIPp. This
+  means a version above 3.5.0, or the master git branch from
+  https://github.com/SIPp/sipp.
+
+  -->
+
+  <label id="invite"/>
+
+  <send retrans="500" start_txn="invite">
+    <![CDATA[
+
+      INVITE sip:[tel]@[remote_ip]:[remote_port] SIP/2.0
+      Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
+      From: sip:[service]@[local_ip]:[local_port];tag=[pid]SIPpTag00[call_number]
+      To: sip:[tel]@[remote_ip]:[remote_port]
+      Contact: sip:[service]@[local_ip]:[local_port]
+      Call-ID: [call_id]
+      CSeq: [cseq] INVITE
+      Max-Forwards: 70
+      Content-Type: application/sdp
+      Content-Length: [len]
+
+      v=0
+      o=- 144969 144969 IN IP[local_ip_type] [local_ip]
+      s=-
+      c=IN IP[media_ip_type] [media_ip]
+      t=0 0
+      m=audio [media_port] RTP/AVP 8 0
+      a=rtpmap:8 PCMA/8000
+      a=rtpmap:0 PCMU/8000
+
+    ]]>
+  </send>
+
+  <recv response="100" optional="true" response_txn="invite"/>
+
+  <recv response="180" optional="true" response_txn="invite"/>
+
+  <recv response="181" optional="true" response_txn="invite"/>
+
+  <recv response="183" optional="true" response_txn="invite"/>
+
+  <recv response="200" optional="true" rrs="true" response_txn="invite" next="invite-ack"/>
+
+  <recv response="401" optional="true" rrs="true" next="invite-with-auth" auth="true" rrs="true" response_txn="invite"/>
+
+  <recv response="407" auth="true" rrs="true" response_txn="invite"/>
+
+  <label id="invite-with-auth"/>
+
+  <send ack_txn="invite">
+    <![CDATA[
+
+      ACK sip:[tel]@[remote_ip]:[remote_port] SIP/2.0
+      [last_Via:]
+      [last_From:]
+      [last_To:]
+      Contact: sip:[service]@[local_ip]:[local_port]
+      Call-ID: [call_id]
+      CSeq: [cseq] ACK
+      Max-Forwards: 70
+      Content-Length: 0
+
+    ]]>
+  </send>
+
+  <send retrans="500" start_txn="invite">
+    <![CDATA[
+
+      INVITE sip:[tel]@[remote_ip]:[remote_port] SIP/2.0
+      Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
+      From: sip:[service]@[local_ip]:[local_port];tag=[pid]SIPpTag00[call_number]
+      To: sip:[tel]@[remote_ip]:[remote_port]
+      Contact: sip:[service]@[local_ip]:[local_port]
+      [authentication]
+      Call-ID: [call_id]
+      CSeq: [cseq] INVITE
+      Max-Forwards: 70
+      Content-Type: application/sdp
+      Content-Length: [len]
+
+      v=0
+      o=- 144969 144969 IN IP[local_ip_type] [local_ip]
+      s=-
+      c=IN IP[media_ip_type] [media_ip]
+      t=0 0
+      m=audio [media_port] RTP/AVP 8 0
+      a=rtpmap:8 PCMA/8000
+      a=rtpmap:0 PCMU/8000
+
+    ]]>
+  </send>
+
+  <recv response="100" response_txn="invite"/>
+
+  <recv response="180" optional="true" response_txn="invite"/>
+
+  <recv response="181" optional="true" response_txn="invite"/>
+
+  <recv response="183" optional="true" response_txn="invite"/>
+
+  <recv response="200" rrs="true" response_txn="invite"/>
+
+  <label id="invite-ack"/>
+
+  <send ack_txn="invite">
+    <![CDATA[
+
+      ACK [next_url] SIP/2.0
+      [last_Via:]
+      [routes]
+      [last_From:]
+      [last_To:]
+      Contact: sip:[service]@[local_ip]:[local_port]
+      Call-ID: [call_id]
+      CSeq: [cseq] ACK
+      Max-Forwards: 70
+      Content-Length: 0
+
+    ]]>
+  </send>
+
+  <!-- Send a bit of noise to start the RTP. You may need to use
+       the -i MY_IP command line option. -->
+  <pause milliseconds="500"/>
+
+  <nop>
+    <action>
+      <exec play_pcap_audio="g711a.pcap"/>
+    </action>
+  </nop>
+
+  <pause milliseconds="500"/>
+
+
+  <!-- *****************************************************************
+
+  Initiate re-INVITE to T38.
+
+  ****************************************************************** -->
+
+  <send start_txn="t38invite">
+    <![CDATA[
+
+      INVITE [next_url] SIP/2.0
+      Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
+      [routes]
+      [last_From:]
+      [last_To:]
+      Contact: sip:[service]@[local_ip]:[local_port]
+      Call-ID: [call_id]
+      CSeq: [cseq] INVITE
+      Max-Forwards: 70
+      Content-Type: application/sdp
+      Content-Length: [len]
+
+      v=0
+      o=- 145280 145280 IN IP[local_ip_type] [local_ip]
+      s=-
+      c=IN IP[media_ip_type] [media_ip]
+      t=0 0
+      m=image [media_port] udptl t38
+      a=T38FaxVersion:0
+      a=T38MaxBitRate:14400
+      a=T38FaxRateManagement:transferredTCF
+      a=T38FaxMaxBuffer:200
+      a=T38FaxMaxDatagram:200
+      a=T38FaxUdpEC:t38UDPRedundancy
+
+    ]]>
+  </send>
+
+  <recv response="100" optional="true" response_txn="t38invite"/>
+
+  <recv response="488" optional="true" response_txn="t38invite" next="abort"/>
+
+  <recv response="200" response_txn="t38invite"/>
+
+  <send ack_txn="t38invite">
+    <![CDATA[
+
+      ACK [next_url] SIP/2.0
+      [last_Via:]
+      [routes]
+      [last_From:]
+      [last_To:]
+      Contact: sip:[service]@[local_ip]:[local_port]
+      Call-ID: [call_id]
+      CSeq: [cseq] ACK
+      Max-Forwards: 70
+      Content-Length: 0
+
+    ]]>
+  </send>
+
+  <!-- Enable the nop/action below to replay the FAX image. You may need to use
+       the -i MY_IP command line option. -->
+  <pause milliseconds="500"/>
+
+  <nop>
+    <action>
+      <exec play_pcap_image="sipp-sendfax.pcap"/>
+    </action>
+  </nop>
+
+
+  <!-- *****************************************************************
+
+  Wait for re-INVITE back to audio.
+
+  ****************************************************************** -->
+
+  <recv request="INVITE"/>
+
+  <send retrans="500">
+    <![CDATA[
+
+      SIP/2.0 200 OK
+      [last_Via:]
+      [last_Record-Route:]
+      [last_From:]
+      [last_To:]
+      Contact: sip:[service]@[local_ip]:[local_port]
+      [last_Call-ID:]
+      [last_CSeq:]
+      Max-Forwards: 70
+      Content-Type: application/sdp
+      Content-Length: [len]
+
+      v=0
+      o=- 146312 146312 IN IP[local_ip_type] [local_ip]
+      s=-
+      c=IN IP[media_ip_type] [media_ip]
+      t=0 0
+      m=audio [media_port] RTP/AVP 8 0
+      a=rtpmap:8 PCMA/8000
+      a=rtpmap:0 PCMU/8000
+
+    ]]>
+  </send>
+
+  <recv request="ACK"/>
+
+  <recv request="BYE"/>
+
+  <send next="done">
+    <![CDATA[
+
+      SIP/2.0 200 OK
+      [last_Via:]
+      [last_Record-Route:]
+      [last_From:]
+      [last_To:]
+      Contact: sip:[service]@[local_ip]:[local_port]
+      [last_Call-ID:]
+      [last_CSeq:]
+      Content-Length: 0
+
+    ]]>
+  </send>
+
+
+  <!-- *****************************************************************
+
+  Abort the call ourselves
+
+  ****************************************************************** -->
+
+  <label id="abort"/>
+
+  <send ack_txn="t38invite">
+    <![CDATA[
+
+      ACK [next_url] SIP/2.0
+      [last_Via:]
+      [routes]
+      [last_From:]
+      [last_To:]
+      Contact: sip:[service]@[local_ip]:[local_port]
+      Call-ID: [call_id]
+      CSeq: [cseq] ACK
+      Max-Forwards: 70
+      Content-Length: 0
+
+    ]]>
+  </send>
+
+  <send start_txn="bye">
+    <![CDATA[
+
+      BYE [next_url] SIP/2.0
+      [last_Via:]
+      [routes]
+      [last_From:]
+      [last_To:]
+      Contact: sip:[service]@[local_ip]:[local_port]
+      Call-ID: [call_id]
+      CSeq: [cseq] BYE
+      Max-Forwards: 70
+      Content-Length: 0
+
+    ]]>
+  </send>
+
+  <recv response="200" response_txn="bye" next="done"/>
+
+
+  <!-- *****************************************************************
+
+  Finalize
+
+  ****************************************************************** -->
+
+  <label id="done"/>
+
+  <!-- Keep call open to be able to retransmit stuff -->
+  <timewait milliseconds="2000"/>
+
+</scenario><!-- vim: set ts=8 sw=2 sts=2 et ai: -->
diff --git a/contrib/scripts/spandspflow2pcap.log b/contrib/scripts/spandspflow2pcap.log
new file mode 100644 (file)
index 0000000..7ed0ed9
--- /dev/null
@@ -0,0 +1,605 @@
+[2015-12-02 11:55:55] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx     0: indicator no-signal
+[2015-12-02 11:55:55] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx     1: indicator ced
+[2015-12-02 11:55:58] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx     2: IFP 00
+[2015-12-02 11:55:58] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx     2: indicator no-signal
+[2015-12-02 11:55:58] FAX[13876][C-00000001] res_fax.c: FLOW T.30 No signal is present
+[2015-12-02 11:55:58] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx     3: IFP 06
+[2015-12-02 11:55:58] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx     3: indicator v21-preamble
+[2015-12-02 11:55:58] FAX[13876][C-00000001] res_fax.c: FLOW T.30 A signal is present
+[2015-12-02 11:55:58] FAX[13876][C-00000001] res_fax.c: FLOW T.30 HDLC signal status is Carrier up (-2) in state 1
+[2015-12-02 11:55:58] FAX[13876][C-00000001] res_fax.c: FLOW T.30 HDLC signal status is Framing OK (-6) in state 1
+[2015-12-02 11:55:58] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Changing from phase T30_PHASE_A_CED to T30_PHASE_B_RX
+[2015-12-02 11:55:58] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Set rx type 4
+[2015-12-02 11:55:58] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Set tx type 0
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx     4: IFP c0 01 80 00 00 ff
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx     4: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx     5: IFP c0 01 80 00 00 c0
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx     5: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx     6: IFP c0 01 80 00 00 c2
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx     6: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx     7: IFP c0 01 80 00 00 76
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx     7: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx     8: IFP c0 01 80 00 00 ee
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx     8: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx     9: IFP c0 01 80 00 00 f6
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx     9: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    10: IFP c0 01 80 00 00 76
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    10: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    11: IFP c0 01 80 00 00 d6
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    11: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    12: IFP c0 01 80 00 00 76
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    12: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    13: IFP c0 01 80 00 00 ae
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    13: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    14: IFP c0 01 80 00 00 04
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    14: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    15: IFP c0 01 80 00 00 04
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    15: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    16: IFP c0 01 80 00 00 04
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    16: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    17: IFP c0 01 80 00 00 04
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    17: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    18: IFP c0 01 80 00 00 04
+[2015-12-02 11:55:59] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    18: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    19: IFP c0 01 80 00 00 04
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    19: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    20: IFP c0 01 80 00 00 04
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    20: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    21: IFP c0 01 80 00 00 04
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    21: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    22: IFP c0 01 80 00 00 04
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    22: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    23: IFP c0 01 80 00 00 04
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    23: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    24: IFP c0 01 80 00 00 04
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    24: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    25: IFP c0 01 80 00 00 04
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    25: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    26: IFP c0 01 80 00 00 04
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    26: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    27: IFP c0 01 20
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    27: (0) data v21/hdlc-fcs-OK + 0 byte(s)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type TSI - CRC OK (clean)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop none (0 remaining)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  TSI without final frame tag
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 03 43 6e 77 6f 6e 6b 6e 75 20 20 20 20 20 20 20 20 20 20 20 20 20
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Remote gave TSI as: "unknown"
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    28: IFP c0 01 80 00 00 ff
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    28: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    29: IFP c0 01 80 00 00 c8
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    29: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    30: IFP c0 01 80 00 00 c1
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    30: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    31: IFP c0 01 80 00 00 00
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    31: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    32: IFP c0 01 80 00 00 46
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    32: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    33: IFP c0 01 80 00 00 1f
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    33: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    34: IFP c0 01 80 00 00 22
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    34: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    35: IFP c0 01 40
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    35: (0) data v21/hdlc-fcs-OK-sig-end + 0 byte(s)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type DCS - CRC OK, sig end (clean)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop none (0 remaining)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  DCS with final frame tag
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 13 83 00 62 f8 44
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx final frame in state 1
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30 DCS before DIS
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30 DCS:
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30   .... ...0= Store and forward Internet fax (T.37): Not set
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30   .... .0..= Real-time Internet fax (T.38): Not set
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30   .... 0...= 3G mobile network: Not set
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30   .... ..1.= Receive fax: Set
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30   ..10 00..= Selected data signalling rate: V.17 14400bps
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30   .1.. ....= R8x7.7lines/mm and/or 200x200pels/25.4mm: Set
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30   0... ....= 2-D coding: Not set
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30   .... ..00= Recording width: 215mm +- 1%
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30   .... 10..= Recording length: Unlimited
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30   .111 ....= Minimum scan line time: 0ms
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30   1... ....= Extension indicator: Set
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30   .... ..0.= Compressed/uncompressed mode: Compressed
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30   .... .1..= Error correction mode (ECM): ECM
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30   .... 0...= Frame size: 256 octets
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30   .1.. ....= T.6 coding: Set
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30   0... ....= Extension indicator: Not set
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Selected compression T.6 (3)
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Get document at 14400bps, modem 7
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Changing from state 1 to 7
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Start T2
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30 HDLC signal status is Carrier down (-1) in state 7
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Changing from phase T30_PHASE_B_RX to T30_PHASE_C_NON_ECM_RX
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Set rx type 0
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Set rx type 7
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Set tx type 0
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30 No signal is present
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    36: IFP 00
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    36: indicator no-signal
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    37: IFP 1e
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    37: indicator v17-14400-long-training
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30 A signal is present
+[2015-12-02 11:56:00] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop T2 (55840 remaining)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    38: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    38: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Non-ECM signal status is Training succeeded (-4) in state 7
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop none (0 remaining)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    39: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    39: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    40: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    40: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    41: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    41: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    42: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    42: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    43: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    43: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    44: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    44: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    45: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    45: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    46: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    46: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    47: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    47: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    48: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    48: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    49: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    49: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    50: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    50: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    51: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    51: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    52: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    52: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    53: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    53: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    54: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    54: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    55: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    55: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    56: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    56: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    57: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    57: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    58: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    58: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    59: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    59: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    60: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    60: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    61: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    61: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    62: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:02] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    62: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    63: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    63: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    64: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    64: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    65: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    65: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    66: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    66: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    67: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    67: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    68: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    68: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    69: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    69: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    70: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    70: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    71: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    71: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    72: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    72: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    73: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    73: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    74: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    74: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    75: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    75: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    76: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    76: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    77: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    77: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    78: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    78: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    79: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    79: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    80: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    80: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    81: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    81: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    82: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    82: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    83: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    83: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    84: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    84: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    85: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    85: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    86: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    86: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    87: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    87: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    88: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    88: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    89: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    89: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    90: IFP d0 01 e0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    90: (0) data v17-14400/t4-non-ecm-data + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    91: IFP d0 01 f0 00 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    91: (0) data v17-14400/t4-non-ecm-sig-end + 54 byte(s)
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Receive complete in phase T30_PHASE_C_NON_ECM_RX, state 7
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Non-ECM signal status is Carrier down (-1) in state 7
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Trainability (TCF) test result - 23328 total bits. longest run of zeros was 23328
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Changing from phase T30_PHASE_C_NON_ECM_RX to T30_PHASE_B_TX
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Set rx type 0
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Set tx type 4
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Changing from state 7 to 8
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Tx:  CFR with final frame tag
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Tx:  ff 13 84
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.30 No signal is present
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    92: IFP 00
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    92: indicator no-signal
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx     2: indicator no-signal
+[2015-12-02 11:56:03] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx     3: indicator v21-preamble
+[2015-12-02 11:56:04] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx     4: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:04] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx     4: IFP c0 01 80 00 00 ff
+[2015-12-02 11:56:04] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx     5: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:04] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx     5: IFP c0 01 80 00 00 c8
+[2015-12-02 11:56:04] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx     6: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:04] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx     6: IFP c0 01 80 00 00 21
+[2015-12-02 11:56:04] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Send complete in phase T30_PHASE_B_TX, state 8
+[2015-12-02 11:56:04] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx     7: (0) data v21/hdlc-fcs-OK-sig-end + 0 byte(s)
+[2015-12-02 11:56:04] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx     7: IFP c0 01 40
+[2015-12-02 11:56:04] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Send complete in phase T30_PHASE_B_TX, state 8
+[2015-12-02 11:56:04] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Changing from state 8 to 12
+[2015-12-02 11:56:04] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Changing from phase T30_PHASE_B_TX to T30_PHASE_C_ECM_RX
+[2015-12-02 11:56:04] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Set rx type 7
+[2015-12-02 11:56:04] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Set tx type 0
+[2015-12-02 11:56:04] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Start T2
+[2015-12-02 11:56:04] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx     8: indicator no-signal
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    93: IFP 1c
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    93: indicator v17-14400-short-training
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.30 A signal is present
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop T2 (51520 remaining)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    94: IFP d0 01 80 00 35 ff c0 60 00 ff ff ff ff ff ff ff ff 2b 92 8a 4c c2 9d 8b 22 38 68 23 a8 22 87 0c 8e 90 60 81 21 10 c8 ea da b1 91 d5 06 e1 38 55 04 ed b6 b5 49 7b df c2 45 90 c9
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    94: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    95: IFP d0 01 80 00 35 17 45 d1 84 54 91 74 5d 18 45 2d 17 44 55 17 45 d1 74 5d 17 45 d1 74 5d 17 45 d1 74 76 24 8b a2 e8 c2 25 08 ba 2e 8b a2 e8 ba 2e 8b a2 e8 ba 2e 8b a3 b1 24 61 17
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    95: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    96: IFP d0 01 80 00 35 44 b1 17 45 d1 74 5d 17 45 d1 74 5d 17 45 d1 75 ed b2 ba 11 1c 8c 81 51 1c ce c1 51 1c 08 23 a2 2e 88 e1 9c 8e 8a 9a 08 49 98 28 71 11 11 11 11 11 06 76 a1 11 c3
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    96: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    97: IFP d0 01 80 00 35 39 1d 04 22 22 22 22 22 24 f6 a0 a1 c4 48 a3 94 06 50 e2 22 22 22 22 22 0f a4 08 a1 d0 41 46 10 51 a1 1c 47 1b c4 60 8a 1e 84 64 75 1f 77 8c 20 a2 d3 23 a4 1a 60
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    97: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    98: IFP d0 01 80 00 2b 8a 1d a0 dd 30 8a 1d f5 50 54 30 45 0e 30 45 0f 23 a0 a3 82 28 79 1d 61 06 3d db a2 3a b5 42 0e 23 50 8a 1f 11 84 50 ed 03 5a 54 11
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    98: (0) data v17-14400/hdlc-data + 44 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    99: IFP d0 01 20
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx    99: (0) data v17-14400/hdlc-fcs-OK + 0 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type FCD - CRC OK (clean)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop none (0 remaining)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  FCD without final frame tag
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 03 06 00 ff ff ff ff ff ff ff ff d4 49 51 32 43 b9 d1 44 1c 16 c4 15 44 e1 30 71 09 06 81 84 08 13 57 5b 8d 89 ab 60 87 1c aa 20 b7 6d ad 92 de fb 43 a2 09 93 e8 a2 8b 21 2a 89 2e ba 18 a2 b4 e8 22 aa e8 a2 8b 2e ba e8 a2 8b 2e ba e8 a2 8b 2e 6e 24 d1 45 17 43 a4 10 5d 74 d1 45 17 5d 74 d1 45 17 5d 74 d1 c5 8d 24 86 e8 22 8d e8 a2 8b 2e ba e8 a2 8b 2e ba e8 a2 8b ae b7 4d 5d 88 38 31 81 8a 38 73 83 8a 38 10 c4 45 74 11 87 39 71 51 59 10 92 19 14 8e 88 88 88 88 88 60 6e 85 88 c3 9c b8 20 44 44 44 44 44 24 6f 05 85 23 12 c5 29 60 0a 47 44 44 44 44 44 f0 25 10 85 0b 82 62 08 8a 85 38 e2 d8 23 06 51 78 21 26 ae f8 ee 31 04 45 cb c4 25 58 06 51 b8 05 bb 0c 51 b8 af 0a 2a 0c a2 70 0c a2 f0 c4 05 c5 41 14 9e b8 86 60 bc db 45 5c ad 42 70 c4 0a 51 f8 88 21 0a b7 c0 5a 2a 88
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Storing ECM frame 0, length 256
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   100: IFP d0 01 80 00 35 ff c0 60 80 43 c5 25 0a 10 61 5c 10 63 41 56 1a d9 0d 04 2f b0 8a 1d 84 50 fd be de d2 d2 2a 11 1d 2e 15 dd 42 84 50 f5 23 ae d1 74 f4 28 a5 f5 7c 34 19 02 40 af
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   100: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   101: IFP d0 01 80 00 35 0c 6c 22 87 61 14 3e 11 50 10 ac 23 08 48 e8 ba ad 42 a1 e1 42 51 0c 78 8b 74 08 10 88 df 0e 18 22 87 84 50 f8 6e 11 43 bf 4a 29 74 93 8e 96 e1 14 3f bb f7 60 bd
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   101: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   102: IFP d0 01 80 00 35 84 50 ef 1a af fe 6b 0d 30 8a 1d 63 09 48 e8 22 87 56 ea f0 c8 31 6c 22 87 21 b2 24 75 8c 83 ec a0 a1 c8 6c 89 1d 48 3e ca 88 6c 86 c8 60 c1 52 32 49 35 d8 20 45
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   102: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   103: IFP d0 01 80 00 35 5a 61 06 d5 23 e8 fa 60 83 69 1e 47 d0 45 0e 10 45 5e 8f a3 e8 f2 19 5c a9 18 45 d1 74 47 44 74 47 44 74 47 44 74 47 44 74 47 58 22 9d 97 45 d1 74 47 44 74 47 44
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   103: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   104: IFP d0 01 80 00 2b 74 5d 17 40 8a 79 74 61 02 28 70 cb a2 ea 88 e8 5e 10 6f a1 1a 23 a3 09 b6 c4 5a 16 1d 08 8c c8 c0 72 28 1c e8 1a 44 69 11 c3 0a 77
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   104: (0) data v17-14400/hdlc-data + 44 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   105: IFP d0 01 20
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   105: (0) data v17-14400/hdlc-fcs-OK + 0 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type FCD - CRC OK (clean)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop none (0 remaining)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  FCD without final frame tag
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 03 06 01 c2 a3 a4 50 08 86 3a 08 c6 82 6a 58 9b b0 20 f4 0d 51 b8 21 0a bf 7d 7b 4b 4b 54 88 b8 74 a8 bb 42 21 0a af c4 75 8b 2e 2f 14 a5 af 3e 2c 98 40 02 f5 30 36 44 e1 86 28 7c 88 0a 08 35 c4 10 12 17 5d b5 42 85 87 42 8a 30 1e d1 2e 10 08 11 fb 70 18 44 e1 21 0a 1f 76 88 c2 fd 52 94 2e c9 71 69 87 28 fc dd ef 06 bd 21 0a f7 58 f5 7f d6 b0 0c 51 b8 c6 90 12 17 44 e1 6a 57 0f 13 8c 36 44 e1 84 4d 24 ae 31 c1 37 05 85 13 36 91 b8 12 7c 53 11 36 61 13 06 83 4a 4c 92 ac 1b 04 a2 5a 86 60 ab c4 17 5f 06 c1 96 78 e2 0b a2 70 08 a2 7a f1 c5 17 4f 98 3a 95 18 a2 8b 2e e2 22 2e e2 22 2e e2 22 2e e2 22 2e e2 1a 44 b9 e9 a2 8b 2e e2 22 2e e2 22 2e ba e8 02 51 9e 2e 86 40 14 0e d3 45 57 11 17 7a 08 f6 85 58 c4 c5 90 6d 23 5a 68 b8 10 31 13 03 4e 14 38 17 58 22 96 88 c3 50 ee
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Storing ECM frame 1, length 256
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   106: IFP d0 01 80 00 35 ff c0 60 40 40 53 3a a2 3a 23 82 82 3a 29 03 90 60 e4 74 77 c0 a6 49 a2 38 30 47 44 59 11 c3 61 1d 12 e0 a6 8a 1d 0b 84 8b a0 45 45 54 8e 82 42 21 d2 08 a1 d2 28
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   106: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   107: IFP d0 01 80 00 35 74 b4 e1 c3 08 28 b6 d0 71 11 06 99 1d 21 a6 08 12 11 61 05 11 64 75 0c 58 20 8a 76 d0 88 45 3c 8e 9d c5 a0 8a 79 1d 3b 45 d0 b0 db ea 94 45 50 52 3a 4d 76 e2 35
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   107: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   108: IFP d0 01 80 00 35 41 18 42 d0 48 ba 1b 7c 24 5d 0d aa 42 d5 6f c1 14 3e db 6c 8e ae c2 64 74 08 a1 de 23 b8 b7 db 8b bd 58 45 0e eb f1 d0 41 91 d5 d2 40 87 1e 77 a2 23 ad 69 14 3d
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   108: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   109: IFP d0 01 80 00 35 25 c8 e9 57 1a bf 69 ec 6d 82 28 74 e9 91 d2 78 8b 7b 63 be e3 b6 df d6 81 14 3a 5b 76 b4 c2 5a 54 11 43 d9 0c 3d 68 22 87 6b 09 a5 ef bb 76 c3 4a ec 8e bf a1 78
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   109: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   110: IFP d0 01 80 00 2b 4e c3 a1 77 23 a0 8a 1e 11 43 dc 8e bd 6b 4a 92 a4 08 a1 d8 45 0f d5 48 e8 fa 23 a2 3a 08 a1 ed 17 5e 47 44 74 47 44 74 5d 29 a2 23
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   110: (0) data v17-14400/hdlc-data + 44 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   111: IFP d0 01 20
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   111: (0) data v17-14400/hdlc-fcs-OK + 0 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type FCD - CRC OK (clean)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop none (0 remaining)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  FCD without final frame tag
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 03 06 02 02 ca 5c 45 5c c4 41 41 5c 94 c0 09 06 27 2e ee 03 65 92 45 1c 0c e2 22 9a 88 c3 86 b8 48 07 65 51 b8 d0 21 d1 05 a2 a2 2a 71 41 42 84 4b 10 85 4b 14 2e 2d 87 c3 10 14 6d 0b 8e 88 60 99 b8 84 65 10 48 88 86 a0 88 26 ae 30 1a 04 51 6e 0b 11 a2 3c 71 b9 a3 05 51 9e b8 dc a2 0b 0d db 57 29 a2 0a 4a 5c b2 6e 47 ac 82 18 42 0b 12 5d d8 3e 24 ba b0 55 42 ab f6 83 28 7c db 36 71 75 43 26 2e 10 85 7b c4 1d ed db d1 bd 1a a2 70 d7 8f 0b 82 89 ab 4b 02 e1 78 ee 45 c4 b5 96 28 bc a4 13 97 ea 58 fd 96 37 b6 41 14 2e 97 89 4b 1e d1 de c6 7d c7 6d fb 6b 81 28 5c da 6e 2d 43 5a 2a 88 c2 9b 30 bc 16 44 e1 d6 90 a5 f7 dd 6e c3 52 37 71 fd 85 1e 72 c3 85 ee c4 05 51 78 88 c2 3b 71 bd d6 52 49 25 10 85 1b a2 f0 ab 12 17 5f c4 45 5c 10 85 b7 e8 7a e2 22 2e e2 22 2e ba 94 45 c4
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Storing ECM frame 2, length 256
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   112: IFP d0 01 80 00 35 ff c0 60 c0 a2 3a 2e 82 28 7d 97 44 74 47 44 74 5d 34 5d 1e 44 74 47 44 74 3a 19 1d 11 d1 1d 11 d1 75 b0 8a 1d d8 45 0e ed 86 1b 23 aa 23 a7 61 b7 db 42 10 4c 43
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   112: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   113: IFP d0 01 80 00 35 08 21 6c 22 9c 21 c2 28 71 11 10 cc 22 3a 68 ba 08 28 88 63 c4 44 58 91 d1 75 88 41 31 16 11 4e e2 22 21 97 44 75 48 6a 9a ae e8 70 90 4b 04 50 eb 6c 11 43 a1 12
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   113: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   114: IFP d0 01 80 00 35 3a c6 0c 71 6c 11 51 43 1a 6c 52 8c 6f ff 6d ad c3 7c 6b 23 a0 45 0e c5 ca 74 5d 0e 83 23 a2 ea c1 14 3b 08 a1 db 64 74 61 64 74 83 6e 0c 8e b9 1d 04 50 f2 3a c2
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   114: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   115: IFP d0 01 80 00 35 ee 8a 1e 47 41 14 3a a4 95 a0 aa 2d e2 3c 62 47 49 36 35 16 91 85 88 45 0e 9a b2 eb 89 c4 47 0a e2 db b4 47 41 14 3c 5b 8a 6a c8 ea ee 9f 08 a1 df 21 aa e5 6c 3d
+[2015-12-02 11:56:05] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   115: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   116: IFP d0 01 80 00 2b f1 0c 76 c2 28 7c 43 23 ae f9 ad 1d 01 70 a0 ca e2 04 0b e3 3b ad 1c 02 0d a3 68 da 36 82 28 77 08 19 56 50 e4 33 d9 56 55 95 65 6c
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   116: (0) data v17-14400/hdlc-data + 44 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   117: IFP d0 01 20
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   117: (0) data v17-14400/hdlc-fcs-OK + 0 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type FCD - CRC OK (clean)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop none (0 remaining)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  FCD without final frame tag
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 03 06 03 45 5c 74 41 14 be e9 22 2e e2 22 2e ba 2c ba 78 22 2e e2 22 2e 5c 98 b8 88 8b b8 88 8b ae 0d 51 b8 1b a2 70 b7 61 d8 c4 55 c4 e5 86 ed db 42 08 32 c2 10 84 36 44 39 84 43 14 8e 88 08 33 44 5c 16 5d 10 14 11 c6 23 22 1a 89 8b ae 11 82 8c 68 88 72 47 44 84 e9 22 ae 12 56 59 75 17 0e 09 d2 20 0a d7 36 88 c2 85 48 5c 63 30 8e 36 88 8a c2 58 36 4a 31 f6 ff b6 b5 c3 3e d6 c4 05 a2 70 a3 53 2e ba 70 c1 c4 45 57 83 28 dc 10 85 db 26 2e 86 26 2e c1 76 30 71 9d b8 20 0a 4f 5c 43 77 51 78 e2 82 28 5c 25 a9 05 55 b4 47 3c 46 e2 92 6c ac 68 89 a1 11 a2 70 59 4d d7 91 23 e2 50 47 db 2d e2 82 28 3c da 51 56 13 57 77 f9 10 85 fb 84 55 a7 36 bc 8f 30 6e 43 14 3e c2 c4 75 9f b5 b8 80 0e 05 53 47 20 d0 c7 dc b5 38 40 b0 c5 16 5b 6c 41 14 ee 10 98 6a 0a 27 cc 9b 6a aa a9 a6 36
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Storing ECM frame 3, length 256
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   118: IFP d0 01 80 00 35 ff c0 60 20 4c a1 d1 75 a7 5c 3a 5d 3f 1c 8e ae e4 74 9e 08 10 98 45 d1 74 11 4f 90 d1 46 08 10 84 54 23 68 ba 2e 8b a2 e8 ba 2e 91 50 74 ed c1 02 10 8a 74 08 10
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   118: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   119: IFP d0 01 80 00 35 88 89 74 c8 67 43 90 60 38 20 42 21 84 08 10 88 88 d0 ee fd 91 d5 f6 d9 1d 5d dd c2 28 78 84 50 f0 8a 1e 22 22 2e 91 74 8a 1d 08 d0 88 88 88 88 40 83 29 ca 20 a7
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   119: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   120: IFP d0 01 80 00 35 48 21 16 84 42 08 c2 0f 91 d0 45 42 23 a1 c4 ed 4d 05 49 42 28 7f 69 75 74 92 a6 47 51 86 39 1d 0d db 42 2f 62 22 2d 87 b7 10 8a 77 88 a2 85 ae f8 df 64 74 42 03
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   120: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   121: IFP d0 01 80 00 35 5b ee 11 43 86 47 44 18 35 ee ed d2 4d 05 54 5d 3d 06 9a a0 82 16 b1 2e 8b ac 11 43 85 e9 71 85 f5 1b 4f f8 77 76 f5 16 ec 22 87 61 14 eb 61 3e 47 42 3b 57 bf 91
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   121: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   122: IFP d0 01 80 00 2b d5 de dc 34 fb ef 91 d2 91 d1 84 92 c2 a4 87 1a 5c 8e 8d 49 3b c1 14 3a 4b d6 f4 b4 92 ad 2f b8 d8 ed ee e4 11 17 44 74 47 44 74 47
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   122: (0) data v17-14400/hdlc-data + 44 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   123: IFP d0 01 20
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   123: (0) data v17-14400/hdlc-fcs-OK + 0 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type FCD - CRC OK (clean)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop none (0 remaining)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  FCD without final frame tag
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 03 06 04 32 85 8b ae e5 3a 5c ba fc 38 71 75 27 2e 79 10 08 19 a2 8b 2e 88 f2 09 8b 62 10 08 21 2a c4 16 5d 74 d1 45 17 5d 74 89 0a 2e b7 83 40 08 51 2e 10 08 11 91 2e 13 e6 c2 09 06 1c 04 42 84 21 10 08 11 11 0b 77 bf 89 ab 6f 9b b8 ba bb 43 14 1e 21 0a 0f 51 78 44 44 74 89 2e 51 b8 10 0b 11 11 11 11 02 c1 94 53 04 e5 12 84 68 21 42 10 43 f0 89 0b a2 42 c4 85 23 b7 b2 a0 92 42 14 fe 96 ae 2e 49 65 e2 8a 61 9c b8 b0 db 42 f4 46 44 b4 e1 ed 08 51 ee 11 45 a1 75 1f fb 26 2e 42 c0 da 77 88 c2 61 e2 22 18 ac 77 b7 4b b2 a0 2a ba bc 60 59 05 41 68 8d 74 d1 35 88 c2 a1 97 8e a1 af d8 f2 1f ee 6e af 68 37 44 e1 86 28 d7 86 7c e2 42 dc ea fd 89 ab 7b 3b 2c df f7 89 4b 89 8b 21 49 43 25 e1 58 3a 71 b1 92 dc 83 28 5c d2 6b 2f 2d 49 b5 f4 1d 1b b7 77 27 88 e8 22 2e e2 22 2e e2
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Storing ECM frame 4, length 256
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   124: IFP d0 01 80 00 35 ff c0 60 a0 44 74 47 44 74 08 a1 ee 47 4d c4 19 1d 11 d1 1d 11 d1 1d 04 14 6c 86 c1 ca 72 8a ed b6 d0 45 0e dd bd b7 76 1f be e4 75 08 a1 e4 75 91 d5 17 55 45 d2
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   124: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   125: IFP d0 01 80 00 35 e0 81 31 11 11 11 11 a4 34 84 44 44 46 85 89 1d 60 8a 1c 2a c6 b4 50 f2 3a 5a 4b 7f d4 22 87 71 bb 08 a1 d8 dd 8b 76 21 43 db b0 7b 0b c1 14 fc 49 01 a4 de e1 14
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   125: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   126: IFP d0 01 80 00 35 3b 2a 03 4e f6 9c 48 61 a4 47 55 04 50 f1 a4 92 49 22 52 82 c2 49 58 64 75 82 28 74 a4 75 42 b9 02 46 11 38 66 52 b4 d1 ad 18 44 e1 97 5a 82 29 e6 a4 61 13 86 64
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   126: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   127: IFP d0 01 80 00 35 38 b9 1d 53 bb b6 10 4e ef 84 50 e3 2e b6 8b a6 c3 de 22 11 57 23 ad c8 e9 a2 3a c4 4f 24 54 07 76 1a 1a 11 45 47 69 84 50 f2 3a fe 9c 22 9d 78 86 32 3a c1 14 3c
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   127: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   128: IFP d0 01 80 00 2b 76 15 62 11 56 d6 c1 15 08 71 14 54 2e 83 09 48 e8 a8 42 8a 89 1d 42 28 77 b8 de 11 43 bb 04 50 f1 c8 ea f0 8a 71 91 d5 b0 b1 08 a1
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   128: (0) data v17-14400/hdlc-data + 44 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   129: IFP d0 01 20
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   129: (0) data v17-14400/hdlc-fcs-OK + 0 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type FCD - CRC OK (clean)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop none (0 remaining)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  FCD without final frame tag
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 03 06 05 22 2e e2 22 2e 10 85 77 e2 b2 23 98 b8 88 8b b8 88 8b b8 20 28 36 61 83 53 4e 51 b7 6d 0b a2 70 bb bd ed 6e f8 7d 27 ae 10 85 27 ae 89 ab e8 aa a2 4b 07 81 8c 88 88 88 88 25 2c 21 22 22 62 a1 91 b8 06 51 38 54 63 2d 0a 4f 5c 5a d2 fe 2b 44 e1 8e dd 10 85 1b bb d1 6e 84 c2 db 0d de d0 83 28 3f 92 80 25 7b 87 28 dc 54 c0 72 6f 39 12 86 25 e2 aa 20 0a 8f 25 49 92 44 4a 41 43 92 1a 26 ae 41 14 2e 25 ae 42 9d 40 62 88 1c 66 4a 2d 8b b5 18 22 87 e9 5a 41 94 67 25 86 c8 61 26 1c 9d b8 ca dd 6d 08 72 f7 21 0a c7 74 6d d1 65 c3 7b 44 88 ea c4 b5 13 97 45 5c 23 f2 24 2a e0 6e 58 58 88 a2 e2 96 21 0a 4f 5c 7f 39 44 b9 1e 61 4c 5c 83 28 3c 6e a8 46 88 6a 6b 83 a8 10 8e 28 2a 74 c1 90 12 17 15 42 51 91 b8 42 14 ee 1d 7b 88 c2 dd 20 0a 8f 13 57 0f 51 8e 89 ab 0d 8d 10 85
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Storing ECM frame 5, length 256
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   130: IFP d0 01 80 00 35 ff c0 60 60 f9 17 42 11 59 7c 42 2b 48 83 d6 11 47 2a 22 22 7c 33 c6 3d 2c 69 27 51 4b 1b a0 45 0e 94 cd 1b 43 e2 2f a8 9b 40 8a 1e 1f c8 e8 4d a1 57 b8 22 9e fe
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   130: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   131: IFP d0 01 80 00 35 e0 8a 7b 0d bb 6c 8e b6 9b 23 a1 1b c2 29 fb 91 d0 8b 61 14 ed bc 46 c2 29 f5 15 d5 71 50 45 0e 8c 2a a0 d9 75 82 28 74 5d 50 82 28 75 8b d6 34 34 95 84 50 e8 5e
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   131: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   132: IFP d0 01 80 00 35 df 6d b7 6a c3 1f 0d 8e 34 36 3e d8 68 8e a1 ab 61 85 64 74 38 45 3f a4 95 24 90 55 5c 11 58 c8 eb 04 50 e1 29 1d 6a 11 43 a1 14 81 14 3f 1a 10 45 0f 1f 16 f6 ed
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   132: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   133: IFP d0 01 80 00 35 bc 36 f1 0d ee d8 22 87 b8 ed 91 d0 ee d8 dd d2 f2 eb ac 22 87 55 41 15 0f 04 50 eb 1f f1 ae c2 55 7b b1 bb c2 09 b2 ea da 23 a1 08 ab 76 c2 61 af 76 a4 75 84 50
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   133: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   134: IFP d0 01 80 00 2b ed fe 96 95 22 1b 03 8a 62 b2 0b ee 9a a4 ab a7 51 08 a1 e3 4a bb 6e 1b ec 11 b4 61 3a 0d e8 c2 26 88 3e 11 43 dc 22 87 e1 14 3c 22
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   134: (0) data v17-14400/hdlc-data + 44 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   135: IFP d0 01 20
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   135: (0) data v17-14400/hdlc-fcs-OK + 0 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type FCD - CRC OK (clean)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop none (0 remaining)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  FCD without final frame tag
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 03 06 06 9f e8 42 88 9a 3e 42 d4 12 c1 6b 88 e2 54 44 44 3e cc 63 bc 34 96 e4 8a d2 d8 05 a2 70 29 b3 d8 c2 47 f4 15 d9 02 51 78 f8 13 17 b2 85 ea 1d 44 79 7f 07 51 de b0 dd 36 71 6d d9 c4 85 d8 43 94 df 89 0b d1 86 28 b7 3d 62 43 94 af a8 ab 8e 0a a2 70 31 54 05 9b ae 41 14 2e ba 0a 41 14 ae d1 6b 2c 2c a9 21 0a 17 7a fb b6 ed 56 c3 f8 b0 71 2c 6c 7c 1b 16 71 85 d5 86 a1 26 2e 1c a2 fc 25 a9 24 09 aa 3a 88 1a 13 d7 20 0a 87 94 b8 56 88 c2 85 28 81 28 fc 58 08 a2 f0 f8 68 6f b7 3d 6c 8f b0 77 1b 44 e1 1d b7 89 0b 77 1b bb 4b 4f d7 35 44 e1 aa 82 a8 f0 20 0a d7 f8 8f 75 43 aa de 8d dd 43 90 4d 57 5b c4 85 10 d5 6e 43 86 f5 6e 25 ae 21 0a b7 7f 69 a9 44 d8 c0 51 46 4d d0 77 59 25 d5 e5 8a 10 85 c7 52 dd 76 d8 37 88 2d 86 5c b0 17 43 64 11 7c 88 c2 3b 44 e1 87 28 3c 44
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Storing ECM frame 6, length 256
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   136: IFP d0 01 80 00 35 ff c0 60 e0 87 6e d4 3d ec 82 81 d5 6a a9 02 04 22 11 43 c2 28 75 a8 41 09 18 8b a2 e8 84 46 10 f6 d5 be e3 82 28 74 5d 12 11 26 82 91 d5 02 28 74 4b 10 58 45 0f
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   136: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   137: IFP d0 01 80 00 35 7d cb a6 db b1 1d b2 3a b2 3a 3a 22 e8 ba 63 38 85 84 25 d0 41 34 61 3e 47 47 44 5d 17 49 36 47 49 17 59 50 88 e8 8e 88 e8 83 41 5b 23 a6 c4 20 84 ba 2e 87 16 cb
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   137: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   138: IFP d0 01 80 00 35 a1 a3 a2 23 a2 3a 23 a0 82 78 d2 4b 0e aa b5 14 c5 21 60 c4 90 81 03 10 82 88 62 47 4f 62 29 04 50 e8 22 9d 82 28 74 38 20 4c 62 47 41 04 e9 82 28 70 81 02 68 4d
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   138: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   139: IFP d0 01 80 00 35 68 15 b1 3e 82 91 d0 20 4c 62 47 42 bc 39 1d 37 64 74 47 4b 6d 91 d7 21 88 6d 91 d1 a2 04 09 03 23 a0 8a 1c 33 08 ba 04 09 94 38 6c 31 27 41 14 3b 86 47 46 88 b9
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   139: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   140: IFP d0 01 80 00 2b 91 d3 44 74 30 c8 e9 c8 eb 65 0e 18 97 41 04 e1 b2 3a 08 27 14 19 1d 11 d1 74 10 43 c3 23 a6 84 42 0c 4b a3 a2 0b 5c 69 14 38 c4 8e
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   140: (0) data v17-14400/hdlc-data + 44 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   141: IFP d0 01 20
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   141: (0) data v17-14400/hdlc-fcs-OK + 0 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type FCD - CRC OK (clean)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop none (0 remaining)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  FCD without final frame tag
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 03 06 07 e1 76 2b bc 37 41 81 ab 56 95 40 20 44 88 c2 43 14 ae 15 82 90 18 d1 45 17 21 62 08 6f ab 7d c7 41 14 2e ba 48 88 64 41 89 ab 40 14 2e d2 08 1a a2 f0 be d3 65 db 8d b8 4d 5c 4d 5c 5c 44 17 5d c6 1c a1 21 a4 0b 82 2c 86 7c e2 e2 22 ba e8 92 6c e2 92 e8 9a 0a 11 17 71 11 17 c1 82 da c4 65 23 04 21 5d 74 e1 68 d3 85 c5 45 c4 45 5c c4 05 41 1e 4b d2 70 55 ad 28 a3 84 06 23 09 81 c0 08 41 11 46 e2 f2 46 94 20 0a 17 44 b9 41 14 2e 1c 04 32 46 e2 82 20 97 41 14 0e 81 40 16 b2 16 a8 8d 7c 41 89 0b 04 32 46 e2 42 3d 9c b8 ec 26 2e e2 d2 b6 89 eb 84 11 b6 89 8b 45 20 90 c0 c4 05 51 38 cc 10 5d 20 90 29 1c 36 8c e4 82 28 dc 61 e2 62 11 9d 89 cb 22 2e 0c 13 97 13 d7 a6 70 18 e9 82 20 87 4d 5c 10 e4 28 98 b8 88 8b 2e 08 c2 c3 c4 65 21 42 30 d2 c5 45 d0 3a 96 28 1c 23 71
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Storing ECM frame 7, length 256
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   142: IFP d0 01 80 00 35 ff c0 60 10 8b a5 49 0c 8e 8c 22 e8 ba 50 8a 1e e4 75 65 d1 74 08 13 16 2c 31 10 82 10 87 06 47 45 d0 41 0a 15 65 d1 74 08 14 5a 65 d1 74 47 45 d1 74 5d 17 45 d1
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   142: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   143: IFP d0 01 80 00 35 74 5d 26 5d 02 42 44 23 08 c2 04 50 f2 3a 2e 98 31 23 a2 3a 2e 8b a6 a3 04 09 a0 45 0e 23 48 ba 23 a2 3a 08 21 04 82 29 d9 74 08 a1 e0 8a 1c 18 91 d1 1d 11 d1 74
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   143: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   144: IFP d0 01 80 00 35 47 41 05 15 6d f1 62 23 6d 88 88 8d c2 29 dc 44 47 11 71 11 1b 11 11 71 11 11 11 11 10 c8 e8 31 16 10 88 88 89 16 65 0e 22 22 29 88 c8 e9 88 88 88 c8 e8 62 22 c6
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   144: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   145: IFP d0 01 80 00 35 22 22 22 2a d2 4a b5 82 28 74 2d 91 d6 47 48 a1 d0 45 0f 5b a5 68 ba 51 08 a1 d0 c2 09 70 d3 61 bf 76 ec 5c 76 ef bc 5a 69 dc ba 84 53 a7 23 aa a5 54 12 fa 54 ad
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   145: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   146: IFP d0 01 80 00 2b 61 14 3a 7d 20 90 c7 23 ac 6d db 0f 86 1b b7 7b fb 74 47 54 47 41 b7 a8 aa 4b 5a 54 e1 14 3a a4 50 f2 3a d1 4e 12 c2 68 42 28 74 2c
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   146: (0) data v17-14400/hdlc-data + 44 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   147: IFP d0 01 20
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   147: (0) data v17-14400/hdlc-fcs-OK + 0 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type FCD - CRC OK (clean)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop none (0 remaining)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  FCD without final frame tag
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 03 06 08 d1 a5 92 30 71 31 44 17 5d 0a 51 78 27 ae a6 8b 2e 10 c8 68 34 8c 08 41 08 e1 60 e2 a2 0b 82 50 a8 a6 8b 2e 10 28 5a a6 8b 2e e2 a2 8b 2e ba e8 a2 8b 2e ba 64 ba 40 42 22 c4 10 43 20 0a 4f 5c 74 19 8c c4 45 5c 74 d1 65 c5 20 90 05 a2 70 c4 12 5d c4 45 5c 10 84 20 41 94 9b 2e 10 85 07 51 38 18 89 8b b8 88 8b 2e e2 82 a0 a8 b6 8f 46 c4 b6 11 11 b1 43 94 3b 22 e2 88 8e 88 d8 88 88 8e 88 88 88 88 08 13 17 8c 68 08 11 11 91 68 a6 70 44 44 94 11 13 97 11 11 11 13 17 46 44 63 44 44 44 54 4b 52 ad 41 14 2e b4 89 6b e2 12 85 0b a2 f0 da a5 16 5d 8a 10 85 0b 43 90 0e cb 86 fd 6e 37 3a 6e f7 3d 5a 96 3b 5d 21 ca e5 c4 55 a5 2a 48 5f 2a b5 86 28 5c be 04 09 e3 c4 35 b6 db f0 61 d8 ed de df 2e e2 2a e2 82 ed 15 55 d2 5a 2a 87 28 5c 25 0a 4f 5c 8b 72 48 43 16 42 14 2e 34
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Storing ECM frame 8, length 256
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   148: IFP d0 01 80 00 35 ff c0 60 90 2a 87 69 c3 76 ee 47 4c 3b 10 f4 2d e2 d3 d0 45 45 da ad 3e d5 04 53 ca 12 42 8a 1d 04 53 ae b5 5d 04 35 09 14 3a 41 72 3a bb 7b 16 85 45 b2 3a 17 0d
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   148: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   149: IFP d0 01 80 00 35 b4 47 4d 38 6b 72 3a 69 a1 da 23 aa 42 8a 1d 24 ea 8a 1e 12 4d 5a 48 5d 5a 2e 95 84 28 a1 d2 4c 2a 1b 8e e1 15 09 c5 b6 88 e8 36 0e 11 50 81 84 db 86 10 bc 21 0c
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   149: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   150: IFP d0 01 80 00 35 20 c2 30 83 09 85 69 f1 0e 47 54 18 4a 3b 42 1a 2e 83 08 c2 08 a7 0b 0c 2d 14 38 46 13 09 82 10 d3 08 c2 e4 74 11 4e ad a1 b7 6a c2 29 d0 45 3a 08 21 08 a7 40 81
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   150: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   151: IFP d0 01 80 00 35 08 86 b0 8a 74 5d 62 1a 10 d1 74 11 4e 88 e9 a2 3a 08 a8 08 74 23 45 d2 41 15 01 34 08 ab 08 c2 a6 10 86 10 86 10 88 68 51 43 84 61 24 34 2d 22 9c 10 45 3a 11 06
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   151: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   152: IFP d0 01 80 00 2b 10 82 2a c2 11 45 38 45 d4 1a 06 08 5c 4c c1 c9 08 22 9c 21 45 79 06 0e 08 41 84 61 04 55 82 08 ae 20 88 28 21 53 20 9e 52 b2 bc 83
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   152: (0) data v17-14400/hdlc-data + 44 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   153: IFP d0 01 20
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   153: (0) data v17-14400/hdlc-fcs-OK + 0 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type FCD - CRC OK (clean)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop none (0 remaining)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  FCD without final frame tag
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 03 06 09 54 e1 96 c3 6e 77 e2 32 dc 08 2f b4 47 cb 0b a2 a2 5b b5 7c ab 20 ca 53 48 42 51 b8 20 ca 75 ad ba 20 ac 90 28 5c 82 4e 5c dd de 68 a1 a2 4d 5c e8 b0 2d e2 b2 1c d6 4e 5c 96 85 5b c4 55 42 51 b8 24 57 51 78 48 b2 5a 12 ba 5a 74 a9 21 14 85 4b 32 54 d8 71 87 a8 90 a3 6d 11 17 6c 70 88 0a 81 21 db 61 08 3d 84 30 04 43 0c c1 90 a1 96 8f 70 e2 2a 18 52 dc 42 58 74 c1 10 43 10 e5 d0 30 b4 28 1c 62 c8 90 41 08 cb 10 43 27 2e 88 72 b5 85 ed 56 43 94 0b a2 5c 10 84 10 e5 02 81 10 61 0d 51 2e ba 46 58 08 8b 2e 88 72 11 97 45 5c 10 15 10 2e c4 a2 4b 82 a8 80 2c 10 d5 10 43 65 08 61 08 61 08 11 16 8a c2 21 86 24 2c b4 44 39 08 a2 5c 88 60 08 41 54 43 88 a2 1c a2 2b 58 60 10 3a 32 83 93 10 44 39 84 a2 9e 60 70 10 82 21 86 20 aa 41 10 75 04 11 14 84 ca 04 79 4a 4d 3d c1
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Storing ECM frame 9, length 256
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   154: IFP d0 01 80 00 35 ff c0 60 50 ac 90 7d 83 08 8d 05 38 82 29 c2 12 70 c0 9f 08 46 d2 2a 64 1f 65 a5 61 08 58 43 0b d6 22 47 41 48 d2 08 aa 8a 82 a4 90 a2 e5 39 52 17 2a a2 a0 a1 32
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   154: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   155: IFP d0 01 80 00 35 ab 28 50 a4 e5 59 40 a5 56 55 94 df 8a 72 93 95 05 6c a0 ad 0a 82 84 8a 72 aa 2a 0a d9 51 41 95 05 0d 14 e5 27 2a 0a 5d 02 d8 88 88 88 88 88 88 88 88 88 88 88 88
+[2015-12-02 11:56:06] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   155: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   156: IFP d0 01 80 00 35 88 88 88 88 88 8c ae 28 8b a0 94 20 9b 23 a2 3a 7b 18 82 28 7c 11 43 86 47 45 d3 71 88 65 d0 4a 84 7a dd 05 6a 14 8e ad 0f 84 53 a8 d1 75 0c 21 86 8b a8 68 60 8a
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   156: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   157: IFP d0 01 80 00 35 b0 8b a8 84 52 61 58 9f 46 14 47 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   157: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   158: IFP d0 01 80 00 2b ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   158: (0) data v17-14400/hdlc-data + 44 byte(s)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   159: IFP d0 01 20
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   159: (0) data v17-14400/hdlc-fcs-OK + 0 byte(s)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type FCD - CRC OK (clean)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop none (0 remaining)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  FCD without final frame tag
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 03 06 0a 35 09 be c1 10 b1 a0 1c 41 94 43 48 0e 03 f9 10 62 4b 54 26 f8 a6 a5 86 10 1a c2 d0 6b 44 e2 82 12 4b 10 55 51 41 25 09 45 a7 9c 4a e8 54 45 05 85 4c d5 14 0a 25 a7 9a 02 a5 6a aa 29 fb 51 4e c9 a9 a0 36 05 b5 50 41 21 51 4e 55 54 50 9b 8a 82 a9 a0 b0 28 a7 e4 54 50 ba 40 1b 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 31 75 14 d1 05 29 04 d9 c4 45 5c de 18 41 14 3e 88 c2 61 e2 a2 cb 8e 11 a6 0b 52 21 5e bb a0 56 28 71 b5 f0 21 ca 15 8b ae 30 84 61 d1 15 16 06 51 0d d1 15 21 4a 86 1a f9 62 28 e2 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Storing ECM frame 10, length 256
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   160: IFP d0 01 80 00 35 ff c0 60 d0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   160: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   161: IFP d0 01 80 00 35 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   161: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   162: IFP d0 01 80 00 35 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   162: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   163: IFP d0 01 80 00 35 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff fe 00 20 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   163: (0) data v17-14400/hdlc-data + 54 byte(s)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   164: IFP d0 01 80 00 2b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   164: (0) data v17-14400/hdlc-data + 44 byte(s)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   165: IFP d0 01 20
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   165: (0) data v17-14400/hdlc-fcs-OK + 0 byte(s)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type FCD - CRC OK (clean)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop none (0 remaining)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  FCD without final frame tag
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 03 06 0b ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 7f 00 04 c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Storing ECM frame 11, length 256
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   166: IFP d0 01 80 00 02 ff c0 61
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   166: (0) data v17-14400/hdlc-data + 3 byte(s)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   167: IFP d0 01 20
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   167: (0) data v17-14400/hdlc-fcs-OK + 0 byte(s)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type RCP - CRC OK (clean)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop none (0 remaining)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  RCP without final frame tag
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 03 86
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Changing from state 12 to 13
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Start T2
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   168: IFP d0 01 80 00 02 ff c0 61
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   168: (0) data v17-14400/hdlc-data + 3 byte(s)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   169: IFP d0 01 20
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   169: (0) data v17-14400/hdlc-fcs-OK + 0 byte(s)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type RCP - CRC OK (clean)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop T2 (55840 remaining)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  RCP without final frame tag
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 03 86
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Start T2
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   170: IFP d0 01 80 00 02 ff c0 61
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   170: (0) data v17-14400/hdlc-data + 3 byte(s)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   171: IFP d0 01 20
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   171: (0) data v17-14400/hdlc-fcs-OK + 0 byte(s)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type RCP - CRC OK (clean)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop T2 (55840 remaining)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  RCP without final frame tag
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 03 86
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Start T2
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   172: IFP d0 01 80 00 02 ff c0 61
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   172: (0) data v17-14400/hdlc-data + 3 byte(s)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   173: IFP d0 01 40
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   173: (0) data v17-14400/hdlc-fcs-OK-sig-end + 0 byte(s)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type RCP - CRC OK, sig end (clean)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop T2 (55840 remaining)
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  RCP without final frame tag
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 03 86
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Start T2
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 HDLC signal status is Carrier down (-1) in state 13
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Changing from phase T30_PHASE_C_ECM_RX to T30_PHASE_D_RX
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Set rx type 4
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Set tx type 0
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 No signal is present
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   174: IFP 00
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   174: indicator no-signal
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   175: IFP 06
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   175: indicator v21-preamble
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 A signal is present
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 HDLC signal status is Carrier up (-2) in state 13
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 HDLC signal status is Framing OK (-6) in state 13
+[2015-12-02 11:56:07] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Start T2A
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   176: IFP c0 01 80 00 00 ff
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   176: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   177: IFP c0 01 80 00 00 c8
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   177: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   178: IFP c0 01 80 00 00 fd
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   178: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   179: IFP c0 01 80 00 00 f4
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   179: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   180: IFP c0 01 80 00 00 00
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   180: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   181: IFP c0 01 80 00 00 00
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   181: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   182: IFP c0 01 80 00 00 d0
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   182: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   183: IFP c0 01 40
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   183: (0) data v21/hdlc-fcs-OK-sig-end + 0 byte(s)
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type PPS - CRC OK, sig end (clean)
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop T2A (16960 remaining)
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  PPS with final frame tag
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 13 bf 2f 00 00 0b
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx final frame in state 13
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Received PPS + EOP - page 0, block 0, 12 frames
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Partial page OK - committing block 0, 12 frames
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Page no = 1
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Image size = 1728 x 2292 pixels
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Image resolution = 8031/m x 7700/m
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Compression = T.6 (3)
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Compressed image size = 2998 bytes
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Changing from state 13 to 14
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Tx:  MCF with final frame tag
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Tx:  ff 13 8c
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.30 HDLC signal status is Carrier down (-1) in state 14
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Changing from phase T30_PHASE_D_RX to T30_PHASE_D_TX
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Set rx type 0
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Set tx type 4
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.30 No signal is present
+[2015-12-02 11:56:08] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx     9: indicator v21-preamble
+[2015-12-02 11:56:09] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   184: IFP 00
+[2015-12-02 11:56:09] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   184: indicator no-signal
+[2015-12-02 11:56:09] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx    10: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:09] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx    10: IFP c0 01 80 00 00 ff
+[2015-12-02 11:56:09] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx    11: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:09] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx    11: IFP c0 01 80 00 00 c8
+[2015-12-02 11:56:09] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx    12: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:09] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx    12: IFP c0 01 80 00 00 31
+[2015-12-02 11:56:09] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Send complete in phase T30_PHASE_D_TX, state 14
+[2015-12-02 11:56:09] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx    13: (0) data v21/hdlc-fcs-OK-sig-end + 0 byte(s)
+[2015-12-02 11:56:09] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx    13: IFP c0 01 40
+[2015-12-02 11:56:09] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Send complete in phase T30_PHASE_D_TX, state 14
+[2015-12-02 11:56:09] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Changing from phase T30_PHASE_D_TX to T30_PHASE_D_RX
+[2015-12-02 11:56:09] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Set rx type 4
+[2015-12-02 11:56:09] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Set tx type 0
+[2015-12-02 11:56:09] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Start T4
+[2015-12-02 11:56:09] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Tx    14: indicator no-signal
+[2015-12-02 11:56:10] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   185: IFP 06
+[2015-12-02 11:56:10] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   185: indicator v21-preamble
+[2015-12-02 11:56:10] FAX[13876][C-00000001] res_fax.c: FLOW T.30 A signal is present
+[2015-12-02 11:56:10] FAX[13876][C-00000001] res_fax.c: FLOW T.30 HDLC signal status is Carrier up (-2) in state 14
+[2015-12-02 11:56:10] FAX[13876][C-00000001] res_fax.c: FLOW T.30 HDLC signal status is Framing OK (-6) in state 14
+[2015-12-02 11:56:10] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Start T4A
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   186: IFP c0 01 80 00 00 ff
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   186: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   187: IFP c0 01 80 00 00 c8
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   187: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   188: IFP c0 01 80 00 00 df
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   188: (0) data v21/hdlc-data + 1 byte(s)
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   189: IFP c0 01 40
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.38 Rx   189: (0) data v21/hdlc-fcs-OK-sig-end + 0 byte(s)
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Type DCN - CRC OK, sig end (clean)
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Stop T4A (15680 remaining)
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  DCN with final frame tag
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx:  ff 13 fb
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Rx final frame in state 14
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Disconnecting
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Changing from phase T30_PHASE_D_RX to T30_PHASE_E
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Set rx type 0
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Set tx type 1
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Changing from state 14 to 2
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.30 HDLC signal status is Carrier down (-1) in state 2
+[2015-12-02 11:56:11] FAX[13876][C-00000001] res_fax.c: FLOW T.30 No signal is present
+[2015-12-02 11:56:12] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Send complete in phase T30_PHASE_E, state 2
+[2015-12-02 11:56:12] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Changing from state 2 to 32
+[2015-12-02 11:56:12] FAX[13876][C-00000001] res_fax.c: FLOW T.30 Changing from phase T30_PHASE_E to T30_PHASE_CALL_FINISHED
+[2015-12-02 11:56:12] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Set rx type 9
+[2015-12-02 11:56:12] FAX[13876][C-00000001] res_fax.c: FLOW T.38T Set tx type 9
+[2015-12-02 11:56:12] FAX[13876][C-00000001] res_fax.c: FLOW T.38T FAX exchange complete
diff --git a/contrib/scripts/spandspflow2pcap.py b/contrib/scripts/spandspflow2pcap.py
new file mode 100755 (executable)
index 0000000..a6546b6
--- /dev/null
@@ -0,0 +1,197 @@
+#!/usr/bin/env python
+# vim: set ts=8 sw=4 sts=4 et ai tw=79:
+'''
+Usage: ./spandspflow2pcap.py SPANDSP_LOG SENDFAX_PCAP
+
+Takes a log from Asterisk with SpanDSP, extracts the "received" data
+and puts it in a pcap file. Use 'fax set debug on' and configure
+logger.conf to get fax logs.
+
+Input data should look something like this::
+
+    [2013-08-07 15:17:34] FAX[23479] res_fax.c: FLOW T.38 Rx     5: IFP c0 01 ...
+
+Output data will look like a valid pcap file ;-)
+
+This allows you to reconstruct received faxes into replayable pcaps.
+
+Replaying is expected to be done by SIPp with sipp-sendfax.xml. The
+SIPp binary used for replaying must have image (fax) support. This means
+you'll need a version higher than 3.5.0 (unreleased when writing this),
+or the git master branch: https://github.com/SIPp/sipp
+
+
+Author: Walter Doekes, OSSO B.V. (2013,2015,2016)
+License: Public Domain
+'''
+from base64 import b16decode
+from datetime import datetime, timedelta
+from re import search
+from time import mktime
+from struct import pack
+import sys
+
+
+LOSSY = False
+EMPTY_RECOVERY = False
+
+
+def n2b(text):
+    return b16decode(text.replace(' ', '').replace('\n', '').upper())
+
+
+class FaxPcap(object):
+    PCAP_PREAMBLE = n2b('d4 c3 b2 a1 02 00 04 00'
+                        '00 00 00 00 00 00 00 00'
+                        'ff ff 00 00 71 00 00 00')
+
+    def __init__(self, outfile):
+        self.outfile = outfile
+        self.date = None
+        self.dateoff = timedelta(seconds=0)
+        self.seqno = None
+        self.udpseqno = 128
+        self.prev_data = None
+
+        # Only do this if at pos 0?
+        self.outfile.write(self.PCAP_PREAMBLE)
+
+    def data2packet(self, date, udpseqno, seqno, data, prev_data):
+        sum16 = '\x43\x21'  # checksum is irrelevant for sipp sending
+
+        new_prev = data  # without seqno..
+        data = '%s%s' % (pack('>H', seqno), data)
+        if prev_data:
+            if LOSSY and (seqno % 3) == 2:
+                return '', new_prev
+            if EMPTY_RECOVERY:
+                # struct ast_frame f[16], we have room for a few
+                # packets.
+                packets = 14
+                data += '\x00%c%s%s' % (
+                    chr(packets + 1), '\x00' * packets, prev_data)
+            else:
+                # Add 1 previous packet, without the seqno.
+                data += '\x00\x01' + prev_data
+
+        kwargs = {'udpseqno': pack('>H', udpseqno), 'sum16': sum16}
+
+        kwargs['data'] = data
+        kwargs['lenb16'] = pack('>H', len(kwargs['data']) + 8)
+        udp = '\x00\x01\x00\x02%(lenb16)s%(sum16)s%(data)s' % kwargs
+
+        kwargs['data'] = udp
+        kwargs['lenb16'] = pack('>H', len(kwargs['data']) + 20)
+        ip = ('\x45\xb8%(lenb16)s%(udpseqno)s\x00\x00\xf9\x11%(sum16)s\x01'
+              '\x01\x01\x01\x02\x02\x02\x02%(data)s') % kwargs
+
+        kwargs['data'] = ip
+        frame = ('\x00\x00\x00\x01\x00\x06\x00\x30\x48\xb1\x1c\x34\x00\x00'
+                 '\x08\x00%(data)s') % kwargs
+
+        kwargs['data'] = frame
+        sec = mktime(date.timetuple())
+        msec = date.microsecond
+        datalen = len(kwargs['data'])
+        kwargs['pre'] = pack('<IIII', sec, msec, datalen, datalen)
+        packet = '%(pre)s%(data)s' % kwargs
+
+        return (packet, new_prev)
+
+    def add(self, date, seqno, data):
+        if self.seqno is None:
+            self.seqno = 0
+            for i in range(seqno):
+                # In case the first zeroes were dropped, add them.
+                self.add(date, i, '\x00')
+        assert seqno == self.seqno, '%s != %s' % (seqno, self.seqno)
+
+        # Data is prepended by len(data).
+        data = chr(len(data)) + data
+
+        # Auto-increasing dates
+        if self.date is None or date > self.date:
+            # print 'date is larger', date, self.date
+            self.date = date
+        elif (date < self.date.replace(microsecond=0)):
+            assert False, ('We increased too fast.. decrease delta: %r/%r' %
+                           (date, self.date))
+        else:
+            self.date += timedelta(microseconds=9000)
+
+        print seqno, '\t', self.date + self.dateoff
+
+        # Make packet.
+        packet, prev_data = self.data2packet(self.date + self.dateoff,
+                                             self.udpseqno, self.seqno,
+                                             data, self.prev_data)
+        self.outfile.write(packet)
+
+        # Increase values.
+        self.udpseqno += 1
+        self.seqno += 1
+        self.prev_data = prev_data
+
+    def add_garbage(self, date):
+        if self.date is None or date > self.date:
+            self.date = date
+
+        packet, ignored = self.data2packet(self.date, self.udpseqno,
+                                           0xffff, 'GARBAGE', '')
+        self.udpseqno += 1
+
+        self.outfile.write(packet)
+
+
+with open(sys.argv[1], 'r') as infile:
+    with open(sys.argv[2], 'wb') as outfile:
+        first = True
+        p = FaxPcap(outfile)
+        # p.add(datetime.now(), 0, n2b('06'))
+        # p.add(datetime.now(), 1, n2b('c0 01 80 00 00 ff'))
+
+        for lineno, line in enumerate(infile):
+            # Look for lines like:
+            # [2013-08-07 15:17:34] FAX[23479] res_fax.c: \
+            #   FLOW T.38 Rx     5: IFP c0 01 80 00 00 ff
+            if 'FLOW T.38 Rx' not in line:
+                continue
+            if 'IFP' not in line:
+                continue
+
+            match = search(r'(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)', line)
+            assert match
+            date = datetime(*[int(i) for i in match.groups()])
+
+            match = search(r'Rx\s*(\d+):', line)
+            assert match
+            seqno = int(match.groups()[0])
+
+            match = search(r': IFP ([0-9a-f ]+)', line)
+            assert match
+            data = n2b(match.groups()[0])
+
+            # Have the file start a second early.
+            if first:
+                p.add_garbage(date)
+                first = False
+
+            # Add the packets.
+            #
+            # T.38 basic format of UDPTL payload section with redundancy:
+            #
+            # UDPTL_SEQNO
+            # - 2 sequence number (big endian)
+            # UDPTL_PRIMARY_PAYLOAD (T30?)
+            # - 1 subpacket length (excluding this byte)
+            # - 1 type of message (e.g. 0xd0 for data(?))
+            # - 1 items in data field (e.g. 0x01)
+            # - 2 length of data (big endian)
+            # - N data
+            # RECOVERY (optional)
+            # - 2 count of previous seqno packets (big endian)
+            # - N UDPTL_PRIMARY_PAYLOAD of (seqno-1)
+            # - N UDPTL_PRIMARY_PAYLOAD of (seqno-2)
+            # - ...
+            #
+            p.add(date, seqno, data)
index 8d98479..ae15f6a 100644 (file)
@@ -221,6 +221,26 @@ STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_read_message_type);
 STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_write_message_type);
 STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_prop_write_message_type);
 
+static struct timeval cdr_retrieve_time(struct ast_channel *chan, const char *time_name)
+{
+       struct timeval time;
+       char *value = NULL;
+       char tempbuf[128];
+
+       if (ast_strlen_zero(ast_channel_name(chan))) {
+               /* Format request on a dummy channel */
+               ast_cdr_format_var(ast_channel_cdr(chan), time_name, &value, tempbuf, sizeof(tempbuf), 1);
+       } else {
+               ast_cdr_getvar(ast_channel_name(chan), time_name, tempbuf, sizeof(tempbuf));
+       }
+
+       if (sscanf(tempbuf, "%ld.%ld", &time.tv_sec, &time.tv_usec) != 2) {
+               ast_log(AST_LOG_WARNING, "Failed to fully extract '%s' from CDR\n", time_name);
+       }
+
+       return time;
+}
+
 static void cdr_read_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
 {
        struct cdr_func_payload *payload = stasis_message_data(message);
@@ -268,16 +288,21 @@ static void cdr_read_callback(void *data, struct stasis_subscription *sub, struc
 
        if (ast_test_flag(&flags, OPT_FLOAT)
                && (!strcasecmp("billsec", args.variable) || !strcasecmp("duration", args.variable))) {
-               long ms;
-               double dtime;
+               struct timeval start = cdr_retrieve_time(payload->chan, !strcasecmp("billsec", args.variable) ? "answer" : "start");
+               struct timeval finish = cdr_retrieve_time(payload->chan, "end");
+               double delta;
 
-               if (sscanf(tempbuf, "%30ld", &ms) != 1) {
-                       ast_log(AST_LOG_WARNING, "Unable to parse %s (%s) from the CDR for channel %s\n",
-                               args.variable, tempbuf, ast_channel_name(payload->chan));
-                       return;
+               if (ast_tvzero(finish)) {
+                       finish = ast_tvnow();
                }
-               dtime = (double)(ms / 1000.0);
-               snprintf(tempbuf, sizeof(tempbuf), "%lf", dtime);
+
+               if (ast_tvzero(start)) {
+                       delta = 0.0;
+               } else {
+                       delta = (double)(ast_tvdiff_us(finish, start) / 1000000.0);
+               }
+               snprintf(tempbuf, sizeof(tempbuf), "%lf", delta);
+
        } else if (!ast_test_flag(&flags, OPT_UNPARSED)) {
                if (!strcasecmp("start", args.variable)
                        || !strcasecmp("end", args.variable)
index afe9796..39d7499 100644 (file)
@@ -208,6 +208,30 @@ ASTERISK_REGISTER_FILE()
                                                <para>R/W whether or not context tracing is enabled, only available
                                                <emphasis>if CHANNEL_TRACE is defined</emphasis>.</para>
                                        </enum>
+                                       <enum name="hangupsource">
+                                               <para>R/W returns the channel responsible for hangup.</para>
+                                       </enum>
+                                       <enum name="appname">
+                                               <para>R/O returns the internal application name.</para>
+                                       </enum>
+                                       <enum name="appdata">
+                                               <para>R/O returns the application data if available.</para>
+                                       </enum>
+                                       <enum name="exten">
+                                               <para>R/O returns the extension for an outbound channel.</para>
+                                       </enum>
+                                       <enum name="context">
+                                               <para>R/O returns the context for an outbound channel.</para>
+                                       </enum>
+                                       <enum name="channame">
+                                               <para>R/O returns the channel name for an outbound channel.</para>
+                                       </enum>
+                                       <enum name="uniqueid">
+                                               <para>R/O returns the channel uniqueid.</para>
+                                       </enum>
+                                       <enum name="linkedid">
+                                               <para>R/O returns the linkedid if available, otherwise returns the uniqueid.</para>
+                                       </enum>
                                </enumlist>
                                <para><emphasis>chan_sip</emphasis> provides the following additional options:</para>
                                <enumlist>
index 2966f87..7963f31 100644 (file)
 
 int load_modules(unsigned int);                /*!< Provided by loader.c */
 int load_pbx(void);                    /*!< Provided by pbx.c */
+int load_pbx_builtins(void);   /*!< Provided by pbx_builtins.c */
+int load_pbx_functions_cli(void);      /*!< Provided by pbx_functions.c */
+int load_pbx_variables(void);  /*!< Provided by pbx_variables.c */
+int load_pbx_switch(void);             /*!< Provided by pbx_switch.c */
+int load_pbx_app(void);                /*!< Provided by pbx_app.c */
+int load_pbx_hangup_handler(void);     /*!< Provided by pbx_hangup_handler.c */
 int init_logger(void);                 /*!< Provided by logger.c */
 void close_logger(void);               /*!< Provided by logger.c */
 void logger_queue_start(void);         /*!< Provided by logger.c */
index 3975fda..d86b633 100644 (file)
@@ -580,6 +580,7 @@ int ast_vm_is_registered(void);
  *
  * \retval 0 on success.
  * \retval -1 on error.
+ * \retval AST_MODULE_LOAD_DECLINE if there's already another provider registered.
  */
 int __ast_vm_register(const struct ast_vm_functions *vm_table, struct ast_module *module);
 
@@ -648,6 +649,7 @@ int ast_vm_greeter_is_registered(void);
  *
  * \retval 0 on success.
  * \retval -1 on error.
+ * \retval AST_MODULE_LOAD_DECLINE if there's already another greeter registered.
  */
 int __ast_vm_greeter_register(const struct ast_vm_greeter_functions *vm_table, struct ast_module *module);
 
index 6c9a8ae..83c34be 100644 (file)
@@ -30,6 +30,7 @@ extern "C" {
 
 #ifndef _ASTERISK_ASTMM_H
 #define _ASTERISK_ASTMM_H
+/* IWYU pragma: private, include "asterisk/utils.h" */
 
 #ifndef STANDALONE
 
index 17aac1d..d86ba4a 100644 (file)
@@ -2,10 +2,9 @@
 
 #ifndef ASTERISK_AUTOCONFIG_H
 #define ASTERISK_AUTOCONFIG_H
+/* IWYU pragma: private, include "asterisk.h" */
 
-#include "asterisk/buildopts.h"
-
-
+#include "asterisk/buildopts.h" /* IWYU pragma: export */
 
 /* Define to 1 if internal poll should be used. */
 #undef AST_POLL_COMPAT
    code using `volatile' can become incorrect without. Disable with care. */
 #undef volatile
 
-#endif
+#endif /* ASTERISK_AUTOCONFIG_H */
index 8858cf0..acea2f0 100644 (file)
@@ -746,6 +746,18 @@ int ast_bridge_suspend(struct ast_bridge *bridge, struct ast_channel *chan);
  */
 int ast_bridge_unsuspend(struct ast_bridge *bridge, struct ast_channel *chan);
 
+/*!
+ * \brief Sets BRIDGECHANNEL and BRIDGEPVTCALLID for a channel
+ *
+ * \pre chan must be locked before calling
+ *
+ * \param name channel name of the bridged peer
+ * \param pvtid Private CallID of the bridged peer
+ *
+ * \return nothing
+ */
+void ast_bridge_vars_set(struct ast_channel *chan, const char *name, const char *pvtid);
+
 struct ast_unreal_pvt;
 
 /*!
index c9c99c1..3eb6c96 100644 (file)
  * especially those related to header files.
  */
 
-#include "asterisk/compiler.h"
-
 #ifndef _COMPAT_H
 #define _COMPAT_H
+/* IWYU pragma: private, include "asterisk.h" */
+/* IWYU pragma: begin_exports */
+
+#include "asterisk/compiler.h"
 
 #ifndef __STDC_VERSION__
 /* flex output wants to find this defined. */
@@ -231,5 +233,5 @@ float roundf(float x);
 #ifndef NAN
 #define NAN (0.0/0.0)
 #endif
-
+/* IWYU pragma: end_exports */
 #endif
index b15759b..baaff18 100644 (file)
@@ -102,6 +102,21 @@ struct ast_features_xfer_config {
 struct ast_features_xfer_config *ast_get_chan_features_xfer_config(struct ast_channel *chan);
 
 /*!
+ * \brief Get the transfer configuration option xferfailsound
+ *
+ * \note The channel should be locked before calling this function.
+ * \note The returned value has to be freed.
+ *
+ * If no channel is provided, then option is pulled from the global
+ * transfer configuration.
+ *
+ * \param chan The channel to get configuration options for
+ * \retval NULL Failed to get configuration
+ * \retval non-NULL The xferfailsound
+ */
+char *ast_get_chan_features_xferfailsound(struct ast_channel *chan);
+
+/*!
  * \brief Configuration relating to call pickup
  */
 struct ast_features_pickup_config {
index 23492ff..cd49dbe 100644 (file)
@@ -266,12 +266,12 @@ AST_OPTIONAL_API(int, ast_websocket_read_string,
  * \param session Pointer to the WebSocket session
  * \param opcode WebSocket operation code to place in the frame
  * \param payload Optional pointer to a payload to add to the frame
- * \param actual_length Length of the payload (0 if no payload)
+ * \param payload_size Length of the payload (0 if no payload)
  *
  * \retval 0 if successfully written
  * \retval -1 if error occurred
  */
-AST_OPTIONAL_API(int, ast_websocket_write, (struct ast_websocket *session, enum ast_websocket_opcode opcode, char *payload, uint64_t actual_length), { errno = ENOSYS; return -1;});
+AST_OPTIONAL_API(int, ast_websocket_write, (struct ast_websocket *session, enum ast_websocket_opcode opcode, char *payload, uint64_t payload_size), { errno = ENOSYS; return -1;});
 
 /*!
  * \brief Construct and transmit a WebSocket frame containing string data.
index 9fbeb5e..d5616e9 100644 (file)
@@ -68,7 +68,7 @@ enum ast_module_unload_mode {
 enum ast_module_load_result {
        AST_MODULE_LOAD_SUCCESS = 0,    /*!< Module loaded and configured */
        AST_MODULE_LOAD_DECLINE = 1,    /*!< Module is not configured */
-       AST_MODULE_LOAD_SKIP = 2,       /*!< Module was skipped for some reason */
+       AST_MODULE_LOAD_SKIP = 2,       /*!< Module was skipped for some reason (For loader.c use only. Should never be returned by modules)*/
        AST_MODULE_LOAD_PRIORITY = 3,   /*!< Module is not loaded yet, but is added to prioity heap */
        AST_MODULE_LOAD_FAILURE = -1,   /*!< Module could not be loaded properly */
 };
diff --git a/include/asterisk/res_pjproject.h b/include/asterisk/res_pjproject.h
new file mode 100644 (file)
index 0000000..8828b34
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2016, Fairview 5 Engineering, LLC
+ *
+ * George Joseph <george.joseph@fairview5.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+#ifndef _RES_PJPROJECT_H
+#define _RES_PJPROJECT_H
+
+/*! \brief Determines whether the res_pjproject module is loaded */
+#define CHECK_PJPROJECT_MODULE_LOADED()                 \
+       do {                                                \
+               if (!ast_module_check("res_pjproject.so")) {    \
+                       return AST_MODULE_LOAD_DECLINE;             \
+               }                                               \
+       } while(0)
+
+/*!
+ * \brief Retrieve a pjproject build option
+ *
+ * \param option The build option requested
+ * \param format_string A scanf-style format string to parse the option value into
+ * \param ... Pointers to variables to receive the values parsed
+ *
+ * \retval The number of values parsed
+ *
+ * \since 13.8.0
+ *
+ * \note The option requested must be from those returned by pj_dump_config()
+ * which can be displayed with the 'pjsip show buildopts' CLI command.
+ *
+ *   <b>Sample Usage:</b>
+ *   \code
+ *
+ *   int max_hostname;
+ *
+ *   ast_sip_get_pjproject_buildopt("PJ_MAX_HOSTNAME", "%d", &max_hostname);
+ *
+ *   \endcode
+ *
+ */
+int ast_pjproject_get_buildopt(char *option, char *format_string, ...) __attribute__((format(scanf, 2, 3)));
+
+/*!
+ * \brief Begin PJPROJECT log interception for CLI output.
+ * \since 13.8.0
+ *
+ * \param fd CLI file descriptior to send intercepted output.
+ *
+ * \note ast_pjproject_log_intercept_begin() and
+ * ast_pjproject_log_intercept_end() must always be called
+ * in pairs.
+ *
+ * \return Nothing
+ */
+void ast_pjproject_log_intercept_begin(int fd);
+
+/*!
+ * \brief End PJPROJECT log interception for CLI output.
+ * \since 13.8.0
+ *
+ * \note ast_pjproject_log_intercept_begin() and
+ * ast_pjproject_log_intercept_end() must always be called
+ * in pairs.
+ *
+ * \return Nothing
+ */
+void ast_pjproject_log_intercept_end(void);
+
+/*!
+ * \brief Increment the res_pjproject reference count.
+ *
+ * This ensures graceful shutdown happens in the proper order.
+ */
+void ast_pjproject_ref(void);
+
+/*!
+ * \brief Decrement the res_pjproject reference count.
+ *
+ * This ensures graceful shutdown happens in the proper order.
+ */
+void ast_pjproject_unref(void);
+
+#endif /* _RES_PJPROJECT_H */
index 95b8f23..1ff361f 100644 (file)
@@ -159,6 +159,8 @@ struct ast_sip_contact {
                AST_STRING_FIELD(path);
                /*! Content of the User-Agent header in REGISTER request */
                AST_STRING_FIELD(user_agent);
+               /*! The name of the aor this contact belongs to */
+               AST_STRING_FIELD(aor);
        );
        /*! Absolute time that this contact is no longer valid after */
        struct timeval expiration_time;
@@ -193,6 +195,12 @@ enum ast_sip_contact_status_type {
  */
 struct ast_sip_contact_status {
        SORCERY_OBJECT(details);
+       AST_DECLARE_STRING_FIELDS(
+               /*! The original contact's URI */
+               AST_STRING_FIELD(uri);
+               /*! The name of the aor this contact_status belongs to */
+               AST_STRING_FIELD(aor);
+       );
        /*! Current status for a contact (default - unavailable) */
        enum ast_sip_contact_status_type status;
        /*! The round trip start time set before sending a qualify request */
@@ -567,6 +575,8 @@ struct ast_sip_endpoint_media_configuration {
        unsigned int cos_video;
        /*! Is g.726 packed in a non standard way */
        unsigned int g726_non_standard;
+       /*! Bind the RTP instance to the media_address */
+       unsigned int bind_rtp_to_media_address;
 };
 
 /*!
@@ -1098,32 +1108,36 @@ struct ast_sip_endpoint *ast_sip_get_artificial_endpoint(void);
 
 /*!
  * \brief Create a new serializer for SIP tasks
+ * \since 13.8.0
  *
  * See \ref ast_threadpool_serializer for more information on serializers.
  * SIP creates serializers so that tasks operating on similar data will run
  * in sequence.
  *
+ * \param name Name of the serializer. (must be unique)
+ *
  * \retval NULL Failure
  * \retval non-NULL Newly-created serializer
  */
-struct ast_taskprocessor *ast_sip_create_serializer(void);
+struct ast_taskprocessor *ast_sip_create_serializer(const char *name);
 
 struct ast_serializer_shutdown_group;
 
 /*!
  * \brief Create a new serializer for SIP tasks
- * \since 13.5.0
+ * \since 13.8.0
  *
  * See \ref ast_threadpool_serializer for more information on serializers.
  * SIP creates serializers so that tasks operating on similar data will run
  * in sequence.
  *
+ * \param name Name of the serializer. (must be unique)
  * \param shutdown_group Group shutdown controller. (NULL if no group association)
  *
  * \retval NULL Failure
  * \retval non-NULL Newly-created serializer
  */
-struct ast_taskprocessor *ast_sip_create_serializer_group(struct ast_serializer_shutdown_group *shutdown_group);
+struct ast_taskprocessor *ast_sip_create_serializer_group(const char *name, struct ast_serializer_shutdown_group *shutdown_group);
 
 /*!
  * \brief Set a serializer on a SIP dialog so requests and responses are automatically serialized
@@ -2015,6 +2029,17 @@ void ast_sip_unregister_supplement(struct ast_sip_supplement *supplement);
 char *ast_sip_get_debug(void);
 
 /*!
+ * \brief Retrieve the global regcontext setting.
+ *
+ * \since 13.8.0
+ *
+ * \note returned string needs to be de-allocated by caller.
+ *
+ * \retval the global regcontext setting
+ */
+char *ast_sip_get_regcontext(void);
+
+/*!
  * \brief Retrieve the global endpoint_identifier_order setting.
  *
  * Specifies the order by which endpoint identifiers should be regarded.
index 2ea643e..e61d3e9 100644 (file)
@@ -109,6 +109,8 @@ struct stasis_cp_single;
 /*!
  * \brief Create the 'one' side of the cache pattern.
  *
+ * Create the 'one' and forward to all's topic and topic_cached.
+ *
  * Dispose of using stasis_cp_single_unsubscribe().
  *
  * \param all Corresponding all side.
@@ -119,6 +121,23 @@ struct stasis_cp_single *stasis_cp_single_create(struct stasis_cp_all *all,
        const char *name);
 
 /*!
+ * \brief Create a sink in the cache pattern
+ *
+ * Create the 'one' but do not automatically forward to the all's topic.
+ * This is useful when aggregating other topic's messages created with
+ * \c stasis_cp_single_create in another caching topic without replicating
+ * those messages in the all's topics.
+ *
+ * Dispose of using stasis_cp_single_unsubscribe().
+ *
+ * \param all Corresponding all side.
+ * \param name Base name for the topics.
+ * \return One side instance
+ */
+struct stasis_cp_single *stasis_cp_sink_create(struct stasis_cp_all *all,
+       const char *name);
+
+/*!
  * \brief Stops caching and forwarding messages.
  *
  * \param one One side of the cache pattern.
index a04407f..4cbd213 100644 (file)
 #include "asterisk/optional_api.h"
 
 /*! An instantaneous measurement of a value. */
-#define AST_STATSD_GUAGE "g"
+#define AST_STATSD_GAUGE "g"
+/*!
+ * Embarrassingly, gauge was misspelled for quite some time.
+ * \deprecated You should spell gauge correctly.
+ */
+#define AST_STATSD_GUAGE AST_STATSD_GAUGE
 /*! A change in a value. */
 #define AST_STATSD_COUNTER "c"
 /*! Measure of milliseconds. */
@@ -57,9 +62,31 @@ AST_OPTIONAL_API(void, ast_statsd_log_string, (const char *metric_name,
 
 /*!
  * \brief Send a stat to the configured statsd server.
+ * \since 13.7.0
+ *
+ * This is the most flexible function for sending a message to the statsd
+ * server. In addition to allowing the string value and sample rate to be specified,
+ * the metric_name can be formed as a printf style string with variable
+ * arguments.
+ *
+ * \param metric_name Format string (UTF-8) specifying the name of the metric.
+ * \param metric_type Type of metric to send.
+ * \param value Value to send.
+ * \param sample_rate Percentage of samples to send.
+ *
+ * Example Usage:
+ * \code
+ *     ast_statsd_log_string_va(AST_STATSD_GAUGE, "+1", 1.0, "endpoints.states.%s", state_name);
+ * \endcode
+ */
+AST_OPTIONAL_API_ATTR(void, format(printf, 1, 5), ast_statsd_log_string_va,
+       (const char *metric_name, const char *metric_type, const char *value, double sample_rate, ...), {});
+
+/*!
+ * \brief Send a stat to the configured statsd server.
  *
- * The is the most flexible function for sending a message to the statsd server,
- * but also the least easy to use. See ast_statsd_log() or
+ * The is nearly the most flexible function for sending a message to the statsd
+ * server, but also the least easy to use. See ast_statsd_log() or
  * ast_statsd_log_sample() for a slightly more convenient interface.
  *
  * \param metric_name String (UTF-8) name of the metric.
@@ -73,6 +100,28 @@ AST_OPTIONAL_API(void, ast_statsd_log_full, (const char *metric_name,
 
 /*!
  * \brief Send a stat to the configured statsd server.
+ * \since 13.7.0
+ *
+ * This is the most flexible function for sending a message to the statsd
+ * server. In addition to allowing the value and sample rate to be specified,
+ * the metric_name can be formed as a printf style string with variable
+ * arguments.
+ *
+ * \param metric_name Format string (UTF-8) specifying the name of the metric.
+ * \param metric_type Type of metric to send.
+ * \param value Value to send.
+ * \param sample_rate Percentage of samples to send.
+ *
+ * Example Usage:
+ * \code
+ *     ast_statsd_log_full_va(AST_STATSD_TIMER, rtt, 1.0, "endpoint.%s.rtt", endpoint_name);
+ * \endcode
+ */
+AST_OPTIONAL_API_ATTR(void, format(printf, 1, 5), ast_statsd_log_full_va,
+       (const char *metric_name, const char *metric_type, intmax_t value, double sample_rate, ...), {});
+
+/*!
+ * \brief Send a stat to the configured statsd server.
  * \param metric_name String (UTF-8) name of the metric.
  * \param metric_type Type of metric to send.
  * \param value Value to send.
index 6ebf072..af3ce74 100644 (file)
@@ -56,6 +56,9 @@
 
 struct ast_taskprocessor;
 
+/*! \brief Suggested maximum taskprocessor name length (less null terminator). */
+#define AST_TASKPROCESSOR_MAX_NAME     45
+
 #define AST_TASKPROCESSOR_HIGH_WATER_LEVEL 500
 
 /*!
@@ -259,6 +262,30 @@ int ast_taskprocessor_execute(struct ast_taskprocessor *tps);
 int ast_taskprocessor_is_task(struct ast_taskprocessor *tps);
 
 /*!
+ * \brief Get the next sequence number to create a human friendly taskprocessor name.
+ * \since 13.8.0
+ *
+ * \return Sequence number for use in creating human friendly taskprocessor names.
+ */
+unsigned int ast_taskprocessor_seq_num(void);
+
+/*!
+ * \brief Build a taskprocessor name with a sequence number on the end.
+ * \since 13.8.0
+ *
+ * \param buf Where to put the built taskprocessor name.
+ * \param size How large is buf including null terminator.
+ * \param format printf format to create the non-sequenced part of the name.
+ *
+ * \note The user supplied part of the taskprocessor name is truncated
+ * to allow the full sequence number to be appended within the supplied
+ * buffer size.
+ *
+ * \return Nothing
+ */
+void __attribute__((format(printf, 3, 4))) ast_taskprocessor_build_name(char *buf, unsigned int size, const char *format, ...);
+
+/*!
  * \brief Return the name of the taskprocessor singleton
  * \since 1.6.1
  */
index 18d743b..f91b047 100644 (file)
@@ -67,8 +67,8 @@ extern "C" {
 #define COLORIZE_FMT   "%s%s%s"
 #define COLORIZE(fg, bg, str)  ast_term_color(fg,bg),str,ast_term_reset()
 /*! \brief Maximum number of characters needed for a color escape sequence,
- *         plus a null char */
-#define AST_TERM_MAX_ESCAPE_CHARS   12
+ *         and another one for a trailing reset, plus a null char */
+#define AST_TERM_MAX_ESCAPE_CHARS   23
 #define AST_TERM_MAX_ROTATING_BUFFERS  15
 
 /*! \brief Colorize a specified string by adding terminal color codes
@@ -137,10 +137,6 @@ char *term_strip(char *outbuf, const char *inbuf, int maxout);
 
 void term_filter_escapes(char *line);
 
-char *term_prompt(char *outbuf, const char *inbuf, int maxout);
-
-const char *term_prep(void);
-
 const char *term_end(void);
 
 const char *term_quit(void);
index 5294906..f49d689 100644 (file)
 
 /* We have to let the compiler learn what types to use for the elements of a
    struct timeval since on linux, it's time_t and suseconds_t, but on *BSD,
-   they are just a long. */
-extern struct timeval tv;
-typedef typeof(tv.tv_sec) ast_time_t;
-typedef typeof(tv.tv_usec) ast_suseconds_t;
+   they are just a long.
+   note:dummy_tv_var_for_types never actually gets exported, only used as
+   local place holder. */
+extern struct timeval dummy_tv_var_for_types;
+typedef typeof(dummy_tv_var_for_types.tv_sec) ast_time_t;
+typedef typeof(dummy_tv_var_for_types.tv_usec) ast_suseconds_t;
 
 /*!
  * \brief Computes the difference (in seconds) between two \c struct \c timeval instances.
index 87e9a2c..b8cd219 100644 (file)
@@ -223,6 +223,14 @@ struct ast_trans_pvt {
        struct ast_trans_pvt *next; /*!< next in translator chain */
        struct timeval nextin;
        struct timeval nextout;
+       /*! If a translation path using a format with attributes requires the output
+        * to be a specific set of attributes, this variable will be set describing
+        * those attributes to the translator. Otherwise, the translator must choose
+        * a set of format attributes for the destination that preserves the quality
+        * of the audio in the best way possible. For example with the Opus Codec,
+        * explicit_dst contains an attribute which describes whether both parties
+        * want to do forward-error correction (FEC). */
+       struct ast_format *explicit_dst;
 };
 
 /*! \brief generic frameout function */
index 664e347..c7a4737 100644 (file)
@@ -1089,4 +1089,27 @@ char *ast_crypt_encrypt(const char *key);
  */
 int ast_crypt_validate(const char *key, const char *expected);
 
+/*
+ * \brief Test that a file exists and is readable by the effective user.
+ * \since 13.7.0
+ *
+ * \param filename File to test.
+ * \return True (non-zero) if the file exists and is readable.
+ * \return False (zero) if the file either doesn't exists or is not readable.
+ */
+int ast_file_is_readable(const char *filename);
+
+/*
+ * \brief Compare 2 major.minor.patch.extra version strings.
+ * \since 13.7.0
+ *
+ * \param version1.
+ * \param version2.
+ *
+ * \return <0 if version 1 < version 2.
+ * \return =0 if version 1 = version 2.
+ * \return >0 if version 1 > version 2.
+ */
+int ast_compare_versions(const char *version1, const char *version2);
+
 #endif /* _ASTERISK_UTILS_H */
index ba44fbf..54edafa 100644 (file)
@@ -1667,11 +1667,11 @@ static struct ast_json *charge_to_json(const struct ast_aoc_decoded *decoded)
        }
 
        return ast_json_pack(
-               "{s:s, s:s, s:s, s:O}",
+               "{s:s, s:s, s:s, s:o}",
                "Type", aoc_charge_type_str(decoded->charge_type),
                "BillingID", aoc_billingid_str(decoded->billing_id),
                "TotalType", aoc_type_of_totaling_str(decoded->total_type),
-               obj_type, obj);
+               obj_type, ast_json_ref(obj));
 }
 
 static struct ast_json *association_to_json(const struct ast_aoc_decoded *decoded)
@@ -1738,10 +1738,10 @@ static struct ast_json *s_to_json(const struct ast_aoc_decoded *decoded)
                                        "Scale", decoded->aoc_s_entries[i].rate.duration.granularity_time_scale);
                        }
 
-                       type = ast_json_pack("{s:O, s:s, s:O, s:O}", "Currency", currency, "ChargingType",
+                       type = ast_json_pack("{s:o, s:s, s:o, s:o}", "Currency", ast_json_ref(currency), "ChargingType",
                                             decoded->aoc_s_entries[i].rate.duration.charging_type ?
-                                            "StepFunction" : "ContinuousCharging", "Time", time,
-                                            "Granularity", granularity ? granularity : ast_json_null());
+                                            "StepFunction" : "ContinuousCharging", "Time", ast_json_ref(time),
+                                            "Granularity", granularity ? ast_json_ref(granularity) : ast_json_ref(ast_json_null()));
 
                        break;
                }
@@ -1751,7 +1751,7 @@ static struct ast_json *s_to_json(const struct ast_aoc_decoded *decoded)
                                decoded->aoc_s_entries[i].rate.flat.amount,
                                decoded->aoc_s_entries[i].rate.flat.multiplier);
 
-                       type = ast_json_pack("{s:O}", "Currency", currency);
+                       type = ast_json_pack("{s:o}", "Currency", ast_json_ref(currency));
                        break;
                case AST_AOC_RATE_TYPE_VOLUME:
                        currency = currency_to_json(
@@ -1760,9 +1760,9 @@ static struct ast_json *s_to_json(const struct ast_aoc_decoded *decoded)
                                decoded->aoc_s_entries[i].rate.volume.multiplier);
 
                        type = ast_json_pack(
-                               "{s:s, s:O}", "Unit", aoc_volume_unit_str(
+                               "{s:s, s:o}", "Unit", aoc_volume_unit_str(
                                        decoded->aoc_s_entries[i].rate.volume.volume_unit),
-                               "Currency", currency);
+                               "Currency", ast_json_ref(currency));
                        break;
                case AST_AOC_RATE_TYPE_SPECIAL_CODE:
                        type = ast_json_pack("{s:i}", "SpecialCode",
@@ -1772,8 +1772,8 @@ static struct ast_json *s_to_json(const struct ast_aoc_decoded *decoded)
                        break;
                }
 
-               rate = ast_json_pack("{s:s, s:O}", "Chargeable", charge_item,
-                                    aoc_rate_type_str(decoded->aoc_s_entries[i].rate_type), type);
+               rate = ast_json_pack("{s:s, s:o}", "Chargeable", charge_item,
+                                    aoc_rate_type_str(decoded->aoc_s_entries[i].rate_type), ast_json_ref(type));
                if (ast_json_array_append(rates, rate)) {
                        break;
                }
index dabf15d..826e411 100644 (file)
@@ -357,6 +357,11 @@ int ast_app_exec_macro(struct ast_channel *autoservice_chan, struct ast_channel
        if (autoservice_chan) {
                ast_autoservice_stop(autoservice_chan);
        }
+
+       if (ast_check_hangup_locked(macro_chan)) {
+               ast_queue_hangup(macro_chan);
+       }
+
        return res;
 }
 
@@ -433,6 +438,11 @@ int ast_app_exec_sub(struct ast_channel *autoservice_chan, struct ast_channel *s
        if (autoservice_chan) {
                ast_autoservice_stop(autoservice_chan);
        }
+
+       if (!ignore_hangup && ast_check_hangup_locked(sub_chan)) {
+               ast_queue_hangup(sub_chan);
+       }
+
        return res;
 }
 
@@ -494,7 +504,7 @@ int __ast_vm_register(const struct ast_vm_functions *vm_table, struct ast_module
        if (table) {
                ast_log(LOG_WARNING, "Voicemail provider already registered by %s.\n",
                        table->module_name);
-               return -1;
+               return AST_MODULE_LOAD_DECLINE;
        }
 
        table = ao2_alloc_options(sizeof(*table), NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
@@ -605,7 +615,7 @@ int __ast_vm_greeter_register(const struct ast_vm_greeter_functions *vm_table, s
        if (table) {
                ast_log(LOG_WARNING, "Voicemail greeter provider already registered by %s.\n",
                        table->module_name);
-               return -1;
+               return AST_MODULE_LOAD_DECLINE;
        }
 
        table = ao2_alloc_options(sizeof(*table), NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
index e0a87d6..a7842a6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Asterisk -- An open source telephony toolkit.
  *
- * Copyright (C) 1999 - 2015, Digium, Inc.
+ * Copyright (C) 1999 - 2016, Digium, Inc.
  *
  * Mark Spencer <markster@digium.com>
  *
@@ -53,7 +53,7 @@
  *
  * \section copyright Copyright and Author
  *
- * Copyright (C) 1999 - 2015, Digium, Inc.
+ * Copyright (C) 1999 - 2016, Digium, Inc.
  * Asterisk is a <a href="http://www.digium.com/en/company/view-policy.php?id=Trademark-Policy">registered trademark</a>
  * of <a rel="nofollow" href="http://www.digium.com">Digium, Inc</a>.
  *
@@ -302,7 +302,7 @@ int daemon(int, int);  /* defined in libresolv of all places */
 
 /*! \brief Welcome message when starting a CLI interface */
 #define WELCOME_MESSAGE \
-    ast_verbose("Asterisk %s, Copyright (C) 1999 - 2015, Digium, Inc. and others.\n" \
+    ast_verbose("Asterisk %s, Copyright (C) 1999 - 2016, Digium, Inc. and others.\n" \
                 "Created by Mark Spencer <markster@digium.com>\n" \
                 "Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.\n" \
                 "This is free software, with components licensed under the GNU General Public\n" \
@@ -373,9 +373,14 @@ struct console consoles[AST_MAX_CONNECTS];
 
 char ast_defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
 
-static int ast_el_add_history(char *);
-static int ast_el_read_history(char *);
-static int ast_el_write_history(char *);
+static int ast_el_add_history(const char *);
+static int ast_el_read_history(const char *);
+static int ast_el_write_history(const char *);
+
+static void ast_el_read_default_histfile(void);
+static void ast_el_write_default_histfile(void);
+
+static void asterisk_daemon(int isroot, const char *runuser, const char *rungroup);
 
 struct _cfg_paths {
        char config_dir[PATH_MAX];
@@ -1965,13 +1970,7 @@ static void really_quit(int num, shutdown_nice_t niceness, int restart)
        }
 
        if (ast_opt_console || (ast_opt_remote && !ast_opt_exec)) {
-               char filename[80] = "";
-               if (getenv("HOME")) {
-                       snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
-               }
-               if (!ast_strlen_zero(filename)) {
-                       ast_el_write_history(filename);
-               }
+               ast_el_write_default_histfile();
                if (consolethread == AST_PTHREADT_NULL || consolethread == pthread_self()) {
                        /* Only end if we are the consolethread, otherwise there's a race with that thread. */
                        if (el != NULL) {
@@ -2202,7 +2201,7 @@ static void console_verboser(const char *s)
        }
 }
 
-static int ast_all_zeros(char *s)
+static int ast_all_zeros(const char *s)
 {
        while (*s) {
                if (*s > 32)
@@ -2213,7 +2212,7 @@ static int ast_all_zeros(char *s)
 }
 
 /* This is the main console CLI command handler.  Run by the main() thread. */
-static void consolehandler(char *s)
+static void consolehandler(const char *s)
 {
        printf("%s", term_end());
        fflush(stdout);
@@ -2231,7 +2230,7 @@ static void consolehandler(char *s)
                ast_cli_command(STDOUT_FILENO, s);
 }
 
-static int remoteconsolehandler(char *s)
+static int remoteconsolehandler(const char *s)
 {
        int ret = 0;
 
@@ -3147,7 +3146,7 @@ static int ast_el_initialize(void)
 
 #define MAX_HISTORY_COMMAND_LENGTH 256
 
-static int ast_el_add_history(char *buf)
+static int ast_el_add_history(const char *buf)
 {
        HistEvent ev;
        char *stripped_buf;
@@ -3169,7 +3168,7 @@ static int ast_el_add_history(char *buf)
        return history(el_hist, &ev, H_ENTER, stripped_buf);
 }
 
-static int ast_el_write_history(char *filename)
+static int ast_el_write_history(const char *filename)
 {
        HistEvent ev;
 
@@ -3179,7 +3178,7 @@ static int ast_el_write_history(char *filename)
        return (history(el_hist, &ev, H_SAVE, filename));
 }
 
-static int ast_el_read_history(char *filename)
+static int ast_el_read_history(const char *filename)
 {
        HistEvent ev;
 
@@ -3190,11 +3189,32 @@ static int ast_el_read_history(char *filename)
        return history(el_hist, &ev, H_LOAD, filename);
 }
 
+static void ast_el_read_default_histfile(void)
+{
+       char histfile[80] = "";
+       const char *home = getenv("HOME");
+
+       if (!ast_strlen_zero(home)) {
+               snprintf(histfile, sizeof(histfile), "%s/.asterisk_history", home);
+               ast_el_read_history(histfile);
+       }
+}
+
+static void ast_el_write_default_histfile(void)
+{
+       char histfile[80] = "";
+       const char *home = getenv("HOME");
+
+       if (!ast_strlen_zero(home)) {
+               snprintf(histfile, sizeof(histfile), "%s/.asterisk_history", home);
+               ast_el_write_history(histfile);
+       }
+}
+
 static void ast_remotecontrol(char *data)
 {
        char buf[256] = "";
        int res;
-       char filename[80] = "";
        char *hostname;
        char *cpid;
        char *version;
@@ -3204,6 +3224,10 @@ static void ast_remotecontrol(char *data)
        char *ebuf;
        int num = 0;
 
+       ast_term_init();
+       printf("%s", term_end());
+       fflush(stdout);
+
        memset(&sig_flags, 0, sizeof(sig_flags));
        signal(SIGINT, __remote_quit_handler);
        signal(SIGTERM, __remote_quit_handler);
@@ -3302,16 +3326,12 @@ static void ast_remotecontrol(char *data)
 
        ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
        remotehostname = hostname;
-       if (getenv("HOME"))
-               snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
        if (el_hist == NULL || el == NULL)
                ast_el_initialize();
+       ast_el_read_default_histfile();
 
        el_set(el, EL_GETCFN, ast_el_read_char);
 
-       if (!ast_strlen_zero(filename))
-               ast_el_read_history(filename);
-
        for (;;) {
                ebuf = (char *)el_gets(el, &num);
 
@@ -3345,7 +3365,7 @@ static int show_version(void)
 
 static int show_cli_help(void)
 {
-       printf("Asterisk %s, Copyright (C) 1999 - 2015, Digium, Inc. and others.\n", ast_get_version());
+       printf("Asterisk %s, Copyright (C) 1999 - 2016, Digium, Inc. and others.\n", ast_get_version());
        printf("Usage: asterisk [OPTIONS]\n");
        printf("Valid Options:\n");
        printf("   -V              Display version number and exit\n");
@@ -3780,17 +3800,10 @@ static void main_atexit(void)
 int main(int argc, char *argv[])
 {
        int c;
-       char filename[80] = "";
-       char hostname[MAXHOSTNAMELEN] = "";
        char * xarg = NULL;
        int x;
-       FILE *f;
-       sigset_t sigs;
-       int num;
        int isroot = 1, rundir_exists = 0;
-       char *buf;
        const char *runuser = NULL, *rungroup = NULL;
-       int moduleresult;         /*!< Result from the module load subsystem */
        struct rlimit l;
        static const char *getopt_settings = "BC:cde:FfG:ghIiL:M:mnpqRrs:TtU:VvWXx:";
 
@@ -3810,13 +3823,8 @@ int main(int argc, char *argv[])
        if (argv[0] && (strstr(argv[0], "rasterisk")) != NULL) {
                ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
        }
-       if (gethostname(hostname, sizeof(hostname)-1))
-               ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
        ast_mainpid = getpid();
 
-       if (getenv("HOME"))
-               snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
-
        /* Set config file to default before checking arguments for override. */
        ast_copy_string(cfg_paths.config_file, DEFAULT_CONFIG_FILE, sizeof(cfg_paths.config_file));
 
@@ -4197,6 +4205,10 @@ int main(int argc, char *argv[])
                                quit_handler(0, SHUTDOWN_FAST, 0);
                                exit(0);
                        }
+                       ast_term_init();
+                       printf("%s", term_end());
+                       fflush(stdout);
+
                        print_intro_message(runuser, rungroup);
                        printf("%s", term_quit());
                        ast_remotecontrol(NULL);
@@ -4213,6 +4225,19 @@ int main(int argc, char *argv[])
                exit(1);
        }
 
+       /* Not a remote console? Start the daemon. */
+       asterisk_daemon(isroot, runuser, rungroup);
+       return 0;
+}
+
+static void asterisk_daemon(int isroot, const char *runuser, const char *rungroup)
+{
+       FILE *f;
+       sigset_t sigs;
+       int num;
+       char *buf;
+       int moduleresult;         /*!< Result from the module load subsystem */
+
        /* This needs to remain as high up in the initial start up as possible.
         * daemon causes a fork to occur, which has all sorts of unintended
         * consequences for things that interact with threads.  This call *must*
@@ -4309,9 +4334,7 @@ int main(int argc, char *argv[])
        if (ast_opt_console) {
                if (el_hist == NULL || el == NULL)
                        ast_el_initialize();
-
-               if (!ast_strlen_zero(filename))
-                       ast_el_read_history(filename);
+               ast_el_read_default_histfile();
        }
 
        ast_json_init();
@@ -4476,7 +4499,7 @@ int main(int argc, char *argv[])
 
        /* initialize the data retrieval API */
        if (ast_data_init()) {
-               printf ("Failed: ast_data_init\n%s", term_quit());
+               printf("Failed: ast_data_init\n%s", term_quit());
                exit(1);
        }
 
@@ -4572,6 +4595,36 @@ int main(int argc, char *argv[])
                exit(1);
        }
 
+       if (load_pbx_builtins()) {
+               printf("Failed: load_pbx_builtins\n%s", term_quit());
+               exit(1);
+       }
+
+       if (load_pbx_functions_cli()) {
+               printf("Failed: load_pbx_functions_cli\n%s", term_quit());
+               exit(1);
+       }
+
+       if (load_pbx_variables()) {
+               printf("Failed: load_pbx_variables\n%s", term_quit());
+               exit(1);
+       }
+
+       if (load_pbx_switch()) {
+               printf("Failed: load_pbx_switch\n%s", term_quit());
+               exit(1);
+       }
+
+       if (load_pbx_app()) {
+               printf("Failed: load_pbx_app\n%s", term_quit());
+               exit(1);
+       }
+
+       if (load_pbx_hangup_handler()) {
+               printf("Failed: load_pbx_hangup_handler\n%s", term_quit());
+               exit(1);
+       }
+
        if (ast_local_init()) {
                printf("Failed: ast_local_init\n%s", term_quit());
                exit(1);
@@ -4658,6 +4711,11 @@ int main(int argc, char *argv[])
                /* Console stuff now... */
                /* Register our quit function */
                char title[256];
+               char hostname[MAXHOSTNAMELEN] = "";
+
+               if (gethostname(hostname, sizeof(hostname) - 1)) {
+                       ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
+               }
 
                ast_pthread_create_detached(&mon_sig_flags, NULL, monitor_sig_flags, NULL);
 
@@ -4675,30 +4733,17 @@ int main(int argc, char *argv[])
                        buf = (char *) el_gets(el, &num);
 
                        if (!buf && write(1, "", 1) < 0)
-                               goto lostterm;
+                               return; /* quit */
 
                        if (buf) {
                                if (buf[strlen(buf)-1] == '\n')
                                        buf[strlen(buf)-1] = '\0';
 
-                               consolehandler((char *)buf);
-                       } else if (ast_opt_remote && (write(STDOUT_FILENO, "\nUse EXIT or QUIT to exit the asterisk console\n",
-                                  strlen("\nUse EXIT or QUIT to exit the asterisk console\n")) < 0)) {
-                               /* Whoa, stdout disappeared from under us... Make /dev/null's */
-                               int fd;
-                               fd = open("/dev/null", O_RDWR);
-                               if (fd > -1) {
-                                       dup2(fd, STDOUT_FILENO);
-                                       dup2(fd, STDIN_FILENO);
-                               } else
-                                       ast_log(LOG_WARNING, "Failed to open /dev/null to recover from dead console. Bad things will happen!\n");
-                               break;
+                               consolehandler(buf);
                        }
                }
        }
 
+       /* Stall until a quit signal is given */
        monitor_sig_flags(NULL);
-
-lostterm:
-       return 0;
 }
index 8260460..1599d10 100644 (file)
@@ -663,6 +663,32 @@ int __ast_vasprintf(char **strp, const char *fmt, va_list ap, const char *file,
        return size;
 }
 
+/*!
+ * \internal
+ * \brief Count the number of bytes in the specified freed region.
+ *
+ * \param freed Already freed region blocks storage.
+ *
+ * \note reglock must be locked before calling.
+ *
+ * \return Number of bytes in freed region.
+ */
+static size_t freed_regions_size(struct ast_freed_regions *freed)
+{
+       size_t total_len = 0;
+       int idx;
+       struct ast_region *old;
+
+       for (idx = 0; idx < ARRAY_LEN(freed->regions); ++idx) {
+               old = freed->regions[idx];
+               if (old) {
+                       total_len += old->len;
+               }
+       }
+
+       return total_len;
+}
+
 static char *handle_memory_atexit_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        switch (cmd) {
@@ -765,12 +791,54 @@ static char *handle_memory_atexit_summary(struct ast_cli_entry *e, int cmd, stru
        return CLI_SUCCESS;
 }
 
+/*!
+ * \internal
+ * \brief Common summary output at the end of the memory show commands.
+ *
+ * \param fd CLI output file descriptor.
+ * \param whales_len Accumulated size of free large allocations.
+ * \param minnows_len Accumulated size of free small allocations.
+ * \param total_len Accumulated size of all current allocations.
+ * \param selected_len Accumulated size of the selected allocations.
+ * \param cache_len Accumulated size of the allocations that are part of a cache.
+ * \param count Number of selected allocations.
+ *
+ * \return Nothing
+ */
+static void print_memory_show_common_stats(int fd,
+       unsigned int whales_len,
+       unsigned int minnows_len,
+       unsigned int total_len,
+       unsigned int selected_len,
+       unsigned int cache_len,
+       unsigned int count)
+{
+       if (cache_len) {
+               ast_cli(fd, "%10u bytes allocated (%u in caches) in %u selected allocations\n\n",
+                       selected_len, cache_len, count);
+       } else {
+               ast_cli(fd, "%10u bytes allocated in %u selected allocations\n\n",
+                       selected_len, count);
+       }
+
+       ast_cli(fd, "%10u bytes in all allocations\n", total_len);
+       ast_cli(fd, "%10u bytes in deferred free large allocations\n", whales_len);
+       ast_cli(fd, "%10u bytes in deferred free small allocations\n", minnows_len);
+       ast_cli(fd, "%10u bytes in deferred free allocations\n",
+               whales_len + minnows_len);
+       ast_cli(fd, "%10u bytes in all allocations and deferred free allocations\n",
+               total_len + whales_len + minnows_len);
+}
+
 static char *handle_memory_show_allocations(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        const char *fn = NULL;
        struct ast_region *reg;
        unsigned int idx;
-       unsigned int len = 0;
+       unsigned int whales_len;
+       unsigned int minnows_len;
+       unsigned int total_len = 0;
+       unsigned int selected_len = 0;
        unsigned int cache_len = 0;
        unsigned int count = 0;
 
@@ -804,6 +872,7 @@ static char *handle_memory_show_allocations(struct ast_cli_entry *e, int cmd, st
        ast_mutex_lock(&reglock);
        for (idx = 0; idx < ARRAY_LEN(regions); ++idx) {
                for (reg = regions[idx]; reg; reg = AST_LIST_NEXT(reg, node)) {
+                       total_len += reg->len;
                        if (fn && strcasecmp(fn, reg->file)) {
                                continue;
                        }
@@ -814,21 +883,21 @@ static char *handle_memory_show_allocations(struct ast_cli_entry *e, int cmd, st
                                (unsigned int) reg->len, reg->cache ? " (cache)" : "",
                                reg->func, reg->lineno, reg->file);
 
-                       len += reg->len;
+                       selected_len += reg->len;
                        if (reg->cache) {
                                cache_len += reg->len;
                        }
                        ++count;
                }
        }
+
+       whales_len = freed_regions_size(&whales);
+       minnows_len = freed_regions_size(&minnows);
        ast_mutex_unlock(&reglock);
 
-       if (cache_len) {
-               ast_cli(a->fd, "%u bytes allocated (%u in caches) in %u allocations\n",
-                       len, cache_len, count);
-       } else {
-               ast_cli(a->fd, "%u bytes allocated in %u allocations\n", len, count);
-       }
+       print_memory_show_common_stats(a->fd,
+               whales_len, minnows_len, total_len,
+               selected_len, cache_len, count);
 
        return CLI_SUCCESS;
 }
@@ -841,7 +910,10 @@ static char *handle_memory_show_summary(struct ast_cli_entry *e, int cmd, struct
        int idx;
        int cmp;
        struct ast_region *reg;
-       unsigned int len = 0;
+       unsigned int whales_len;
+       unsigned int minnows_len;
+       unsigned int total_len = 0;
+       unsigned int selected_len = 0;
        unsigned int cache_len = 0;
        unsigned int count = 0;
        struct file_summary {
@@ -859,7 +931,7 @@ static char *handle_memory_show_summary(struct ast_cli_entry *e, int cmd, struct
                e->usage =
                        "Usage: memory show summary [<file>]\n"
                        "       Summarizes heap memory allocations by file, or optionally\n"
-                       "       by line, if a file is specified.\n";
+                       "       by line if a file is specified.\n";
                return NULL;
        case CLI_GENERATE:
                return NULL;
@@ -874,6 +946,7 @@ static char *handle_memory_show_summary(struct ast_cli_entry *e, int cmd, struct
        ast_mutex_lock(&reglock);
        for (idx = 0; idx < ARRAY_LEN(regions); ++idx) {
                for (reg = regions[idx]; reg; reg = AST_LIST_NEXT(reg, node)) {
+                       total_len += reg->len;
                        if (fn) {
                                if (strcasecmp(fn, reg->file)) {
                                        continue;
@@ -932,11 +1005,14 @@ static char *handle_memory_show_summary(struct ast_cli_entry *e, int cmd, struct
                        ++cur->count;
                }
        }
+
+       whales_len = freed_regions_size(&whales);
+       minnows_len = freed_regions_size(&minnows);
        ast_mutex_unlock(&reglock);
 
        /* Dump the whole list */
        for (cur = list; cur; cur = cur->next) {
-               len += cur->len;
+               selected_len += cur->len;
                cache_len += cur->cache_len;
                count += cur->count;
                if (cur->cache_len) {
@@ -958,12 +1034,9 @@ static char *handle_memory_show_summary(struct ast_cli_entry *e, int cmd, struct
                }
        }
 
-       if (cache_len) {
-               ast_cli(a->fd, "%u bytes allocated (%u in caches) in %u allocations\n",
-                       len, cache_len, count);
-       } else {
-               ast_cli(a->fd, "%u bytes allocated in %u allocations\n", len, count);
-       }
+       print_memory_show_common_stats(a->fd,
+               whales_len, minnows_len, total_len,
+               selected_len, cache_len, count);
 
        return CLI_SUCCESS;
 }
index 73bb0ff..e308913 100644 (file)
@@ -824,13 +824,20 @@ static struct ast_frame *audiohook_list_translate_to_slin(struct ast_audiohook_l
                return new_frame;
        }
 
-       if (ast_format_cmp(frame->subclass.format, in_translate->format) == AST_FORMAT_CMP_NOT_EQUAL) {
+       if (!in_translate->format ||
+               ast_format_cmp(frame->subclass.format, in_translate->format) != AST_FORMAT_CMP_EQUAL) {
+               struct ast_trans_pvt *new_trans;
+
+               new_trans = ast_translator_build_path(slin, frame->subclass.format);
+               if (!new_trans) {
+                       return NULL;
+               }
+
                if (in_translate->trans_pvt) {
                        ast_translator_free_path(in_translate->trans_pvt);
                }
-               if (!(in_translate->trans_pvt = ast_translator_build_path(slin, frame->subclass.format))) {
-                       return NULL;
-               }
+               in_translate->trans_pvt = new_trans;
+
                ao2_replace(in_translate->format, frame->subclass.format);
        }
 
index ebbfc39..7451a16 100644 (file)
@@ -1211,7 +1211,7 @@ static void check_bridge_play_sounds(struct ast_bridge *bridge)
        }
 }
 
-static void update_bridge_vars_set(struct ast_channel *chan, const char *name, const char *pvtid)
+void ast_bridge_vars_set(struct ast_channel *chan, const char *name, const char *pvtid)
 {
        ast_channel_stage_snapshot(chan);
        pbx_builtin_setvar_helper(chan, "BRIDGEPEER", name);
@@ -1251,12 +1251,12 @@ static void set_bridge_peer_vars_2party(struct ast_channel *c0, struct ast_chann
        ast_channel_unlock(c1);
 
        ast_channel_lock(c0);
-       update_bridge_vars_set(c0, c1_name, c1_pvtid);
+       ast_bridge_vars_set(c0, c1_name, c1_pvtid);
        UPDATE_BRIDGE_VARS_GET(c0, c0_name, c0_pvtid);
        ast_channel_unlock(c0);
 
        ast_channel_lock(c1);
-       update_bridge_vars_set(c1, c0_name, c0_pvtid);
+       ast_bridge_vars_set(c1, c0_name, c0_pvtid);
        ast_channel_unlock(c1);
 }
 
@@ -1357,7 +1357,7 @@ static void set_bridge_peer_vars_multiparty(struct ast_bridge *bridge)
                ++idx;
 
                ast_channel_lock(bridge_channel->chan);
-               update_bridge_vars_set(bridge_channel->chan, buf, NULL);
+               ast_bridge_vars_set(bridge_channel->chan, buf, NULL);
                ast_channel_unlock(bridge_channel->chan);
        }
 }
@@ -1379,7 +1379,7 @@ static void set_bridge_peer_vars_holding(struct ast_bridge *bridge)
 
        AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
                ast_channel_lock(bridge_channel->chan);
-               update_bridge_vars_set(bridge_channel->chan, NULL, NULL);
+               ast_bridge_vars_set(bridge_channel->chan, NULL, NULL);
                ast_channel_unlock(bridge_channel->chan);
        }
 }
index 5e20f30..8d7fbae 100644 (file)
@@ -1296,8 +1296,6 @@ struct attended_transfer_properties {
                AST_STRING_FIELD(exten);
                /*! Context of transfer target */
                AST_STRING_FIELD(context);
-               /*! Sound to play on failure */
-               AST_STRING_FIELD(failsound);
                /*! Sound to play when transfer completes */
                AST_STRING_FIELD(xfersound);
                /*! The channel technology of the transferer channel */
@@ -1421,12 +1419,21 @@ static struct attended_transfer_properties *attended_transfer_properties_alloc(
        struct ast_flags *transferer_features;
 
        props = ao2_alloc(sizeof(*props), attended_transfer_properties_destructor);
-       if (!props || ast_string_field_init(props, 64)) {
+       if (!props) {
+               ast_log(LOG_ERROR, "Unable to create props - channel %s, context %s\n",
+                       ast_channel_name(transferer), context);
                return NULL;
        }
 
        ast_cond_init(&props->cond, NULL);
 
+       if (ast_string_field_init(props, 64)) {
+               ast_log(LOG_ERROR, "Unable to initialize prop fields - channel %s, context %s\n",
+                       ast_channel_name(transferer), context);
+               ao2_ref(props, -1);
+               return NULL;
+       }
+
        props->target_framehook_id = -1;
        props->transferer = ast_channel_ref(transferer);
 
@@ -1447,7 +1454,6 @@ static struct attended_transfer_properties *attended_transfer_properties_alloc(
        props->atxfernoanswertimeout = xfer_cfg->atxfernoanswertimeout;
        props->atxferloopdelay = xfer_cfg->atxferloopdelay;
        ast_string_field_set(props, context, get_transfer_context(transferer, context));
-       ast_string_field_set(props, failsound, xfer_cfg->xferfailsound);
        ast_string_field_set(props, xfersound, xfer_cfg->xfersound);
        ao2_ref(xfer_cfg, -1);
 
@@ -1708,6 +1714,44 @@ static void play_sound(struct ast_channel *chan, const char *sound)
 }
 
 /*!
+ * \brief Helper method to play a fail sound on a channel in a bridge
+ *
+ * \param chan The channel to play the fail sound to
+ */
+static void play_failsound(struct ast_channel *chan)
+{
+       char *sound;
+
+       ast_channel_lock(chan);
+       sound = ast_get_chan_features_xferfailsound(chan);
+       ast_channel_unlock(chan);
+
+       if (sound) {
+               play_sound(chan, sound);
+               ast_free(sound);
+       }
+}
+
+/*!
+ * \brief Helper method to stream a fail sound on a channel
+ *
+ * \param chan The channel to stream the fail sound to
+ */
+static void stream_failsound(struct ast_channel *chan)
+{
+       char *sound;
+
+       ast_channel_lock(chan);
+       sound = ast_get_chan_features_xferfailsound(chan);
+       ast_channel_unlock(chan);
+
+       if (sound) {
+               ast_stream_and_wait(chan, sound, AST_DIGIT_NONE);
+               ast_free(sound);
+       }
+}
+
+/*!
  * \brief Helper method to place a channel in a bridge on hold
  */
 static void hold(struct ast_channel *chan)
@@ -2049,7 +2093,7 @@ static enum attended_transfer_state calling_target_exit(struct attended_transfer
 {
        switch (stimulus) {
        case STIMULUS_TRANSFEREE_HANGUP:
-               play_sound(props->transferer, props->failsound);
+               play_failsound(props->transferer);
                publish_transfer_fail(props);
                return TRANSFER_FAIL;
        case STIMULUS_DTMF_ATXFER_COMPLETE:
@@ -2061,7 +2105,7 @@ static enum attended_transfer_state calling_target_exit(struct attended_transfer
        case STIMULUS_TRANSFER_TARGET_HANGUP:
        case STIMULUS_TIMEOUT:
        case STIMULUS_DTMF_ATXFER_ABORT:
-               play_sound(props->transferer, props->failsound);
+               play_failsound(props->transferer);
                return TRANSFER_REBRIDGE;
        case STIMULUS_DTMF_ATXFER_THREEWAY:
                bridge_unhold(props->transferee_bridge);
@@ -2090,7 +2134,7 @@ static enum attended_transfer_state hesitant_exit(struct attended_transfer_prope
 {
        switch (stimulus) {
        case STIMULUS_TRANSFEREE_HANGUP:
-               play_sound(props->transferer, props->failsound);
+               play_failsound(props->transferer);
                publish_transfer_fail(props);
                return TRANSFER_FAIL;
        case STIMULUS_DTMF_ATXFER_COMPLETE:
@@ -2101,7 +2145,7 @@ static enum attended_transfer_state hesitant_exit(struct attended_transfer_prope
        case STIMULUS_TRANSFER_TARGET_HANGUP:
        case STIMULUS_TIMEOUT:
        case STIMULUS_DTMF_ATXFER_ABORT:
-               play_sound(props->transferer, props->failsound);
+               play_failsound(props->transferer);
                return TRANSFER_RESUME;
        case STIMULUS_DTMF_ATXFER_THREEWAY:
                return TRANSFER_THREEWAY;
@@ -2163,7 +2207,7 @@ static enum attended_transfer_state consulting_exit(struct attended_transfer_pro
                 * a sound to the transferer to indicate the transferee is gone.
                 */
                bridge_basic_change_personality(props->target_bridge, BRIDGE_BASIC_PERSONALITY_NORMAL, NULL);
-               play_sound(props->transferer, props->failsound);
+               play_failsound(props->transferer);
                ast_bridge_merge_inhibit(props->target_bridge, -1);
                /* These next two lines are here to ensure that our reference to the target bridge
                 * is cleaned up properly and that the target bridge is not destroyed when the
@@ -2178,8 +2222,9 @@ static enum attended_transfer_state consulting_exit(struct attended_transfer_pro
                bridge_unhold(props->transferee_bridge);
                return TRANSFER_COMPLETE;
        case STIMULUS_TRANSFER_TARGET_HANGUP:
+               return TRANSFER_REBRIDGE;
        case STIMULUS_DTMF_ATXFER_ABORT:
-               play_sound(props->transferer, props->failsound);
+               play_failsound(props->transferer);
                return TRANSFER_REBRIDGE;
        case STIMULUS_DTMF_ATXFER_THREEWAY:
                bridge_unhold(props->transferee_bridge);
@@ -2211,7 +2256,7 @@ static enum attended_transfer_state double_checking_exit(struct attended_transfe
 {
        switch (stimulus) {
        case STIMULUS_TRANSFEREE_HANGUP:
-               play_sound(props->transferer, props->failsound);
+               play_failsound(props->transferer);
                publish_transfer_fail(props);
                return TRANSFER_FAIL;
        case STIMULUS_TRANSFERER_HANGUP:
@@ -2221,7 +2266,7 @@ static enum attended_transfer_state double_checking_exit(struct attended_transfe
                return TRANSFER_COMPLETE;
        case STIMULUS_TRANSFER_TARGET_HANGUP:
        case STIMULUS_DTMF_ATXFER_ABORT:
-               play_sound(props->transferer, props->failsound);
+               play_failsound(props->transferer);
                return TRANSFER_RESUME;
        case STIMULUS_DTMF_ATXFER_THREEWAY:
                bridge_unhold(props->target_bridge);
@@ -3295,7 +3340,7 @@ static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel,
        props->transfer_target = dial_transfer(bridge_channel->chan, destination);
        if (!props->transfer_target) {
                ast_log(LOG_ERROR, "Unable to request outbound channel for attended transfer target.\n");
-               ast_stream_and_wait(props->transferer, props->failsound, AST_DIGIT_NONE);
+               stream_failsound(props->transferer);
                ast_bridge_channel_write_unhold(bridge_channel);
                attended_transfer_properties_shutdown(props);
                return 0;
@@ -3306,7 +3351,7 @@ static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel,
        props->target_bridge = ast_bridge_basic_new();
        if (!props->target_bridge) {
                ast_log(LOG_ERROR, "Unable to create bridge for attended transfer target.\n");
-               ast_stream_and_wait(props->transferer, props->failsound, AST_DIGIT_NONE);
+               stream_failsound(props->transferer);
                ast_bridge_channel_write_unhold(bridge_channel);
                ast_hangup(props->transfer_target);
                props->transfer_target = NULL;
@@ -3317,7 +3362,7 @@ static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel,
 
        if (attach_framehook(props, props->transfer_target)) {
                ast_log(LOG_ERROR, "Unable to attach framehook to transfer target.\n");
-               ast_stream_and_wait(props->transferer, props->failsound, AST_DIGIT_NONE);
+               stream_failsound(props->transferer);
                ast_bridge_channel_write_unhold(bridge_channel);
                ast_hangup(props->transfer_target);
                props->transfer_target = NULL;
@@ -3332,7 +3377,7 @@ static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel,
 
        if (ast_call(props->transfer_target, destination, 0)) {
                ast_log(LOG_ERROR, "Unable to place outbound call to transfer target.\n");
-               ast_stream_and_wait(bridge_channel->chan, props->failsound, AST_DIGIT_NONE);
+               stream_failsound(props->transferer);
                ast_bridge_channel_write_unhold(bridge_channel);
                ast_hangup(props->transfer_target);
                props->transfer_target = NULL;
@@ -3348,7 +3393,7 @@ static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel,
        if (ast_bridge_impart(props->target_bridge, props->transfer_target, NULL, NULL,
                AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
                ast_log(LOG_ERROR, "Unable to place transfer target into bridge.\n");
-               ast_stream_and_wait(bridge_channel->chan, props->failsound, AST_DIGIT_NONE);
+               stream_failsound(props->transferer);
                ast_bridge_channel_write_unhold(bridge_channel);
                ast_hangup(props->transfer_target);
                props->transfer_target = NULL;
@@ -3358,7 +3403,7 @@ static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel,
 
        if (ast_pthread_create_detached(&thread, NULL, attended_transfer_monitor_thread, props)) {
                ast_log(LOG_ERROR, "Unable to create monitoring thread for attended transfer.\n");
-               ast_stream_and_wait(bridge_channel->chan, props->failsound, AST_DIGIT_NONE);
+               stream_failsound(props->transferer);
                ast_bridge_channel_write_unhold(bridge_channel);
                attended_transfer_properties_shutdown(props);
                return 0;
@@ -3383,35 +3428,46 @@ static void blind_transfer_cb(struct ast_channel *new_channel, struct transfer_c
 /*! \brief Internal built in feature for blind transfers */
 static int feature_blind_transfer(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 {
-       char exten[AST_MAX_EXTENSION] = "";
+       char xfer_exten[AST_MAX_EXTENSION] = "";
        struct ast_bridge_features_blind_transfer *blind_transfer = hook_pvt;
-       const char *context;
+       const char *xfer_context;
        char *goto_on_blindxfr;
 
        ast_bridge_channel_write_hold(bridge_channel, NULL);
 
        ast_channel_lock(bridge_channel->chan);
-       context = ast_strdupa(get_transfer_context(bridge_channel->chan,
+       xfer_context = ast_strdupa(get_transfer_context(bridge_channel->chan,
                blind_transfer ? blind_transfer->context : NULL));
        goto_on_blindxfr = ast_strdupa(S_OR(pbx_builtin_getvar_helper(bridge_channel->chan,
                "GOTO_ON_BLINDXFR"), ""));
        ast_channel_unlock(bridge_channel->chan);
 
        /* Grab the extension to transfer to */
-       if (grab_transfer(bridge_channel->chan, exten, sizeof(exten), context)) {
+       if (grab_transfer(bridge_channel->chan, xfer_exten, sizeof(xfer_exten), xfer_context)) {
                ast_bridge_channel_write_unhold(bridge_channel);
                return 0;
        }
 
        if (!ast_strlen_zero(goto_on_blindxfr)) {
+               const char *chan_context;
+               const char *chan_exten;
+               int chan_priority;
+
                ast_debug(1, "After transfer, transferer %s goes to %s\n",
                                ast_channel_name(bridge_channel->chan), goto_on_blindxfr);
-               ast_bridge_set_after_go_on(bridge_channel->chan, NULL, NULL, 0, goto_on_blindxfr);
+
+               ast_channel_lock(bridge_channel->chan);
+               chan_context = ast_strdupa(ast_channel_context(bridge_channel->chan));
+               chan_exten = ast_strdupa(ast_channel_exten(bridge_channel->chan));
+               chan_priority = ast_channel_priority(bridge_channel->chan);
+               ast_channel_unlock(bridge_channel->chan);
+               ast_bridge_set_after_go_on(bridge_channel->chan,
+                       chan_context, chan_exten, chan_priority, goto_on_blindxfr);
        }
 
-       if (ast_bridge_transfer_blind(0, bridge_channel->chan, exten, context, blind_transfer_cb,
-                       bridge_channel->chan) != AST_BRIDGE_TRANSFER_SUCCESS &&
-                       !ast_strlen_zero(goto_on_blindxfr)) {
+       if (ast_bridge_transfer_blind(0, bridge_channel->chan, xfer_exten, xfer_context,
+               blind_transfer_cb, bridge_channel->chan) != AST_BRIDGE_TRANSFER_SUCCESS
+               && !ast_strlen_zero(goto_on_blindxfr)) {
                ast_bridge_discard_after_goto(bridge_channel->chan);
        }
 
index be0819a..f3483e4 100644 (file)
@@ -289,6 +289,10 @@ void ast_bridge_channel_leave_bridge_nolock(struct ast_bridge_channel *bridge_ch
 
        channel_set_cause(bridge_channel->chan, cause);
 
+       ast_channel_lock(bridge_channel->chan);
+       ast_bridge_vars_set(bridge_channel->chan, NULL, NULL);
+       ast_channel_unlock(bridge_channel->chan);
+
        /* Change the state on the bridge channel */
        bridge_channel->state = new_state;
 
index 51edae7..307f71b 100644 (file)
@@ -4663,7 +4663,7 @@ int ast_cc_init(void)
                                        "Create generic monitor container"))) {
                return -1;
        }
-       if (!(cc_core_taskprocessor = ast_taskprocessor_get("CCSS core", TPS_REF_DEFAULT))) {
+       if (!(cc_core_taskprocessor = ast_taskprocessor_get("CCSS_core", TPS_REF_DEFAULT))) {
                return -1;
        }
        if (!(cc_sched_context = ast_sched_context_create())) {
index 5e24075..b6a0b42 100644 (file)
@@ -1359,10 +1359,10 @@ static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snaps
 
        ast_assert(strcasecmp(snapshot->name, cdr->party_a.snapshot->name) == 0);
 
-       /* Ignore any snapshots from a dead or dying channel */
+       /* Finalize the CDR if we're in hangup logic and we're set to do so */
        if (ast_test_flag(&snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)
-                       && ast_test_flag(&mod_cfg->general->settings, CDR_END_BEFORE_H_EXTEN)) {
-               cdr_object_check_party_a_hangup(cdr);
+               && ast_test_flag(&mod_cfg->general->settings, CDR_END_BEFORE_H_EXTEN)) {
+               cdr_object_finalize(cdr);
                return 0;
        }
 
@@ -2976,7 +2976,7 @@ int ast_cdr_setvar(const char *channel_name, const char *name, const char *value
                for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
                        struct varshead *headp = NULL;
 
-                       if (it_cdr->fn_table == &finalized_state_fn_table) {
+                       if (it_cdr->fn_table == &finalized_state_fn_table && it_cdr->next != NULL) {
                                continue;
                        }
                        if (!strcasecmp(channel_name, it_cdr->party_a.snapshot->name)) {
index 013d2e2..f5a9afa 100644 (file)
@@ -877,6 +877,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
        ast_channel_hold_state_set(tmp, AST_CONTROL_UNHOLD);
 
        ast_channel_streamid_set(tmp, -1);
+       ast_channel_vstreamid_set(tmp, -1);
 
        ast_channel_fin_set(tmp, global_fin);
        ast_channel_fout_set(tmp, global_fout);
index b3d4cac..9173055 100644 (file)
@@ -1076,10 +1076,12 @@ static char *handle_chanlist(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
                                char locbuf[40] = "(None)";
                                char appdata[40] = "(None)";
 
-                               if (!cs->context && !cs->exten)
+                               if (!ast_strlen_zero(cs->context) && !ast_strlen_zero(cs->exten)) {
                                        snprintf(locbuf, sizeof(locbuf), "%s@%s:%d", cs->exten, cs->context, cs->priority);
-                               if (cs->appl)
+                               }
+                               if (!ast_strlen_zero(cs->appl)) {
                                        snprintf(appdata, sizeof(appdata), "%s(%s)", cs->appl, S_OR(cs->data, ""));
+                               }
                                ast_cli(a->fd, FORMAT_STRING, cs->name, locbuf, ast_state2str(cs->state), appdata);
                        }
                }
index 98fa9a2..04e9367 100644 (file)
@@ -3863,6 +3863,8 @@ static void config_shutdown(void)
 
        ast_cli_unregister_multiple(cli_config, ARRAY_LEN(cli_config));
 
+       clear_config_maps();
+
        ao2_cleanup(cfg_hooks);
        cfg_hooks = NULL;
 }