[asterisk-commits] dvossel: branch group/v6-new r267443 - in /team/group/v6-new: doc/ include/as...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Jun 3 09:43:32 CDT 2010
Author: dvossel
Date: Thu Jun 3 09:43:28 2010
New Revision: 267443
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=267443
Log:
addition of missing aoc files
Added:
team/group/v6-new/doc/advice_of_charge.txt (with props)
team/group/v6-new/include/asterisk/aoc.h (with props)
team/group/v6-new/main/aoc.c (with props)
team/group/v6-new/tests/test_aoc.c (with props)
Added: team/group/v6-new/doc/advice_of_charge.txt
URL: http://svnview.digium.com/svn/asterisk/team/group/v6-new/doc/advice_of_charge.txt?view=auto&rev=267443
==============================================================================
--- team/group/v6-new/doc/advice_of_charge.txt (added)
+++ team/group/v6-new/doc/advice_of_charge.txt Thu Jun 3 09:43:28 2010
@@ -1,0 +1,189 @@
+================
+Advice of Charge
+================
+
+Written by: David Vossel
+Initial version: 04-19-2010
+Email: dvossel at digium.com
+
+This document is designed to give an overview of how to configure and
+generate Advice of Charge along with a detailed explanation of how each
+option works.
+
+--------------------------------------
+| READ THIS FIRST |
+--------------------------------------
+PLEASE REPORT ANY ISSUES ENCOUNTERED WHILE USING AOC. This feature
+has had very little community feedback so far. If you are using this
+feature please share with us any problems you are having and any
+improvements that could make this feature more useful. Thank you!
+
+--------------------------------------
+| Terminology |
+--------------------------------------
+AOC: Advice of Charge
+
+AOC-S: Advice of Charge message sent at the beginning of a call during
+call setup. This message contains a list of rates associated with the
+call.
+
+AOC-D: Advice of Charge message sent during the call. This message
+is typically used to update the endpoint with the current call charge.
+
+AOC-E: Advice of Charge message sent at the end of a call. This
+message is used to indicate to the endpoint the final call charge.
+
+AMI: Asterisk Manager Interface. This interface is used to generate
+AOC messages and listen for AOC events.
+
+--------------------------------------
+| AOC in chan_dahdi |
+--------------------------------------
+----- LibPRI Support:
+ETSI, or euroisdn, is the only switchtype that LibPRI currently supports
+for AOC.
+
+----- Enable AOC Pass-through in chan_dahdi
+To enable AOC pass-through between the ISDN and Asterisk use the
+'aoc_enable' config option. This option allows for any combination
+of AOC-S, AOC-D, and AOC-E to be enabled or disabled.
+
+For example:
+aoc_enable=s,d,e ; enables pass-through of AOC-S, AOC-D, and AOC-E
+
+aoc_enable=s,d ; enables pass-through of AOC-S and AOC-D. Rejects
+ ; AOC-E and AOC-E request messages
+
+Since AOC messages are often transported on facility messages, the
+'facilityenable' option must be enabled as well to fully support AOC
+pass-through.
+
+----- Handling AOC-E in chan_dahdi
+Whenever a dahdi channel receives an AOC-E message from Asterisk, it
+stores that message to deliver it at the appropriate time during call
+termination. This means that if two AOC-E messages are received on the
+same call, the last one will override the first one and only one AOC-E
+message will be sent during call termination.
+
+There are some tricky situations involving the final AOC-E message. During
+a bridged call, if the endpoint receiving the AOC messages terminates
+the call before the endpoint delivering the AOC does, the final AOC-E
+message sent by the sending side during termination will never make it to
+the receiving end because Asterisk will have already torn down that channel.
+This is where the chan_dahdi.conf 'aoce_delayhangup' option comes into play.
+
+By enabling 'aoce_delayhangup', anytime a hangup is initiated by the
+ISDN side of an Asterisk channel, instead of hanging up the channel,
+the channel sends a unique internal AOC-E termination request to its bridge
+channel. This indicates it is about to hangup and wishes to receive the
+final AOC-E message from the bridged channel before completely tearing
+down. If the bridged channel knows what to do with this AOC-E termination
+request, it will do whatever is necessary to indicate to its endpoint that
+the call is being terminated without actually hanging up the Asterisk channel.
+This allows the final AOC-E message to come in and be sent across the bridge
+while both channels are still up. If the channel delaying its hangup for
+the final AOC-E message times out, the call will be torn down just as it
+normally would. In chan_dahdi the timeout period is 1/2 the T305 timer
+which by default is 15 seconds.
+
+'aoce_delayhangup' currently only works when both bridged channels are
+dahdi_channels. If a SIP channel receives an AOC-E termination request, it
+just responds by immediately hanging up the channel. Using this option when
+bridged to any channel technology besides SIP or DAHDI will result in the
+15 second timeout period before tearing down the call completely.
+
+----- Requesting AOC services
+AOC can be requested on a call by call basis using the DAHDI dialstring
+option, A(). The A() option takes in 's', 'd', and 'e' parameters which
+represent the three types of AOC messages, AOC-S, AOC-D, and AOC-E. By using
+this option Asterisk will indicate to the endpoint during call setup that it
+wishes to receive the specified forms of AOC during the call.
+
+Example Usage in extensions.conf
+exten => 1111,1,Dial(DAHDI/g1/1112/A(s,d,e) ; requests AOC-S, AOC-D, and AOC-E on
+ ; call setup
+exten => 1111,1,Dial(DAHDI/g1/1112/A(d,e) ; requests only AOC-D, and AOC-E on
+ ; call setup
+
+--------------------------------------
+| AOC in chan_sip |
+--------------------------------------
+Asterisk supports a very basic way of sending AOC on a SIP channel to Snom
+phones using an AOC specification designed by Snom. This support is limited
+to the sending of AOC-D and AOC-E pass-through messages. No support for
+AOC-E on call termination is present, so if the Snom endpoint receiving the
+AOC messages from Asterisk terminates the call, the channel will be torn
+down before the phone can receive the final AOC-E message.
+
+To enable passthrough of AOC messages via the snom specification, use
+the 'snom_aoc_enabled' option in sip.conf.
+
+--------------------------------------
+| Generate AOC Messages via AMI |
+--------------------------------------
+Asterisk supports a way to generate AOC messages on a channel via
+the AMI action AOCMessage. At the moment the AOCMessage action is limited
+to AOC-D and AOC-E message generation. There are some limitations
+involved with delivering the final AOC-E message as well. The AOCMessage
+action has its own detailed parameter documentation so this discussion will
+focus on higher level use. When generating AOC messages on a Dahdi channel
+first make sure the appropriate chan_dahdi.conf options are enabled. Without
+enabling 'aoc_enable' correctly for pass-through the AOC messages will never
+make it out the pri. The same goes with SIP, the 'snom_aoc_enabled' option
+must be configured before messages can successfully be set to the endpoint.
+
+----- AOC-D Message Generation
+AOC-D message generation can happen anytime throughout the call. This
+message type is very straight forward.
+
+Example: AOCMessage action generating AOC-D currency message with Success
+response.
+
+Action: AOCMessage
+Channel: DAHDI/i1/1111-1
+MsgType: d
+ChargeType: Currency
+CurrencyAmount: 16
+CurrencyName: USD
+CurrencyMultiplier: OneThousandth
+AOCBillingId: Normal
+ActionID: 1234
+
+Response: Success
+ActionID: 1234
+Message: AOC Message successfully queued on channel
+
+----- AOC-E Message Generation
+AOC-E messages are sent during call termination and represent the final charge
+total for the call. Since Asterisk call termination results in the channel
+being destroyed, it is currently not possible for the AOCMessage AMI action to
+be used to send the final AOC-E message on call hangup. There is however a
+work around for this issue that can be used for Dahdi channels. By default
+chan_dahdi saves any AOC-E message it receives from Asterisk during a call and
+waits to deliver that message during call termination. If multiple AOC-E messages
+are received from Asterisk on the same Dahdi channel, only the last message received
+is stored for delivery. This means that each new AOC-E message received on the
+channel overrides the previous one. Knowing this the final AOC-E message can be
+continually updated on a Dahdi channel until call termination occurs allowing
+the last update to be sent on hangup. This method is only as accurate as the
+intervals in which it is updated, but allows some form of AOC-E to be generated.
+
+Example: AOCMessage action generating AOC-E unit message with Success response.
+
+Action: AOCMessage
+Channel: DAHDI/i1/1111-1
+MsgType: e
+ChargeType: Unit
+UnitAmount(0): 111
+UnitType(0): 6
+UnitAmount(1): 222
+UnitType(1): 5
+UnitAmount(2): 333
+UnitType(3): 4
+UnitAmount(4): 444
+AOCBillingId: Normal
+ActionID: 1234
+
+Response: Success
+ActionID: 1234
+Message: AOC Message successfully queued on channel
Propchange: team/group/v6-new/doc/advice_of_charge.txt
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/group/v6-new/doc/advice_of_charge.txt
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/group/v6-new/doc/advice_of_charge.txt
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: team/group/v6-new/include/asterisk/aoc.h
URL: http://svnview.digium.com/svn/asterisk/team/group/v6-new/include/asterisk/aoc.h?view=auto&rev=267443
==============================================================================
--- team/group/v6-new/include/asterisk/aoc.h (added)
+++ team/group/v6-new/include/asterisk/aoc.h Thu Jun 3 09:43:28 2010
@@ -1,0 +1,584 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2010, Digium, Inc.
+ *
+ * David Vossel <dvossel at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Generic Advice of Charge encode and decode routines
+ *
+ * \author David Vossel <dvossel at digium.com>
+ */
+
+#ifndef _AST_AOC_H_
+#define _AST_AOC_H_
+
+#include "asterisk/channel.h"
+
+#define AOC_CURRENCY_NAME_SIZE (10 + 1)
+
+/*! \brief Defines the currency multiplier for an aoc message. */
+enum ast_aoc_currency_multiplier {
+ AST_AOC_MULT_ONETHOUSANDTH = 1,
+ AST_AOC_MULT_ONEHUNDREDTH,
+ AST_AOC_MULT_ONETENTH,
+ AST_AOC_MULT_ONE,
+ AST_AOC_MULT_TEN,
+ AST_AOC_MULT_HUNDRED,
+ AST_AOC_MULT_THOUSAND,
+ AST_AOC_MULT_NUM_ENTRIES, /* must remain the last item in enum, this is not a valid type */
+};
+
+/*!
+ * \brief Defines the billing id options for an aoc message.
+ * \note AOC-D is limited to NORMAL, REVERSE_CHARGE, and CREDIT_CARD.
+ */
+enum ast_aoc_billing_id {
+ AST_AOC_BILLING_NA = 0,
+ AST_AOC_BILLING_NORMAL,
+ AST_AOC_BILLING_REVERSE_CHARGE,
+ AST_AOC_BILLING_CREDIT_CARD,
+ AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL,
+ AST_AOC_BILLING_CALL_FWD_BUSY,
+ AST_AOC_BILLING_CALL_FWD_NO_REPLY,
+ AST_AOC_BILLING_CALL_DEFLECTION,
+ AST_AOC_BILLING_CALL_TRANSFER,
+ AST_AOC_BILLING_NUM_ENTRIES /* must remain the last item in enum, not a valid billing id */
+};
+
+enum ast_aoc_type {
+ AST_AOC_REQUEST = 0,
+ AST_AOC_S,
+ AST_AOC_D,
+ AST_AOC_E, /* aoc-e must remain the last item in this enum */
+};
+
+enum ast_aoc_charge_type {
+ AST_AOC_CHARGE_NA = 0,
+ AST_AOC_CHARGE_FREE,
+ AST_AOC_CHARGE_CURRENCY,
+ AST_AOC_CHARGE_UNIT, /* unit must remain the last item in enum */
+};
+
+enum ast_aoc_request {
+ AST_AOC_REQUEST_S = (1 << 0),
+ AST_AOC_REQUEST_D = (1 << 1),
+ AST_AOC_REQUEST_E = (1 << 2),
+};
+
+enum ast_aoc_total_type {
+ AST_AOC_TOTAL = 0,
+ AST_AOC_SUBTOTAL = 1,
+};
+
+enum ast_aoc_time_scale {
+ AST_AOC_TIME_SCALE_HUNDREDTH_SECOND,
+ AST_AOC_TIME_SCALE_TENTH_SECOND,
+ AST_AOC_TIME_SCALE_SECOND,
+ AST_AOC_TIME_SCALE_TEN_SECOND,
+ AST_AOC_TIME_SCALE_MINUTE,
+ AST_AOC_TIME_SCALE_HOUR,
+ AST_AOC_TIME_SCALE_DAY,
+};
+
+struct ast_aoc_time {
+ /*! LengthOfTimeUnit (Not valid if length is zero.) */
+ uint32_t length;
+ uint16_t scale;
+};
+
+struct ast_aoc_duration_rate {
+ uint32_t amount;
+ uint32_t time;
+ /*! Not present if the granularity time is zero. */
+ uint32_t granularity_time;
+
+ uint16_t multiplier;
+ uint16_t time_scale;
+ uint16_t granularity_time_scale;
+
+ /*! Name of currency involved. Null terminated. */
+ char currency_name[AOC_CURRENCY_NAME_SIZE];
+
+ /*!
+ * \brief Charging interval type
+ * \details
+ * continuousCharging(0),
+ * stepFunction(1)
+ */
+ uint8_t charging_type;
+};
+
+enum ast_aoc_volume_unit {
+ AST_AOC_VOLUME_UNIT_OCTET,
+ AST_AOC_VOLUME_UNIT_SEGMENT,
+ AST_AOC_VOLUME_UNIT_MESSAGE,
+};
+
+struct ast_aoc_volume_rate {
+ uint32_t amount;
+ uint16_t multiplier;
+ uint16_t volume_unit;
+ char currency_name[AOC_CURRENCY_NAME_SIZE];
+};
+
+struct ast_aoc_flat_rate {
+ uint32_t amount;
+ uint16_t multiplier;
+ /*! Name of currency involved. Null terminated. */
+ char currency_name[AOC_CURRENCY_NAME_SIZE];
+};
+
+enum ast_aoc_s_charged_item {
+ AST_AOC_CHARGED_ITEM_NA,
+ AST_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT,
+ AST_AOC_CHARGED_ITEM_BASIC_COMMUNICATION,
+ AST_AOC_CHARGED_ITEM_CALL_ATTEMPT,
+ AST_AOC_CHARGED_ITEM_CALL_SETUP,
+ AST_AOC_CHARGED_ITEM_USER_USER_INFO,
+ AST_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE,
+};
+
+enum ast_aoc_s_rate_type {
+ AST_AOC_RATE_TYPE_NA,
+ AST_AOC_RATE_TYPE_FREE,
+ AST_AOC_RATE_TYPE_FREE_FROM_BEGINNING,
+ AST_AOC_RATE_TYPE_DURATION,
+ AST_AOC_RATE_TYPE_FLAT,
+ AST_AOC_RATE_TYPE_VOLUME,
+ AST_AOC_RATE_TYPE_SPECIAL_CODE,
+};
+
+struct ast_aoc_s_entry {
+ uint16_t charged_item;
+ uint16_t rate_type;
+
+ /*! \brief Charge rate being applied. */
+ union {
+ struct ast_aoc_duration_rate duration;
+ struct ast_aoc_flat_rate flat;
+ struct ast_aoc_volume_rate volume;
+ uint16_t special_code; /* 1...10 */
+ } rate;
+} __attribute__((packed));
+
+struct ast_aoc_unit_entry {
+ char valid_amount;
+ unsigned int amount;
+ char valid_type;
+ unsigned int type; /* 1 - 16 by ETSI standard */
+};
+
+enum AST_AOC_CHARGING_ASSOCIATION {
+ AST_AOC_CHARGING_ASSOCIATION_NA,
+ AST_AOC_CHARGING_ASSOCIATION_NUMBER,
+ AST_AOC_CHARGING_ASSOCIATION_ID,
+};
+struct ast_aoc_charging_association_number {
+ uint8_t plan;
+ char number[32];
+} __attribute__((packed));
+struct ast_aoc_charging_association {
+ union {
+ int32_t id;
+ struct ast_aoc_charging_association_number number;
+ } charge;
+ /*! \see enum AST_AOC_CHARGING_ASSOCIATION */
+ uint8_t charging_type;
+} __attribute__((packed));
+
+/*! \brief AOC Payload Header. Holds all the encoded AOC data to pass on the wire */
+struct ast_aoc_encoded;
+
+/*! \brief Decoded AOC data. This value is used to set all the values in an AOC message before encoding.*/
+struct ast_aoc_decoded;
+
+/*!
+ * \brief creates a ast_aoc_decode object of a specific message type
+ * \since 1.8
+ *
+ * \param msg_type AOC-D, AOC-E, or AOC Request
+ * \param charge_type this is ignored if message type is not AOC-D or AOC-E.
+ * \param requests flags. This defines the types of AOC requested. This
+ * field should only be set when the message type is AOC Request,
+ * the value is ignored otherwise.
+ *
+ * \retval heap allocated ast_aoc_decoded object ptr on success
+ * \retval NULL failure
+ */
+struct ast_aoc_decoded *ast_aoc_create(const enum ast_aoc_type msg_type,
+ const enum ast_aoc_charge_type charge_type,
+ const enum ast_aoc_request requests);
+
+
+/*! \brief free an ast_aoc_decoded object */
+void *ast_aoc_destroy_decoded(struct ast_aoc_decoded *decoded);
+
+/*! \brief free an ast_aoc_encoded object */
+void *ast_aoc_destroy_encoded(struct ast_aoc_encoded *encoded);
+
+/*!
+ * \brief decodes an encoded aoc payload.
+ * \since 1.8
+ *
+ * \param encoded the encoded payload to decode.
+ * \param size total size of encoded payload
+ * \param chan ast channel, Optional for DEBUG output purposes
+ *
+ * \retval heap allocated ast_aoc_decoded object ptr on success
+ * \retval NULL failure
+ */
+struct ast_aoc_decoded *ast_aoc_decode(struct ast_aoc_encoded *encoded, size_t size, struct ast_channel *chan);
+
+/*!
+ * \brief encodes a decoded aoc structure so it can be passed on the wire
+ * \since 1.8
+ *
+ * \param decoded the decoded struct to be encoded
+ * \param out_size output parameter representing size of encoded data
+ * \param chan ast channel, Optional for DEBUG output purposes
+ *
+ * \retval pointer to encoded data
+ * \retval NULL failure
+ */
+struct ast_aoc_encoded *ast_aoc_encode(struct ast_aoc_decoded *decoded, size_t *out_size, struct ast_channel *chan);
+
+/*!
+ * \brief Sets the type of total for a AOC-D message
+ * \since 1.8
+ *
+ * \param decoded ast_aoc_decoded struct to set values on
+ * \param type total type: TOTAL or SUBTOTAL
+ *
+ * \note If this value is not set, the default for the message is TOTAL
+ *
+ * \retval 0 success
+ */
+int ast_aoc_set_total_type(struct ast_aoc_decoded *decoded, const enum ast_aoc_total_type type);
+
+/*!
+ * \brief Sets the currency values for a AOC-D or AOC-E message
+ * \since 1.8
+ *
+ * \param decoded ast_aoc_decoded struct to set values on
+ * \param amount currency amount REQUIRED
+ * \param multiplier currency multiplier REQUIRED, 0 or undefined value defaults to AST_AOC_MULT_ONE.
+ * \param name currency name OPTIONAL
+ *
+ * \retval 0 success
+ */
+int ast_aoc_set_currency_info(struct ast_aoc_decoded *decoded,
+ const unsigned int amount,
+ const enum ast_aoc_currency_multiplier multiplier,
+ const char *name);
+
+/*!
+ * \brief Adds a unit entry into the list of units
+ * \since 1.8
+ *
+ * \param decoded ast_aoc_decoded struct to set values on
+ * \param amount_is_present set this if the number of units is actually present.
+ * \param amount number of units
+ * \param type_is_present set this if the type value is present
+ * \param type unit type
+ *
+ * \note If neither the amount nor the type is present, the entry will
+ * not be added.
+ *
+ * \retval 0 success
+ */
+int ast_aoc_add_unit_entry(struct ast_aoc_decoded *decoded,
+ const unsigned int amount_is_present,
+ const unsigned int amount,
+ const unsigned int type_is_present,
+ const unsigned int type);
+
+/*!
+ * \brief set the billing id for a AOC-D or AST_AOC_E message
+ * \since 1.8
+ *
+ * \param decoded ast_aoc_decoded struct to set values on
+ * \param id billing id
+ *
+ * \retval 0 success
+ */
+int ast_aoc_set_billing_id(struct ast_aoc_decoded *decoded, const enum ast_aoc_billing_id id);
+
+/*!
+ * \brief set the charging association id for an AST_AOC_E message
+ * \since 1.8
+ *
+ * \param decoded ast_aoc_decoded struct to set values on
+ * \param id charging association identifier
+ *
+ * \note If the association number was set, this will override that value. Only the id OR the
+ * number can be set at a time, not both.
+ *
+ * \retval 0 success
+ */
+int ast_aoc_set_association_id(struct ast_aoc_decoded *decoded, const int id);
+
+/*!
+ * \brief set the charging accociation number for an AOC-E message
+ * \since 1.8
+ *
+ * \param decoded ast_aoc_decoded struct to set values on
+ * \param num charging association number
+ * \param plan charging association number plan and type-of-number fields
+ *
+ * \note If the association id was set, this will override that value. Only the id OR the
+ * number can be set at a time, not both.
+ *
+ * \retval 0 success
+ */
+int ast_aoc_set_association_number(struct ast_aoc_decoded *decoded, const char *num, uint8_t plan);
+
+/*!
+ * \brief Mark the AST_AOC_REQUEST message as a termination request.
+ * \since 1.8
+ *
+ * \param decoded ast_aoc_decoded struct to set values on
+ *
+ * \note A termination request indicates that the call has terminated,
+ * but that the other side is waiting for a short period of time before
+ * hanging up so it can get the final AOC-E message.
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_aoc_set_termination_request(struct ast_aoc_decoded *decoded);
+
+/*!
+ * \brief Add AOC-S duration rate entry
+ * \since 1.8
+ *
+ * \param decoded aoc decoded object to add entry to
+ * \param charged_item ast_aoc_s_charged_item
+ * \param amount currency amount
+ * \param multiplier currency multiplier
+ * \param currency_name truncated after 10 characters
+ * \param time
+ * \param time_scale from ast_aoc_time_scale enum
+ * \param granularity_time (optional, set to 0 if not present);
+ * \param granularity_time_scale (optional, set to 0 if not present);
+ * \param step_function set to 1 if this is to use a step function, 0 if continuious
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_aoc_s_add_rate_duration(struct ast_aoc_decoded *decoded,
+ enum ast_aoc_s_charged_item charged_item,
+ unsigned int amount,
+ enum ast_aoc_currency_multiplier multiplier,
+ const char *currency_name,
+ unsigned long time,
+ enum ast_aoc_time_scale time_scale,
+ unsigned long granularity_time,
+ enum ast_aoc_time_scale granularity_time_scale,
+ int step_function);
+
+/*!
+ * \brief Add AOC-S flat rate entry
+ * \since 1.8
+ *
+ * \param decoded aoc decoded object to add entry to
+ * \param charged_item ast_aoc_s_charged_item
+ * \param amount currency amount
+ * \param multiplier currency multiplier
+ * \param currency_name truncated after 10 characters
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_aoc_s_add_rate_flat(struct ast_aoc_decoded *decoded,
+ enum ast_aoc_s_charged_item charged_item,
+ unsigned int amount,
+ enum ast_aoc_currency_multiplier multiplier,
+ const char *currency_name);
+
+/*!
+ * \brief Add AOC-S volume rate entry
+ * \since 1.8
+ *
+ * \param decoded aoc decoded object to add entry to
+ * \param charged_item ast_aoc_s_charged_item
+ * \param volume_unit from ast_aoc_volume_unit enum
+ * \param amount currency amount
+ * \param multiplier currency multiplier
+ * \param currency_name truncated after 10 characters
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_aoc_s_add_rate_volume(struct ast_aoc_decoded *decoded,
+ enum ast_aoc_s_charged_item charged_item,
+ enum ast_aoc_volume_unit volume_unit,
+ unsigned int amount,
+ enum ast_aoc_currency_multiplier multiplier,
+ const char *currency_name);
+
+/*!
+ * \brief Add AOC-S special rate entry
+ * \since 1.8
+ *
+ * \param decoded aoc decoded object to add entry to
+ * \param charged_item ast_aoc_s_charged_item
+ * \param code special charging code
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_aoc_s_add_rate_special_charge_code(struct ast_aoc_decoded *decoded,
+ enum ast_aoc_s_charged_item charged_item,
+ unsigned int code);
+
+/*!
+ * \brief Add AOC-S indicating charge item is free
+ * \since 1.8
+ *
+ * \param decoded aoc decoded object to add entry to
+ * \param charged_item ast_aoc_s_charged_item
+ * \param from_beginning TRUE if the rate is free from beginning.
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_aoc_s_add_rate_free(struct ast_aoc_decoded *decoded,
+ enum ast_aoc_s_charged_item charged_item, int from_beginning);
+
+/*!
+ * \brief Add AOC-S entry indicating charge item is not available
+ * \since 1.8
+ *
+ * \param decoded aoc decoded object to add entry to
+ * \param charged_item ast_aoc_s_charged_item
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_aoc_s_add_rate_na(struct ast_aoc_decoded *decoded,
+ enum ast_aoc_s_charged_item charged_item);
+
+/*!
+ * \brief Add AOC-S special arrangement entry
+ * \since 1.8
+ *
+ * \param decoded aoc decoded object to add entry to
+ * \param code special arrangement code
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_aoc_s_add_special_arrangement(struct ast_aoc_decoded *decoded,
+ unsigned int code);
+
+/*!
+ * \brief Convert decoded aoc msg to string representation
+ * \since 1.8
+ *
+ * \param decoded ast_aoc_decoded struct to convert to string
+ * \param msg dynamic heap allocated ast_str object to store string representation in
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_aoc_decoded2str(const struct ast_aoc_decoded *decoded, struct ast_str **msg);
+
+/*! \brief generate AOC manager event for an AOC-S, AOC-D, or AOC-E msg */
+int ast_aoc_manager_event(const struct ast_aoc_decoded *decoded, struct ast_channel *chan);
+
+/*! \brief get the message type, AOC-D, AOC-E, or AOC Request */
+enum ast_aoc_type ast_aoc_get_msg_type(struct ast_aoc_decoded *decoded);
+
+/*! \brief get the charging type for an AOC-D or AOC-E message */
+enum ast_aoc_charge_type ast_aoc_get_charge_type(struct ast_aoc_decoded *decoded);
+
+/*! \brief get the types of AOC requested for when message type is AOC Request */
+enum ast_aoc_request ast_aoc_get_request(struct ast_aoc_decoded *decoded);
+
+/*! \brief get the type of total for a AOC-D message */
+enum ast_aoc_total_type ast_aoc_get_total_type(struct ast_aoc_decoded *decoded);
+
+/*! \brief get the currency amount for AOC-D and AOC-E messages*/
+unsigned int ast_aoc_get_currency_amount(struct ast_aoc_decoded *decoded);
+
+/*! \brief get the number rates associated with an AOC-S message */
+unsigned int ast_aoc_s_get_count(struct ast_aoc_decoded *decoded);
+
+/*!
+ * \brief get a specific AOC-S rate entry.
+ * \since 1.8
+ *
+ * \note This can be used in conjunction with ast_aoc_s_get_count to create
+ * a unit entry iterator.
+ */
+const struct ast_aoc_s_entry *ast_aoc_s_get_rate_info(struct ast_aoc_decoded *decoded, unsigned int entry_number);
+
+/*! \brief get the number of unit entries for AOC-D and AOC-E messages*/
+unsigned int ast_aoc_get_unit_count(struct ast_aoc_decoded *decoded);
+
+/*!
+ * \brief get a specific unit entry.
+ * \since 1.8
+ *
+ * \note This can be used in conjunction with ast_aoc_get_unit_count to create
+ * a unit entry iterator.
+ */
+const struct ast_aoc_unit_entry *ast_aoc_get_unit_info(struct ast_aoc_decoded *decoded, unsigned int entry_number);
+
+/*! \brief get the currency multiplier for AOC-D and AOC-E messages */
+enum ast_aoc_currency_multiplier ast_aoc_get_currency_multiplier(struct ast_aoc_decoded *decoded);
+
+/*! \brief get the currency multiplier for AOC-D and AOC-E messages in decimal format */
+const char *ast_aoc_get_currency_multiplier_decimal(struct ast_aoc_decoded *decoded);
+
+/*! \brief get the currency name for AOC-D and AOC-E messages*/
+const char *ast_aoc_get_currency_name(struct ast_aoc_decoded *decoded);
+
+/*! \brief get the billing id for AOC-D and AOC-E messages*/
+enum ast_aoc_billing_id ast_aoc_get_billing_id(struct ast_aoc_decoded *decoded);
+
+/*! \brief get the charging association info for AOC-E messages*/
+const struct ast_aoc_charging_association *ast_aoc_get_association_info(struct ast_aoc_decoded *decoded);
+
+/*!
+ * \brief get whether or not the AST_AOC_REQUEST message as a termination request.
+ * \since 1.8
+ *
+ * \note a termination request indicates that the call has terminated,
+ * but that the other side is waiting for a short period of time
+ * before hanging up so it can get the final AOC-E message.
+ *
+ * \param decoded ast_aoc_decoded struct to get values on
+ *
+ * \retval 0 not a termination request
+ * \retval 1 is a termination request
+ */
+int ast_aoc_get_termination_request(struct ast_aoc_decoded *decoded);
+
+/*!
+ * \brief test aoc encode decode routines.
+ * \since 1.8
+ *
+ * \note This function verifies that a decoded message matches itself after
+ * the encode decode routine.
+ */
+int ast_aoc_test_encode_decode_match(struct ast_aoc_decoded *decoded);
+
+/*! \brief enable aoc cli options */
+int ast_aoc_cli_init(void);
+
+#endif /* _AST_AOC_H_ */
Propchange: team/group/v6-new/include/asterisk/aoc.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/group/v6-new/include/asterisk/aoc.h
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/group/v6-new/include/asterisk/aoc.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: team/group/v6-new/main/aoc.c
URL: http://svnview.digium.com/svn/asterisk/team/group/v6-new/main/aoc.c?view=auto&rev=267443
==============================================================================
--- team/group/v6-new/main/aoc.c (added)
+++ team/group/v6-new/main/aoc.c Thu Jun 3 09:43:28 2010
@@ -1,0 +1,1607 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2010, Digium, Inc.
+ *
+ * David Vossel <dvossel at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief generic AOC payload generation encoding and decoding
+ *
+ * \author David Vossel <dvossel at digium.com>
+ */
+
+#include "asterisk.h"
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
+
+#include "asterisk/aoc.h"
+#include "asterisk/utils.h"
+#include "asterisk/strings.h"
+#include "asterisk/_private.h"
+#include "asterisk/cli.h"
+#include "asterisk/manager.h"
+
+/* Encoded Payload Flags */
+#define AST_AOC_ENCODED_TYPE_REQUEST (0 << 0)
+#define AST_AOC_ENCODED_TYPE_D (1 << 0)
+#define AST_AOC_ENCODED_TYPE_E (2 << 0)
+#define AST_AOC_ENCODED_TYPE_S (3 << 0)
+
+#define AST_AOC_ENCODED_REQUEST_S (1 << 2)
+#define AST_AOC_ENCODED_REQUEST_D (1 << 3)
+#define AST_AOC_ENCODED_REQUEST_E (1 << 4)
+
+#define AST_AOC_ENCODED_CHARGE_NA (0 << 5)
+#define AST_AOC_ENCODED_CHARGE_FREE (1 << 5)
+#define AST_AOC_ENCODED_CHARGE_CURRENCY (2 << 5)
+#define AST_AOC_ENCODED_CHARGE_UNIT (3 << 5)
+
+#define AST_AOC_ENCODED_CHARGE_SUBTOTAL (1 << 7)
+#define AST_AOC_ENCODED_CHARGE_TOTAL (0 << 7)
+
+#define AST_AOC_ENCODE_VERSION 1
+
+
+static char aoc_debug_enabled = 0;
+static void aoc_display_decoded_debug(const struct ast_aoc_decoded *decoded, int decoding, struct ast_channel *chan);
+static int aoc_s_add_entry(struct ast_aoc_decoded *decoded, struct ast_aoc_s_entry *entry);
+
+/* AOC Payload Header. Holds all the encoded AOC data to pass on the wire */
+struct ast_aoc_encoded {
+ uint8_t version;
+ uint8_t flags;
+ uint16_t datalen;
+ unsigned char data[0];
+};
+
+/* Decoded AOC data */
+struct ast_aoc_decoded {
+ enum ast_aoc_type msg_type;
+ enum ast_aoc_charge_type charge_type;
+ enum ast_aoc_request request_flag;
+ enum ast_aoc_total_type total_type;
+
+ /* currency information */
+ enum ast_aoc_currency_multiplier multiplier;
+ unsigned int currency_amount;
+ char currency_name[AOC_CURRENCY_NAME_SIZE];
+
+ /* unit information */
+ int unit_count;
+ struct ast_aoc_unit_entry unit_list[32];
+
+ /* Billing Id */
+ enum ast_aoc_billing_id billing_id;
+
+ /* Charging Association information */
+ struct ast_aoc_charging_association charging_association;
+
+ /* AOC-S charge information */
+ int aoc_s_count;
+ struct ast_aoc_s_entry aoc_s_entries[10];
+
+ /* Is this an AOC Termination Request */
+ char termination_request;
+};
+
+/*! \brief AOC Payload Information Elements */
+enum AOC_IE {
+ AOC_IE_CURRENCY = 1,
+ AOC_IE_UNIT = 2,
+ AOC_IE_BILLING = 3,
+ AOC_IE_CHARGING_ASSOCIATION = 4,
+ AOC_IE_RATE = 5,
+ AOC_IE_TERMINATION_REQUEST = 6,
+};
+
+/*! \brief AOC IE payload header */
+struct aoc_pl_ie_hdr {
+ uint8_t ie_id;
+ uint8_t datalen;
+ char data[0];
+} __attribute__((packed));
+
+struct aoc_ie_currency {
+ uint32_t amount;
+ uint8_t multiplier;
+ char name[AOC_CURRENCY_NAME_SIZE];
+} __attribute__((packed));
+
+struct aoc_ie_unit {
+ uint32_t amount;
+ uint8_t valid_type;
+ uint8_t valid_amount;
+ uint8_t type;
+} __attribute__((packed));
+
+struct aoc_ie_billing {
+ uint8_t id;
+} __attribute__((packed));
+
+struct aoc_ie_charging_association {
+ struct ast_aoc_charging_association ca;
+} __attribute__((packed));
+
+struct aoc_ie_charging_rate {
+ struct ast_aoc_s_entry entry;
+} __attribute__((packed));
+
+struct ast_aoc_decoded *ast_aoc_create(const enum ast_aoc_type msg_type,
+ const enum ast_aoc_charge_type charge_type,
+ const enum ast_aoc_request requests)
+{
+ struct ast_aoc_decoded *decoded = NULL;
+
+ /* verify input */
+ if (((unsigned int) charge_type > AST_AOC_CHARGE_UNIT) ||
+ ((unsigned int) msg_type > AST_AOC_E) ||
+ ((msg_type == AST_AOC_REQUEST) && !requests)) {
+
+ ast_log(LOG_WARNING, "Failed to create ast_aoc_decoded object, invalid input\n");
+ return NULL;
+ }
+
+ if (!(decoded = ast_calloc(1, sizeof(struct ast_aoc_decoded)))) {
+ ast_log(LOG_WARNING, "Failed to create ast_aoc_decoded object \n");
+ return NULL;
+ }
+
+ decoded->msg_type = msg_type;
+
+ if (msg_type == AST_AOC_REQUEST) {
+ decoded->request_flag = requests;
+ } else if ((msg_type == AST_AOC_D) || (msg_type == AST_AOC_E)) {
+ decoded->charge_type = charge_type;
+ }
+
+ return decoded;
+}
+
+void *ast_aoc_destroy_decoded(struct ast_aoc_decoded *decoded)
+{
+ ast_free(decoded);
+ return NULL;
+}
+
+void *ast_aoc_destroy_encoded(struct ast_aoc_encoded *encoded)
+{
+ ast_free(encoded);
+ return NULL;
+}
+
+static void aoc_parse_ie_charging_rate(struct ast_aoc_decoded *decoded, const struct aoc_ie_charging_rate *ie)
+{
+ struct ast_aoc_s_entry entry = { 0, };
+
+ entry.charged_item = ntohs(ie->entry.charged_item);
+ entry.rate_type = ntohs(ie->entry.rate_type);
+
+ switch (entry.rate_type) {
+ case AST_AOC_RATE_TYPE_DURATION:
+ entry.rate.duration.multiplier = ntohs(ie->entry.rate.duration.multiplier);
+ entry.rate.duration.amount = ntohl(ie->entry.rate.duration.amount);
+ entry.rate.duration.time = ntohl(ie->entry.rate.duration.time);
+ entry.rate.duration.time_scale = ntohs(ie->entry.rate.duration.time_scale);
+ entry.rate.duration.granularity_time = ntohl(ie->entry.rate.duration.granularity_time);
+ entry.rate.duration.granularity_time_scale = ntohs(ie->entry.rate.duration.granularity_time_scale);
+ entry.rate.duration.charging_type = ie->entry.rate.duration.charging_type; /* only one byte */
+
+ if (!ast_strlen_zero(ie->entry.rate.duration.currency_name)) {
+ ast_copy_string(entry.rate.duration.currency_name,
+ ie->entry.rate.duration.currency_name,
+ sizeof(entry.rate.duration.currency_name));
+ }
+ break;
+ case AST_AOC_RATE_TYPE_FLAT:
+ entry.rate.flat.multiplier = ntohs(ie->entry.rate.flat.multiplier);
+ entry.rate.flat.amount = ntohl(ie->entry.rate.flat.amount);
+ if (!ast_strlen_zero(ie->entry.rate.flat.currency_name)) {
+ ast_copy_string(entry.rate.flat.currency_name,
+ ie->entry.rate.flat.currency_name,
+ sizeof(entry.rate.flat.currency_name));
+ }
+ break;
+ case AST_AOC_RATE_TYPE_VOLUME:
+ entry.rate.volume.multiplier = ntohs(ie->entry.rate.volume.multiplier);
+ entry.rate.volume.amount = ntohl(ie->entry.rate.volume.amount);
+ entry.rate.volume.volume_unit = ntohs(ie->entry.rate.volume.volume_unit);
+ if (!ast_strlen_zero(ie->entry.rate.volume.currency_name)) {
+ ast_copy_string(entry.rate.volume.currency_name,
+ ie->entry.rate.volume.currency_name,
+ sizeof(entry.rate.volume.currency_name));
+ }
+ break;
+ case AST_AOC_RATE_TYPE_SPECIAL_CODE:
+ entry.rate.special_code = ntohs(ie->entry.rate.special_code);
+ break;
+ }
+
+ aoc_s_add_entry(decoded, &entry);
+}
+
+static int aoc_parse_ie(struct ast_aoc_decoded *decoded, unsigned char *data, unsigned int datalen)
+{
+ enum AOC_IE ie_id;
+ unsigned int len;
+
+ while (datalen >= 2) {
+ ie_id = data[0];
+ len = data[1];
+ if (len > datalen -2) {
+ ast_log(LOG_ERROR, "AOC information element length exceeds the total message size\n");
+ return -1;
+ }
+
+ switch(ie_id) {
+ case AOC_IE_CURRENCY:
+ if (len == sizeof(struct aoc_ie_currency)) {
+ struct aoc_ie_currency ie;
+ memcpy(&ie, data + 2, len);
+ decoded->currency_amount = ntohl(ie.amount);
+ decoded->multiplier = ie.multiplier; /* only one byte */
+ memcpy(decoded->currency_name, ie.name, sizeof(decoded->currency_name));
+ } else {
+ ast_log(LOG_WARNING, "Recieved invalid currency ie\n");
+ }
+ break;
+ case AOC_IE_UNIT:
+ if (len == sizeof(struct aoc_ie_unit)) {
+ struct aoc_ie_unit ie;
+ memcpy(&ie, data + 2, len);
+ ast_aoc_add_unit_entry(decoded, ie.valid_amount, ntohl(ie.amount), ie.valid_type, ie.type);
+ } else {
+ ast_log(LOG_WARNING, "Recieved invalid unit ie\n");
+ }
+ break;
+ case AOC_IE_BILLING:
+ if (len == sizeof(struct aoc_ie_billing)) {
+ struct aoc_ie_billing ie;
+ memcpy(&ie, data + 2, len);
+ decoded->billing_id = ie.id; /* only one byte */
+ } else {
+ ast_log(LOG_WARNING, "Recieved invalid billing ie\n");
+ }
+ break;
+ case AOC_IE_CHARGING_ASSOCIATION:
+ if (len == sizeof(struct aoc_ie_charging_association)) {
+ memcpy(&decoded->charging_association, data + 2, sizeof(decoded->charging_association));
+ /* everything in the charging_association struct is a single byte except for the id */
+ if (decoded->charging_association.charging_type == AST_AOC_CHARGING_ASSOCIATION_ID) {
+ decoded->charging_association.charge.id = ntohl(decoded->charging_association.charge.id);
+ }
+ } else {
+ ast_log(LOG_WARNING, "Recieved invalid charging association ie\n");
+ }
+ break;
+ case AOC_IE_RATE:
+ if (len == sizeof(struct aoc_ie_charging_rate)) {
+ struct aoc_ie_charging_rate ie;
+ memcpy(&ie, data + 2, len);
+ aoc_parse_ie_charging_rate(decoded, &ie);
+ } else {
+ ast_log(LOG_WARNING, "Recieved invalid charging rate ie\n");
+ }
+ break;
+ case AOC_IE_TERMINATION_REQUEST:
+ if (len == 0) {
+ decoded->termination_request = 1;
+ } else {
+ ast_log(LOG_WARNING, "Recieved invalid termination request ie\n");
+ }
+ break;
+ default:
+ ast_log(LOG_WARNING, "Unknown AOC Information Element, ignoring.\n");
+ }
+
+ datalen -= (len + 2);
+ data += (len + 2);
+ }
+ return 0;
+}
+
+struct ast_aoc_decoded *ast_aoc_decode(struct ast_aoc_encoded *encoded, size_t size, struct ast_channel *chan)
+{
+ struct ast_aoc_decoded *decoded;
+
+ /* verify our encoded payload is actually large enough to hold all the ies */
+ if ((size - (sizeof(struct ast_aoc_encoded)) != ntohs(encoded->datalen))) {
+ ast_log(LOG_WARNING, "Corrupted aoc encoded object, can not decode\n");
+ return NULL;
+ }
+
+ if (!(decoded = ast_calloc(1, sizeof(struct ast_aoc_decoded)))) {
+ ast_log(LOG_WARNING, "Failed to create ast_aoc_decoded object \n");
+ return NULL;
+ }
+
+ /* decode flags */
+
+ if ((encoded->flags & AST_AOC_ENCODED_TYPE_S) == AST_AOC_ENCODED_TYPE_S) {
+ decoded->msg_type = AST_AOC_S;
+ } else if (encoded->flags & AST_AOC_ENCODED_TYPE_E) {
+ decoded->msg_type = AST_AOC_E;
+ } else if (encoded->flags & AST_AOC_ENCODED_TYPE_D) {
+ decoded->msg_type = AST_AOC_D;
+ } else {
+ decoded->msg_type = AST_AOC_REQUEST;
+ }
+
+ if (decoded->msg_type == AST_AOC_REQUEST) {
[... 1988 lines stripped ...]
More information about the asterisk-commits
mailing list