[asterisk-commits] rmudgett: branch rmudgett/mcid r267301 - in /team/rmudgett/mcid: ./ apps/ cha...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jun 2 16:33:46 CDT 2010


Author: rmudgett
Date: Wed Jun  2 16:33:40 2010
New Revision: 267301

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=267301
Log:
Merged revisions 266926,267008,267041,267065,267093,267096-267097,267138,267181,267261 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/trunk

................
  r266926 | rmudgett | 2010-06-02 11:14:12 -0500 (Wed, 02 Jun 2010) | 11 lines
  
  Add ETSI Explicit Call Transfer (ECT) support.
  
  Added ability to send and receive ETSI Explicit Call Transfer (ECT)
  messages to eliminate tromboned calls.
  
  Note: Asterisk already supported initiating the transfer of calls to
  eliminate tromboned calls to libpri so there was nothing to do for the
  asterisk portion.
  
  Review:	https://reviewboard.asterisk.org/r/520/
................
  r267008 | rmudgett | 2010-06-02 12:13:53 -0500 (Wed, 02 Jun 2010) | 7 lines
  
  Add ETSI Advice Of Charge (AOC) event reporting.
  
  This feature generates AMI events in the new aoc event class from the
  events passed up by libpri.
  
  Review:	https://reviewboard.asterisk.org/r/537/
................
  r267041 | pabelanger | 2010-06-02 12:25:05 -0500 (Wed, 02 Jun 2010) | 14 lines
  
  Merged revisions 267009 via svnmerge from 
  https://origsvn.digium.com/svn/asterisk/branches/1.4
  
  ........
    r267009 | pabelanger | 2010-06-02 13:14:37 -0400 (Wed, 02 Jun 2010) | 7 lines
    
    Cleanup error/warning messages in AEL2 parser
    
    (closes issue #16684)
    Reported by: Silmaril
    Patches:
          patch_ael2_logmsg.diff uploaded by Silmaril (license 979)
  ........
................
  r267065 | jpeeler | 2010-06-02 12:29:35 -0500 (Wed, 02 Jun 2010) | 12 lines
  
  Fix infinite loop when loading codec speex
  
  This changes the sample slinear frame data to contain non-zero data so that
  translation calculations for speex works when preprocessing and VAD is turned
  on. The encoder expects samples to be returned, but when attempted with the
  mentioned two options and silent sample frames everything was discarded. 
  
  (closes issue #17240)
  Reported by: seandarcy
  
  Review: https://reviewboard.asterisk.org/r/682/
................
  r267093 | russell | 2010-06-02 12:57:39 -0500 (Wed, 02 Jun 2010) | 2 lines
  
  Silence a compiler warning.
................
  r267096 | rmudgett | 2010-06-02 13:10:15 -0500 (Wed, 02 Jun 2010) | 38 lines
  
  Generic Advice of Charge.
  
  Asterisk Generic AOC Representation
  - Generic AOC encode/decode routines.
    (Generic AOC must be encoded to be passed on the wire in the AST_CONTROL_AOC frame)
  - AST_CONTROL_AOC frame type to represent generic encoded AOC data
  - Manager events for AOC-S, AOC-D, and AOC-E messages
  
  Asterisk App Support
  - app_dial AOC-S pass-through support on call setup
  - app_queue AOC-S pass-through support on call setup
  
  AOC Unit Tests
  - AOC Unit Tests for encode/decode routines
  - AOC Unit Test for manager event representation.
  
  SIP AOC Support
  - Pass-through of generic AOC-D and AOC-E messages to snom phones via the
    snom AOC specification.
  - Creation of chan_sip page3 flags for the addition of the new
    'snom_aoc_enabled' sip.conf option.
  
  IAX AOC Support
  - Natively supports AOC pass-through through the use of the new
    AST_CONTROL_AOC frame type
  
  DAHDI AOC Support
  - ETSI PRI full AOC Pass-through support
  - 'aoc_enable' chan_dahdi.conf option for independently enabling
    pass-through of AOC-S, AOC-D, AOC-E.
  - 'aoce_delayhangup' option for retrieving AOC-E on disconnect.
  - DAHDI A() dial string option for requesting AOC services.
    example usage:
    ;requests AOC-S, AOC-D, and AOC-E on call setup
    exten=>1111,1,Dial(DAHDI/g1/1112/A(s,d,e))
  
  Review:	https://reviewboard.asterisk.org/r/552/
................
  r267097 | mmichelson | 2010-06-02 13:13:18 -0500 (Wed, 02 Jun 2010) | 9 lines
  
  Prevent use of uninitialized values.
  
  Two struct sockaddr_ins are created when applying directmedia
  host access rules. The addresses of these are passed to the RTP
  engine to be filled in. However, the RTP engine inspects the fields
  of the structs before actually taking action. This inspection caused
  valgrind to be a bit unhappy.
................
  r267138 | russell | 2010-06-02 13:53:38 -0500 (Wed, 02 Jun 2010) | 4 lines
  
  Add a CLI command that blocks until Asterisk has fully booted.
  
  Review: https://reviewboard.asterisk.org/r/684/
................
  r267181 | dvossel | 2010-06-02 14:33:56 -0500 (Wed, 02 Jun 2010) | 2 lines
  
  Update CHANGES and aoc help doc to reflect AOC additions
................
  r267261 | rmudgett | 2010-06-02 16:05:32 -0500 (Wed, 02 Jun 2010) | 20 lines
  
  Add ETSI Call Waiting support.
  
  Add the ability to announce a call to an endpoint when there are no B
  channels available.  A call waiting call is a SETUP message with no B
  channel selected.
  
  Relevant specification: EN 300 056, EN 300 057, EN 300 058
  
  For DAHDI/ISDN channels, the CHANNEL() dialplan function now supports the
  "no_media_path" option.
  * Returns "0" if there is a B channel associated with the call.
  * Returns "1" if no B channel is associated with the call.  The call is
  either on hold or is a call waiting call.
  
  If you are going to allow incoming call waiting calls then you need to use
  CHANNEL(no_media_path) do determine if you must drop a call to accept the
  new call.
  
  Review:	https://reviewboard.asterisk.org/r/568/
................

Added:
    team/rmudgett/mcid/doc/advice_of_charge.txt
      - copied unchanged from r267261, trunk/doc/advice_of_charge.txt
    team/rmudgett/mcid/include/asterisk/aoc.h
      - copied unchanged from r267261, trunk/include/asterisk/aoc.h
    team/rmudgett/mcid/main/aoc.c
      - copied unchanged from r267261, trunk/main/aoc.c
    team/rmudgett/mcid/tests/test_aoc.c
      - copied unchanged from r267261, trunk/tests/test_aoc.c
Modified:
    team/rmudgett/mcid/   (props changed)
    team/rmudgett/mcid/CHANGES
    team/rmudgett/mcid/apps/app_dial.c
    team/rmudgett/mcid/apps/app_queue.c
    team/rmudgett/mcid/apps/app_voicemail.c
    team/rmudgett/mcid/channels/chan_dahdi.c
    team/rmudgett/mcid/channels/chan_sip.c
    team/rmudgett/mcid/channels/sig_pri.c
    team/rmudgett/mcid/channels/sig_pri.h
    team/rmudgett/mcid/channels/sip/include/sip.h
    team/rmudgett/mcid/configs/chan_dahdi.conf.sample
    team/rmudgett/mcid/configs/manager.conf.sample
    team/rmudgett/mcid/configs/sip.conf.sample
    team/rmudgett/mcid/configure
    team/rmudgett/mcid/configure.ac
    team/rmudgett/mcid/include/asterisk/autoconfig.h.in
    team/rmudgett/mcid/include/asterisk/frame.h
    team/rmudgett/mcid/include/asterisk/manager.h
    team/rmudgett/mcid/include/asterisk/slin.h
    team/rmudgett/mcid/main/ast_expr2.y
    team/rmudgett/mcid/main/asterisk.c
    team/rmudgett/mcid/main/channel.c
    team/rmudgett/mcid/main/cli.c
    team/rmudgett/mcid/main/features.c
    team/rmudgett/mcid/main/manager.c

Propchange: team/rmudgett/mcid/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/rmudgett/mcid/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Propchange: team/rmudgett/mcid/
------------------------------------------------------------------------------
--- mcid-integrated (original)
+++ mcid-integrated Wed Jun  2 16:33:40 2010
@@ -1,1 +1,1 @@
-/trunk:1-266909
+/trunk:1-267261

Modified: team/rmudgett/mcid/CHANGES
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/mcid/CHANGES?view=diff&rev=267301&r1=267300&r2=267301
==============================================================================
--- team/rmudgett/mcid/CHANGES (original)
+++ team/rmudgett/mcid/CHANGES Wed Jun  2 16:33:40 2010
@@ -61,6 +61,8 @@
    the particular peer. The dialstring format is SIP/peer/exten/host_or_IP.
  * Added directmediapermit/directmediadeny to limit which peers can send direct media
    to each other
+ * Added the 'snom_aoc_enabled' option to turn on support for sending Advice of
+   Charge messages to snom phones.
 
 IAX2 Changes
 -----------
@@ -203,6 +205,11 @@
    prefixing the name of the hash at assignment with the appropriate number of
    underscores, just like variables.
  * GROUP_MATCH_COUNT has been improved to allow regex matching on category
+ * For DAHDI/ISDN channels, the CHANNEL() dialplan function now supports the
+   "no_media_path" option.
+   Returns "0" if there is a B channel associated with the call.
+   Returns "1" if no B channel is associated with the call.  The call is either
+   on hold or is a call waiting call.
 
 Dialplan Variables
 ------------------
@@ -332,6 +339,13 @@
    dialing option.  Dial(DAHDI/g1/[extension]/K(<keypad_digits>))
    Access any received keypad digits in SETUP message by: ${CHANNEL(keypad_digits)}
    (requires latest LibPRI)
+ * Added ability to send and receive ETSI Explicit Call Transfer (ECT) messages
+   to eliminate tromboned calls.  A tromboned call goes out an interface and comes
+   back into the same interface.  Tromboned calls happen because of call routing,
+   call deflection, call forwarding, and call transfer.
+ * Added the ability to send and receive ETSI Advice-Of-Charge messages. 
+ * Added the ability to support call waiting calls.  (The SETUP has no B channel
+   assigned.)
  * Added Malicious Call ID (MCID) event to the AMI call event class.
 
 Asterisk Manager Interface
@@ -361,6 +375,10 @@
    in a MixMonitor recording.
  * The 'iax2 show peers' output is now similar to the expected output of
    'sip show peers'.
+ * Added Advice-Of-Charge events (AOC-S, AOC-D, and AOC-E) in the new
+   aoc event class.
+ * Added Advice-Of-Charge manager action, AOCMessage, for generating AOC-D and
+   AOC-E messages on a channel.
 
 Channel Event Logging
 ---------------------

Modified: team/rmudgett/mcid/apps/app_dial.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/mcid/apps/app_dial.c?view=diff&rev=267301&r1=267300&r2=267301
==============================================================================
--- team/rmudgett/mcid/apps/app_dial.c (original)
+++ team/rmudgett/mcid/apps/app_dial.c Wed Jun  2 16:33:40 2010
@@ -62,6 +62,7 @@
 #include "asterisk/global_datastores.h"
 #include "asterisk/dsp.h"
 #include "asterisk/cel.h"
+#include "asterisk/aoc.h"
 #include "asterisk/ccss.h"
 #include "asterisk/indications.h"
 
@@ -638,6 +639,7 @@
 	struct ast_party_connected_line connected;
 	/*! TRUE if an AST_CONTROL_CONNECTED_LINE update was saved to the connected element. */
 	unsigned int pending_connected_update:1;
+	struct ast_aoc_decoded *aoc_s_rate_list;
 };
 
 static int detect_disconnect(struct ast_channel *chan, char code, struct ast_str *featurecode);
@@ -645,6 +647,7 @@
 static void chanlist_free(struct chanlist *outgoing)
 {
 	ast_party_connected_line_free(&outgoing->connected);
+	ast_aoc_destroy_decoded(outgoing->aoc_s_rate_list);
 	ast_free(outgoing);
 }
 
@@ -1053,6 +1056,14 @@
 							ast_party_connected_line_free(&connected_caller);
 						}
 					}
+					if (o->aoc_s_rate_list) {
+						size_t encoded_size;
+						struct ast_aoc_encoded *encoded;
+						if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) {
+							ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size);
+							ast_aoc_destroy_encoded(encoded);
+						}
+					}
 					peer = c;
 					ast_copy_flags64(peerflags, o,
 						OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
@@ -1113,6 +1124,14 @@
 								connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
 								ast_channel_update_connected_line(in, &connected_caller);
 								ast_party_connected_line_free(&connected_caller);
+							}
+						}
+						if (o->aoc_s_rate_list) {
+							size_t encoded_size;
+							struct ast_aoc_encoded *encoded;
+							if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) {
+								ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size);
+								ast_aoc_destroy_encoded(encoded);
 							}
 						}
 						peer = c;
@@ -1230,6 +1249,17 @@
 						}
 					}
 					break;
+				case AST_CONTROL_AOC:
+					{
+						struct ast_aoc_decoded *decoded = ast_aoc_decode(f->data.ptr, f->datalen, o->chan);
+						if (decoded && (ast_aoc_get_msg_type(decoded) == AST_AOC_S)) {
+							ast_aoc_destroy_decoded(o->aoc_s_rate_list);
+							o->aoc_s_rate_list = decoded;
+						} else {
+							ast_aoc_destroy_decoded(decoded);
+						}
+					}
+					break;
 				case AST_CONTROL_REDIRECTING:
 					if (ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
 						ast_verb(3, "Redirecting update to %s prevented.\n", in->name);

Modified: team/rmudgett/mcid/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/mcid/apps/app_queue.c?view=diff&rev=267301&r1=267300&r2=267301
==============================================================================
--- team/rmudgett/mcid/apps/app_queue.c (original)
+++ team/rmudgett/mcid/apps/app_queue.c Wed Jun  2 16:33:40 2010
@@ -94,6 +94,7 @@
 #include "asterisk/strings.h"
 #include "asterisk/global_datastores.h"
 #include "asterisk/taskprocessor.h"
+#include "asterisk/aoc.h"
 #include "asterisk/callerid.h"
 #include "asterisk/cel.h"
 #include "asterisk/data.h"
@@ -820,6 +821,7 @@
 	unsigned int pending_connected_update:1;
 	/*! TRUE if caller id is not available for connected line */
 	unsigned int dial_callerid_absent:1;
+	struct ast_aoc_decoded *aoc_s_rate_list;
 };
 
 
@@ -2654,6 +2656,7 @@
 		}
 		oo = outgoing;
 		outgoing = outgoing->q_next;
+		ast_aoc_destroy_decoded(oo->aoc_s_rate_list);
 		callattempt_free(oo);
 	}
 }
@@ -3333,6 +3336,14 @@
 							connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
 							ast_channel_update_connected_line(in, &connected_caller);
 							ast_party_connected_line_free(&connected_caller);
+						}
+					}
+					if (o->aoc_s_rate_list) {
+						size_t encoded_size;
+						struct ast_aoc_encoded *encoded;
+						if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) {
+							ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size);
+							ast_aoc_destroy_encoded(encoded);
 						}
 					}
 					peer = o;
@@ -3452,6 +3463,14 @@
 										connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
 										ast_channel_update_connected_line(in, &connected_caller);
 										ast_party_connected_line_free(&connected_caller);
+									}
+								}
+								if (o->aoc_s_rate_list) {
+									size_t encoded_size;
+									struct ast_aoc_encoded *encoded;
+									if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) {
+										ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size);
+										ast_aoc_destroy_encoded(encoded);
 									}
 								}
 								peer = o;
@@ -3520,6 +3539,17 @@
 							} else {
 								if (ast_channel_connected_line_macro(o->chan, in, f, 1, 1)) {
 									ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
+								}
+							}
+							break;
+						case AST_CONTROL_AOC:
+							{
+								struct ast_aoc_decoded *decoded = ast_aoc_decode(f->data.ptr, f->datalen, o->chan);
+								if (decoded && (ast_aoc_get_msg_type(decoded) == AST_AOC_S)) {
+									ast_aoc_destroy_decoded(o->aoc_s_rate_list);
+									o->aoc_s_rate_list = decoded;
+								} else {
+									ast_aoc_destroy_decoded(decoded);
 								}
 							}
 							break;

Modified: team/rmudgett/mcid/apps/app_voicemail.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/mcid/apps/app_voicemail.c?view=diff&rev=267301&r1=267300&r2=267301
==============================================================================
--- team/rmudgett/mcid/apps/app_voicemail.c (original)
+++ team/rmudgett/mcid/apps/app_voicemail.c Wed Jun  2 16:33:40 2010
@@ -12395,7 +12395,9 @@
 	char attach[] = "/var/lib/asterisk/sounds/en/tt-weasels", attach2[] = "/var/lib/asterisk/sounds/en/tt-somethingwrong";
 	char buf[256] = ""; /* No line should actually be longer than 80 */
 	struct ast_channel *chan = NULL;
-	struct ast_vm_user *vmu, vmus;
+	struct ast_vm_user *vmu, vmus = {
+		.flags = 0,
+	};
 	FILE *file;
 	struct {
 		char *name;

Modified: team/rmudgett/mcid/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/mcid/channels/chan_dahdi.c?view=diff&rev=267301&r1=267300&r2=267301
==============================================================================
--- team/rmudgett/mcid/channels/chan_dahdi.c (original)
+++ team/rmudgett/mcid/channels/chan_dahdi.c Wed Jun  2 16:33:40 2010
@@ -800,7 +800,10 @@
 	unsigned int didtdd:1;				/*!< flag to say its done it once */
 	/*! \brief TRUE if analog type line dialed no digits in Dial() */
 	unsigned int dialednone:1;
-	/*! \brief TRUE if in the process of dialing digits or sending something. */
+	/*!
+	 * \brief TRUE if in the process of dialing digits or sending something.
+	 * \note This is used as a receive squelch for ISDN until connected.
+	 */
 	unsigned int dialing:1;
 	/*! \brief TRUE if the transfer capability of the call is digital. */
 	unsigned int digital:1;
@@ -1075,6 +1078,8 @@
 	 * \note The "group" bitmapped group string read in from chan_dahdi.conf
 	 */
 	ast_group_t group;
+	/*! \brief Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW. */
+	int law_default;
 	/*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
 	int law;
 	int confno;					/*!< Our conference */
@@ -2232,7 +2237,8 @@
 		p->dsp = NULL;
 	}
 
-	law = DAHDI_LAW_DEFAULT;
+	p->law = p->law_default;
+	law = p->law_default;
 	res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
 	if (res < 0)
 		ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
@@ -2391,10 +2397,22 @@
 	int audio;
 	int newlaw = -1;
 
-	/* Set to audio mode at this point */
-	audio = 1;
-	if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
-		ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, audio, strerror(errno));
+	switch (p->sig) {
+	case SIG_PRI_LIB_HANDLE_CASES:
+		if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
+			/* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
+			break;
+		}
+		/* Fall through */
+	default:
+		/* Set to audio mode at this point */
+		audio = 1;
+		if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
+			ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
+				p->channel, audio, strerror(errno));
+		}
+		break;
+	}
 
 	if (law != SIG_PRI_DEFLAW) {
 		dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
@@ -2414,6 +2432,54 @@
 			break;
 	}
 	return dahdi_new(p, state, startpbx, SUB_REAL, newlaw, transfercapability, requestor ? requestor->linkedid : "");
+}
+#endif	/* defined(HAVE_PRI) */
+
+static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
+
+#if defined(HAVE_PRI)
+/*!
+ * \internal
+ * \brief Open the PRI channel media path.
+ * \since 1.8
+ *
+ * \param p Channel private control structure.
+ *
+ * \return Nothing
+ */
+static void my_pri_open_media(void *p)
+{
+	struct dahdi_pvt *pvt = p;
+	int res;
+	int dfd;
+	int set_val;
+
+	dfd = pvt->subs[SUB_REAL].dfd;
+
+	/* Open the media path. */
+	set_val = 1;
+	res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
+	if (res < 0) {
+		ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
+			pvt->channel, strerror(errno));
+	}
+
+	/* Set correct companding law for this call. */
+	res = dahdi_setlaw(dfd, pvt->law);
+	if (res < 0) {
+		ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
+	}
+
+	/* Set correct gain for this call. */
+	if (pvt->digital) {
+		res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
+	} else {
+		res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
+			pvt->law);
+	}
+	if (res < 0) {
+		ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
+	}
 }
 #endif	/* defined(HAVE_PRI) */
 
@@ -2734,6 +2800,17 @@
 	new_chan->dsp_features = old_chan->dsp_features;
 	old_chan->dsp = NULL;
 	old_chan->dsp_features = 0;
+
+	/* Transfer flags from the old channel. */
+	new_chan->dialing = old_chan->dialing;
+	new_chan->digital = old_chan->digital;
+	new_chan->outgoing = old_chan->outgoing;
+	old_chan->dialing = 0;
+	old_chan->digital = 0;
+	old_chan->outgoing = 0;
+
+	/* More stuff to transfer to the new channel. */
+	new_chan->law = old_chan->law;
 }
 
 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
@@ -2997,6 +3074,9 @@
 	ast_module_unref(ast_module_info->self);
 }
 
+#if defined(HAVE_PRI_CALL_WAITING)
+static void my_pri_init_config(void *priv, struct sig_pri_pri *pri);
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
 static int dahdi_new_pri_nobch_channel(struct sig_pri_pri *pri);
 
 static struct sig_pri_callback dahdi_pri_callbacks =
@@ -3016,11 +3096,15 @@
 	.set_dnid = my_pri_set_dnid,
 	.set_rdnis = my_pri_set_rdnis,
 	.new_nobch_intf = dahdi_new_pri_nobch_channel,
+#if defined(HAVE_PRI_CALL_WAITING)
+	.init_config = my_pri_init_config,
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
 	.get_orig_dialstring = my_get_orig_dialstring,
 	.make_cc_dialstring = my_pri_make_cc_dialstring,
 	.update_span_devstate = dahdi_pri_update_span_devstate,
 	.module_ref = my_module_ref,
 	.module_unref = my_module_unref,
+	.open_media = my_pri_open_media,
 };
 #endif	/* defined(HAVE_PRI) */
 
@@ -3155,6 +3239,7 @@
 	.set_needringing = my_set_needringing,
 };
 
+/*! Round robin search locations. */
 static struct dahdi_pvt *round_robin[32];
 
 #if defined(HAVE_SS7)
@@ -4179,7 +4264,7 @@
 	if (slavechannel < 1) {
 		p->confno = zi.confno;
 	}
-	memcpy(&c->curconf, &zi, sizeof(c->curconf));
+	c->curconf = zi;
 	ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
 	return 0;
 }
@@ -4850,13 +4935,8 @@
 
 #ifdef HAVE_PRI
 	if (dahdi_sig_pri_lib_handles(p->sig)) {
-		struct dahdi_params ps;
-
-		memset(&ps, 0, sizeof(ps));
-		if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps)) {
-			ast_log(LOG_ERROR, "Could not get params\n");
-		}
-		res = sig_pri_call(p->sig_pvt, ast, rdest, timeout, (ps.curlaw == DAHDI_LAW_MULAW) ? PRI_LAYER_1_ULAW : PRI_LAYER_1_ALAW);
+		res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
+			(p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
 		ast_mutex_unlock(&p->lock);
 		return res;
 	}
@@ -5736,7 +5816,8 @@
 		}
 		revert_fax_buffers(p, ast);
 		dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
-		law = DAHDI_LAW_DEFAULT;
+		p->law = p->law_default;
+		law = p->law_default;
 		res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
 		dahdi_disable_ec(p);
 		update_conf(p);
@@ -5907,7 +5988,8 @@
 
 		revert_fax_buffers(p, ast);
 
-		law = DAHDI_LAW_DEFAULT;
+		p->law = p->law_default;
+		law = p->law_default;
 		res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
 		if (res < 0)
 			ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
@@ -6464,6 +6546,22 @@
 		}
 		ast_mutex_unlock(&p->lock);
 #endif	/* defined(HAVE_PRI_SETUP_KEYPAD) */
+	} else if (!strcasecmp(data, "no_media_path")) {
+		ast_mutex_lock(&p->lock);
+		switch (p->sig) {
+		case SIG_PRI_LIB_HANDLE_CASES:
+			/*
+			 * TRUE if the call is on hold or is call waiting because
+			 * there is no media path available.
+			 */
+			snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
+			break;
+		default:
+			*buf = '\0';
+			res = -1;
+			break;
+		}
+		ast_mutex_unlock(&p->lock);
 #endif	/* defined(HAVE_PRI) */
 	} else {
 		*buf = '\0';
@@ -6904,7 +7002,7 @@
 #ifdef PRI_2BCT
 		if (!triedtopribridge) {
 			triedtopribridge = 1;
-			if (p0->pri && p0->pri == p1->pri && p0->transfer && p1->transfer) {
+			if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
 				ast_mutex_lock(&p0->pri->lock);
 				switch (p0->sig) {
 				case SIG_PRI_LIB_HANDLE_CASES:
@@ -8871,12 +8969,10 @@
 {
 	struct ast_channel *tmp;
 	format_t deflaw;
-	int res;
 	int x;
 	int features;
 	struct ast_str *chan_name;
 	struct ast_variable *v;
-	struct dahdi_params ps;
 
 	if (i->subs[idx].owner) {
 		ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
@@ -8907,21 +9003,29 @@
 	}
 #endif	/* defined(HAVE_PRI) */
 	ast_channel_cc_params_init(tmp, i->cc_params);
-	memset(&ps, 0, sizeof(ps));
-	res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
-	if (res) {
-		ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
-		ps.curlaw = DAHDI_LAW_MULAW;
-	}
-	if (ps.curlaw == DAHDI_LAW_ALAW)
-		deflaw = AST_FORMAT_ALAW;
-	else
-		deflaw = AST_FORMAT_ULAW;
 	if (law) {
-		if (law == DAHDI_LAW_ALAW)
+		i->law = law;
+		if (law == DAHDI_LAW_ALAW) {
 			deflaw = AST_FORMAT_ALAW;
-		else
+		} else {
 			deflaw = AST_FORMAT_ULAW;
+		}
+	} else {
+		switch (i->sig) {
+		case SIG_PRI_LIB_HANDLE_CASES:
+			/* Make sure companding law is known. */
+			i->law = (i->law_default == DAHDI_LAW_ALAW)
+				? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
+			break;
+		default:
+			i->law = i->law_default;
+			break;
+		}
+		if (i->law_default == DAHDI_LAW_ALAW) {
+			deflaw = AST_FORMAT_ALAW;
+		} else {
+			deflaw = AST_FORMAT_ULAW;
+		}
 	}
 	ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
 	tmp->nativeformats = deflaw;
@@ -11538,6 +11642,7 @@
 					destroy_dahdi_pvt(tmp);
 					return NULL;
 				}
+				tmp->law_default = p.curlaw;
 				tmp->law = p.curlaw;
 				tmp->span = p.spanno;
 				span = p.spanno - 1;
@@ -11777,7 +11882,18 @@
 						pris[span].pri.cc_qsig_signaling_link_rsp =
 							conf->pri.pri.cc_qsig_signaling_link_rsp;
 #endif	/* defined(HAVE_PRI_CCSS) */
+#if defined(HAVE_PRI_CALL_WAITING)
+						pris[span].pri.max_call_waiting_calls =
+							conf->pri.pri.max_call_waiting_calls;
+						pris[span].pri.allow_call_waiting_calls =
+							conf->pri.pri.allow_call_waiting_calls;
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
+						pris[span].pri.transfer = conf->chan.transfer;
 						pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
+#if defined(HAVE_PRI_AOC_EVENTS)
+						pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
+						pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
+#endif	/* defined(HAVE_PRI_AOC_EVENTS) */
 						ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
 						ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
 						ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
@@ -11791,6 +11907,20 @@
 						for (x = 0; x < PRI_MAX_TIMERS; x++) {
 							pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
 						}
+
+#if defined(HAVE_PRI_CALL_WAITING)
+						/* Channel initial config parameters. */
+						pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
+						pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
+						pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
+						pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
+						pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
+						pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
+						pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
+						pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
+						ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
+						ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
 					} else {
 						ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
 						destroy_dahdi_pvt(tmp);
@@ -12261,8 +12391,10 @@
 	return 1;
 }
 
-static int available(struct dahdi_pvt *p)
-{
+static int available(struct dahdi_pvt **pvt, int is_specific_channel)
+{
+	struct dahdi_pvt *p = *pvt;
+
 	if (p->inalarm)
 		return 0;
 
@@ -12272,7 +12404,15 @@
 #ifdef HAVE_PRI
 	switch (p->sig) {
 	case SIG_PRI_LIB_HANDLE_CASES:
-		return sig_pri_available(p->sig_pvt);
+		{
+			struct sig_pri_chan *pvt_chan;
+			int res;
+
+			pvt_chan = p->sig_pvt;
+			res = sig_pri_available(&pvt_chan, is_specific_channel);
+			*pvt = pvt_chan->chan_pvt;
+			return res;
+		}
 	default:
 		break;
 	}
@@ -12309,6 +12449,38 @@
 
 	return 0;
 }
+
+#if defined(HAVE_PRI)
+#if defined(HAVE_PRI_CALL_WAITING)
+/*!
+ * \internal
+ * \brief Init the private channel configuration using the span controller.
+ * \since 1.8
+ *
+ * \param priv Channel to init the configuration.
+ * \param pri sig_pri PRI control structure.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ *
+ * \return Nothing
+ */
+static void my_pri_init_config(void *priv, struct sig_pri_pri *pri)
+{
+	struct dahdi_pvt *pvt = priv;
+
+	pvt->stripmsd = pri->ch_cfg.stripmsd;
+	pvt->hidecallerid = pri->ch_cfg.hidecallerid;
+	pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
+	pvt->immediate = pri->ch_cfg.immediate;
+	pvt->priexclusive = pri->ch_cfg.priexclusive;
+	pvt->priindication_oob = pri->ch_cfg.priindication_oob;
+	pvt->use_callerid = pri->ch_cfg.use_callerid;
+	pvt->use_callingpres = pri->ch_cfg.use_callingpres;
+	ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
+	ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
+}
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
+#endif	/* defined(HAVE_PRI) */
 
 #if defined(HAVE_PRI)
 /*!
@@ -12376,7 +12548,15 @@
 	}
 	chan->no_b_channel = 1;
 
+	/*
+	 * Pseudo channel companding law.
+	 * Needed for outgoing call waiting calls.
+	 * XXX May need to make this determined by switchtype or user option.
+	 */
+	pvt->law_default = DAHDI_LAW_ALAW;
+
 	pvt->sig = pri->sig;
+	pvt->outsigmod = -1;
 	pvt->pri = pri;
 	pvt->sig_pvt = chan;
 	pri->pvts[pvt_idx] = chan;
@@ -12572,13 +12752,18 @@
 			} else
 				p = iflist;
 		} else {
+			if (ARRAY_LEN(round_robin) <= x) {
+				ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
+					x, data);
+				return NULL;
+			}
 			if (args.group[0] == 'R') {
 				param->backwards = 1;
-				p = round_robin[x]?round_robin[x]->prev:ifend;
+				p = round_robin[x] ? round_robin[x]->prev : ifend;
 				if (!p)
 					p = ifend;
 			} else {
-				p = round_robin[x]?round_robin[x]->next:iflist;
+				p = round_robin[x] ? round_robin[x]->next : iflist;
 				if (!p)
 					p = iflist;
 			}
@@ -12638,7 +12823,7 @@
 			round_robin[start.rr_starting_point] = p;
 
 		if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
-			&& available(p)) {
+			&& available(&p, channelmatched)) {
 			ast_debug(1, "Using channel %d\n", p->channel);
 
 			callwait = (p->owner != NULL);
@@ -12697,6 +12882,20 @@
 			}
 			if (!tmp) {
 				p->outgoing = 0;
+#if defined(HAVE_PRI)
+#if defined(HAVE_PRI_CALL_WAITING)
+				switch (p->sig) {
+				case SIG_PRI_LIB_HANDLE_CASES:
+					if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
+						((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
+						ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
+					}
+					break;
+				default:
+					break;
+				}
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
+#endif	/* defined(HAVE_PRI) */
 			} else {
 				snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
 			}
@@ -15085,7 +15284,7 @@
 			ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
 			ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
 			ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
-			ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
+			ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
 			ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
 			ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
 			ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
@@ -17194,6 +17393,21 @@
 #endif /* PRI_GETSET_TIMERS */
 			} else if (!strcasecmp(v->name, "facilityenable")) {
 				confp->pri.pri.facilityenable = ast_true(v->value);
+#if defined(HAVE_PRI_AOC_EVENTS)
+			} else if (!strcasecmp(v->name, "aoc_enable")) {
+				confp->pri.pri.aoc_passthrough_flag = 0;
+				if (strchr(v->value, 's') || strchr(v->value, 'S')) {
+					confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
+				}
+				if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
+					confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
+				}
+				if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
+					confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
+				}
+			} else if (!strcasecmp(v->name, "aoce_delayhangup")) {
+				confp->pri.pri.aoce_delayhangup = ast_true(v->value);
+#endif	/* defined(HAVE_PRI_AOC_EVENTS) */
 #if defined(HAVE_PRI_CALL_HOLD)
 			} else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
 				confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
@@ -17226,6 +17440,16 @@
 					confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
 				}
 #endif	/* defined(HAVE_PRI_CCSS) */
+#if defined(HAVE_PRI_CALL_WAITING)
+			} else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
+				confp->pri.pri.max_call_waiting_calls = atoi(v->value);
+				if (confp->pri.pri.max_call_waiting_calls < 0) {
+					/* Negative values are not allowed. */
+					confp->pri.pri.max_call_waiting_calls = 0;
+				}
+			} else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
+				confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
 #endif /* HAVE_PRI */
 #ifdef HAVE_SS7
 			} else if (!strcasecmp(v->name, "ss7type")) {

Modified: team/rmudgett/mcid/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/mcid/channels/chan_sip.c?view=diff&rev=267301&r1=267300&r2=267301
==============================================================================
--- team/rmudgett/mcid/channels/chan_sip.c (original)
+++ team/rmudgett/mcid/channels/chan_sip.c Wed Jun  2 16:33:40 2010
@@ -261,6 +261,7 @@
 #include "asterisk/event.h"
 #include "asterisk/stun.h"
 #include "asterisk/cel.h"
+#include "asterisk/aoc.h"
 #include "sip/include/sip.h"
 #include "sip/include/globals.h"
 #include "sip/include/config_parser.h"
@@ -804,7 +805,7 @@
 static int regobjs = 0;       /*!< Registry objects */
 /* }@ */
 
-static struct ast_flags global_flags[2] = {{0}};  /*!< global SIP_ flags */
+static struct ast_flags global_flags[3] = {{0}};  /*!< global SIP_ flags */
 static int global_t38_maxdatagram;                /*!< global T.38 FaxMaxDatagram override */
 
 static char used_context[AST_MAX_CONTEXT];        /*!< name of automatically created context for unloading */
@@ -1275,6 +1276,7 @@
 static int transmit_publish(struct sip_epa_entry *epa_entry, enum sip_publish_type publish_type, const char * const explicit_uri);
 static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init, const char * const explicit_uri);
 static int transmit_reinvite_with_sdp(struct sip_pvt *p, int t38version, int oldsdp);
+static int transmit_info_with_aoc(struct sip_pvt *p, struct ast_aoc_decoded *decoded);
 static int transmit_info_with_digit(struct sip_pvt *p, const char digit, unsigned int duration);
 static int transmit_info_with_vidupdate(struct sip_pvt *p);
 static int transmit_message_with_text(struct sip_pvt *p, const char *text);
@@ -4702,6 +4704,7 @@
 
 	ast_copy_flags(&dialog->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY);
 	ast_copy_flags(&dialog->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
+	ast_copy_flags(&dialog->flags[2], &peer->flags[2], SIP_PAGE3_FLAGS_TO_COPY);
 	dialog->capability = peer->capability;
 	dialog->prefs = peer->prefs;
 	if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_T38SUPPORT)) {
@@ -6249,6 +6252,41 @@
 	case AST_CONTROL_REDIRECTING:
 		update_redirecting(p, data, datalen);
 		break;
+	case AST_CONTROL_AOC:
+		{
+			struct ast_aoc_decoded *decoded = ast_aoc_decode((struct ast_aoc_encoded *) data, datalen, ast);
+			if (!decoded) {
+				ast_log(LOG_ERROR, "Error decoding indicated AOC data\n");
+				res = -1;
+				break;
+			}
+			switch (ast_aoc_get_msg_type(decoded)) {
+			case AST_AOC_REQUEST:
+				if (ast_aoc_get_termination_request(decoded)) {
+					/* TODO, once there is a way to get AOC-E on hangup, attempt that here
+					 * before hanging up the channel.*/
+
+					/* The other side has already initiated the hangup. This frame
+					 * just says they are waiting to get AOC-E before completely tearing
+					 * the call down.  Since SIP does not support this at the moment go
+					 * ahead and terminate the call here to avoid an unnecessary timeout. */
+					ast_log(LOG_DEBUG, "AOC-E termination request received on %s. This is not yet supported on sip. Continue with hangup \n", p->owner->name);
+					ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
+				}
+				break;
+			case AST_AOC_D:
+			case AST_AOC_E:
+				if (ast_test_flag(&p->flags[2], SIP_PAGE3_SNOM_AOC)) {
+					transmit_info_with_aoc(p, decoded);
+				}
+				break;
+			case AST_AOC_S: /* S not supported yet */
+			default:
+				break;
+			}
+			ast_aoc_destroy_decoded(decoded);
+		}
+		break;
 	case -1:
 		res = -1;
 		break;
@@ -6888,6 +6926,7 @@
 	/* Copy global flags to this PVT at setup. */
 	ast_copy_flags(&p->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY);
 	ast_copy_flags(&p->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY);
+	ast_copy_flags(&p->flags[2], &global_flags[2], SIP_PAGE3_FLAGS_TO_COPY);
 
 	p->do_history = recordhistory;
 
@@ -11856,6 +11895,53 @@
 	*/
 }
 
+/*! \brief Send SIP INFO advice of charge message */
+static int transmit_info_with_aoc(struct sip_pvt *p, struct ast_aoc_decoded *decoded)
+{
+	struct sip_request req;
+	struct ast_str *str = ast_str_alloca(512);
+	const struct ast_aoc_unit_entry *unit_entry = ast_aoc_get_unit_info(decoded, 0);
+	enum ast_aoc_charge_type charging = ast_aoc_get_charge_type(decoded);
+
+	reqprep(&req, p, SIP_INFO, 0, 1);
+
+	if (ast_aoc_get_msg_type(decoded) == AST_AOC_D) {
+		ast_str_append(&str, 0, "type=active;");
+	} else if (ast_aoc_get_msg_type(decoded) == AST_AOC_E) {
+		ast_str_append(&str, 0, "type=terminated;");
+	} else {
+		/* unsupported message type */
+		return -1;
+	}
+
+	switch (charging) {
+	case AST_AOC_CHARGE_FREE:
+		ast_str_append(&str, 0, "free-of-charge;");
+		break;
+	case AST_AOC_CHARGE_CURRENCY:
+		ast_str_append(&str, 0, "charging;");
+		ast_str_append(&str, 0, "charging-info=currency;");
+		ast_str_append(&str, 0, "amount=%u;", ast_aoc_get_currency_amount(decoded));
+		ast_str_append(&str, 0, "multiplier=%s;", ast_aoc_get_currency_multiplier_decimal(decoded));
+		if (!ast_strlen_zero(ast_aoc_get_currency_name(decoded))) {
+			ast_str_append(&str, 0, "currency=%s;", ast_aoc_get_currency_name(decoded));
+		}
+		break;
+	case AST_AOC_CHARGE_UNIT:
+		ast_str_append(&str, 0, "charging;");
+		ast_str_append(&str, 0, "charging-info=pulse;");
+		if (unit_entry) {
+			ast_str_append(&str, 0, "recorded-units=%u;", unit_entry->amount);
+		}
+		break;
+	default:
+		ast_str_append(&str, 0, "not-available;");
+	};
+
+	add_header(&req, "AOC", ast_str_buffer(str));
+
+	return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+}
 
 /*! \brief Send SIP INFO dtmf message, see Cisco documentation on cisco.com */
 static int transmit_info_with_digit(struct sip_pvt *p, const char digit, unsigned int duration)

[... 3449 lines stripped ...]



More information about the asterisk-commits mailing list