[svn-commits] dvossel: branch dvossel/generic_aoc r252648 - in /team/dvossel/generic_aoc: c...
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Mon Mar 15 17:21:46 CDT 2010
Author: dvossel
Date: Mon Mar 15 17:21:42 2010
New Revision: 252648
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=252648
Log:
addition of generic aoc changes
Modified:
team/dvossel/generic_aoc/channels/chan_sip.c
team/dvossel/generic_aoc/channels/sip/include/sip.h
team/dvossel/generic_aoc/configs/sip.conf.sample
team/dvossel/generic_aoc/include/asterisk/frame.h
team/dvossel/generic_aoc/main/channel.c
team/dvossel/generic_aoc/main/manager.c
Modified: team/dvossel/generic_aoc/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/generic_aoc/channels/chan_sip.c?view=diff&rev=252648&r1=252647&r2=252648
==============================================================================
--- team/dvossel/generic_aoc/channels/chan_sip.c (original)
+++ team/dvossel/generic_aoc/channels/chan_sip.c Mon Mar 15 17:21:42 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"
@@ -803,7 +804,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 */
@@ -1274,6 +1275,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);
@@ -4699,6 +4701,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)) {
@@ -6206,6 +6209,18 @@
case AST_CONTROL_REDIRECTING:
update_redirecting(p, data, datalen);
break;
+ case AST_CONTROL_AOC:
+ if (ast_test_flag(&p->flags[2], SIP_PAGE3_SNOM_AOC)) {
+ struct ast_aoc_decoded *decoded = ast_aoc_decode((struct ast_aoc_encoded *) data, datalen);
+ if (decoded) {
+ transmit_info_with_aoc(p, decoded);
+ ast_aoc_destroy_decoded(decoded);
+ } else {
+ ast_log(LOG_ERROR, "Error decoding indicated AOC data\n");
+ res = -1;
+ }
+ }
+ break;
case -1:
res = -1;
break;
@@ -6843,6 +6858,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;
@@ -11822,6 +11838,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) == AOC_D) {
+ ast_str_append(&str, 0, "type=active;");
+ } else if (ast_aoc_get_msg_type(decoded) == AOC_E) {
+ ast_str_append(&str, 0, "type=terminated;");
+ } else {
+ /* unsupported message type */
+ return -1;
+ }
+
+ switch (charging) {
+ case AOC_CHARGE_FREE:
+ ast_str_append(&str, 0, "free-of-charge;");
+ break;
+ case 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 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)
@@ -13979,6 +14042,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;
@@ -14023,6 +14087,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);
@@ -23850,6 +23915,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))
@@ -24554,6 +24620,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);
@@ -24658,8 +24725,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;
@@ -25026,6 +25093,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);
}
}
@@ -25195,6 +25264,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 */
}
@@ -25923,6 +25993,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: team/dvossel/generic_aoc/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/generic_aoc/channels/sip/include/sip.h?view=diff&rev=252648&r1=252647&r2=252648
==============================================================================
--- team/dvossel/generic_aoc/channels/sip/include/sip.h (original)
+++ team/dvossel/generic_aoc/channels/sip/include/sip.h Mon Mar 15 17:21:42 2010
@@ -348,6 +348,12 @@
SIP_PAGE2_UDPTL_DESTINATION | SIP_PAGE2_VIDEOSUPPORT_ALWAYS | SIP_PAGE2_PREFERRED_CODEC | \
SIP_PAGE2_RPID_IMMEDIATE | SIP_PAGE2_RPID_UPDATE | SIP_PAGE2_SYMMETRICRTP |\
SIP_PAGE2_Q850_REASON)
+
+
+#define SIP_PAGE3_SNOM_AOC (1 << 0) /*!< DPG: Allow snom aoc messages */
+
+#define SIP_PAGE3_FLAGS_TO_COPY \
+ (SIP_PAGE3_SNOM_AOC)
/*@}*/
@@ -937,7 +943,7 @@
ast_group_t callgroup; /*!< Call group */
ast_group_t pickupgroup; /*!< Pickup group */
int lastinvite; /*!< Last Cseq of invite */
- struct ast_flags flags[2]; /*!< SIP_ flags */
+ struct ast_flags flags[3]; /*!< SIP_ flags */
/* boolean flags that don't belong in flags */
unsigned short do_history:1; /*!< Set if we want to record history */
@@ -1163,7 +1169,7 @@
struct ast_codec_pref prefs; /*!< codec prefs */
int lastmsgssent;
unsigned int sipoptions; /*!< Supported SIP options */
- struct ast_flags flags[2]; /*!< SIP_ flags */
+ struct ast_flags flags[3]; /*!< SIP_ flags */
/*! Mailboxes that this peer cares about */
AST_LIST_HEAD_NOLOCK(, sip_mailbox) mailboxes;
Modified: team/dvossel/generic_aoc/configs/sip.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/generic_aoc/configs/sip.conf.sample?view=diff&rev=252648&r1=252647&r2=252648
==============================================================================
--- team/dvossel/generic_aoc/configs/sip.conf.sample (original)
+++ team/dvossel/generic_aoc/configs/sip.conf.sample Mon Mar 15 17:21:42 2010
@@ -866,6 +866,12 @@
; it may be a mandatory requirement for some
; destinations which do not have a prior
; account relationship with your server.
+
+;------------------------------ Advice of Charge CONFIGURATION --------------------------
+; snom_aoc_enabled = yes; ; This options turns on and off support for sending AOC-D and
+ ; AOC-E to snom endpoints. This option can be used both in the
+ ; peer and global scope. The default for this option is off.
+
;------------------------------ JITTER BUFFER CONFIGURATION --------------------------
; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of a
Modified: team/dvossel/generic_aoc/include/asterisk/frame.h
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/generic_aoc/include/asterisk/frame.h?view=diff&rev=252648&r1=252647&r2=252648
==============================================================================
--- team/dvossel/generic_aoc/include/asterisk/frame.h (original)
+++ team/dvossel/generic_aoc/include/asterisk/frame.h Mon Mar 15 17:21:42 2010
@@ -326,6 +326,7 @@
AST_CONTROL_T38_PARAMETERS = 24, /*! T38 state change request/notification with parameters */
AST_CONTROL_CC = 25, /*!< Indication that Call completion service is possible */
AST_CONTROL_SRCCHANGE = 26, /*!< Media source has changed and requires a new RTP SSRC */
+ AST_CONTROL_AOC = 27, /*!< Advice of Charge with encoded generic AOC payload */
};
enum ast_control_t38 {
Modified: team/dvossel/generic_aoc/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/generic_aoc/main/channel.c?view=diff&rev=252648&r1=252647&r2=252648
==============================================================================
--- team/dvossel/generic_aoc/main/channel.c (original)
+++ team/dvossel/generic_aoc/main/channel.c Mon Mar 15 17:21:42 2010
@@ -3617,6 +3617,7 @@
case AST_CONTROL_T38_PARAMETERS:
case _XXX_AST_CONTROL_T38:
case AST_CONTROL_CC:
+ case AST_CONTROL_AOC:
break;
case AST_CONTROL_CONGESTION:
@@ -3760,6 +3761,7 @@
case AST_CONTROL_CONNECTED_LINE:
case AST_CONTROL_REDIRECTING:
case AST_CONTROL_CC:
+ case AST_CONTROL_AOC:
/* Nothing left to do for these. */
res = 0;
break;
Modified: team/dvossel/generic_aoc/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/generic_aoc/main/manager.c?view=diff&rev=252648&r1=252647&r2=252648
==============================================================================
--- team/dvossel/generic_aoc/main/manager.c (original)
+++ team/dvossel/generic_aoc/main/manager.c Mon Mar 15 17:21:42 2010
@@ -74,6 +74,7 @@
#include "asterisk/astobj2.h"
#include "asterisk/features.h"
#include "asterisk/security_events.h"
+#include "asterisk/aoc.h"
/*** DOCUMENTATION
<manager name="Ping" language="en_US">
@@ -692,6 +693,114 @@
<description>
<para>Checks if Asterisk module is loaded. Will return Success/Failure.
For success returns, the module revision number is included.</para>
+ </description>
+ </manager>
+ <manager name="AOCMessage" language="en_US">
+ <synopsis>
+ Generate an Advice of Charge message on a channel.
+ </synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+ <parameter name="Channel" required="true">
+ <para>Channel name to generate the AOC message on.</para>
+ </parameter>
+ <parameter name="ChannelPrefix">
+ <para>Partial channel prefix. By using this option one can match the beginning part
+ of a channel name without having to put the entire name in. For example
+ if a channel name is SIP/snom-00000001 and this value is set to SIP/snom, then
+ that channel matches and the message will be sent. Note however that only
+ the first matched channel has the message sent on it. </para>
+ </parameter>
+ <parameter name="MsgType" required="true">
+ <para>Defines what time of AOC message to create, ACO-D or AOC-E</para>
+ <enumlist>
+ <enum name="D" />
+ <enum name="E" />
+ </enumlist>
+ </parameter>
+ <parameter name="ChargeType" required="true">
+ <para>Defines what kind of charge this message represents.</para>
+ <enumlist>
+ <enum name="NA" />
+ <enum name="FREE" />
+ <enum name="Currency" />
+ <enum name="Unit" />
+ </enumlist>
+ </parameter>
+ <parameter name="UnitAmount(0)">
+ <para>This represents the amount of units charged. The ETSI AOC standard specifies that
+ this value along with the optional UnitType value are entries in a list. To accommodate this
+ these values take an index value starting at 0 which can be used to generate this list of
+ unit entries. For Example, If two unit entires were required this could be achieved by setting the
+ paramter UnitAmount(0)=1234 and UnitAmount(1)=5678. Note that UnitAmount at index 0 is
+ required when ChargeType=Unit, all other entries in the list are optional.
+ </para>
+ </parameter>
+ <parameter name="UnitType(0)">
+ <para>Defines the type of unit. ETSI AOC standard specifies this as an integer
+ value between 1 and 16, but this value is left open to accept any positive
+ integer. Like the UnitAmount parameter, this value represents a list entry
+ and has an index parameter that starts at 0.
+ </para>
+ </parameter>
+ <parameter name="CurrencyName">
+ <para>Specifies the currency's name. Note that this value is truncated after 10 characters.</para>
+ </parameter>
+ <parameter name="CurrencyAmount">
+ <para>Specifies the charge unit amount as a positive integer. This value is required
+ when ChargeType==Currency.</para>
+ </parameter>
+ <parameter name="CurrencyMultiplier">
+ <para>Specifies the currency multiplier. This value is required when ChargeType==Currency.</para>
+ <enumlist>
+ <enum name="OneThousandth" />
+ <enum name="OneHundredth" />
+ <enum name="OneTenth" />
+ <enum name="One" />
+ <enum name="Ten" />
+ <enum name="Hundred" />
+ <enum name="Thousand" />
+ </enumlist>
+ </parameter>
+ <parameter name="TotalType" default="Total">
+ <para>Defines what kind of AOC-D total is represented.</para>
+ <enumlist>
+ <enum name="Total" />
+ <enum name="SubTotal" />
+ </enumlist>
+ </parameter>
+ <parameter name="AOCDBillingId">
+ <para>Represents a billing id associated with a AOC-D message.</para>
+ <enumlist>
+ <enum name="Normal" />
+ <enum name="ReverseCharge" />
+ <enum name="CreditCard" />
+ </enumlist>
+ </parameter>
+ <parameter name="AOCEBillingId">
+ <para>Represents a billing id associated with a AOC-E message.</para>
+ <enumlist>
+ <enum name="Normal" />
+ <enum name="ReverseCharge" />
+ <enum name="CreditCard" />
+ <enum name="CallFwdUnconditional" />
+ <enum name="CallFwdBusy" />
+ <enum name="CallFwdNoReply" />
+ <enum name="CallDeflection" />
+ <enum name="CallTransfer" />
+ </enumlist>
+ </parameter>
+ <parameter name="ChargingAssociationId">
+ <para>Charging association identifier. This is optional for AOC-E and can be
+ set to any value between -32768 and 32767</para>
+ </parameter>
+ <parameter name="ChargingAssociationNumber">
+ <para>Represents the charging association party number. This value is optional
+ for AOC-E.</para>
+ </parameter>
+ </syntax>
+ <description>
+ <para>Generates an AOC-D or AOC-E message on a channel.</para>
</description>
</manager>
***/
@@ -3374,6 +3483,228 @@
return NULL;
}
+static int aocmessage_get_unit_entry(const struct message *m, struct ast_aoc_unit_entry *entry, unsigned int entry_num)
+{
+ const char *unitamount;
+ const char *unittype;
+ struct ast_str *str = ast_str_alloca(32);
+
+ memset(entry, 0, sizeof(*entry));
+
+ ast_str_set(&str, 0, "UnitAmount(%u)", entry_num);
+ unitamount = astman_get_header(m, ast_str_buffer(str));
+
+ ast_str_set(&str, 0, "UnitType(%u)", entry_num);
+ unittype = astman_get_header(m, ast_str_buffer(str));
+
+ /* unit amount is required, so we can't have a type without a amount */
+ if (ast_strlen_zero(unitamount) || (sscanf(unitamount, "%30u", &entry->amount) != 1)) {
+ return -1;
+ }
+
+ if (!ast_strlen_zero(unittype)) {
+ sscanf(unittype, "%30u", &entry->type);
+ }
+
+
+ return 0;
+}
+
+static int action_aocmessage(struct mansession *s, const struct message *m)
+{
+ const char *channel = astman_get_header(m, "Channel");
+ const char *pchannel = astman_get_header(m, "ChannelPrefix");
+ const char *msgtype = astman_get_header(m, "MsgType");
+ const char *chargetype = astman_get_header(m, "ChargeType");
+ const char *currencyname = astman_get_header(m, "CurrencyName");
+ const char *currencyamount = astman_get_header(m, "CurrencyAmount");
+ const char *mult = astman_get_header(m, "CurrencyMultiplier");
+ const char *totaltype = astman_get_header(m, "TotalType");
+ const char *aocebillingid = astman_get_header(m, "AOCEBillingId");
+ const char *aocdbillingid = astman_get_header(m, "AOCDBillingId");
+ const char *association_id= astman_get_header(m, "ChargingAssociationId");
+ const char *association_num = astman_get_header(m, "ChargingAssociationNumber");
+
+ enum ast_aoc_type _msgtype;
+ enum ast_aoc_charge_type _chargetype;
+ enum ast_aoc_currency_multiplier _mult = AST_AOC_MULT_ONE;
+ enum ast_aoc_total_type _totaltype = AOC_TOTAL;
+ enum ast_aoc_billing_id _billingid = AST_AOC_BILLING_NA;
+ unsigned int _currencyamount = 0;
+ int _association_id = 0;
+ struct ast_channel *chan = NULL;
+
+ struct ast_aoc_decoded *decoded = NULL;
+ struct ast_aoc_encoded *encoded = NULL;
+ size_t encoded_size = 0;
+
+ if (ast_strlen_zero(channel) && ast_strlen_zero(pchannel)) {
+ astman_send_error(s, m, "Channel and PartialChannel are not specified. Specify at least one of these.");
+ goto aocmessage_cleanup;
+ }
+
+ if (!(chan = ast_channel_get_by_name(channel)) && !ast_strlen_zero(pchannel)) {
+ chan = ast_channel_get_by_name_prefix(pchannel, strlen(pchannel));
+ }
+
+ if (!chan) {
+ astman_send_error(s, m, "No such channel");
+ goto aocmessage_cleanup;
+ }
+
+ if (ast_strlen_zero(msgtype) || (strcasecmp(msgtype, "d") && strcasecmp(msgtype, "e"))) {
+ astman_send_error(s, m, "Invalid MsgType");
+ goto aocmessage_cleanup;
+ }
+
+ if (ast_strlen_zero(chargetype)) {
+ astman_send_error(s, m, "ChargeType not specified");
+ goto aocmessage_cleanup;
+ }
+
+ _msgtype = strcasecmp(msgtype, "d") ? AOC_E : AOC_D;
+
+ if (!strcasecmp(chargetype, "NA")) {
+ _chargetype = AOC_CHARGE_NA;
+ } else if (!strcasecmp(chargetype, "Free")) {
+ _chargetype = AOC_CHARGE_FREE;
+ } else if (!strcasecmp(chargetype, "Currency")) {
+ _chargetype = AOC_CHARGE_CURRENCY;
+ } else if (!strcasecmp(chargetype, "Unit")) {
+ _chargetype = AOC_CHARGE_UNIT;
+ } else {
+ astman_send_error(s, m, "Invalid ChargeType");
+ goto aocmessage_cleanup;
+ }
+
+ if (_chargetype == AOC_CHARGE_CURRENCY) {
+
+ if (ast_strlen_zero(currencyamount) || (sscanf(currencyamount, "%30u", &_currencyamount) != 1)) {
+ astman_send_error(s, m, "Invalid CurrencyAmount, CurrencyAmount is a required when ChargeType is Currency");
+ }
+
+ if (ast_strlen_zero(mult)) {
+ astman_send_error(s, m, "ChargeMultiplier unspecified, ChargeMultiplier is required when ChargeType is Currency.");
+ goto aocmessage_cleanup;
+ } else if (!strcasecmp(mult, "onethousandth")) {
+ _mult = AST_AOC_MULT_ONETHOUSANDTH;
+ } else if (!strcasecmp(mult, "onehundredth")) {
+ _mult = AST_AOC_MULT_ONEHUNDREDTH;
+ } else if (!strcasecmp(mult, "onetenth")) {
+ _mult = AST_AOC_MULT_ONETENTH;
+ } else if (!strcasecmp(mult, "one")) {
+ _mult = AST_AOC_MULT_ONE;
+ } else if (!strcasecmp(mult, "ten")) {
+ _mult = AST_AOC_MULT_TEN;
+ } else if (!strcasecmp(mult, "hundred")) {
+ _mult = AST_AOC_MULT_HUNDRED;
+ } else if (!strcasecmp(mult, "thousand")) {
+ _mult = AST_AOC_MULT_THOUSAND;
+ } else {
+ astman_send_error(s, m, "Invalid ChargeMultiplier");
+ goto aocmessage_cleanup;
+ }
+ }
+
+ if (_msgtype == AOC_D) {
+ if (!ast_strlen_zero(totaltype) && !strcasecmp(totaltype, "subtotal")) {
+ _totaltype = AOC_SUBTOTAL;
+ }
+
+ if (ast_strlen_zero(aocdbillingid)) {
+ /* ignore this is optional */
+ } else if (!strcasecmp(aocdbillingid, "Normal")) {
+ _billingid = AST_AOC_BILLING_NORMAL;
+ } else if (!strcasecmp(aocdbillingid, "ReverseCharge")) {
+ _billingid = AST_AOC_BILLING_REVERSE_CHARGE;
+ } else if (!strcasecmp(aocdbillingid, "CreditCard")) {
+ _billingid = AST_AOC_BILLING_CREDIT_CARD;
+ } else {
+ astman_send_error(s, m, "Invalid AOCDBillingId");
+ goto aocmessage_cleanup;
+ }
+ } else {
+ if (ast_strlen_zero(aocebillingid)) {
+ /* ignore this is optional */
+ } else if (!strcasecmp(aocebillingid, "Normal")) {
+ _billingid = AST_AOC_BILLING_NORMAL;
+ } else if (!strcasecmp(aocebillingid, "ReverseCharge")) {
+ _billingid = AST_AOC_BILLING_REVERSE_CHARGE;
+ } else if (!strcasecmp(aocebillingid, "CreditCard")) {
+ _billingid = AST_AOC_BILLING_CREDIT_CARD;
+ } else if (!strcasecmp(aocebillingid, "CallFwdUnconditional")) {
+ _billingid = AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL;
+ } else if (!strcasecmp(aocebillingid, "CallFwdBusy")) {
+ _billingid = AST_AOC_BILLING_CALL_FWD_BUSY;
+ } else if (!strcasecmp(aocebillingid, "CallFwdNoReply")) {
+ _billingid = AST_AOC_BILLING_CALL_FWD_NO_REPLY;
+ } else if (!strcasecmp(aocebillingid, "CallDeflection")) {
+ _billingid = AST_AOC_BILLING_CALL_DEFLECTION;
+ } else if (!strcasecmp(aocebillingid, "CallTransfer")) {
+ _billingid = AST_AOC_BILLING_CALL_TRANSFER;
+ } else {
+ astman_send_error(s, m, "Invalid AOCEBillingId");
+ goto aocmessage_cleanup;
+ }
+
+ if (!ast_strlen_zero(association_id) && (sscanf(association_id, "%30d", &_association_id) != 1)) {
+ astman_send_error(s, m, "Invalid ChargingAssociationId");
+ }
+
+ }
+
+ /* create decoded object and start setting values */
+ if (!(decoded = ast_aoc_create(_msgtype, _chargetype, 0))) {
+ astman_send_error(s, m, "Message Creation Failed");
+ goto aocmessage_cleanup;
+ }
+
+ if (_chargetype == AOC_CHARGE_CURRENCY) {
+ ast_aoc_set_currency_info(decoded, _currencyamount, _mult, ast_strlen_zero(currencyname) ? NULL : currencyname);
+ } else if (_chargetype == AOC_CHARGE_UNIT) {
+ struct ast_aoc_unit_entry entry;
+ int i;
+
+ /* multiple unit entries are possible, lets get them all */
+ for (i = 0; i < 32; i++) {
+ if (aocmessage_get_unit_entry(m, &entry, i)) {
+ break; /* that's the end then */
+ }
+
+ ast_aoc_add_unit_entry(decoded, entry.amount, entry.type);
+ }
+
+ /* at least one unit entry is required */
+ if (!i) {
+ astman_send_error(s, m, "Invalid UnitAmount(0), At least one valid unit entry is required when ChargeType is set to Unit");
+ goto aocmessage_cleanup;
+ }
+
+ }
+
+ ast_aoc_set_association_number(decoded, association_num);
+ ast_aoc_set_association_id(decoded, _association_id);
+ ast_aoc_set_billing_id(decoded, _billingid);
+ ast_aoc_set_total_type(decoded, _totaltype);
+
+
+ if ((encoded = ast_aoc_encode(decoded, &encoded_size)) && !ast_indicate_data(chan, AST_CONTROL_AOC, encoded, encoded_size)) {
+ astman_send_ack(s, m, "AOC Message successfully queued on channel");
+ } else {
+ astman_send_error(s, m, "Error encoding AOC message, could not queue onto channel");
+ }
+
+aocmessage_cleanup:
+
+ ast_aoc_destroy_decoded(decoded);
+ ast_aoc_destroy_encoded(encoded);
+
+ if (chan) {
+ chan = ast_channel_unref(chan);
+ }
+ return 0;
+}
+
static int action_originate(struct mansession *s, const struct message *m)
{
const char *name = astman_get_header(m, "Channel");
@@ -5586,6 +5917,7 @@
ast_manager_register_xml("CoreShowChannels", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coreshowchannels);
ast_manager_register_xml("ModuleLoad", EVENT_FLAG_SYSTEM, manager_moduleload);
ast_manager_register_xml("ModuleCheck", EVENT_FLAG_SYSTEM, manager_modulecheck);
+ ast_manager_register_xml("AOCMessage", EVENT_FLAG_CALL, action_aocmessage);
ast_cli_register_multiple(cli_manager, ARRAY_LEN(cli_manager));
ast_extension_state_add(NULL, NULL, manager_state_cb, NULL);
More information about the svn-commits
mailing list