[svn-commits] russell: branch russell/aoc r204014 - in /team/russell/aoc: ./ apps/ build_to...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Mon Jun 29 10:06:21 CDT 2009


Author: russell
Date: Mon Jun 29 10:06:14 2009
New Revision: 204014

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=204014
Log:
resolve, reset

Added:
    team/russell/aoc/cdr/cdr_syslog.c
      - copied unchanged from r204013, trunk/cdr/cdr_syslog.c
    team/russell/aoc/configs/cdr_syslog.conf.sample
      - copied unchanged from r204013, trunk/configs/cdr_syslog.conf.sample
Modified:
    team/russell/aoc/   (props changed)
    team/russell/aoc/CHANGES
    team/russell/aoc/UPGRADE.txt
    team/russell/aoc/apps/app_chanspy.c
    team/russell/aoc/apps/app_fax.c
    team/russell/aoc/apps/app_voicemail.c
    team/russell/aoc/build_tools/menuselect-deps.in
    team/russell/aoc/channels/chan_dahdi.c
    team/russell/aoc/channels/chan_iax2.c
    team/russell/aoc/channels/chan_sip.c
    team/russell/aoc/channels/sig_pri.c
    team/russell/aoc/configs/sip.conf.sample
    team/russell/aoc/configure
    team/russell/aoc/configure.ac
    team/russell/aoc/doc/manager_1_1.txt
    team/russell/aoc/include/asterisk/devicestate.h
    team/russell/aoc/include/asterisk/frame.h
    team/russell/aoc/main/app.c
    team/russell/aoc/main/channel.c
    team/russell/aoc/main/devicestate.c
    team/russell/aoc/main/file.c
    team/russell/aoc/main/frame.c
    team/russell/aoc/main/manager.c
    team/russell/aoc/main/pbx.c
    team/russell/aoc/main/rtp_engine.c

Propchange: team/russell/aoc/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/russell/aoc/
------------------------------------------------------------------------------
Binary property 'branch-1.4-blocked' - no diff available.

Propchange: team/russell/aoc/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Propchange: team/russell/aoc/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Mon Jun 29 10:06:14 2009
@@ -1,1 +1,1 @@
-/trunk:1-203691
+/trunk:1-204013

Modified: team/russell/aoc/CHANGES
URL: http://svn.asterisk.org/svn-view/asterisk/team/russell/aoc/CHANGES?view=diff&rev=204014&r1=204013&r2=204014
==============================================================================
--- team/russell/aoc/CHANGES (original)
+++ team/russell/aoc/CHANGES Mon Jun 29 10:06:14 2009
@@ -34,6 +34,13 @@
    will accept the SDP even if the SDP version number is not properly incremented,
    but will generate a warning in the log indicating that the SIP peer that sent
    the SDP should have the 'ignoresdpversion' option set.
+ * The 'nat' option has now been been changed to have yes, no, force_rport, and
+   comedia as valid values. Setting it to yes forces RFC 3581 behavior and enables
+   symmetric RTP support. Setting it to no only enables RFC 3581 behavior if the
+   remote side requests it and disables symmetric RTP support. Setting it to
+   force_rport forces RFC 3581 behavior and disables symmetric RTP support.
+   Setting it to comedia enables RFC 3581 behavior if the remote side requests it
+   and enables symmetric RTP support.
 
 IAX2 Changes
 -----------
@@ -43,16 +50,19 @@
 Applications
 ------------
  * Added progress option to the app_dial D() option.  When progress DTMF is
-   present, those values are sent immediatly upon receiving a PROGRESS message
+   present, those values are sent immediately upon receiving a PROGRESS message
    regardless if the call has been answered or not.
  * Added functionality to the app_dial F() option to continue with execution
    at the current location when no parameters are provided.
  * Added c() option to app_chanspy. This option allows custom DTMF to be set
-   to cycle through the next avaliable channel.  By default this is still '*'.
+   to cycle through the next available channel.  By default this is still '*'.
  * Added x() option to app_chanspy.  This option allows DTMF to be set to
    exit the application.
  * The Voicemail application has been improved to automatically ignore messages
    that only contain silence.
+ * The ChanSpy application now has the 's' option, which makes the application
+   automatically exit once it hits a point where no more channels are available
+   to spy on.
 
 Dialplan Functions
 ------------------
@@ -77,7 +87,7 @@
 
    The possible values are:
 
-     on - normal mode (the echo canceller is actually reinitalized)
+     on - normal mode (the echo canceller is actually reinitialized)
      off - disabled
      fax - FAX/data mode (NLP disabled if possible, otherwise completely
            disabled)
@@ -156,12 +166,6 @@
    reflect this change.  Previous options such as 'sslenable' still work,
    but options with the 'tls' prefix are preferred.
 
-Logger
-------
- * The rarely used 'event_log' and LOG_EVENT channel have been removed; the few
-   users of this channel in the tree have been converted to LOG_NOTICE or removed
-   (in cases where the same message was already generated to another channel).
-
 Channel Event Logging
 ---------------------
  * A new interface, CEL, is introduced here. CEL logs single events, much like
@@ -178,6 +182,8 @@
    linkedid is based on uniqueID, but spreads to other channels as transfers, dials,
    etc are performed. Thus the peices of CDR can be grouped into multilegged sets.
  * Multiple files and formats can now be specified in cdr_custom.conf.
+ * cdr_syslog has been added which allows CDRs to be written directly to syslog.
+   See configs/cdr_syslog.conf.sample for more information.
 
 Calendaring for Asterisk
 ------------------------
@@ -493,12 +499,8 @@
    as well as periodically updating the IP address. These properties allow for
    better performance as well as recovery in the event of an IP change.
  * Performance improvements via using hash tables (astobj2) and doubly-linked lists to improve 
-   load/reload of large numbers of peers/users by ~40x (for large lists of peers.
-   Initially, we saw 4x improvement in call setup/destruction, but at the time
-   of merging, this gain has disappeared; further research will be done to try
-   and restore this performance improvement. Astobj2 refcounting is now used
-   for users, peers, and dialogs.  Users are encouraged to assist in regression
-   testing and problem reporting!
+   load/reload of large numbers of peers/users by ~40x (for large lists of peers).
+   These changes also provide performance improvements for call setup and tear down.
  * Added ability to specify registration expiry time on a per registration basis in
    the register line.
  * Added support for T140 RED - redundancy in T.140 to prevent text loss due to
@@ -1134,11 +1136,11 @@
 --------------
   * Added rotatestrategy option to logger.conf, along with two new options:
      "timestamp" which will use the time to name the logger files instead of
-     sequence number; and "rotate", which rotates the names of the logfiles,
+     sequence number; and "rotate", which rotates the names of the log files,
      similar to the way syslog rotates files.
   * Added exec_after_rotate option to logger.conf, which allows a system
      command to be run after rotation.  This is primarily useful with
-     rotatestrategry=rotate, to allow a limit on the number of logfiles kept
+     rotatestrategy=rotate, to allow a limit on the number of log files kept
      and to ensure that the oldest log file gets deleted.
   * Added realtime support for the queue log
 

Modified: team/russell/aoc/UPGRADE.txt
URL: http://svn.asterisk.org/svn-view/asterisk/team/russell/aoc/UPGRADE.txt?view=diff&rev=204014&r1=204013&r2=204014
==============================================================================
--- team/russell/aoc/UPGRADE.txt (original)
+++ team/russell/aoc/UPGRADE.txt Mon Jun 29 10:06:14 2009
@@ -20,11 +20,16 @@
 
 From 1.6.2 to 1.6.3:
 
+* The rarely used 'event_log' and LOG_EVENT channel have been removed; the few
+  users of this channel in the tree have been converted to LOG_NOTICE or removed
+  (in cases where the same message was already generated to another channel).
+
 * The usage of RTP inside of Asterisk has now become modularized. This means
   the Asterisk RTP stack now exists as a loadable module, res_rtp_asterisk.
   If you are not using autoload=yes in modules.conf you will need to ensure
   it is set to load. If not, then any module which uses RTP (such as chan_sip)
   will not be able to send or receive calls.
+
 * The app_dahdiscan.c file has been removed, but the dialplan app DAHDIScan still 
   remains. It now exists within app_chanspy.c and retains the exact same 
   functionality as before. 

Modified: team/russell/aoc/apps/app_chanspy.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/russell/aoc/apps/app_chanspy.c?view=diff&rev=204014&r1=204013&r2=204014
==============================================================================
--- team/russell/aoc/apps/app_chanspy.c (original)
+++ team/russell/aoc/apps/app_chanspy.c Mon Jun 29 10:06:14 2009
@@ -134,6 +134,9 @@
 					</option>
 					<option name="o">
 						<para>Only listen to audio coming from this channel.</para>
+					</option>
+					<option name="s">
+						<para>Stop when no more channels are left to spy on.</para>
 					</option>
 					<option name="X">
 						<para>Allow the user to exit ChanSpy to a valid single digit
@@ -266,6 +269,9 @@
 					<option name="o">
 						<para>Only listen to audio coming from this channel.</para>
 					</option>
+					<option name="s">
+						<para>Stop when there are no more extensions left to spy on.</para>
+					</option>
 					<option name="X">
 						<para>Allow the user to exit ChanSpy to a valid single digit
 						numeric extension in the current context or the context
@@ -349,6 +355,7 @@
 	OPTION_DTMF_EXIT         = (1 << 14),	/* Set DTMF to exit, added for DAHDIScan integration */
 	OPTION_DTMF_CYCLE        = (1 << 15),	/* Custom DTMF for cycling next avaliable channel, (default is '*') */
 	OPTION_DAHDI_SCAN        = (1 << 16),	/* Scan groups in DAHDIScan mode */
+	OPTION_STOP              = (1 << 17),
 };
 
 enum {
@@ -373,6 +380,7 @@
 	AST_APP_OPTION_ARG('r', OPTION_RECORD, OPT_ARG_RECORD),
 	AST_APP_OPTION_ARG('e', OPTION_ENFORCED, OPT_ARG_ENFORCED),
 	AST_APP_OPTION('o', OPTION_READONLY),
+	AST_APP_OPTION('s', OPTION_STOP),
 	AST_APP_OPTION('X', OPTION_EXIT),
 	AST_APP_OPTION('s', OPTION_NOTECH),
 	AST_APP_OPTION_ARG('n', OPTION_NAME, OPT_ARG_NAME),
@@ -956,6 +964,9 @@
 
 		if (res == -1 || ast_check_hangup(chan))
 			break;
+		if (ast_test_flag(flags, OPTION_STOP) && !next_autochan) {
+			break;
+		}
 	}
 exit:
 

Modified: team/russell/aoc/apps/app_fax.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/russell/aoc/apps/app_fax.c?view=diff&rev=204014&r1=204013&r2=204014
==============================================================================
--- team/russell/aoc/apps/app_fax.c (original)
+++ team/russell/aoc/apps/app_fax.c Mon Jun 29 10:06:14 2009
@@ -161,7 +161,7 @@
 	int direction;			/* Fax direction: 0 - receiving, 1 - sending */
 	int caller_mode;
 	char *file_name;
-	
+	struct ast_control_t38_parameters t38parameters;
 	volatile int finished;
 } fax_session;
 
@@ -372,7 +372,6 @@
 	struct ast_frame *fr;
 	int last_state = 0;
 	struct timeval now, start, state_change;
-	enum ast_control_t38 t38control;
 
 #if SPANDSP_RELEASE_DATE >= 20080725
         /* for spandsp shaphots 0.0.6 and higher */
@@ -456,9 +455,16 @@
 			/* Do not pass channel to ast_dsp_process otherwise it may queue modified audio frame back */
 			fr = ast_dsp_process(NULL, dsp, fr);
 			if (fr && fr->frametype == AST_FRAME_DTMF && fr->subclass == 'f') {
+				struct ast_control_t38_parameters parameters = { .request_response = AST_T38_REQUEST_NEGOTIATE,
+										 .version = 0,
+										 .max_datagram = 400,
+										 .rate = AST_T38_RATE_9600,
+										 .rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERED_TCF,
+										 .fill_bit_removal = 1,
+										 .transcoding_mmr = 1,
+				};
 				ast_debug(1, "Fax tone detected. Requesting T38\n");
-				t38control = AST_T38_REQUEST_NEGOTIATE;
-				ast_indicate_data(s->chan, AST_CONTROL_T38, &t38control, sizeof(t38control));
+				ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
 				detect_tone = 0;
 			}
 
@@ -483,11 +489,11 @@
 				state_change = ast_tvnow();
 				last_state = t30state->state;
 			}
-		} else if (inf->frametype == AST_FRAME_CONTROL && inf->subclass == AST_CONTROL_T38 &&
-				inf->datalen == sizeof(enum ast_control_t38)) {
-			t38control =*((enum ast_control_t38 *) inf->data.ptr);
-			if (t38control == AST_T38_NEGOTIATED) {
+		} else if (inf->frametype == AST_FRAME_CONTROL && inf->subclass == AST_CONTROL_T38_PARAMETERS) {
+			struct ast_control_t38_parameters *parameters = inf->data.ptr;
+			if (parameters->request_response == AST_T38_NEGOTIATED) {
 				/* T38 switchover completed */
+				s->t38parameters = *parameters;
 				ast_debug(1, "T38 negotiated, finishing audio loop\n");
 				res = 1;
 				break;
@@ -548,8 +554,6 @@
 	struct ast_frame *inf = NULL;
 	int last_state = 0;
 	struct timeval now, start, state_change, last_frame;
-	enum ast_control_t38 t38control;
-
 	t30_state_t *t30state;
 	t38_core_state_t *t38state;
 
@@ -570,6 +574,17 @@
 		return -1;
 	}
 
+	t38_set_max_datagram_size(t38state, s->t38parameters.max_datagram);
+
+	if (s->t38parameters.fill_bit_removal) {
+		t38_set_fill_bit_removal(t38state, TRUE);
+	}
+	if (s->t38parameters.transcoding_mmr) {
+		t38_set_mmr_transcoding(t38state, TRUE);
+	} else if (s->t38parameters.transcoding_jbig) {
+		t38_set_jbig_transcoding(t38state, TRUE);
+	}
+
 	/* Setup logging */
 	set_logging(&t38.logging);
 	set_logging(&t30state->logging);
@@ -613,12 +628,9 @@
 				state_change = ast_tvnow();
 				last_state = t30state->state;
 			}
-		} else if (inf->frametype == AST_FRAME_CONTROL && inf->subclass == AST_CONTROL_T38 &&
-				inf->datalen == sizeof(enum ast_control_t38)) {
-
-			t38control = *((enum ast_control_t38 *) inf->data.ptr);
-
-			if (t38control == AST_T38_TERMINATED || t38control == AST_T38_REFUSED) {
+		} else if (inf->frametype == AST_FRAME_CONTROL && inf->subclass == AST_CONTROL_T38_PARAMETERS) {
+			struct ast_control_t38_parameters *parameters = inf->data.ptr;
+			if (parameters->request_response == AST_T38_TERMINATED || parameters->request_response == AST_T38_REFUSED) {
 				ast_debug(1, "T38 down, terminating\n");
 				res = -1;
 				break;
@@ -709,7 +721,7 @@
 {
 	int res = 0;
 	char *parse;
-	fax_session session;
+	fax_session session = { 0, };
 	char restore_digit_detect = 0;
 
 	AST_DECLARE_APP_ARGS(args,

Modified: team/russell/aoc/apps/app_voicemail.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/russell/aoc/apps/app_voicemail.c?view=diff&rev=204014&r1=204013&r2=204014
==============================================================================
--- team/russell/aoc/apps/app_voicemail.c (original)
+++ team/russell/aoc/apps/app_voicemail.c Mon Jun 29 10:06:14 2009
@@ -10750,8 +10750,9 @@
 		if ((val = ast_variable_retrieve(cfg, "general", "minsecs"))) {
 			if (sscanf(val, "%d", &x) == 1) {
 				vmminsecs = x;
-				if (maxsilence <= vmminsecs)
+				if (maxsilence / 1000 >= vmminsecs) {
 					ast_log(AST_LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
+				}
 			} else {
 				ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
 			}
@@ -10763,8 +10764,9 @@
 			}
 			if (sscanf(val, "%d", &x) == 1) {
 				vmminsecs = x;
-				if (maxsilence <= vmminsecs)
+				if (maxsilence / 1000 >= vmminsecs) {
 					ast_log(AST_LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
+				}
 			} else {
 				ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
 			}

Modified: team/russell/aoc/build_tools/menuselect-deps.in
URL: http://svn.asterisk.org/svn-view/asterisk/team/russell/aoc/build_tools/menuselect-deps.in?view=diff&rev=204014&r1=204013&r2=204014
==============================================================================
--- team/russell/aoc/build_tools/menuselect-deps.in (original)
+++ team/russell/aoc/build_tools/menuselect-deps.in Mon Jun 29 10:06:14 2009
@@ -49,6 +49,7 @@
 SS7=@PBX_SS7@
 OPENSSL=@PBX_OPENSSL@
 SUPPSERV=@PBX_SUPPSERV@
+SYSLOG=@PBX_SYSLOG@
 TONEZONE=@PBX_TONEZONE@
 UNIXODBC=@PBX_UNIXODBC@
 USB=@PBX_USB@

Modified: team/russell/aoc/channels/chan_dahdi.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/russell/aoc/channels/chan_dahdi.c?view=diff&rev=204014&r1=204013&r2=204014
==============================================================================
--- team/russell/aoc/channels/chan_dahdi.c (original)
+++ team/russell/aoc/channels/chan_dahdi.c Mon Jun 29 10:06:14 2009
@@ -15673,7 +15673,7 @@
 	}
 	/*< \todo why check for the pseudo in the per-channel section.
 	 * Any actual use for manual setup of the pseudo channel? */
-	if (!found_pseudo && reload == 0) {
+	if (!found_pseudo && reload != 1) {
 		/* use the default configuration for a channel, so
 		   that any settings from real configured channels
 		   don't "leak" into the pseudo channel config

Modified: team/russell/aoc/channels/chan_iax2.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/russell/aoc/channels/chan_iax2.c?view=diff&rev=204014&r1=204013&r2=204014
==============================================================================
--- team/russell/aoc/channels/chan_iax2.c (original)
+++ team/russell/aoc/channels/chan_iax2.c Mon Jun 29 10:06:14 2009
@@ -3709,7 +3709,7 @@
 	memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs));
 	/* Move the calling channel's native codec to the top of the preference list */
 	if (c) {
-		ast_log(LOG_DEBUG, "prepending %x to prefs\n", c->nativeformats);
+		ast_debug(1, "prepending %x to prefs\n", c->nativeformats);
 		ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1);
 	}
 	ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);

Modified: team/russell/aoc/channels/chan_sip.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/russell/aoc/channels/chan_sip.c?view=diff&rev=204014&r1=204013&r2=204014
==============================================================================
--- team/russell/aoc/channels/chan_sip.c (original)
+++ team/russell/aoc/channels/chan_sip.c Mon Jun 29 10:06:14 2009
@@ -1452,12 +1452,9 @@
 #define SIP_DTMF_AUTO		(3 << 15)	/*!< DP: DTMF Support: AUTO switch between rfc2833 and in-band DTMF */
 #define SIP_DTMF_SHORTINFO      (4 << 15)       /*!< DP: DTMF Support: SIP Info messages - "info" - short variant */
 
-/* NAT settings - see nat2str() */
-#define SIP_NAT			(3 << 18)	/*!< DP: four settings, uses two bits */
-#define SIP_NAT_NEVER		(0 << 18)	/*!< DP: No nat support */
-#define SIP_NAT_RFC3581		(1 << 18)	/*!< DP: NAT RFC3581 */
-#define SIP_NAT_ROUTE		(2 << 18)	/*!< DP: NAT Only ROUTE */
-#define SIP_NAT_ALWAYS		(3 << 18)	/*!< DP: NAT Both ROUTE and RFC3581 */
+/* NAT settings */
+#define SIP_NAT_FORCE_RPORT     (1 << 18)       /*!< DP: Force rport even if not present in the request */
+#define SIP_NAT_RPORT_PRESENT   (1 << 19)       /*!< DP: rport was present in the request */
 
 /* re-INVITE related settings */
 #define SIP_REINVITE		(7 << 20)	/*!< DP: four settings, uses three bits */
@@ -1487,7 +1484,7 @@
 /*! \brief Flags to copy from peer/user to dialog */
 #define SIP_FLAGS_TO_COPY \
 	(SIP_PROMISCREDIR | SIP_TRUSTRPID | SIP_SENDRPID | SIP_DTMF | SIP_REINVITE | \
-	 SIP_PROG_INBAND | SIP_USECLIENTCODE | SIP_NAT | SIP_G726_NONSTANDARD | \
+	 SIP_PROG_INBAND | SIP_USECLIENTCODE | SIP_NAT_FORCE_RPORT | SIP_G726_NONSTANDARD | \
 	 SIP_USEREQPHONE | SIP_INSECURE)
 /*@}*/ 
 
@@ -1499,6 +1496,7 @@
 #define SIP_PAGE2_RTAUTOCLEAR		(1 << 2)	/*!< GP: Should we clean memory from peers after expiry? */
 #define SIP_PAGE2_RPID_UPDATE		(1 << 3)
 /* Space for addition of other realtime flags in the future */
+#define SIP_PAGE2_SYMMETRICRTP          (1 << 8)        /*!< GDP: Whether symmetric RTP is enabled or not */
 #define SIP_PAGE2_STATECHANGEQUEUE	(1 << 9)	/*!< D: Unsent state pending change exists */
 
 #define SIP_PAGE2_CONNECTLINEUPDATE_PEND		(1 << 10)
@@ -1512,10 +1510,10 @@
 #define SIP_PAGE2_SUBSCRIBEMWIONLY	(1 << 18)	/*!< GP: Only issue MWI notification if subscribed to */
 #define SIP_PAGE2_IGNORESDPVERSION	(1 << 19)	/*!< GDP: Ignore the SDP session version number we receive and treat all sessions as new */
 
-#define SIP_PAGE2_T38SUPPORT		(7 << 20)	/*!< GDP: T38 Fax Passthrough Support */
-#define SIP_PAGE2_T38SUPPORT_UDPTL	(1 << 20)	/*!< GDP: T38 Fax Passthrough Support */
-#define SIP_PAGE2_T38SUPPORT_RTP	(2 << 20)	/*!< GDP: T38 Fax Passthrough Support (not implemented) */
-#define SIP_PAGE2_T38SUPPORT_TCP	(4 << 20)	/*!< GDP: T38 Fax Passthrough Support (not implemented) */
+#define SIP_PAGE2_T38SUPPORT		        (7 << 20)	/*!< GDP: T38 Fax Passthrough Support */
+#define SIP_PAGE2_T38SUPPORT_UDPTL	        (1 << 20)	/*!< GDP: T38 Fax Passthrough Support (no error correction) */
+#define SIP_PAGE2_T38SUPPORT_UDPTL_FEC	        (2 << 20)	/*!< GDP: T38 Fax Passthrough Support (FEC error correction) */
+#define SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY	(4 << 20)	/*!< GDP: T38 Fax Passthrough Support (redundancy error correction) */
 
 #define SIP_PAGE2_CALL_ONHOLD		(3 << 23)	/*!< D: Call hold states: */
 #define SIP_PAGE2_CALL_ONHOLD_ACTIVE    (1 << 23)       /*!< D: Active hold */
@@ -1535,7 +1533,7 @@
 	SIP_PAGE2_VIDEOSUPPORT | SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE | \
 	SIP_PAGE2_BUGGY_MWI | SIP_PAGE2_TEXTSUPPORT | SIP_PAGE2_FAX_DETECT | \
 	SIP_PAGE2_UDPTL_DESTINATION | SIP_PAGE2_VIDEOSUPPORT_ALWAYS | SIP_PAGE2_PREFERRED_CODEC | \
-	SIP_PAGE2_RPID_IMMEDIATE | SIP_PAGE2_RPID_UPDATE)
+	SIP_PAGE2_RPID_IMMEDIATE | SIP_PAGE2_RPID_UPDATE | SIP_PAGE2_SYMMETRICRTP)
 
 /*@}*/ 
 
@@ -1593,7 +1591,6 @@
 enum t38state {
 	T38_DISABLED = 0,                /*!< Not enabled */
 	T38_LOCAL_REINVITE,              /*!< Offered from local - REINVITE */
-	T38_PEER_DIRECT,                 /*!< Offered from peer */
 	T38_PEER_REINVITE,               /*!< Offered from peer - REINVITE */
 	T38_ENABLED                      /*!< Negotiated (enabled) */
 };
@@ -1605,7 +1602,6 @@
 	int peercapability;		/*!< Peers T38 capability */
 	int jointcapability;		/*!< Supported T38 capability at both ends */
 	enum t38state state;		/*!< T.38 state */
-	unsigned int direct:1;          /*!< Whether the T38 came from the initial invite or not */
 };
 
 /*! \brief Parameters to know status of transfer */
@@ -2439,7 +2435,7 @@
 				struct ast_str **m_buf, struct ast_str **a_buf,
 				int debug);
 static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int oldsdp, int add_audio, int add_t38);
-static void do_setnat(struct sip_pvt *p, int natflags);
+static void do_setnat(struct sip_pvt *p);
 static void stop_media_flows(struct sip_pvt *p);
 
 /*--- Authentication stuff */
@@ -2523,7 +2519,6 @@
 static const char *sip_nat_mode(const struct sip_pvt *p);
 static char *sip_show_inuse(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
 static char *transfermode2str(enum transfermodes mode) attribute_const;
-static const char *nat2str(int nat) attribute_const;
 static int peer_status(struct sip_peer *peer, char *status, int statuslen);
 static char *sip_show_sched(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
 static char * _sip_show_peers(int fd, int *total, struct mansession *s, const struct message *m, int argc, const char *argv[]);
@@ -2908,6 +2903,8 @@
 		reqcpy.data = str_save;
 		ast_str_reset(reqcpy.data);
 
+		memset(buf, 0, sizeof(buf));
+
 		if (tcptls_session->ssl) {
 			set_socket_transport(&req.socket, SIP_TRANSPORT_TLS);
 			req.socket.port = htons(ourport_tls);
@@ -3318,13 +3315,13 @@
 	if (p->outboundproxy)
 		return &p->outboundproxy->ip;
 
-	return ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE ? &p->recv : &p->sa;
+	return ast_test_flag(&p->flags[0], SIP_NAT_FORCE_RPORT) || ast_test_flag(&p->flags[0], SIP_NAT_RPORT_PRESENT) ? &p->recv : &p->sa;
 }
 
 /*! \brief Display SIP nat mode */
 static const char *sip_nat_mode(const struct sip_pvt *p)
 {
-	return ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE ? "NAT" : "no NAT";
+	return ast_test_flag(&p->flags[0], SIP_NAT_FORCE_RPORT) ? "NAT" : "no NAT";
 }
 
 /*! \brief Test PVT for debugging output */
@@ -3462,7 +3459,7 @@
 static void build_via(struct sip_pvt *p)
 {
 	/* Work around buggy UNIDEN UIP200 firmware */
-	const char *rport = ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_RFC3581 ? ";rport" : "";
+	const char *rport = (ast_test_flag(&p->flags[0], SIP_NAT_FORCE_RPORT) || ast_test_flag(&p->flags[0], SIP_NAT_RPORT_PRESENT)) ? ";rport" : "";
 
 	/* z9hG4bK is a magic cookie.  See RFC 3261 section 8.1.1.7 */
 	snprintf(p->via, sizeof(p->via), "SIP/2.0/%s %s:%d;branch=z9hG4bK%08x%s",
@@ -4058,7 +4055,7 @@
 
 	add_blank(req);
 	if (sip_debug_test_pvt(p)) {
-		if (ast_test_flag(&p->flags[0], SIP_NAT_ROUTE))
+		if (ast_test_flag(&p->flags[0], SIP_NAT_FORCE_RPORT))
 			ast_verbose("%sTransmitting (NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port), req->data->str);
 		else
 			ast_verbose("%sTransmitting (no NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port), req->data->str);
@@ -4162,7 +4159,6 @@
 		if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT)) {
 			switch (p->t38.state) {
 			case T38_LOCAL_REINVITE:
-			case T38_PEER_DIRECT:
 			case T38_PEER_REINVITE:
 				state = T38_STATE_NEGOTIATING;
 				break;
@@ -4866,9 +4862,13 @@
 }
 
 /*! \brief Set nat mode on the various data sockets */
-static void do_setnat(struct sip_pvt *p, int natflags)
-{
-	const char *mode = natflags ? "On" : "Off";
+static void do_setnat(struct sip_pvt *p)
+{
+	const char *mode;
+	int natflags;
+
+	natflags = ast_test_flag(&p->flags[1], SIP_PAGE2_SYMMETRICRTP);
+	mode = natflags ? "On" : "Off";
 
 	if (p->rtp) {
 		ast_debug(1, "Setting NAT on RTP to %s\n", mode);
@@ -4888,21 +4888,62 @@
 	}
 }
 
+/*! \brief Helper function which interprets T.38 capabilities and fills a parameters structure in */
+static void fill_t38_parameters(int capabilities, struct ast_control_t38_parameters *parameters, struct sip_pvt *p)
+{
+	if (capabilities & T38FAX_VERSION_0) {
+		parameters->version = 0;
+	} else if (capabilities & T38FAX_VERSION_1) {
+		parameters->version = 1;
+	}
+
+	if (capabilities & T38FAX_RATE_14400) {
+		parameters->rate = AST_T38_RATE_14400;
+	} else if (capabilities & T38FAX_RATE_12000) {
+		parameters->rate = AST_T38_RATE_12000;
+	} else if (capabilities & T38FAX_RATE_9600) {
+		parameters->rate = AST_T38_RATE_9600;
+	} else if (capabilities & T38FAX_RATE_7200) {
+		parameters->rate = AST_T38_RATE_7200;
+	} else if (capabilities & T38FAX_RATE_4800) {
+		parameters->rate = AST_T38_RATE_4800;
+	} else if (capabilities & T38FAX_RATE_2400) {
+		parameters->rate = AST_T38_RATE_2400;
+	}
+
+	if (capabilities & T38FAX_RATE_MANAGEMENT_TRANSFERED_TCF) {
+		parameters->rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERED_TCF;
+	} else if (capabilities & T38FAX_RATE_MANAGEMENT_LOCAL_TCF) {
+		parameters->rate_management = AST_T38_RATE_MANAGEMENT_LOCAL_TCF;
+	}
+
+	if (capabilities & T38FAX_FILL_BIT_REMOVAL) {
+		parameters->fill_bit_removal = 1;
+	}
+
+	if (capabilities & T38FAX_TRANSCODING_MMR) {
+		parameters->transcoding_mmr = 1;
+	}
+
+	if (capabilities & T38FAX_TRANSCODING_JBIG) {
+		parameters->transcoding_jbig = 1;
+	}
+
+	parameters->max_datagram = ast_udptl_get_far_max_datagram(p->udptl);
+}
+
 /*! \brief Change the T38 state on a SIP dialog */
 static void change_t38_state(struct sip_pvt *p, int state)
 {
 	int old = p->t38.state;
 	struct ast_channel *chan = p->owner;
 	enum ast_control_t38 message = 0;
+	struct ast_control_t38_parameters parameters = { 0, };
 
 	/* Don't bother changing if we are already in the state wanted */
 	if (old == state)
 		return;
 
-	if (state == T38_PEER_DIRECT) {
-		p->t38.direct = 1;
-	}
-
 	p->t38.state = state;
 	ast_debug(2, "T38 state changed to %d on channel %s\n", p->t38.state, chan ? chan->name : "<none>");
 
@@ -4911,16 +4952,20 @@
 		return;
 
 	/* Given the state requested and old state determine what control frame we want to queue up */
-	if (state == T38_PEER_REINVITE)
-		message = AST_T38_REQUEST_NEGOTIATE;
-	else if (state == T38_ENABLED)
-		message = AST_T38_NEGOTIATED;
-	else if (state == T38_DISABLED && old == T38_ENABLED)
-		message = AST_T38_TERMINATED;
+	if (state == T38_PEER_REINVITE) {
+		message = parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
+		fill_t38_parameters(p->t38.peercapability, &parameters, p);
+	} else if (state == T38_ENABLED) {
+		message = parameters.request_response = AST_T38_NEGOTIATED;
+		fill_t38_parameters(p->t38.jointcapability, &parameters, p);
+	} else if (state == T38_DISABLED && old == T38_ENABLED)
+		message = parameters.request_response = AST_T38_TERMINATED;
 	else if (state == T38_DISABLED && old == T38_LOCAL_REINVITE)
-		message = AST_T38_REFUSED;
+		message = parameters.request_response = AST_T38_REFUSED;
 
 	/* Woot we got a message, create a control frame and send it on! */
+	if (parameters.request_response)
+		ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
 	if (message)
 		ast_queue_control_data(chan, AST_CONTROL_T38, &message, sizeof(message));
 
@@ -4952,12 +4997,16 @@
 {
 	p->t38.capability = global_t38_capability;
 	if (p->udptl) {
-		if (ast_udptl_get_error_correction_scheme(p->udptl) == UDPTL_ERROR_CORRECTION_FEC )
+		if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) == SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY) {
+                        ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_REDUNDANCY);
+			p->t38.capability |= T38FAX_UDP_EC_REDUNDANCY;
+		} else if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) == SIP_PAGE2_T38SUPPORT_UDPTL_FEC) {
+			ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_FEC);
 			p->t38.capability |= T38FAX_UDP_EC_FEC;
-		else if (ast_udptl_get_error_correction_scheme(p->udptl) == UDPTL_ERROR_CORRECTION_REDUNDANCY )
-			p->t38.capability |= T38FAX_UDP_EC_REDUNDANCY;
-		else if (ast_udptl_get_error_correction_scheme(p->udptl) == UDPTL_ERROR_CORRECTION_NONE )
+		} else if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) == SIP_PAGE2_T38SUPPORT_UDPTL) {
+			ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_NONE);
 			p->t38.capability |= T38FAX_UDP_EC_NONE;
+		}
 		p->t38.capability |= T38FAX_RATE_MANAGEMENT_TRANSFERED_TCF;
 	}
 }
@@ -5018,7 +5067,7 @@
 
 	ast_rtp_instance_set_qos(dialog->rtp, global_tos_audio, 0, "SIP RTP");
 
-	do_setnat(dialog, ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE);
+	do_setnat(dialog);
 
 	return 0;
 }
@@ -6135,9 +6184,6 @@
 
 		ast_setstate(ast, AST_STATE_UP);
 		ast_debug(1, "SIP answering channel: %s\n", ast->name);
-		if (p->t38.state == T38_PEER_DIRECT) {
-			change_t38_state(p, T38_ENABLED);
-		}
 		ast_rtp_instance_new_source(p->rtp);
 		res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL, FALSE, TRUE);
 		ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
@@ -6177,7 +6223,7 @@
 					p->invitestate = INV_EARLY_MEDIA;
 					transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE, FALSE);
 					ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
-				} else if (p->t38.state == T38_ENABLED && !p->t38.direct) {
+				} else if (p->t38.state == T38_ENABLED) {
 					change_t38_state(p, T38_DISABLED);
 					transmit_reinvite_with_sdp(p, FALSE, FALSE);
 				} else {
@@ -6375,6 +6421,90 @@
 	return res;
 }
 
+/*! \brief Helper function which updates T.38 capability information and triggers a reinvite */
+static void interpret_t38_parameters(struct sip_pvt *p, enum ast_control_t38 request_response, const struct ast_control_t38_parameters *parameters)
+{
+	if (parameters) {
+		if (!parameters->version) {
+			p->t38.capability = p->t38.jointcapability |= T38FAX_VERSION_0;
+		} else if (parameters->version == 1) {
+			p->t38.capability = p->t38.jointcapability |= T38FAX_VERSION_1;
+		}
+
+		if (parameters->rate == AST_T38_RATE_14400) {
+			p->t38.capability = p->t38.jointcapability |= T38FAX_RATE_14400 | T38FAX_RATE_12000 | T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400;
+		} else if (parameters->rate == AST_T38_RATE_12000) {
+			p->t38.capability = p->t38.jointcapability |= T38FAX_RATE_12000 | T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400;
+		} else if (parameters->rate == AST_T38_RATE_9600) {
+			p->t38.capability = p->t38.jointcapability |= T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400;
+		} else if (parameters->rate == AST_T38_RATE_7200) {
+			p->t38.capability = p->t38.jointcapability |= T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400;
+		} else if (parameters->rate == AST_T38_RATE_4800) {
+			p->t38.capability = p->t38.jointcapability |= T38FAX_RATE_4800 | T38FAX_RATE_2400;
+		} else if (parameters->rate == AST_T38_RATE_2400) {
+			p->t38.capability = p->t38.jointcapability |= T38FAX_RATE_2400;
+		}
+
+		if (parameters->rate_management == AST_T38_RATE_MANAGEMENT_TRANSFERED_TCF) {
+			p->t38.capability = p->t38.jointcapability |= T38FAX_RATE_MANAGEMENT_TRANSFERED_TCF;
+		} else if (parameters->rate_management == AST_T38_RATE_MANAGEMENT_LOCAL_TCF) {
+			p->t38.capability = p->t38.jointcapability |= T38FAX_RATE_MANAGEMENT_LOCAL_TCF;
+		}
+
+		if (parameters->fill_bit_removal) {
+			p->t38.capability = p->t38.jointcapability |= T38FAX_FILL_BIT_REMOVAL;
+		} else {
+			p->t38.capability = p->t38.jointcapability &= ~T38FAX_FILL_BIT_REMOVAL;
+		}
+
+		if (parameters->transcoding_mmr) {
+			p->t38.capability = p->t38.jointcapability |= T38FAX_TRANSCODING_MMR;
+		} else {
+			p->t38.capability = p->t38.jointcapability &= ~T38FAX_TRANSCODING_MMR;
+		}
+
+		if (parameters->transcoding_jbig) {
+			p->t38.capability = p->t38.jointcapability |= T38FAX_TRANSCODING_JBIG;
+		} else {
+			p->t38.capability = p->t38.jointcapability &= ~T38FAX_TRANSCODING_JBIG;
+		}
+
+		if (p->udptl && request_response == AST_T38_REQUEST_NEGOTIATE) {
+			ast_udptl_set_local_max_datagram(p->udptl, parameters->max_datagram ? parameters->max_datagram : 400);
+		}
+	}
+
+	switch (request_response) {
+	case AST_T38_NEGOTIATED:
+	case AST_T38_REQUEST_NEGOTIATE:         /* Request T38 */
+		if (p->t38.state == T38_PEER_REINVITE) {
+			AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr"));
+			change_t38_state(p, T38_ENABLED);
+			transmit_response_with_t38_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
+		} else if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT) && p->t38.state != T38_ENABLED) {
+			change_t38_state(p, T38_LOCAL_REINVITE);
+			if (!p->pendinginvite) {
+				transmit_reinvite_with_sdp(p, TRUE, FALSE);
+			} else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
+				ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
+			}
+		}
+		break;
+	case AST_T38_TERMINATED:
+	case AST_T38_REFUSED:
+	case AST_T38_REQUEST_TERMINATE:         /* Shutdown T38 */
+		if (p->t38.state == T38_PEER_REINVITE) {
+			AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr"));
+			change_t38_state(p, T38_DISABLED);
+			transmit_response_reliable(p, "488 Not acceptable here", &p->initreq);
+		} else if (p->t38.state == T38_ENABLED)
+			transmit_reinvite_with_sdp(p, FALSE, FALSE);
+		break;
+	default:
+		break;
+	}
+}
+
 /*! \brief Play indication to user 
  * With SIP a lot of indications is sent as messages, letting the device play
    the indication - busy signal, congestion etc 
@@ -6463,35 +6593,15 @@
 		if (datalen != sizeof(enum ast_control_t38)) {
 			ast_log(LOG_ERROR, "Invalid datalen for AST_CONTROL_T38. Expected %d, got %d\n", (int)sizeof(enum ast_control_t38), (int)datalen);
 		} else {
-			switch (*((enum ast_control_t38 *) data)) {
-			case AST_T38_NEGOTIATED:
-			case AST_T38_REQUEST_NEGOTIATE:		/* Request T38 */
-				if (p->t38.state == T38_PEER_REINVITE) {
-					AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr"));
-					change_t38_state(p, T38_ENABLED);
-					transmit_response_with_t38_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
-				} else if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT) && p->t38.state != T38_ENABLED) {
-					change_t38_state(p, T38_LOCAL_REINVITE);
-					if (!p->pendinginvite) {
-						transmit_reinvite_with_sdp(p, TRUE, FALSE);
-					} else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
-						ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
-					}
-				}
-				break;
-			case AST_T38_TERMINATED:
-			case AST_T38_REFUSED:
-			case AST_T38_REQUEST_TERMINATE:		/* Shutdown T38 */
-				if (p->t38.state == T38_PEER_REINVITE) {
-					AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr"));
-					change_t38_state(p, T38_DISABLED);
-					transmit_response_reliable(p, "488 Not acceptable here", &p->initreq);
-				} else if (p->t38.state == T38_ENABLED)
-					transmit_reinvite_with_sdp(p, FALSE, FALSE);
-				break;
-			default:
-				break;
-			}
+			interpret_t38_parameters(p, *((enum ast_control_t38 *) data), NULL);
+		}
+		break;
+	case AST_CONTROL_T38_PARAMETERS:
+		if (datalen != sizeof(struct ast_control_t38_parameters)) {
+			ast_log(LOG_ERROR, "Invalid datalen for AST_CONTROL_T38_PARAMETERS. Expected %d, got %d\n", (int)sizeof(struct ast_control_t38_parameters), (int)datalen);
+		} else {
+			const struct ast_control_t38_parameters *parameters = data;
+			interpret_t38_parameters(p, parameters->request_response, parameters);
 		}
 		break;
 	case AST_CONTROL_SRCUPDATE:
@@ -6922,7 +7032,7 @@
 	if (f && p->dsp) {
 		f = ast_dsp_process(p->owner, p->dsp, f);
 		if (f && f->frametype == AST_FRAME_DTMF) {
-			if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_UDPTL) && f->subclass == 'f') {
+			if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT) && f->subclass == 'f') {
 				ast_debug(1, "Fax CNG detected on %s\n", ast->name);
 				*faxdetect = 1;
 			} else {
@@ -6947,7 +7057,7 @@
 
 	/* If we are NOT bridged to another channel, and we have detected fax tone we issue T38 re-invite to a peer */
 	/* If we are bridged then it is the responsibility of the SIP device to issue T38 re-invite if it detects CNG or fax preamble */
-	if (faxdetected && ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_UDPTL) && (p->t38.state == T38_DISABLED) && !(ast_bridged_channel(ast))) {
+	if (faxdetected && ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT) && (p->t38.state == T38_DISABLED) && !(ast_bridged_channel(ast))) {
 		if (!ast_test_flag(&p->flags[0], SIP_GOTREFER)) {
 			if (!p->pendinginvite) {
 				ast_debug(3, "Sending reinvite on SIP (%s) for T.38 negotiation.\n", ast->name);
@@ -7100,9 +7210,9 @@
 
 	if (useglobal_nat && sin) {
 		/* Setup NAT structure according to global settings if we have an address */
-		ast_copy_flags(&p->flags[0], &global_flags[0], SIP_NAT);
+		ast_copy_flags(&p->flags[0], &global_flags[0], SIP_NAT_FORCE_RPORT);
 		p->recv = *sin;
-		do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE);
+		do_setnat(p);
 	}
 
 	if (p->method != SIP_REGISTER)
@@ -8172,7 +8282,7 @@
 	if (p->udptl) {
 		if (udptlportno > 0) {
 			sin.sin_port = htons(udptlportno);
-			if (ast_test_flag(&p->flags[0], SIP_NAT) && ast_test_flag(&p->flags[1], SIP_PAGE2_UDPTL_DESTINATION)) {

[... 925 lines stripped ...]



More information about the svn-commits mailing list