[svn-commits] dvossel: branch dvossel/generic_aoc r255111 - in /team/dvossel/generic_aoc: c...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Mar 26 17:13:34 CDT 2010


Author: dvossel
Date: Fri Mar 26 17:13:30 2010
New Revision: 255111

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=255111
Log:
move aoc manager events into the asterisk aoc core

Modified:
    team/dvossel/generic_aoc/channels/sig_pri.c
    team/dvossel/generic_aoc/include/asterisk/aoc.h
    team/dvossel/generic_aoc/main/aoc.c

Modified: team/dvossel/generic_aoc/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/generic_aoc/channels/sig_pri.c?view=diff&rev=255111&r1=255110&r2=255111
==============================================================================
--- team/dvossel/generic_aoc/channels/sig_pri.c (original)
+++ team/dvossel/generic_aoc/channels/sig_pri.c Fri Mar 26 17:13:30 2010
@@ -1936,156 +1936,32 @@
 #if defined(HAVE_PRI_AOC_EVENTS)
 /*!
  * \internal
- * \brief Convert PRI_AOC_CHARGED_ITEM to string.
+ * \brief Convert PRI_AOC_CHARGED_ITEM to ast_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 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) {
-	default:
 	case PRI_AOC_CHARGED_ITEM_NOT_AVAILABLE:
-		str = "NotAvailable";
-		break;
+		return AST_AOC_CHARGED_ITEM_NA;
 	case PRI_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT:
-		str = "SpecialArrangement";
-		break;
+		return AST_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT;
 	case PRI_AOC_CHARGED_ITEM_BASIC_COMMUNICATION:
-		str = "BasicCommunication";
-		break;
+		return AST_AOC_CHARGED_ITEM_BASIC_COMMUNICATION;
 	case PRI_AOC_CHARGED_ITEM_CALL_ATTEMPT:
-		str = "CallAttempt";
-		break;
+		return AST_AOC_CHARGED_ITEM_CALL_ATTEMPT;
 	case PRI_AOC_CHARGED_ITEM_CALL_SETUP:
-		str = "CallSetup";
-		break;
+		return AST_AOC_CHARGED_ITEM_CALL_SETUP;
 	case PRI_AOC_CHARGED_ITEM_USER_USER_INFO:
-		str = "UserUserInfo";
-		break;
+		return AST_AOC_CHARGED_ITEM_USER_USER_INFO;
 	case PRI_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE:
-		str = "SupplementaryService";
-		break;
-	}
-	return str;
-}
-#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;
+		return AST_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE;
+	}
+	return AST_AOC_CHARGED_ITEM_NA;
 }
 #endif	/* defined(HAVE_PRI_AOC_EVENTS) */
 
@@ -2155,206 +2031,40 @@
 #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.
@@ -2365,75 +2075,72 @@
  *
  * \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)
+{
+	struct ast_aoc_decoded *decoded = NULL;
 	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));
+		int charged_item = sig_pri_aoc_charged_item_to_ast(aoc_s->item[idx].chargeable);
 		if (aoc_s->item[idx].chargeable == PRI_AOC_CHARGED_ITEM_NOT_AVAILABLE) {
 			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,
+				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,
+				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,
+				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:
+		case PRI_AOC_RATE_TYPE_FREE_FROM_BEGINNING:
+			ast_aoc_s_add_rate_free(decoded, charged_item);
+			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;
+		}
+	}
+
+	ast_aoc_manager_event(decoded, owner);
+
+	ast_aoc_destroy_decoded(decoded);
+
 }
 #endif	/* defined(HAVE_PRI_AOC_EVENTS) */
 
@@ -2500,6 +2207,7 @@
 	struct ast_aoc_encoded *encoded = NULL;
 	size_t encoded_size = 0;
 	enum ast_aoc_charge_type type;
+
 	if (!owner || !aoc_d) {
 		return;
 	}
@@ -2561,81 +2269,10 @@
 		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.
- * \param owner Asterisk channel associated with the call.
- *
- * \note Assumes the pri->lock is already obtained.
- * \note Assumes the owner channel lock is already obtained.
- *
- * \return Nothing
- */
-static void sig_pri_aoc_d_event(const struct pri_subcmd_aoc_d *aoc_d, struct ast_channel *owner)
-{
-	struct ast_str *msg;
-	const char *charge_str;
-	int idx;
-	char prefix[32];
-
-	msg = ast_str_create(4096);
-	if (!msg) {
-		return;
-	}
-
-	ast_str_append(&msg, 0, "Channel: %s\r\n", owner->name);
-	ast_str_append(&msg, 0, "UniqueID: %s\r\n", owner->uniqueid);
-	/* Queue AST_CONTROL_AOC frame on channel */
-	sig_pri_aoc_d_from_pri(aoc_d, owner);
-
-	charge_str = sig_pri_aoc_de_charge_str(aoc_d->charge);
-	ast_str_append(&msg, 0, "Type: %s\r\n", charge_str);
-	switch (aoc_d->charge) {
-	case PRI_AOC_DE_CHARGE_CURRENCY:
-	case PRI_AOC_DE_CHARGE_UNITS:
-		ast_str_append(&msg, 0, "BillingID: %s\r\n",
-			sig_pri_aoc_d_billing_id_str(aoc_d->billing_id));
-		ast_str_append(&msg, 0, "TypeOfCharging: %s\r\n",
-			aoc_d->billing_accumulation ? "Total" : "SubTotal");
-		break;
-	default:
-		break;
-	}
-	switch (aoc_d->charge) {
-	case PRI_AOC_DE_CHARGE_CURRENCY:
-		ast_str_append(&msg, 0, "%s: %s\r\n", charge_str,
-			aoc_d->recorded.money.currency);
-		sig_pri_aoc_amount(&msg, charge_str, &aoc_d->recorded.money.amount);
-		break;
-	case PRI_AOC_DE_CHARGE_UNITS:
-		ast_str_append(&msg, 0, "%s/NumberItems: %d\r\n", charge_str,
-			aoc_d->recorded.unit.num_items);
-		for (idx = 0; idx < aoc_d->recorded.unit.num_items; ++idx) {
-			snprintf(prefix, sizeof(prefix), "%s/Item(%d)", charge_str, idx);
-
-			/* -1 if not available. */
-			ast_str_append(&msg, 0, "%s/NumberOf: %ld\r\n", prefix,
-				aoc_d->recorded.unit.item[idx].number);
-			/* -1 if not available. */
-			ast_str_append(&msg, 0, "%s/TypeOf: %d\r\n", prefix,
-				aoc_d->recorded.unit.item[idx].type);
-		}
-		break;
-	default:
-		break;
-	}
-
-	ast_manager_event(owner, EVENT_FLAG_AOC, "AOC-D", "%s", ast_str_buffer(msg));
-	ast_free(msg);
 }
 #endif	/* defined(HAVE_PRI_AOC_EVENTS) */
 
@@ -2660,7 +2297,8 @@
 	struct ast_aoc_encoded *encoded = NULL;
 	size_t encoded_size = 0;
 	enum ast_aoc_charge_type type;
-	if (!owner || !aoc_e) {
+
+	if (!aoc_e) {
 		return;
 	}
 
@@ -2746,109 +2384,14 @@
 		}
 	}
 
-	if ((encoded = ast_aoc_encode(decoded, &encoded_size))) {
+	if (owner && (encoded = ast_aoc_encode(decoded, &encoded_size))) {
 		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-E event.
- * \since 1.8
- *
- * \param aoc_e AOC-E event parameters.
- * \param owner Asterisk channel associated with the call.
- * NULL if the event is not associated with an existing call.
- *
- * \note Assumes the pri->lock is already obtained.
- * \note Assumes the owner channel lock is already obtained if associated.
- *
- * \return Nothing
- */
-static void sig_pri_aoc_e_event(const struct pri_subcmd_aoc_e *aoc_e, struct ast_channel *owner)
-{
-	struct ast_channel *chans[1];
-	struct ast_str *msg;
-	const char *charge_str;
-	int idx;
-	char prefix[32];
-
-	msg = ast_str_create(4096);
-	if (!msg) {
-		return;
-	}
-
-	if (owner) {
-		ast_str_append(&msg, 0, "Channel: %s\r\n", owner->name);
-		ast_str_append(&msg, 0, "UniqueID: %s\r\n", owner->uniqueid);
-		/* Queue AST_CONTROL_AOC frame */
-		sig_pri_aoc_e_from_pri(aoc_e, owner);
-	}
-
-	/* If there is no owner then there should be a charging association. */
-	charge_str = "ChargingAssociation";
-	switch (aoc_e->associated.charging_type) {
-	case PRI_AOC_E_CHARGING_ASSOCIATION_NUMBER:
-		if (!aoc_e->associated.charge.number.valid) {
-			break;
-		}
-		snprintf(prefix, sizeof(prefix), "%s/Number", charge_str);
-		ast_str_append(&msg, 0, "%s: %s\r\n", prefix,
-			aoc_e->associated.charge.number.str);
-		ast_str_append(&msg, 0, "%s/Plan: %d\r\n", prefix,
-			aoc_e->associated.charge.number.plan);
-		break;
-	case PRI_AOC_E_CHARGING_ASSOCIATION_ID:
-		ast_str_append(&msg, 0, "%s/ID: %d\r\n", charge_str, aoc_e->associated.charge.id);
-		break;
-	default:
-		break;
-	}
-
-	charge_str = sig_pri_aoc_de_charge_str(aoc_e->charge);
-	ast_str_append(&msg, 0, "Type: %s\r\n", charge_str);
-	switch (aoc_e->charge) {
-	case PRI_AOC_DE_CHARGE_CURRENCY:
-	case PRI_AOC_DE_CHARGE_UNITS:
-		ast_str_append(&msg, 0, "BillingID: %s\r\n",
-			sig_pri_aoc_e_billing_id_str(aoc_e->billing_id));
-		break;
-	default:
-		break;
-	}
-	switch (aoc_e->charge) {
-	case PRI_AOC_DE_CHARGE_CURRENCY:
-		ast_str_append(&msg, 0, "%s: %s\r\n", charge_str,
-			aoc_e->recorded.money.currency);
-		sig_pri_aoc_amount(&msg, charge_str, &aoc_e->recorded.money.amount);
-		break;
-	case PRI_AOC_DE_CHARGE_UNITS:
-		ast_str_append(&msg, 0, "%s/NumberItems: %d\r\n", charge_str,
-			aoc_e->recorded.unit.num_items);
-		for (idx = 0; idx < aoc_e->recorded.unit.num_items; ++idx) {
-			snprintf(prefix, sizeof(prefix), "%s/Item(%d)", charge_str, idx);
-
-			/* -1 if not available. */
-			ast_str_append(&msg, 0, "%s/NumberOf: %ld\r\n", prefix,
-				aoc_e->recorded.unit.item[idx].number);
-			/* -1 if not available. */
-			ast_str_append(&msg, 0, "%s/TypeOf: %d\r\n", prefix,
-				aoc_e->recorded.unit.item[idx].type);
-		}
-		break;
-	default:
-		break;
-	}
-
-	chans[0] = owner;
-	ast_manager_event_multichan(EVENT_FLAG_AOC, "AOC-E", owner ? 1 : 0, chans, "%s",
-		ast_str_buffer(msg));
-	ast_free(msg);
 }
 #endif	/* defined(HAVE_PRI_AOC_EVENTS) */
 
@@ -3239,7 +2782,8 @@
 #endif	/* defined(HAVE_PRI_CCSS) */
 #if defined(HAVE_PRI_AOC_EVENTS)
 		case PRI_SUBCMD_AOC_E:
-			sig_pri_aoc_e_event(&subcmd->u.aoc_e, NULL);
+			/* Queue AST_CONTROL_AOC frame */
+			sig_pri_aoc_e_from_pri(&subcmd->u.aoc_e, NULL);
 			break;
 #endif	/* defined(HAVE_PRI_AOC_EVENTS) */
 		default:
@@ -3484,7 +3028,7 @@
 			sig_pri_lock_owner(pri, chanpos);
 			owner = pri->pvts[chanpos]->owner;
 			if (owner) {
-				sig_pri_aoc_s_event(&subcmd->u.aoc_s, owner);
+				sig_pri_aoc_s_from_pri(&subcmd->u.aoc_s, owner);
 				ast_channel_unlock(owner);
 			}
 			break;
@@ -3494,7 +3038,8 @@
 			sig_pri_lock_owner(pri, chanpos);
 			owner = pri->pvts[chanpos]->owner;
 			if (owner) {
-				sig_pri_aoc_d_event(&subcmd->u.aoc_d, owner);
+				/* Queue AST_CONTROL_AOC frame on channel */
+				sig_pri_aoc_d_from_pri(&subcmd->u.aoc_d, owner);
 				ast_channel_unlock(owner);
 			}
 			break;
@@ -3503,7 +3048,8 @@
 		case PRI_SUBCMD_AOC_E:
 			sig_pri_lock_owner(pri, chanpos);
 			owner = pri->pvts[chanpos]->owner;
-			sig_pri_aoc_e_event(&subcmd->u.aoc_e, owner);
+			/* Queue AST_CONTROL_AOC frame */
+			sig_pri_aoc_e_from_pri(&subcmd->u.aoc_e, owner);
 			if (owner) {
 				ast_channel_unlock(owner);
 			}

Modified: team/dvossel/generic_aoc/include/asterisk/aoc.h
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/generic_aoc/include/asterisk/aoc.h?view=diff&rev=255111&r1=255110&r2=255111
==============================================================================
--- team/dvossel/generic_aoc/include/asterisk/aoc.h (original)
+++ team/dvossel/generic_aoc/include/asterisk/aoc.h Fri Mar 26 17:13:30 2010
@@ -25,6 +25,8 @@
 
 #ifndef _AST_AOC_H_
 #define _AST_AOC_H_
+
+#include "asterisk/channel.h"
 
 #define AOC_CURRENCY_NAME_SIZE (10 + 1)
 
@@ -153,6 +155,7 @@
 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,
@@ -301,12 +304,12 @@
 	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,
-	const char *currency_name);
+	int step_function);
 
 int ast_aoc_s_add_rate_flat(struct ast_aoc_decoded *decoded,
 	enum ast_aoc_s_charged_item charged_item,
@@ -334,6 +337,9 @@
 int ast_aoc_s_add_special_arrangement(struct ast_aoc_decoded *decoded,
 	unsigned int code);
 
+/*! \brief generate AOC manager event */
+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);
 

Modified: team/dvossel/generic_aoc/main/aoc.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/generic_aoc/main/aoc.c?view=diff&rev=255111&r1=255110&r2=255111
==============================================================================
--- team/dvossel/generic_aoc/main/aoc.c (original)
+++ team/dvossel/generic_aoc/main/aoc.c Fri Mar 26 17:13:30 2010
@@ -31,6 +31,7 @@
 #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)
@@ -472,12 +473,12 @@
 	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,
-	const char *currency_name)
+	int step_function)
 {
 
 	struct ast_aoc_s_entry entry = { 0, };
@@ -752,71 +753,226 @@
 	return decoded->charging_association_plan;
 }
 
-static const char *aoc_charge_type_str(const struct ast_aoc_decoded *decoded)
-{
-	switch (decoded->charge_type) {
+/*!
+ * \internal
+ * \brief Convert AST_AOC_VOLUME_UNIT to string.
+ * \since 1.8
+ *
+ * \param value Value to convert to string.
+ *
+ * \return String equivalent.
+ */
+static const char *aoc_volume_unit_str(enum ast_aoc_volume_unit value)
+{
+	const char *str;
+
+	switch (value) {
+	default:
+	case AST_AOC_VOLUME_UNIT_OCTET:
+		str = "Octet";
+		break;
+	case AST_AOC_VOLUME_UNIT_SEGMENT:
+		str = "Segment";
+		break;
+	case AST_AOC_VOLUME_UNIT_MESSAGE:
+		str = "Message";
+		break;
+	}
+	return str;
+}
+
+/*!
+ * \internal
+ * \brief Convert ast_aoc_charged_item to string.
+ * \since 1.8
+ *
+ * \param value Value to convert to string.
+ *
+ * \return String equivalent.
+ */
+static const char *aoc_charged_item_str(enum ast_aoc_s_charged_item value)
+{
+	const char *str;
+
+	switch (value) {
+	default:
+	case AST_AOC_CHARGED_ITEM_NA:
+		str = "NotAvailable";
+		break;
+	case AST_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT:
+		str = "SpecialArrangement";
+		break;
+	case AST_AOC_CHARGED_ITEM_BASIC_COMMUNICATION:
+		str = "BasicCommunication";
+		break;
+	case AST_AOC_CHARGED_ITEM_CALL_ATTEMPT:
+		str = "CallAttempt";
+		break;
+	case AST_AOC_CHARGED_ITEM_CALL_SETUP:
+		str = "CallSetup";
+		break;
+	case AST_AOC_CHARGED_ITEM_USER_USER_INFO:
+		str = "UserUserInfo";
+		break;
+	case AST_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE:
+		str = "SupplementaryService";
+		break;
+	}
+	return str;
+}
+
+/*!
+ * \internal
+ * \brief Convert ast_aoc_rate_type to string.
+ * \since 1.8
+ *
+ * \param value Value to convert to string.
+ *
+ * \return String equivalent.
+ */
+static const char *aoc_rate_type_str(enum ast_aoc_s_rate_type value)
+{
+	const char *str;
+
+	switch (value) {
+	default:
+	case AST_AOC_RATE_TYPE_NA:
+		str = "NotAvailable";
+		break;
+	case AST_AOC_RATE_TYPE_FREE:
+		str = "Free";
+		break;
+	case AST_AOC_RATE_TYPE_FREE_FROM_BEGINNING:
+		str = "FreeFromBeginning";
+		break;
+	case AST_AOC_RATE_TYPE_DURATION:
+		str = "Duration";
+		break;
+	case AST_AOC_RATE_TYPE_FLAT:
+		str = "Flat";
+		break;
+	case AST_AOC_RATE_TYPE_VOLUME:
+		str = "Volume";
+		break;
+	case AST_AOC_RATE_TYPE_SPECIAL_CODE:
+		str = "SpecialCode";
+		break;
+	}
+	return str;
+}
+
+/*!
+ * \internal
+ * \brief Convert AST_AOC_TIME_SCALE to string.
+ * \since 1.8
+ *
+ * \param value Value to convert to string.
+ *
+ * \return String equivalent.
+ */
+static const char *aoc_scale_str(enum ast_aoc_time_scale value)
+{
+	const char *str;
+
+	switch (value) {
+	default:
+	case AST_AOC_TIME_SCALE_HUNDREDTH_SECOND:
+		str = "OneHundredthSecond";
+		break;
+	case AST_AOC_TIME_SCALE_TENTH_SECOND:
+		str = "OneTenthSecond";
+		break;
+	case AST_AOC_TIME_SCALE_SECOND:
+		str = "Second";
+		break;
+	case AST_AOC_TIME_SCALE_TEN_SECOND:
+		str = "TenSeconds";
+		break;
+	case AST_AOC_TIME_SCALE_MINUTE:
+		str = "Minute";
+		break;
+	case AST_AOC_TIME_SCALE_HOUR:
+		str = "Hour";
+		break;
+	case AST_AOC_TIME_SCALE_DAY:
+		str = "Day";
+		break;
+	}
+	return str;
+}
+
+static const char *aoc_charge_type_str(enum ast_aoc_charge_type value)
+{
+	const char *str;
+
+	switch (value) {
+	default:
 	case AST_AOC_CHARGE_NA:
-		return "Charge Not Available";
+		str = "NotAvailable";
+		break;
 	case AST_AOC_CHARGE_FREE:
-		return "Free";
+		str = "Free";
+		break;
 	case AST_AOC_CHARGE_CURRENCY:
-		return "Currency";
+		str = "Currency";
+		break;
 	case AST_AOC_CHARGE_UNIT:
-		return "Unit";
-	}
-	return "Unknown";
-}
-
-static const char *aoc_multiplier_str(const struct ast_aoc_decoded *decoded)
-{
-	switch (decoded->multiplier) {
+		str = "Units";
+		break;
+	}
+
+	return str;
+}
+
+static const char *aoc_multiplier_str(enum ast_aoc_currency_multiplier mult)
+{
+	switch (mult) {
 	case AST_AOC_MULT_ONETHOUSANDTH:
-		return "One Thousandth";
+		return "1/1000";
 	case AST_AOC_MULT_ONEHUNDREDTH:
-		return "One Hundredth";
+		return "1/100";
 	case AST_AOC_MULT_ONETENTH:
-		return "One Tenth";
+		return "1/10";
 	case AST_AOC_MULT_ONE:
-		return "One";
+		return "1";
 	case AST_AOC_MULT_TEN:
-		return "Ten";
+		return "10";
 	case AST_AOC_MULT_HUNDRED:
-		return "Hundred";
+		return "100";
 	case AST_AOC_MULT_THOUSAND:
-		return "Thousand";
+		return "1000";
 	case AST_AOC_MULT_NUM_ENTRIES:
 		break;
 	};
-	return "Unknown";
-}
-
-static const char *aoc_billingid_str(const struct ast_aoc_decoded *decoded)
-{
-	switch (decoded->billing_id) {
+	return "1";
+}
+
+static const char *aoc_billingid_str(enum ast_aoc_billing_id billing_id)
+{
+	switch (billing_id) {
 	case AST_AOC_BILLING_NORMAL:
 		return "Normal";
 	case AST_AOC_BILLING_REVERSE_CHARGE:
 		return "Reverse Charge";
 	case AST_AOC_BILLING_CREDIT_CARD:
-		return "Credit Card";
+		return "CreditCard";
 	case AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL:
-		return "Call Forward Unconditional";
+		return "CallForwardingUnconditional";
 	case AST_AOC_BILLING_CALL_FWD_BUSY:
-		return "Call Forward Busy";
+		return "CallForwardingBusy";
 	case AST_AOC_BILLING_CALL_FWD_NO_REPLY:
-		return "Call Forward No Reply";
+		return "CallForwardingNoReply";
 	case AST_AOC_BILLING_CALL_DEFLECTION:
-		return "Call Deflection";
+		return "CallDeflection";
 	case AST_AOC_BILLING_CALL_TRANSFER:
-		return "Call Transfer";
+		return "CallTransfer";
 	case AST_AOC_BILLING_NA:
-		return "Not Set";
+		return "NotAvailable";
 	case AST_AOC_BILLING_NUM_ENTRIES:
 		break;
 	}
-	return "Unknown";
-}
-
+	return "NotAvailable";
+}
 
 static const char *aoc_msg_type_str(const struct ast_aoc_decoded *decoded)
 {
@@ -836,13 +992,13 @@
 static void aoc_display_decoded_aocd(const struct ast_aoc_decoded *decoded)
 {
 	ast_verb(1, "MsgType:    %s\n", aoc_msg_type_str(decoded));
-	ast_verb(1, "ChargeType: %s\n", aoc_charge_type_str(decoded));
+	ast_verb(1, "ChargeType: %s\n", aoc_charge_type_str(decoded->charge_type));
 	if (decoded->billing_id) {
-		ast_verb(1, "BillingId:  %s\n", aoc_billingid_str(decoded));
+		ast_verb(1, "BillingId:  %s\n", aoc_billingid_str(decoded->billing_id));
 	}
 	ast_verb(1, "TotalType:  %s\n", decoded->total_type ? "Total" : "Subtotal");
 	if (decoded->charge_type == AST_AOC_CHARGE_CURRENCY) {
-		ast_verb(1, "Multiplier:     %s\n", aoc_multiplier_str(decoded));
+		ast_verb(1, "Multiplier:     %s\n", aoc_multiplier_str(decoded->multiplier));
 		ast_verb(1, "CurrencyAmount: %u\n", decoded->currency_amount);
 		ast_verb(1, "CurrencyName:   %s\n", ast_strlen_zero(decoded->currency_name) ? "Not Available" : decoded->currency_name);
 	} else if (decoded->charge_type == AST_AOC_CHARGE_UNIT) {
@@ -858,12 +1014,12 @@
 static void aoc_display_decoded_aoce(const struct ast_aoc_decoded *decoded)
 {
 	ast_verb(1, "MsgType:    %s\n", aoc_msg_type_str(decoded));
-	ast_verb(1, "ChargeType: %s\n", aoc_charge_type_str(decoded));
+	ast_verb(1, "ChargeType: %s\n", aoc_charge_type_str(decoded->charge_type));
 	if (decoded->billing_id) {
-		ast_verb(1, "BillingId:  %s\n", aoc_billingid_str(decoded));
+		ast_verb(1, "BillingId:  %s\n", aoc_billingid_str(decoded->billing_id));
 	}
 	if (decoded->charge_type == AST_AOC_CHARGE_CURRENCY) {
-		ast_verb(1, "Multiplier:     %s\n", aoc_multiplier_str(decoded));
+		ast_verb(1, "Multiplier:     %s\n", aoc_multiplier_str(decoded->multiplier));
 		ast_verb(1, "CurrencyAmount: %u\n", decoded->currency_amount);
 		ast_verb(1, "CurrencyName:   %s\n", ast_strlen_zero(decoded->currency_name) ? "Not Available" : decoded->currency_name);
 	} else if (decoded->charge_type == AST_AOC_CHARGE_UNIT) {
@@ -973,6 +1129,286 @@
 	return CLI_SUCCESS;
 }
 
+/*!
+ * \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.
+ * \param scale Data to convert.
+ *
+ * \return Nothing
+ */
+static void aoc_time_str(struct ast_str **msg, const char *prefix, const char *name, unsigned long time, enum ast_aoc_time_scale scale)
+{
+	ast_str_append(msg, 0, "%s/%s/Length: %lu\r\n", prefix, name, time);
+	ast_str_append(msg, 0, "%s/%s/Scale: %s\r\n", prefix, name,
+		aoc_scale_str(scale));
+}
+
+/*!
+ * \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.
+ * \param multipler to convert
+ *
+ * \return Nothing
+ */
+static void aoc_amount_str(struct ast_str **msg, const char *prefix, unsigned int amount, enum ast_aoc_currency_multiplier mult)
+{
+	static const char name[] = "Amount";
+
+	ast_str_append(msg, 0, "%s/%s/Cost: %u\r\n", prefix, name, amount);
+	ast_str_append(msg, 0, "%s/%s/Multiplier: %s\r\n", prefix, name,
+		aoc_multiplier_str(mult));
+}
+
+static void aoc_s_event(const struct ast_aoc_decoded *decoded, struct ast_channel *owner)
+{
+	struct ast_str *msg;
+	const char *rate_str;
+	char prefix[32];
+	int idx;
+
+
+	if (!owner || !decoded || (decoded->msg_type != AST_AOC_S)) {
+		return;
+	}
+
+	msg = ast_str_create(1024);
+	if (!msg) {
+		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", decoded->aoc_s_count);
+	for (idx = 0; idx < decoded->aoc_s_count; ++idx) {
+		snprintf(prefix, sizeof(prefix), "Rate(%d)", idx);
+
+		ast_str_append(&msg, 0, "%s/Chargeable: %s\r\n", prefix,
+			aoc_charged_item_str(decoded->aoc_s_entries[idx].charged_item));
+		if (decoded->aoc_s_entries[idx].charged_item == AST_AOC_CHARGED_ITEM_NA) {
+			continue;
+		}
+		rate_str = aoc_rate_type_str(decoded->aoc_s_entries[idx].rate_type);
+		ast_str_append(&msg, 0, "%s/Type: %s\r\n", prefix, rate_str);
+		switch (decoded->aoc_s_entries[idx].rate_type) {
+		case AST_AOC_RATE_TYPE_DURATION:
+			strcat(prefix, "/");
+			strcat(prefix, rate_str);
+			ast_str_append(&msg, 0, "%s/Currency: %s\r\n", prefix,
+				decoded->aoc_s_entries[idx].rate.duration.currency_name);
+			aoc_amount_str(&msg, prefix,
+				decoded->aoc_s_entries[idx].rate.duration.amount,
+				decoded->aoc_s_entries[idx].rate.duration.multiplier);
+			ast_str_append(&msg, 0, "%s/ChargingType: %s\r\n", prefix,
+				decoded->aoc_s_entries[idx].rate.duration.charging_type ?
+				"StepFunction" : "ContinuousCharging");
+			aoc_time_str(&msg, prefix, "Time",
+				decoded->aoc_s_entries[idx].rate.duration.time,
+				decoded->aoc_s_entries[idx].rate.duration.time_scale);
+			if (decoded->aoc_s_entries[idx].rate.duration.granularity_time) {
+				aoc_time_str(&msg, prefix, "Granularity",
+					decoded->aoc_s_entries[idx].rate.duration.granularity_time,
+					decoded->aoc_s_entries[idx].rate.duration.granularity_time_scale);
+			}
+			break;
+		case AST_AOC_RATE_TYPE_FLAT:
+			strcat(prefix, "/");
+			strcat(prefix, rate_str);
+			ast_str_append(&msg, 0, "%s/Currency: %s\r\n", prefix,
+				decoded->aoc_s_entries[idx].rate.flat.currency_name);
+			aoc_amount_str(&msg, prefix,
+				decoded->aoc_s_entries[idx].rate.flat.amount,
+				decoded->aoc_s_entries[idx].rate.flat.multiplier);
+			break;
+		case AST_AOC_RATE_TYPE_VOLUME:
+			strcat(prefix, "/");
+			strcat(prefix, rate_str);
+			ast_str_append(&msg, 0, "%s/Currency: %s\r\n", prefix,
+				decoded->aoc_s_entries[idx].rate.volume.currency_name);
+			aoc_amount_str(&msg, prefix,
+				decoded->aoc_s_entries[idx].rate.volume.amount,
+				decoded->aoc_s_entries[idx].rate.volume.multiplier);
+			ast_str_append(&msg, 0, "%s/Unit: %s\r\n", prefix,
+				aoc_volume_unit_str(decoded->aoc_s_entries[idx].rate.volume.unit));
+			break;
+		case AST_AOC_RATE_TYPE_SPECIAL_CODE:
+			ast_str_append(&msg, 0, "%s/%s: %d\r\n", prefix, rate_str,
+				decoded->aoc_s_entries[idx].rate.special_code);
+			break;
+		default:
+			break;
+		}
+	}
+
+	ast_manager_event(owner, EVENT_FLAG_AOC, "AOC-S", "%s", ast_str_buffer(msg));
+	ast_free(msg);
+}
+
+static void aoc_d_event(const struct ast_aoc_decoded *decoded, struct ast_channel *chan)
+{
+	struct ast_str *msg;
+	const char *charge_str;
+	int idx;
+	char prefix[32];
+
+	if (!chan) {
+		return;
+	}
+
+	msg = ast_str_create(1024);
+	if (!msg) {
+		return;
+	}
+
+	ast_str_append(&msg, 0, "Channel: %s\r\n", chan->name);
+	ast_str_append(&msg, 0, "UniqueID: %s\r\n", chan->uniqueid);
+
+	charge_str = aoc_charge_type_str(decoded->charge_type);
+	ast_str_append(&msg, 0, "Type: %s\r\n", charge_str);
+	switch (decoded->charge_type) {
+	case AST_AOC_CHARGE_CURRENCY:
+	case AST_AOC_CHARGE_UNIT:
+		ast_str_append(&msg, 0, "BillingID: %s\r\n",
+			aoc_billingid_str(decoded->billing_id));
+		break;
+	default:
+		break;
+	}
+	switch (decoded->charge_type) {
+	case AST_AOC_CHARGE_CURRENCY:
+		ast_str_append(&msg, 0, "%s: %s\r\n", charge_str,
+			decoded->currency_name);
+		aoc_amount_str(&msg, charge_str,
+			decoded->currency_amount,
+			decoded->multiplier);
+		break;
+	case AST_AOC_CHARGE_UNIT:
+		ast_str_append(&msg, 0, "%s/NumberItems: %d\r\n", charge_str,
+			decoded->unit_count);
+		for (idx = 0; idx < decoded->unit_count; ++idx) {
+			snprintf(prefix, sizeof(prefix), "%s/Item(%d)", charge_str, idx);
+			ast_str_append(&msg, 0, "%s/NumberOf: %u\r\n", prefix,
+				decoded->unit_list[idx].amount);
+			ast_str_append(&msg, 0, "%s/TypeOf: %d\r\n", prefix,
+				decoded->unit_list[idx].type);
+		}
+		break;
+	default:
+		break;
+	}
+
+	ast_manager_event(chan, EVENT_FLAG_AOC, "AOC-D", "%s", ast_str_buffer(msg));
+	ast_free(msg);
+}
+
+static void aoc_e_event(const struct ast_aoc_decoded *decoded, struct ast_channel *owner)
+{
+	struct ast_channel *chans[1];
+	struct ast_str *msg;
+	const char *charge_str;
+	int idx;
+	char prefix[32];
+
+	if (!decoded) {
+		return;
+	}
+
+	msg = ast_str_create(1024);
+	if (!msg) {
+		return;
+	}
+
+	if (owner) {
+		ast_str_append(&msg, 0, "Channel: %s\r\n", owner->name);
+		ast_str_append(&msg, 0, "UniqueID: %s\r\n", owner->uniqueid);
+	}
+
+	charge_str = "ChargingAssociation";
+	if (!ast_strlen_zero(decoded->charging_association_number)) {
+		snprintf(prefix, sizeof(prefix), "%s/Number", charge_str);
+		ast_str_append(&msg, 0, "%s: %s\r\n", prefix,
+			decoded->charging_association_number);
+		ast_str_append(&msg, 0, "%s/Plan: %d\r\n", prefix,
+			decoded->charging_association_plan);
+	} else if (decoded->charging_association_id) {
+		ast_str_append(&msg, 0, "%s/ID: %d\r\n", charge_str, decoded->charging_association_id);
+	}
+
+	charge_str = aoc_charge_type_str(decoded->charge_type);
+	ast_str_append(&msg, 0, "Type: %s\r\n", charge_str);
+	switch (decoded->charge_type) {
+	case AST_AOC_CHARGE_CURRENCY:
+	case AST_AOC_CHARGE_UNIT:
+		ast_str_append(&msg, 0, "BillingID: %s\r\n",
+			aoc_billingid_str(decoded->billing_id));
+		break;
+	default:
+		break;
+	}
+	switch (decoded->charge_type) {
+	case AST_AOC_CHARGE_CURRENCY:
+		ast_str_append(&msg, 0, "%s: %s\r\n", charge_str,
+			decoded->currency_name);
+		aoc_amount_str(&msg, charge_str,
+			decoded->currency_amount,
+			decoded->multiplier);
+		break;
+	case AST_AOC_CHARGE_UNIT:
+		ast_str_append(&msg, 0, "%s/NumberItems: %d\r\n", charge_str,
+			decoded->unit_count);

[... 46 lines stripped ...]



More information about the svn-commits mailing list