[svn-commits] rmudgett: trunk r267096 - in /trunk: apps/ channels/ channels/sip/include/ co...
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Wed Jun 2 13:10:27 CDT 2010
Author: rmudgett
Date: Wed Jun 2 13:10:15 2010
New Revision: 267096
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=267096
Log:
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/
Added:
trunk/doc/advice_of_charge.txt
- copied unchanged from r267092, team/dvossel/generic_aoc/doc/advice_of_charge.txt
trunk/include/asterisk/aoc.h
- copied unchanged from r267092, team/dvossel/generic_aoc/include/asterisk/aoc.h
trunk/main/aoc.c
- copied unchanged from r267092, team/dvossel/generic_aoc/main/aoc.c
trunk/tests/test_aoc.c
- copied unchanged from r267092, team/dvossel/generic_aoc/tests/test_aoc.c
Modified:
trunk/apps/app_dial.c
trunk/apps/app_queue.c
trunk/channels/chan_dahdi.c
trunk/channels/chan_sip.c
trunk/channels/sig_pri.c
trunk/channels/sig_pri.h
trunk/channels/sip/include/sip.h
trunk/configs/chan_dahdi.conf.sample
trunk/configs/manager.conf.sample
trunk/configs/sip.conf.sample
trunk/include/asterisk/frame.h
trunk/main/asterisk.c
trunk/main/channel.c
trunk/main/features.c
trunk/main/manager.c
Modified: trunk/apps/app_dial.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_dial.c?view=diff&rev=267096&r1=267095&r2=267096
==============================================================================
--- trunk/apps/app_dial.c (original)
+++ trunk/apps/app_dial.c Wed Jun 2 13:10:15 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: trunk/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_queue.c?view=diff&rev=267096&r1=267095&r2=267096
==============================================================================
--- trunk/apps/app_queue.c (original)
+++ trunk/apps/app_queue.c Wed Jun 2 13:10:15 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: trunk/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_dahdi.c?view=diff&rev=267096&r1=267095&r2=267096
==============================================================================
--- trunk/channels/chan_dahdi.c (original)
+++ trunk/channels/chan_dahdi.c Wed Jun 2 13:10:15 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: trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_sip.c?view=diff&rev=267096&r1=267095&r2=267096
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Wed Jun 2 13:10:15 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)
@@ -14037,6 +14123,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;
@@ -14081,6 +14168,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);
@@ -24000,6 +24088,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))
@@ -24757,6 +24846,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);
@@ -24863,8 +24953,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;
@@ -25255,6 +25345,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);
}
}
@@ -25424,6 +25516,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 */
}
@@ -26163,6 +26256,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);
}
}
Modified: trunk/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/sig_pri.c?view=diff&rev=267096&r1=267095&r2=267096
==============================================================================
--- trunk/channels/sig_pri.c (original)
+++ trunk/channels/sig_pri.c Wed Jun 2 13:10:15 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);
- ast_str_append(&msg, 0, "%s/Currency: %s\r\n", prefix,
+ ast_aoc_s_add_rate_volume(decoded,
+ charged_item,
+ aoc_s->item[idx].rate.volume.unit,
+ aoc_s->item[idx].rate.volume.amount.cost,
+ sig_pri_aoc_multiplier_from_pri(aoc_s->item[idx].rate.volume.amount.multiplier),
aoc_s->item[idx].rate.volume.currency);
- sig_pri_aoc_amount(&msg, prefix, &aoc_s->item[idx].rate.volume.amount);
- ast_str_append(&msg, 0, "%s/Unit: %s\r\n", prefix,
- sig_pri_aoc_volume_unit_str(aoc_s->item[idx].rate.volume.unit));
break;
case PRI_AOC_RATE_TYPE_SPECIAL_CODE:
- ast_str_append(&msg, 0, "%s/%s: %d\r\n", prefix, rate_str,
+ ast_aoc_s_add_rate_special_charge_code(decoded,
+ charged_item,
aoc_s->item[idx].rate.special);
break;
+ case PRI_AOC_RATE_TYPE_FREE:
+ ast_aoc_s_add_rate_free(decoded, charged_item, 0);
+ break;
+ case PRI_AOC_RATE_TYPE_FREE_FROM_BEGINNING:
+ ast_aoc_s_add_rate_free(decoded, charged_item, 1);
+ break;
default:
- break;
- }
- }
-
- ast_manager_event(owner, EVENT_FLAG_AOC, "AOC-S", "%s", ast_str_buffer(msg));
- ast_free(msg);
+ ast_aoc_s_add_rate_na(decoded, charged_item);
+ break;
+ }
+ }
+
+ if (passthrough && (encoded = ast_aoc_encode(decoded, &encoded_size, owner))) {
+ ast_queue_control_data(owner, AST_CONTROL_AOC, encoded, encoded_size);
+ }
+
+ ast_aoc_manager_event(decoded, owner);
+
+ ast_aoc_destroy_decoded(decoded);
+ ast_aoc_destroy_encoded(encoded);
}
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
#if defined(HAVE_PRI_AOC_EVENTS)
/*!
* \internal
- * \brief Handle the AOC-D event.
- * \since 1.8
- *
- * \param aoc_d AOC-D event parameters.
+ * \brief Generate AOC Request Response
+ * \since 1.8
+ *
+ * \param aoc_request
+ *
+ * \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_request_from_pri(const struct pri_subcmd_aoc_request *aoc_request, struct sig_pri_chan *pvt, q931_call *call)
+{
+ int request;
+
+ if (!aoc_request) {
+ return;
+ }
+
+ request = aoc_request->charging_request;
+
+ if (request & PRI_AOC_REQUEST_S) {
+ if (pvt->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S) {
+ /* An AOC-S response must come from the other side, so save off this invoke_id
+ * and see if an AOC-S message comes in before the call is answered. */
+ pvt->aoc_s_request_invoke_id = aoc_request->invoke_id;
+ pvt->aoc_s_request_invoke_id_valid = 1;
+
+ } else {
+ pri_aoc_s_request_response_send(pvt->pri->pri,
+ call,
+ aoc_request->invoke_id,
+ NULL);
+ }
+ }
+
+ if (request & PRI_AOC_REQUEST_D) {
[... 1701 lines stripped ...]
More information about the svn-commits
mailing list