[asterisk-commits] russell: branch group/security_events r267184 - in /team/group/security_event...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jun 2 15:10:06 CDT 2010


Author: russell
Date: Wed Jun  2 15:10:01 2010
New Revision: 267184

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=267184
Log:
resolve, reset

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

Propchange: team/group/security_events/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/group/security_events/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Propchange: team/group/security_events/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Wed Jun  2 15:10:01 2010
@@ -1,1 +1,1 @@
-/trunk:1-267017
+/trunk:1-267183

Modified: team/group/security_events/CHANGES
URL: http://svnview.digium.com/svn/asterisk/team/group/security_events/CHANGES?view=diff&rev=267184&r1=267183&r2=267184
==============================================================================
--- team/group/security_events/CHANGES (original)
+++ team/group/security_events/CHANGES Wed Jun  2 15:10:01 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
 -----------
@@ -336,6 +338,7 @@
    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. 
 
 Asterisk Manager Interface
 --------------------------
@@ -366,6 +369,8 @@
    '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/group/security_events/apps/app_dial.c
URL: http://svnview.digium.com/svn/asterisk/team/group/security_events/apps/app_dial.c?view=diff&rev=267184&r1=267183&r2=267184
==============================================================================
--- team/group/security_events/apps/app_dial.c (original)
+++ team/group/security_events/apps/app_dial.c Wed Jun  2 15:10:01 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/group/security_events/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/team/group/security_events/apps/app_queue.c?view=diff&rev=267184&r1=267183&r2=267184
==============================================================================
--- team/group/security_events/apps/app_queue.c (original)
+++ team/group/security_events/apps/app_queue.c Wed Jun  2 15:10:01 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/group/security_events/apps/app_voicemail.c
URL: http://svnview.digium.com/svn/asterisk/team/group/security_events/apps/app_voicemail.c?view=diff&rev=267184&r1=267183&r2=267184
==============================================================================
--- team/group/security_events/apps/app_voicemail.c (original)
+++ team/group/security_events/apps/app_voicemail.c Wed Jun  2 15:10:01 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/group/security_events/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/group/security_events/channels/chan_dahdi.c?view=diff&rev=267184&r1=267183&r2=267184
==============================================================================
--- team/group/security_events/channels/chan_dahdi.c (original)
+++ team/group/security_events/channels/chan_dahdi.c Wed Jun  2 15:10:01 2010
@@ -11779,6 +11779,10 @@
 #endif	/* defined(HAVE_PRI_CCSS) */
 						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));
@@ -17195,6 +17199,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);

Modified: team/group/security_events/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/group/security_events/channels/chan_sip.c?view=diff&rev=267184&r1=267183&r2=267184
==============================================================================
--- team/group/security_events/channels/chan_sip.c (original)
+++ team/group/security_events/channels/chan_sip.c Wed Jun  2 15:10:01 2010
@@ -324,6 +324,7 @@
 #include "asterisk/cel.h"
 #include "asterisk/security_events.h"
 #include "asterisk/strings.h"
+#include "asterisk/aoc.h"
 #include "sip/include/sip.h"
 #include "sip/include/globals.h"
 #include "sip/include/config_parser.h"
@@ -867,7 +868,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 */
@@ -1338,6 +1339,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);
@@ -4779,6 +4781,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)) {
@@ -6326,6 +6329,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;
@@ -6965,6 +7003,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;
 
@@ -11935,6 +11974,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)
@@ -14209,6 +14295,7 @@
 	/* Take the peer */
 	ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY);
 	ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
+	ast_copy_flags(&p->flags[2], &peer->flags[2], SIP_PAGE3_FLAGS_TO_COPY);
 
 	if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && p->udptl) {
 		p->t38_maxdatagram = peer->t38_maxdatagram;
@@ -14253,6 +14340,7 @@
 	if (!(res = check_auth(p, req, peer->name, p->peersecret, p->peermd5secret, sipmethod, uri2, reliable, req->ignore))) {
 		ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY);
 		ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
+		ast_copy_flags(&p->flags[2], &peer->flags[2], SIP_PAGE3_FLAGS_TO_COPY);
 		/* If we have a call limit, set flag */
 		if (peer->call_limit)
 			ast_set_flag(&p->flags[0], SIP_CALL_LIMIT);
@@ -24172,6 +24260,7 @@
 	copy_socket_data(&p->socket, &peer->socket);
 	ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY);
 	ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
+	ast_copy_flags(&p->flags[2], &peer->flags[2], SIP_PAGE3_FLAGS_TO_COPY);
 
 	/* Send OPTIONs to peer's fullcontact */
 	if (!ast_strlen_zero(peer->fullcontact))
@@ -24929,6 +25018,7 @@
 	peer->type = SIP_TYPE_PEER;
 	ast_copy_flags(&peer->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY);
 	ast_copy_flags(&peer->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY);
+	ast_copy_flags(&peer->flags[2], &global_flags[2], SIP_PAGE3_FLAGS_TO_COPY);
 	ast_string_field_set(peer, context, sip_cfg.default_context);
 	ast_string_field_set(peer, subscribecontext, sip_cfg.default_subscribecontext);
 	ast_string_field_set(peer, language, default_language);
@@ -25035,8 +25125,8 @@
 	int format = 0;		/* Ama flags */
 	int timerb_set = 0, timert1_set = 0;
 	time_t regseconds = 0;
-	struct ast_flags peerflags[2] = {{(0)}};
-	struct ast_flags mask[2] = {{(0)}};
+	struct ast_flags peerflags[3] = {{(0)}};
+	struct ast_flags mask[3] = {{(0)}};
 	char callback[256] = "";
 	struct sip_peer tmp_peer;
 	const char *srvlookup = NULL;
@@ -25427,6 +25517,8 @@
 				ast_string_field_set(peer, unsolicited_mailbox, v->value);
 			} else if (!strcasecmp(v->name, "use_q850_reason")) {
 				ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_Q850_REASON);
+			} else if (!strcasecmp(v->name, "snom_aoc_enabled")) {
+				ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_SNOM_AOC);
 			}
 		}
 
@@ -25596,6 +25688,7 @@
 
 	ast_copy_flags(&peer->flags[0], &peerflags[0], mask[0].flags);
 	ast_copy_flags(&peer->flags[1], &peerflags[1], mask[1].flags);
+	ast_copy_flags(&peer->flags[2], &peerflags[2], mask[2].flags);
 	if (ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE)) {
 		sip_cfg.allowsubscribe = TRUE;	/* No global ban any more */
 	}
@@ -26335,6 +26428,8 @@
 			}
 		} else if (!strcasecmp(v->name, "use_q850_reason")) {
 			ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_Q850_REASON);
+		} else if (!strcasecmp(v->name, "snom_aoc_enabled")) {
+				ast_set2_flag(&global_flags[2], ast_true(v->value), SIP_PAGE3_SNOM_AOC);
 		}
 	}
 
@@ -26614,7 +26709,7 @@
 
 static int apply_directmedia_ha(struct sip_pvt *p, const char *op)
 {
-	struct sockaddr_in us, them;
+	struct sockaddr_in us = {0,}, them = {0,};
 	int res;
 
 	ast_rtp_instance_get_remote_address(p->rtp, &them);

Modified: team/group/security_events/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/team/group/security_events/channels/sig_pri.c?view=diff&rev=267184&r1=267183&r2=267184
==============================================================================
--- team/group/security_events/channels/sig_pri.c (original)
+++ team/group/security_events/channels/sig_pri.c Wed Jun  2 15:10:01 2010
@@ -46,6 +46,7 @@
 #include "asterisk/cli.h"
 #include "asterisk/transcap.h"
 #include "asterisk/features.h"
+#include "asterisk/aoc.h"
 
 #include "sig_pri.h"
 #ifndef PRI_EVENT_FACILITY
@@ -1086,6 +1087,18 @@
 		new_chan->setup_ack = old_chan->setup_ack;
 		new_chan->outgoing = old_chan->outgoing;
 		new_chan->digital = old_chan->digital;
+#if defined(HAVE_PRI_AOC_EVENTS)
+		new_chan->aoc_s_request_invoke_id = old_chan->aoc_s_request_invoke_id;
+		new_chan->aoc_s_request_invoke_id_valid = old_chan->aoc_s_request_invoke_id_valid;
+		new_chan->holding_aoce = old_chan->holding_aoce;
+		new_chan->waiting_for_aoce = old_chan->waiting_for_aoce;
+		new_chan->aoc_e = old_chan->aoc_e;
+
+		old_chan->holding_aoce = 0;
+		old_chan->aoc_s_request_invoke_id_valid = 0;
+		old_chan->waiting_for_aoce = 0;
+		memset(&old_chan->aoc_e, 0, sizeof(&old_chan->aoc_e));
+#endif	/* defined(HAVE_PRI_AOC_EVENTS) */
 		old_chan->alerting = 0;
 		old_chan->alreadyhungup = 0;
 		old_chan->isidlecall = 0;
@@ -2057,645 +2070,934 @@
 #if defined(HAVE_PRI_AOC_EVENTS)
 /*!
  * \internal
- * \brief Convert PRI_AOC_CHARGED_ITEM to string.
+ * \brief Convert ast_aoc_charged_item to PRI_AOC_CHARGED_ITEM .
  * \since 1.8
  *
  * \param value Value to convert to string.
  *
- * \return String equivalent.
- */
-static const char *sig_pri_aoc_charged_item_str(enum PRI_AOC_CHARGED_ITEM value)
-{
-	const char *str;
-
+ * \return PRI_AOC_CHARGED_ITEM
+ */
+static enum PRI_AOC_CHARGED_ITEM sig_pri_aoc_charged_item_to_pri(enum PRI_AOC_CHARGED_ITEM value)
+{
+	switch (value) {
+	case AST_AOC_CHARGED_ITEM_NA:
+		return PRI_AOC_CHARGED_ITEM_NOT_AVAILABLE;
+	case AST_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT:
+		return PRI_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT;
+	case AST_AOC_CHARGED_ITEM_BASIC_COMMUNICATION:
+		return PRI_AOC_CHARGED_ITEM_BASIC_COMMUNICATION;
+	case AST_AOC_CHARGED_ITEM_CALL_ATTEMPT:
+		return PRI_AOC_CHARGED_ITEM_CALL_ATTEMPT;
+	case AST_AOC_CHARGED_ITEM_CALL_SETUP:
+		return PRI_AOC_CHARGED_ITEM_CALL_SETUP;
+	case AST_AOC_CHARGED_ITEM_USER_USER_INFO:
+		return PRI_AOC_CHARGED_ITEM_USER_USER_INFO;
+	case AST_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE:
+		return PRI_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE;
+	}
+	return PRI_AOC_CHARGED_ITEM_NOT_AVAILABLE;
+}
+#endif	/* defined(HAVE_PRI_AOC_EVENTS) */
+
+#if defined(HAVE_PRI_AOC_EVENTS)
+/*!
+ * \internal
+ * \brief Convert PRI_AOC_CHARGED_ITEM to ast_aoc_charged_item.
+ * \since 1.8
+ *
+ * \param value Value to convert to string.
+ *
+ * \return ast_aoc_charged_item
+ */
+static enum ast_aoc_s_charged_item sig_pri_aoc_charged_item_to_ast(enum PRI_AOC_CHARGED_ITEM value)
+{
+	switch (value) {
+	case PRI_AOC_CHARGED_ITEM_NOT_AVAILABLE:
+		return AST_AOC_CHARGED_ITEM_NA;
+	case PRI_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT:
+		return AST_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT;
+	case PRI_AOC_CHARGED_ITEM_BASIC_COMMUNICATION:
+		return AST_AOC_CHARGED_ITEM_BASIC_COMMUNICATION;
+	case PRI_AOC_CHARGED_ITEM_CALL_ATTEMPT:
+		return AST_AOC_CHARGED_ITEM_CALL_ATTEMPT;
+	case PRI_AOC_CHARGED_ITEM_CALL_SETUP:
+		return AST_AOC_CHARGED_ITEM_CALL_SETUP;
+	case PRI_AOC_CHARGED_ITEM_USER_USER_INFO:
+		return AST_AOC_CHARGED_ITEM_USER_USER_INFO;
+	case PRI_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE:
+		return AST_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE;
+	}
+	return AST_AOC_CHARGED_ITEM_NA;
+}
+#endif	/* defined(HAVE_PRI_AOC_EVENTS) */
+
+#if defined(HAVE_PRI_AOC_EVENTS)
+/*!
+ * \internal
+ * \brief Convert AST_AOC_MULTIPLER to PRI_AOC_MULTIPLIER.
+ * \since 1.8
+ *
+ * \return pri enum equivalent.
+ */
+static int sig_pri_aoc_multiplier_from_ast(enum ast_aoc_currency_multiplier mult)
+{
+	switch (mult) {
+	case AST_AOC_MULT_ONETHOUSANDTH:
+		return PRI_AOC_MULTIPLIER_THOUSANDTH;
+	case AST_AOC_MULT_ONEHUNDREDTH:
+		return PRI_AOC_MULTIPLIER_HUNDREDTH;
+	case AST_AOC_MULT_ONETENTH:
+		return PRI_AOC_MULTIPLIER_TENTH;
+	case AST_AOC_MULT_ONE:
+		return PRI_AOC_MULTIPLIER_ONE;
+	case AST_AOC_MULT_TEN:
+		return PRI_AOC_MULTIPLIER_TEN;
+	case AST_AOC_MULT_HUNDRED:
+		return PRI_AOC_MULTIPLIER_HUNDRED;
+	case AST_AOC_MULT_THOUSAND:
+		return PRI_AOC_MULTIPLIER_THOUSAND;
+	default:
+		return PRI_AOC_MULTIPLIER_ONE;
+	}
+}
+#endif	/* defined(HAVE_PRI_AOC_EVENTS) */
+
+#if defined(HAVE_PRI_AOC_EVENTS)
+/*!
+ * \internal
+ * \brief Convert PRI_AOC_MULTIPLIER to AST_AOC_MULTIPLIER
+ * \since 1.8
+ *
+ * \return ast enum equivalent.
+ */
+static int sig_pri_aoc_multiplier_from_pri(const int mult)
+{
+	switch (mult) {
+	case PRI_AOC_MULTIPLIER_THOUSANDTH:
+		return AST_AOC_MULT_ONETHOUSANDTH;
+	case PRI_AOC_MULTIPLIER_HUNDREDTH:
+		return AST_AOC_MULT_ONEHUNDREDTH;
+	case PRI_AOC_MULTIPLIER_TENTH:
+		return AST_AOC_MULT_ONETENTH;
+	case PRI_AOC_MULTIPLIER_ONE:
+		return AST_AOC_MULT_ONE;
+	case PRI_AOC_MULTIPLIER_TEN:
+		return AST_AOC_MULT_TEN;
+	case PRI_AOC_MULTIPLIER_HUNDRED:
+		return AST_AOC_MULT_HUNDRED;
+	case PRI_AOC_MULTIPLIER_THOUSAND:
+		return AST_AOC_MULT_THOUSAND;
+	default:
+		return AST_AOC_MULT_ONE;
+	}
+}
+#endif	/* defined(HAVE_PRI_AOC_EVENTS) */
+
+#if defined(HAVE_PRI_AOC_EVENTS)
+/*!
+ * \internal
+ * \brief Convert ast_aoc_time_scale representation to PRI_AOC_TIME_SCALE
+ * \since 1.8
+ *
+ * \param value Value to convert to ast representation
+ *
+ * \return PRI_AOC_TIME_SCALE
+ */
+static enum PRI_AOC_TIME_SCALE sig_pri_aoc_scale_to_pri(enum ast_aoc_time_scale value)
+{
 	switch (value) {
 	default:
-	case PRI_AOC_CHARGED_ITEM_NOT_AVAILABLE:
-		str = "NotAvailable";
-		break;
-	case PRI_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT:
-		str = "SpecialArrangement";
-		break;
-	case PRI_AOC_CHARGED_ITEM_BASIC_COMMUNICATION:
-		str = "BasicCommunication";
-		break;
-	case PRI_AOC_CHARGED_ITEM_CALL_ATTEMPT:
-		str = "CallAttempt";
-		break;
-	case PRI_AOC_CHARGED_ITEM_CALL_SETUP:
-		str = "CallSetup";
-		break;
-	case PRI_AOC_CHARGED_ITEM_USER_USER_INFO:
-		str = "UserUserInfo";
-		break;
-	case PRI_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE:
-		str = "SupplementaryService";
-		break;
-	}
-	return str;
+	case AST_AOC_TIME_SCALE_HUNDREDTH_SECOND:
+		return PRI_AOC_TIME_SCALE_HUNDREDTH_SECOND;
+	case AST_AOC_TIME_SCALE_TENTH_SECOND:
+		return PRI_AOC_TIME_SCALE_TENTH_SECOND;
+	case AST_AOC_TIME_SCALE_SECOND:
+		return PRI_AOC_TIME_SCALE_SECOND;
+	case AST_AOC_TIME_SCALE_TEN_SECOND:
+		return PRI_AOC_TIME_SCALE_TEN_SECOND;
+	case AST_AOC_TIME_SCALE_MINUTE:
+		return PRI_AOC_TIME_SCALE_MINUTE;
+	case AST_AOC_TIME_SCALE_HOUR:
+		return PRI_AOC_TIME_SCALE_HOUR;
+	case AST_AOC_TIME_SCALE_DAY:
+		return PRI_AOC_TIME_SCALE_DAY;
+	}
 }
 #endif	/* defined(HAVE_PRI_AOC_EVENTS) */
 
 #if defined(HAVE_PRI_AOC_EVENTS)
 /*!
  * \internal
- * \brief Convert PRI_AOC_RATE_TYPE to string.
- * \since 1.8
- *
- * \param value Value to convert to string.
- *
- * \return String equivalent.
- */
-static const char *sig_pri_aoc_rate_type_str(enum PRI_AOC_RATE_TYPE value)
-{
-	const char *str;
-
-	switch (value) {
-	default:
-	case PRI_AOC_RATE_TYPE_NOT_AVAILABLE:
-		str = "NotAvailable";
-		break;
-	case PRI_AOC_RATE_TYPE_FREE:
-		str = "Free";
-		break;
-	case PRI_AOC_RATE_TYPE_FREE_FROM_BEGINNING:
-		str = "FreeFromBeginning";
-		break;
-	case PRI_AOC_RATE_TYPE_DURATION:
-		str = "Duration";
-		break;
-	case PRI_AOC_RATE_TYPE_FLAT:
-		str = "Flat";
-		break;
-	case PRI_AOC_RATE_TYPE_VOLUME:
-		str = "Volume";
-		break;
-	case PRI_AOC_RATE_TYPE_SPECIAL_CODE:
-		str = "SpecialCode";
-		break;
-	}
-	return str;
-}
-#endif	/* defined(HAVE_PRI_AOC_EVENTS) */
-
-#if defined(HAVE_PRI_AOC_EVENTS)
-/*!
- * \internal
- * \brief Convert PRI_AOC_VOLUME_UNIT to string.
- * \since 1.8
- *
- * \param value Value to convert to string.
- *
- * \return String equivalent.
- */
-static const char *sig_pri_aoc_volume_unit_str(enum PRI_AOC_VOLUME_UNIT value)
-{
-	const char *str;
-
-	switch (value) {
-	default:
-	case PRI_AOC_VOLUME_UNIT_OCTET:
-		str = "Octet";
-		break;
-	case PRI_AOC_VOLUME_UNIT_SEGMENT:
-		str = "Segment";
-		break;
-	case PRI_AOC_VOLUME_UNIT_MESSAGE:
-		str = "Message";
-		break;
-	}
-	return str;
-}
-#endif	/* defined(HAVE_PRI_AOC_EVENTS) */
-
-#if defined(HAVE_PRI_AOC_EVENTS)
-/*!
- * \internal
- * \brief Convert PRI_AOC_MULTIPLIER to string.
- * \since 1.8
- *
- * \param value Value to convert to string.
- *
- * \return String equivalent.
- */
-static const char *sig_pri_aoc_multiplier_str(enum PRI_AOC_MULTIPLIER value)
-{
-	const char *str;
-
-	switch (value) {
-	default:
-	case PRI_AOC_MULTIPLIER_THOUSANDTH:
-		str = "1/1000";
-		break;
-	case PRI_AOC_MULTIPLIER_HUNDREDTH:
-		str = "1/100";
-		break;
-	case PRI_AOC_MULTIPLIER_TENTH:
-		str = "1/10";
-		break;
-	case PRI_AOC_MULTIPLIER_ONE:
-		str = "1";
-		break;
-	case PRI_AOC_MULTIPLIER_TEN:
-		str = "10";
-		break;
-	case PRI_AOC_MULTIPLIER_HUNDRED:
-		str = "100";
-		break;
-	case PRI_AOC_MULTIPLIER_THOUSAND:
-		str = "1000";
-		break;
-	}
-	return str;
-}
-#endif	/* defined(HAVE_PRI_AOC_EVENTS) */
-
-#if defined(HAVE_PRI_AOC_EVENTS)
-/*!
- * \internal
- * \brief Convert PRI_AOC_TIME_SCALE to string.
- * \since 1.8
- *
- * \param value Value to convert to string.
- *
- * \return String equivalent.
- */
-static const char *sig_pri_aoc_scale_str(enum PRI_AOC_TIME_SCALE value)
-{
-	const char *str;
-
+ * \brief Convert PRI_AOC_TIME_SCALE to ast aoc representation
+ * \since 1.8
+ *
+ * \param value Value to convert to ast representation
+ *
+ * \return ast aoc time scale
+ */
+static enum ast_aoc_time_scale sig_pri_aoc_scale_to_ast(enum PRI_AOC_TIME_SCALE value)
+{
 	switch (value) {
 	default:
 	case PRI_AOC_TIME_SCALE_HUNDREDTH_SECOND:
-		str = "OneHundredthSecond";
-		break;
+		return AST_AOC_TIME_SCALE_HUNDREDTH_SECOND;
 	case PRI_AOC_TIME_SCALE_TENTH_SECOND:
-		str = "OneTenthSecond";
-		break;
+		return AST_AOC_TIME_SCALE_TENTH_SECOND;
 	case PRI_AOC_TIME_SCALE_SECOND:
-		str = "Second";
-		break;
+		return AST_AOC_TIME_SCALE_SECOND;
 	case PRI_AOC_TIME_SCALE_TEN_SECOND:
-		str = "TenSeconds";
-		break;
+		return AST_AOC_TIME_SCALE_TEN_SECOND;
 	case PRI_AOC_TIME_SCALE_MINUTE:
-		str = "Minute";
-		break;
+		return AST_AOC_TIME_SCALE_MINUTE;
 	case PRI_AOC_TIME_SCALE_HOUR:
-		str = "Hour";
-		break;
+		return AST_AOC_TIME_SCALE_HOUR;
 	case PRI_AOC_TIME_SCALE_DAY:
-		str = "Day";
-		break;
-	}
-	return str;
+		return AST_AOC_TIME_SCALE_DAY;
+	}
+	return AST_AOC_TIME_SCALE_HUNDREDTH_SECOND;
 }
 #endif	/* defined(HAVE_PRI_AOC_EVENTS) */
 
 #if defined(HAVE_PRI_AOC_EVENTS)
 /*!
  * \internal
- * \brief Convert PRI_AOC_DE_CHARGE to string.
- * \since 1.8
- *
- * \param value Value to convert to string.
- *
- * \return String equivalent.
- */
-static const char *sig_pri_aoc_de_charge_str(enum PRI_AOC_DE_CHARGE value)
-{
-	const char *str;
-
-	switch (value) {
-	default:
-	case PRI_AOC_DE_CHARGE_NOT_AVAILABLE:
-		str = "NotAvailable";
-		break;
-	case PRI_AOC_DE_CHARGE_FREE:
-		str = "Free";
-		break;
-	case PRI_AOC_DE_CHARGE_CURRENCY:
-		str = "Currency";
-		break;
-	case PRI_AOC_DE_CHARGE_UNITS:
-		str = "Units";
-		break;
-	}
-	return str;
-}
-#endif	/* defined(HAVE_PRI_AOC_EVENTS) */
-
-#if defined(HAVE_PRI_AOC_EVENTS)
-/*!
- * \internal
- * \brief Convert PRI_AOC_D_BILLING_ID to string.
- * \since 1.8
- *
- * \param value Value to convert to string.
- *
- * \return String equivalent.
- */
-static const char *sig_pri_aoc_d_billing_id_str(enum PRI_AOC_D_BILLING_ID value)
-{
-	const char *str;
-
-	switch (value) {
-	default:
-	case PRI_AOC_D_BILLING_ID_NOT_AVAILABLE:
-		str = "NotAvailable";
-		break;
-	case PRI_AOC_D_BILLING_ID_NORMAL:
-		str = "Normal";
-		break;
-	case PRI_AOC_D_BILLING_ID_REVERSE:
-		str = "Reverse";
-		break;
-	case PRI_AOC_D_BILLING_ID_CREDIT_CARD:
-		str = "CreditCard";
-		break;
-	}
-	return str;
-}
-#endif	/* defined(HAVE_PRI_AOC_EVENTS) */
-
-#if defined(HAVE_PRI_AOC_EVENTS)
-/*!
- * \internal
- * \brief Convert PRI_AOC_E_BILLING_ID to string.
- * \since 1.8
- *
- * \param value Value to convert to string.
- *
- * \return String equivalent.
- */
-static const char *sig_pri_aoc_e_billing_id_str(enum PRI_AOC_E_BILLING_ID value)
-{
-	const char *str;
-
-	switch (value) {
-	default:
-	case PRI_AOC_E_BILLING_ID_NOT_AVAILABLE:
-		str = "NotAvailable";
-		break;
-	case PRI_AOC_E_BILLING_ID_NORMAL:
-		str = "Normal";
-		break;
-	case PRI_AOC_E_BILLING_ID_REVERSE:
-		str = "Reverse";
-		break;
-	case PRI_AOC_E_BILLING_ID_CREDIT_CARD:
-		str = "CreditCard";
-		break;
-	case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_UNCONDITIONAL:
-		str = "CallForwardingUnconditional";
-		break;
-	case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_BUSY:
-		str = "CallForwardingBusy";
-		break;
-	case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_NO_REPLY:
-		str = "CallForwardingNoReply";
-		break;
-	case PRI_AOC_E_BILLING_ID_CALL_DEFLECTION:
-		str = "CallDeflection";
-		break;
-	case PRI_AOC_E_BILLING_ID_CALL_TRANSFER:
-		str = "CallTransfer";
-		break;
-	}
-	return str;
-}
-#endif	/* defined(HAVE_PRI_AOC_EVENTS) */
-
-#if defined(HAVE_PRI_AOC_EVENTS)
-/*!
- * \internal
- * \brief Append the amount structure to the event message string.
- * \since 1.8
- *
- * \param msg Event message string being built.
- * \param prefix Prefix to add to the amount lines.
- * \param amount Data to convert.
- *
- * \return Nothing
- */
-static void sig_pri_aoc_amount(struct ast_str **msg, const char *prefix, const struct pri_aoc_amount *amount)
-{
-	static const char name[] = "Amount";
-
-	ast_str_append(msg, 0, "%s/%s/Cost: %ld\r\n", prefix, name, amount->cost);
-	ast_str_append(msg, 0, "%s/%s/Multiplier: %s\r\n", prefix, name,
-		sig_pri_aoc_multiplier_str(amount->multiplier));
-}
-#endif	/* defined(HAVE_PRI_AOC_EVENTS) */
-
-#if defined(HAVE_PRI_AOC_EVENTS)
-/*!
- * \internal
- * \brief Append the time structure to the event message string.
- * \since 1.8
- *
- * \param msg Event message string being built.
- * \param prefix Prefix to add to the amount lines.
- * \param name Name of the time structure to convert.
- * \param time Data to convert.
- *
- * \return Nothing
- */
-static void sig_pri_aoc_time(struct ast_str **msg, const char *prefix, const char *name, const struct pri_aoc_time *time)
-{
-	ast_str_append(msg, 0, "%s/%s/Length: %ld\r\n", prefix, name, time->length);
-	ast_str_append(msg, 0, "%s/%s/Scale: %s\r\n", prefix, name,
-		sig_pri_aoc_scale_str(time->scale));
-}
-#endif	/* defined(HAVE_PRI_AOC_EVENTS) */
-
-#if defined(HAVE_PRI_AOC_EVENTS)
-/*!
- * \internal
- * \brief Handle the AOC-S event.
+ * \brief Handle AOC-S control frame
  * \since 1.8
  *
  * \param aoc_s AOC-S event parameters.
  * \param owner Asterisk channel associated with the call.
+ * \param passthrough indicating if this message should be queued on the ast channel
  *
  * \note Assumes the pri->lock is already obtained.
+ * \note Assumes the sig_pri private is locked
  * \note Assumes the owner channel lock is already obtained.
  *
  * \return Nothing
  */
-static void sig_pri_aoc_s_event(const struct pri_subcmd_aoc_s *aoc_s, struct ast_channel *owner)
-{
-	struct ast_str *msg;
-	const char *rate_str;
-	char prefix[32];
+static void sig_pri_aoc_s_from_pri(const struct pri_subcmd_aoc_s *aoc_s, struct ast_channel *owner, int passthrough)
+{
+	struct ast_aoc_decoded *decoded = NULL;
+	struct ast_aoc_encoded *encoded = NULL;
+	size_t encoded_size = 0;
 	int idx;
 
-	msg = ast_str_create(4096);
-	if (!msg) {
+	if (!owner || !aoc_s) {
 		return;
 	}
 
-	ast_str_append(&msg, 0, "Channel: %s\r\n", owner->name);
-	ast_str_append(&msg, 0, "UniqueID: %s\r\n", owner->uniqueid);
-
-	ast_str_append(&msg, 0, "NumberRates: %d\r\n", aoc_s->num_items);
+	if (!(decoded = ast_aoc_create(AST_AOC_S, 0, 0))) {
+		return;
+	}
+
 	for (idx = 0; idx < aoc_s->num_items; ++idx) {
-		snprintf(prefix, sizeof(prefix), "Rate(%d)", idx);
-
-		ast_str_append(&msg, 0, "%s/Chargeable: %s\r\n", prefix,
-			sig_pri_aoc_charged_item_str(aoc_s->item[idx].chargeable));
-		if (aoc_s->item[idx].chargeable == PRI_AOC_CHARGED_ITEM_NOT_AVAILABLE) {
+		enum ast_aoc_s_charged_item charged_item;
+
+		charged_item = sig_pri_aoc_charged_item_to_ast(aoc_s->item[idx].chargeable);
+		if (charged_item == AST_AOC_CHARGED_ITEM_NA) {
+			/* Delete the unknown charged item from the list. */
 			continue;
 		}
-		rate_str = sig_pri_aoc_rate_type_str(aoc_s->item[idx].rate_type);
-		ast_str_append(&msg, 0, "%s/Type: %s\r\n", prefix, rate_str);
 		switch (aoc_s->item[idx].rate_type) {
 		case PRI_AOC_RATE_TYPE_DURATION:
-			strcat(prefix, "/");
-			strcat(prefix, rate_str);
-			ast_str_append(&msg, 0, "%s/Currency: %s\r\n", prefix,
-				aoc_s->item[idx].rate.duration.currency);
-			sig_pri_aoc_amount(&msg, prefix, &aoc_s->item[idx].rate.duration.amount);
-			ast_str_append(&msg, 0, "%s/ChargingType: %s\r\n", prefix,
-				aoc_s->item[idx].rate.duration.charging_type
-				? "StepFunction" : "ContinuousCharging");
-			sig_pri_aoc_time(&msg, prefix, "Time", &aoc_s->item[idx].rate.duration.time);
-			if (aoc_s->item[idx].rate.duration.granularity.length) {
-				sig_pri_aoc_time(&msg, prefix, "Granularity",
-					&aoc_s->item[idx].rate.duration.granularity);
-			}
+			ast_aoc_s_add_rate_duration(decoded,
+				charged_item,
+				aoc_s->item[idx].rate.duration.amount.cost,
+				sig_pri_aoc_multiplier_from_pri(aoc_s->item[idx].rate.duration.amount.multiplier),
+				aoc_s->item[idx].rate.duration.currency,
+				aoc_s->item[idx].rate.duration.time.length,
+				sig_pri_aoc_scale_to_ast(aoc_s->item[idx].rate.duration.time.scale),
+				aoc_s->item[idx].rate.duration.granularity.length,
+				sig_pri_aoc_scale_to_ast(aoc_s->item[idx].rate.duration.granularity.scale),
+				aoc_s->item[idx].rate.duration.charging_type);
 			break;
 		case PRI_AOC_RATE_TYPE_FLAT:
-			strcat(prefix, "/");
-			strcat(prefix, rate_str);
-			ast_str_append(&msg, 0, "%s/Currency: %s\r\n", prefix,
+			ast_aoc_s_add_rate_flat(decoded,
+				charged_item,
+				aoc_s->item[idx].rate.flat.amount.cost,
+				sig_pri_aoc_multiplier_from_pri(aoc_s->item[idx].rate.flat.amount.multiplier),
 				aoc_s->item[idx].rate.flat.currency);
-			sig_pri_aoc_amount(&msg, prefix, &aoc_s->item[idx].rate.flat.amount);
 			break;
 		case PRI_AOC_RATE_TYPE_VOLUME:
-			strcat(prefix, "/");
-			strcat(prefix, rate_str);

[... 1994 lines stripped ...]



More information about the asterisk-commits mailing list