[libpri-commits] rmudgett: branch 1.4 r1737 - /branches/1.4/

SVN commits to the libpri project libpri-commits at lists.digium.com
Fri May 28 13:03:41 CDT 2010


Author: rmudgett
Date: Fri May 28 13:03:38 2010
New Revision: 1737

URL: http://svnview.digium.com/svn/libpri?view=rev&rev=1737
Log:
ETSI Advice Of Charge (AOC) event reporting.

This feature passes ETSI AOC-S, AOC-D, and AOC-E message information to
the upper layer (i.e.  Asterisk) for processing.

Relevant specification: EN 300 182

Consideration was made for the possible future addition of Q.SIG AOC
support (ECMA-212) with the events passed to the upper layer.

Review:	https://reviewboard.asterisk.org/r/538/

Added:
    branches/1.4/pri_aoc.c
      - copied unchanged from r1736, team/rmudgett/aoc_event/pri_aoc.c
Modified:
    branches/1.4/Makefile
    branches/1.4/libpri.h
    branches/1.4/pri_facility.c
    branches/1.4/pri_facility.h
    branches/1.4/pri_internal.h
    branches/1.4/rose_etsi_aoc.c

Modified: branches/1.4/Makefile
URL: http://svnview.digium.com/svn/libpri/branches/1.4/Makefile?view=diff&rev=1737&r1=1736&r2=1737
==============================================================================
--- branches/1.4/Makefile (original)
+++ branches/1.4/Makefile Fri May 28 13:03:38 2010
@@ -47,6 +47,7 @@
 	q921.o \
 	prisched.o \
 	q931.o \
+	pri_aoc.o \
 	pri_cc.o \
 	pri_facility.o \
 	asn1_primitive.o \
@@ -71,6 +72,7 @@
 	q921.lo \
 	prisched.lo \
 	q931.lo \
+	pri_aoc.lo \
 	pri_cc.lo \
 	pri_facility.lo \
 	asn1_primitive.lo \

Modified: branches/1.4/libpri.h
URL: http://svnview.digium.com/svn/libpri/branches/1.4/libpri.h?view=diff&rev=1737&r1=1736&r2=1737
==============================================================================
--- branches/1.4/libpri.h (original)
+++ branches/1.4/libpri.h Fri May 28 13:03:38 2010
@@ -539,6 +539,11 @@
 #define PRI_SUBCMD_CC_CANCEL				15	/*!< Unsolicited indication that CC is canceled */
 #define PRI_SUBCMD_CC_STOP_ALERTING			16	/*!< Indicate that someone else has responed to remote user free */
 #define PRI_SUBCMD_TRANSFER_CALL			17	/*!< Request to transfer the specified calls together. */
+#define PRI_SUBCMD_AOC_S					18	/*!< Advice Of Charge Start information (Rate list) */
+#define PRI_SUBCMD_AOC_D					19	/*!< Advice Of Charge During information */
+#define PRI_SUBCMD_AOC_E					20	/*!< Advice Of Charge End information */
+//#define PRI_SUBCMD_AOC_CHARGING_REQ			21	/*!< Advice Of Charge Request information */
+//#define PRI_SUBCMD_AOC_CHARGING_REQ_RSP		22	/*!< Advice Of Charge Request Response information */
 
 #if defined(STATUS_REQUEST_PLACE_HOLDER)
 struct pri_subcmd_status_request {
@@ -646,6 +651,227 @@
 	int is_call_2_held;
 	/*! Invocation ID to use when sending a reply to the transfer request. */
 	int invoke_id;
+};
+
+/*! \brief What is being charged. */
+enum PRI_AOC_CHARGED_ITEM {
+	PRI_AOC_CHARGED_ITEM_NOT_AVAILABLE,
+	PRI_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT,
+	PRI_AOC_CHARGED_ITEM_BASIC_COMMUNICATION,
+	PRI_AOC_CHARGED_ITEM_CALL_ATTEMPT,
+	PRI_AOC_CHARGED_ITEM_CALL_SETUP,
+	PRI_AOC_CHARGED_ITEM_USER_USER_INFO,
+	PRI_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE,
+};
+
+/*! \brief Rate method being used. */
+enum PRI_AOC_RATE_TYPE {
+	PRI_AOC_RATE_TYPE_NOT_AVAILABLE,
+	PRI_AOC_RATE_TYPE_FREE,
+	PRI_AOC_RATE_TYPE_FREE_FROM_BEGINNING,
+	PRI_AOC_RATE_TYPE_DURATION,
+	PRI_AOC_RATE_TYPE_FLAT,
+	PRI_AOC_RATE_TYPE_VOLUME,
+	PRI_AOC_RATE_TYPE_SPECIAL_CODE,
+};
+
+enum PRI_AOC_TIME_SCALE {
+	PRI_AOC_TIME_SCALE_HUNDREDTH_SECOND,
+	PRI_AOC_TIME_SCALE_TENTH_SECOND,
+	PRI_AOC_TIME_SCALE_SECOND,
+	PRI_AOC_TIME_SCALE_TEN_SECOND,
+	PRI_AOC_TIME_SCALE_MINUTE,
+	PRI_AOC_TIME_SCALE_HOUR,
+	PRI_AOC_TIME_SCALE_DAY,
+};
+
+struct pri_aoc_time {
+	/*! LengthOfTimeUnit (Not valid if length is zero.) */
+	long length;
+	/*! \see enum PRI_AOC_TIME_SCALE */
+	int scale;
+};
+
+enum PRI_AOC_MULTIPLIER {
+	PRI_AOC_MULTIPLIER_THOUSANDTH,
+	PRI_AOC_MULTIPLIER_HUNDREDTH,
+	PRI_AOC_MULTIPLIER_TENTH,
+	PRI_AOC_MULTIPLIER_ONE,
+	PRI_AOC_MULTIPLIER_TEN,
+	PRI_AOC_MULTIPLIER_HUNDRED,
+	PRI_AOC_MULTIPLIER_THOUSAND,
+};
+
+struct pri_aoc_amount {
+	long cost;
+	/*! \see enum PRI_AOC_MULTIPLIER */
+	int multiplier;
+};
+
+struct pri_aoc_duration {
+	struct pri_aoc_amount amount;
+	struct pri_aoc_time time;
+	/*! Not present if the granularity time is zero. */
+	struct pri_aoc_time granularity;
+	/*!
+	 * \brief Charging interval type
+	 * \details
+	 * continuousCharging(0),
+	 * stepFunction(1)
+	 */
+	int charging_type;
+	/*! Name of currency involved.  Null terminated. */
+	char currency[10 + 1];
+};
+
+struct pri_aoc_flat {
+	struct pri_aoc_amount amount;
+	/*! Name of currency involved.  Null terminated. */
+	char currency[10 + 1];
+};
+
+enum PRI_AOC_VOLUME_UNIT {
+	PRI_AOC_VOLUME_UNIT_OCTET,
+	PRI_AOC_VOLUME_UNIT_SEGMENT,
+	PRI_AOC_VOLUME_UNIT_MESSAGE,
+};
+
+struct pri_aoc_volume {
+	struct pri_aoc_amount amount;
+	/*! \see enum PRI_AOC_VOLUME_UNIT */
+	int unit;
+	/*! Name of currency involved.  Null terminated. */
+	char currency[10 + 1];
+};
+
+struct pri_aoc_s_element {
+	/*!
+	 * \brief What is being charged.
+	 * \see enum PRI_AOC_CHARGED_ITEM
+	 */
+	int chargeable;
+	/*!
+	 * \brief Rate method being used.
+	 * \see enum PRI_AOC_RATE_TYPE
+	 */
+	int rate_type;
+	/*! \brief Charge rate being applied. */
+	union {
+		struct pri_aoc_duration duration;
+		struct pri_aoc_flat flat;
+		struct pri_aoc_volume volume;
+		int special;
+	} rate;
+};
+
+struct pri_subcmd_aoc_s {
+	/*!
+	 * \brief Number of items in the rate list.
+	 * \note If the list is empty then the charging information is not available.
+	 */
+	int num_items;
+	struct pri_aoc_s_element item[10];
+};
+
+enum PRI_AOC_DE_CHARGE {
+	PRI_AOC_DE_CHARGE_NOT_AVAILABLE,
+	PRI_AOC_DE_CHARGE_FREE,
+	PRI_AOC_DE_CHARGE_CURRENCY,
+	PRI_AOC_DE_CHARGE_UNITS,
+};
+
+struct pri_aoc_recorded_currency {
+	struct pri_aoc_amount amount;
+	/*! Name of currency involved.  Null terminated. */
+	char currency[10 + 1];
+};
+
+struct pri_aoc_units_element {
+	/*! Number of units recorded. -1 if not available. */
+	long number;
+	/*! Type of unit recorded. -1 if not available. */
+	int type;
+};
+
+struct pri_aoc_recorded_units {
+	int num_items;
+	struct pri_aoc_units_element item[32];
+};
+
+enum PRI_AOC_D_BILLING_ID {
+	PRI_AOC_D_BILLING_ID_NOT_AVAILABLE,
+	PRI_AOC_D_BILLING_ID_NORMAL,
+	PRI_AOC_D_BILLING_ID_REVERSE,
+	PRI_AOC_D_BILLING_ID_CREDIT_CARD,
+};
+struct pri_subcmd_aoc_d {
+	/*!
+	 * \brief What is being charged.
+	 * \see enum PRI_AOC_DE_CHARGE
+	 */
+	int charge;
+	/*!
+	 * \brief Billing accumulation
+	 * \details
+	 * subTotal(0),
+	 * total(1)
+	 */
+	int billing_accumulation;
+	/*! \see enum PRI_AOC_D_BILLING_ID */
+	int billing_id;
+	union {
+		/*! Recorded currency */
+		struct pri_aoc_recorded_currency money;
+		/*! Recorded units list */
+		struct pri_aoc_recorded_units unit;
+	} recorded;
+};
+
+enum PRI_AOC_E_BILLING_ID {
+	PRI_AOC_E_BILLING_ID_NOT_AVAILABLE,
+	PRI_AOC_E_BILLING_ID_NORMAL,
+	PRI_AOC_E_BILLING_ID_REVERSE,
+	PRI_AOC_E_BILLING_ID_CREDIT_CARD,
+	PRI_AOC_E_BILLING_ID_CALL_FORWARDING_UNCONDITIONAL,
+	PRI_AOC_E_BILLING_ID_CALL_FORWARDING_BUSY,
+	PRI_AOC_E_BILLING_ID_CALL_FORWARDING_NO_REPLY,
+	PRI_AOC_E_BILLING_ID_CALL_DEFLECTION,
+	PRI_AOC_E_BILLING_ID_CALL_TRANSFER,
+};
+
+enum PRI_AOC_E_CHARGING_ASSOCIATION {
+	PRI_AOC_E_CHARGING_ASSOCIATION_NOT_AVAILABLE,
+	PRI_AOC_E_CHARGING_ASSOCIATION_NUMBER,
+	PRI_AOC_E_CHARGING_ASSOCIATION_ID,
+};
+
+struct pri_aoc_e_charging_association {
+	union {
+		/*! Charged number */
+		struct pri_party_number number;
+		/*! Charge identifier */
+		int id;
+	} charge;
+	/*! \see enum PRI_AOC_E_CHARGING_ASSOCIATION */
+	int charging_type;
+};
+
+struct pri_subcmd_aoc_e {
+	/*!
+	 * \brief What is being charged.
+	 * \see enum PRI_AOC_DE_CHARGE
+	 */
+	int charge;
+	/*! \see enum PRI_AOC_E_BILLING_ID */
+	int billing_id;
+	union {
+		/*! Recorded currency */
+		struct pri_aoc_recorded_currency money;
+		/*! Recorded units list */
+		struct pri_aoc_recorded_units unit;
+	} recorded;
+	/*! Charging association. */
+	struct pri_aoc_e_charging_association associated;
 };
 
 struct pri_subcommand {
@@ -673,6 +899,9 @@
 		struct pri_subcmd_cc_id cc_call;
 		struct pri_subcmd_cc_cancel cc_cancel;
 		struct pri_subcmd_transfer transfer;
+		struct pri_subcmd_aoc_s aoc_s;
+		struct pri_subcmd_aoc_d aoc_d;
+		struct pri_subcmd_aoc_e aoc_e;
 	} u;
 };
 
@@ -817,7 +1046,7 @@
 	int cause;
 	int cref;
 	q931_call *call;			/* Opaque call pointer of call hanging up. */
-	long aoc_units;				/* Advise of Charge number of charged units */
+	long aoc_units;				/* Advice of Charge number of charged units */
 	char useruserinfo[260];		/* User->User info */
 	struct pri_subcommands *subcmds;
 	/*!
@@ -1379,6 +1608,16 @@
 int pri_transfer_rsp(struct pri *ctrl, q931_call *call, int invoke_id, int is_successful);
 
 /*!
+ * \brief Set the advice of charge events feature enable flag.
+ *
+ * \param ctrl D channel controller.
+ * \param enable TRUE to enable AOC events feature.
+ *
+ * \return Nothing
+ */
+void pri_aoc_events_enable(struct pri *ctrl, int enable);
+
+/*!
  * \brief Set the call hold feature enable flag.
  *
  * \param ctrl D channel controller.

Modified: branches/1.4/pri_facility.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri_facility.c?view=diff&rev=1737&r1=1736&r2=1737
==============================================================================
--- branches/1.4/pri_facility.c (original)
+++ branches/1.4/pri_facility.c Fri May 28 13:03:38 2010
@@ -2699,82 +2699,6 @@
 
 	return error_code;
 }
-
-/* AOC */
-/*!
- * \internal
- * \brief Encode the ETSI AOCEChargingUnit invoke message.
- *
- * \param ctrl D channel controller for diagnostic messages or global options.
- * \param pos Starting position to encode the facility ie contents.
- * \param end End of facility ie contents encoding data buffer.
- * \param chargedunits Number of units charged to encode.
- *
- * \retval Start of the next ASN.1 component to encode on success.
- * \retval NULL on error.
- */
-static unsigned char *enc_etsi_aoce_charging_unit(struct pri *ctrl, unsigned char *pos,
-	unsigned char *end, long chargedunits)
-{
-	struct rose_msg_invoke msg;
-
-	pos = facility_encode_header(ctrl, pos, end, NULL);
-	if (!pos) {
-		return NULL;
-	}
-
-	memset(&msg, 0, sizeof(msg));
-	msg.operation = ROSE_ETSI_AOCEChargingUnit;
-	msg.invoke_id = get_invokeid(ctrl);
-	msg.args.etsi.AOCEChargingUnit.type = 1;	/* charging_unit */
-	if (chargedunits <= 0) {
-		msg.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 1;
-	} else {
-		msg.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.num_records = 1;
-		msg.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.list[0].
-			number_of_units = chargedunits;
-	}
-	pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-	return pos;
-}
-
-/*!
- * \internal
- * \brief Send the ETSI AOCEChargingUnit invoke message.
- *
- * \param ctrl D channel controller for diagnostic messages or global options.
- * \param call Call leg from which to encode AOC.
- * \param chargedunits Number of units charged to encode.
- *
- * \retval 0 on success.
- * \retval -1 on error.
- */
-static int aoc_aoce_charging_unit_encode(struct pri *ctrl, q931_call *call,
-	long chargedunits)
-{
-	unsigned char buffer[255];
-	unsigned char *end;
-
-	/* sample data: [ 91 a1 12 02 02 3a 78 02 01 24 30 09 30 07 a1 05 30 03 02 01 01 ] */
-
-	end =
-		enc_etsi_aoce_charging_unit(ctrl, buffer, buffer + sizeof(buffer), chargedunits);
-	if (!end) {
-		return -1;
-	}
-
-	/* Remember that if we queue a facility IE for a facility message we
-	 * have to explicitly send the facility message ourselves */
-	if (pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL)
-		|| q931_facility(call->pri, call)) {
-		pri_message(ctrl, "Could not schedule facility message for call %d\n", call->cr);
-		return -1;
-	}
-
-	return 0;
-}
-/* End AOC */
 
 /* ===== Call Transfer Supplementary Service (ECMA-178) ===== */
 
@@ -4129,40 +4053,23 @@
 	case ROSE_ETSI_ChargingRequest:
 		/* Ignore messsage */
 		break;
-#if 0	/* Not handled yet */
 	case ROSE_ETSI_AOCSCurrency:
+		aoc_etsi_aoc_s_currency(ctrl, invoke);
 		break;
 	case ROSE_ETSI_AOCSSpecialArr:
+		aoc_etsi_aoc_s_special_arrangement(ctrl, invoke);
 		break;
 	case ROSE_ETSI_AOCDCurrency:
+		aoc_etsi_aoc_d_currency(ctrl, invoke);
 		break;
 	case ROSE_ETSI_AOCDChargingUnit:
+		aoc_etsi_aoc_d_charging_unit(ctrl, invoke);
 		break;
 	case ROSE_ETSI_AOCECurrency:
-		break;
-#endif	/* Not handled yet */
+		aoc_etsi_aoc_e_currency(ctrl, call, invoke);
+		break;
 	case ROSE_ETSI_AOCEChargingUnit:
-		call->aoc_units = 0;
-		if (invoke->args.etsi.AOCEChargingUnit.type == 1
-			&& !invoke->args.etsi.AOCEChargingUnit.charging_unit.free_of_charge) {
-			unsigned index;
-
-			for (index =
-				invoke->args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.
-				num_records; index--;) {
-				if (!invoke->args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.
-					list[index].not_available) {
-					call->aoc_units +=
-						invoke->args.etsi.AOCEChargingUnit.charging_unit.specific.
-						recorded.list[index].number_of_units;
-				}
-			}
-		}
-		/* the following function is currently not used - just to make the compiler happy */
-		if (0) {
-			/* use this function to forward the aoc-e on a bridged channel */
-			aoc_aoce_charging_unit_encode(ctrl, call, call->aoc_units);
-		}
+		aoc_etsi_aoc_e_charging_unit(ctrl, call, invoke);
 		break;
 #if 0	/* Not handled yet */
 	case ROSE_ITU_IdentificationOfCharge:

Modified: branches/1.4/pri_facility.h
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri_facility.h?view=diff&rev=1737&r1=1736&r2=1737
==============================================================================
--- branches/1.4/pri_facility.h (original)
+++ branches/1.4/pri_facility.h Fri May 28 13:03:38 2010
@@ -245,4 +245,11 @@
 void pri_cc_qsig_cancel(struct pri *ctrl, q931_call *call, int msgtype, const struct rose_msg_invoke *invoke);
 void pri_cc_qsig_exec_possible(struct pri *ctrl, q931_call *call, int msgtype, const struct rose_msg_invoke *invoke);
 
+void aoc_etsi_aoc_s_currency(struct pri *ctrl, const struct rose_msg_invoke *invoke);
+void aoc_etsi_aoc_s_special_arrangement(struct pri *ctrl, const struct rose_msg_invoke *invoke);
+void aoc_etsi_aoc_d_currency(struct pri *ctrl, const struct rose_msg_invoke *invoke);
+void aoc_etsi_aoc_d_charging_unit(struct pri *ctrl, const struct rose_msg_invoke *invoke);
+void aoc_etsi_aoc_e_currency(struct pri *ctrl, q931_call *call, const struct rose_msg_invoke *invoke);
+void aoc_etsi_aoc_e_charging_unit(struct pri *ctrl, q931_call *call, const struct rose_msg_invoke *invoke);
+
 #endif /* _PRI_FACILITY_H */

Modified: branches/1.4/pri_internal.h
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri_internal.h?view=diff&rev=1737&r1=1736&r2=1737
==============================================================================
--- branches/1.4/pri_internal.h (original)
+++ branches/1.4/pri_internal.h Fri May 28 13:03:38 2010
@@ -107,6 +107,7 @@
 	unsigned int hangup_fix_enabled:1;/* TRUE if should follow Q.931 Section 5.3.2 instead of blindly sending RELEASE_COMPLETE for certain causes */
 	unsigned int cc_support:1;/* TRUE if upper layer supports call completion. */
 	unsigned int transfer_support:1;/* TRUE if the upper layer supports ECT */
+	unsigned int aoc_support:1;/* TRUE if can send AOC events to the upper layer. */
 
 	/* MDL variables */
 	int mdl_error;

Modified: branches/1.4/rose_etsi_aoc.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/rose_etsi_aoc.c?view=diff&rev=1737&r1=1736&r2=1737
==============================================================================
--- branches/1.4/rose_etsi_aoc.c (original)
+++ branches/1.4/rose_etsi_aoc.c Fri May 28 13:03:38 2010
@@ -623,8 +623,13 @@
 		ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
 		break;
 	case 1:	/* currency_info_list */
-		ASN1_CALL(pos, rose_enc_etsi_AOCSCurrencyInfoList(ctrl, pos, end,
-			ASN1_TAG_SEQUENCE, &args->etsi.AOCSCurrency.currency_info));
+		if (args->etsi.AOCSCurrency.currency_info.num_records) {
+			ASN1_CALL(pos, rose_enc_etsi_AOCSCurrencyInfoList(ctrl, pos, end,
+				ASN1_TAG_SEQUENCE, &args->etsi.AOCSCurrency.currency_info));
+		} else {
+			/* There were no records so encode as charge_not_available */
+			ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
+		}
 		break;
 	default:
 		ASN1_ENC_ERROR(ctrl, "Unknown AOCSCurrency type");




More information about the libpri-commits mailing list