[svn-commits] rmudgett: branch group/issue14068 r854 - /team/group/issue14068/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Jun 4 11:46:23 CDT 2009


Author: rmudgett
Date: Thu Jun  4 11:46:19 2009
New Revision: 854

URL: http://svn.asterisk.org/svn-view/libpri?view=rev&rev=854
Log:
Q.SIG COLP feature completed.

*  Augmented Q.SIG DivertingLegInformation2 to support multiple diversions.
(Original called number)
*  Replaced q931_party_id.status enum with q931_party_id.valid boolean since
the changed value was not needed.
*  Fixed enc_qsig_call_transfer_complete() so it can send the new local party name.
*  Made the behaviour of DivertingLegInformation1-3 closer to the standard.
*  Eliminated the cd_active party and ct_complete party since they are the just
the remote_id party.
*  Added handling of the CallTransferUpdate message for join transfer updates.
*  Enhanced the libpri party id structure with more information.  (valid flag,
separate name and number presentation, name character set)
*  Eliminated the connected-line source parameter as it did not do anything.
*  Merged the original calling party id into the redirecting party structure.
*  Eliminated several added API fields in events.  The connected-line and
redirecting subcommands pass the information instead.

Modified:
    team/group/issue14068/libpri.h
    team/group/issue14068/pri.c
    team/group/issue14068/pri_facility.c
    team/group/issue14068/pri_internal.h
    team/group/issue14068/q931.c

Modified: team/group/issue14068/libpri.h
URL: http://svn.asterisk.org/svn-view/libpri/team/group/issue14068/libpri.h?view=diff&rev=854&r1=853&r2=854
==============================================================================
--- team/group/issue14068/libpri.h (original)
+++ team/group/issue14068/libpri.h Thu Jun  4 11:46:19 2009
@@ -344,41 +344,71 @@
 
 typedef struct q931_call q931_call;
 
-/*! \brief Connected line update source code */
-enum PRI_CONNECTED_LINE_UPDATE_SOURCE {
-	/*! Update for unknown reason (May be interpreted to mean from answer) */
-	PRI_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN,
-	/*! Update from normal call answering */
-	PRI_CONNECTED_LINE_UPDATE_SOURCE_ANSWER,
-	/*! Update from call transfer(active) (Party has already answered) */
-	PRI_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER,
-	/*! Update from call transfer(alerting) (Party has not answered yet) */
-	PRI_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING
+/* Name character set enumeration values */
+#define PRI_CHAR_SET_UNKNOWN				0
+#define PRI_CHAR_SET_ISO8859_1				1
+#define PRI_CHAR_SET_WITHDRAWN				2
+#define PRI_CHAR_SET_ISO8859_2				3
+#define PRI_CHAR_SET_ISO8859_3				4
+#define PRI_CHAR_SET_ISO8859_4				5
+#define PRI_CHAR_SET_ISO8859_5				6
+#define PRI_CHAR_SET_ISO8859_7				7
+#define PRI_CHAR_SET_ISO10646_BMPSTRING		8
+#define PRI_CHAR_SET_ISO10646_UTF_8STRING	9
+
+/*! \brief Q.SIG name information. */
+struct pri_party_name {
+	/*! \brief TRUE if the name information is valid/present */
+	int valid;
+	/*!
+	 * \brief Q.931 presentation-indicator encoded field
+	 * \note Must tollerate the Q.931 screening-indicator field values being present.
+	 */
+	int presentation;
+	/*!
+	 * \brief Character set the name is using.
+	 * \details
+	 * unknown(0),
+	 * iso8859-1(1),
+	 * enum-value-withdrawn-by-ITU-T(2)
+	 * iso8859-2(3),
+	 * iso8859-3(4),
+	 * iso8859-4(5),
+	 * iso8859-5(6),
+	 * iso8859-7(7),
+	 * iso10646-BmpString(8),
+	 * iso10646-utf-8String(9)
+	 * \details
+	 * Set to iso8859-1(1) if unsure what to use.
+	 */
+	int char_set;
+	/*! \brief Name data with null terminator. */
+	char str[64];
+};
+
+struct pri_party_number {
+	/*! \brief TRUE if the number information is valid/present */
+	int valid;
+	/*! \brief Q.931 presentation-indicator and screening-indicator encoded fields */
+	int presentation;
+	/*! \brief Q.931 Type-Of-Number and numbering-plan encoded fields */
+	int plan;
+	/*! \brief Number data with null terminator. */
+	char str[64];
 };
 
 /*! \brief Information needed to identify an endpoint in a call. */
 struct pri_party_id {
-	/*! Subscriber phone number */
-	char number[64];
-	/*! Subscriber name */
-	char name[64];
-	/*! Q.931 encoded "type of number" and "numbering plan identification" */
-	int number_type;
-	/*! Q.931 encoded "presentation indicator" and "screening indicator" */
-	int number_presentation;
+	/*! \brief Subscriber name */
+	struct pri_party_name name;
+	/*! \brief Subscriber phone number */
+	struct pri_party_number number;
 };
 
 /*! \brief Connected Line/Party information */
 struct pri_party_connected_line {
 	/*! Connected party ID */
 	struct pri_party_id id;
-	/*!
-	 * \brief Information about the source of an update.
-	 * \details
-	 * enum PRI_CONNECTED_LINE_UPDATE_SOURCE values
-	 * for Normal-Answer, Call-transfer
-	 */
-	int source;
 };
 
 /*!
@@ -392,9 +422,13 @@
 	struct pri_party_id from;
 	/*! Call is redirecting to a new party (Sent to the caller) */
 	struct pri_party_id to;
+	/*! Originally called party (in cases of multiple redirects) */
+	struct pri_party_id orig_called;
 	/*! Number of times the call was redirected */
 	int count;
-	/*! Redirection reasons */
+	/*! Original reason for redirect (in cases of multiple redirects) */
+	int orig_reason;
+	/*! Redirection reason */
 	int reason;
 };
 
@@ -403,11 +437,11 @@
 #define PRI_SUBCMD_CONNECTED_LINE	2
 
 
-struct pri_subcmd_connected_line {
+struct pri_subcmd_connected_line {/* BUGBUG eliminate this struct since it is not adding anything useful. */
 	struct pri_party_connected_line party;
 };
 
-struct pri_subcmd_redirecting {
+struct pri_subcmd_redirecting {/* BUGBUG eliminate this struct since it is not adding anything useful. */
 	struct pri_party_redirecting party;
 };
 
@@ -419,11 +453,11 @@
 		char reserve_space[512];
 		struct pri_subcmd_connected_line connected_line;
 		struct pri_subcmd_redirecting redirecting;
-	};
+	} u;
 };
 
 /* Max number of subcommands per event message */
-#define PRI_MAX_SUBCOMMANDS	6
+#define PRI_MAX_SUBCOMMANDS	8
 
 struct pri_subcommands {
 	int counter_subcmd;
@@ -454,10 +488,6 @@
 	int progressmask;
 	q931_call *call;
 	char useruserinfo[260];		/* User->User info */
-	char calledname[256];
-	char callednum[256];
-	int calledpres;
-	int calledplan;
 	struct pri_subcommands *subcmds;
 } pri_event_ringing;
 
@@ -469,11 +499,6 @@
 	int progressmask;
 	q931_call *call;
 	char useruserinfo[260];		/* User->User info */
-	char connectednum[256];
-	char connectedname[256];
-	int connectedpres;
-	int connectedplan;
-	int source;
 	struct pri_subcommands *subcmds;
 } pri_event_answer;
 
@@ -533,8 +558,6 @@
 	char origcallednum[256];
 	int callingplanorigcalled;		/* Dialing plan of Originally Called Number */
 	int origredirectingreason;
-	int redirectingpres;
-	int redirectingcount;
 	struct pri_subcommands *subcmds;
 } pri_event_ring;
 
@@ -704,11 +727,17 @@
    Set non-isdn to non-zero if you are not connecting to ISDN equipment */
 int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
 
-/*! \brief Give connected line information to a call */
-int pri_connected_line_update(struct pri *pri, q931_call *call, struct pri_party_connected_line *connected);
-
-/*! \brief Give redirection information to a call */
-int pri_redirecting_update(struct pri *pri, q931_call *call, struct pri_party_redirecting *redirecting);
+/*! 
+ * \brief Give connected line information to a call 
+ * \note Could be used instead of pri_sr_set_caller() before calling pri_setup().
+ */
+int pri_connected_line_update(struct pri *pri, q931_call *call, const struct pri_party_connected_line *connected);
+
+/*! 
+ * \brief Give redirection information to a call
+ * \note Should be used instead of pri_sr_set_redirecting() before calling pri_setup().
+ */
+int pri_redirecting_update(struct pri *pri, q931_call *call, const struct pri_party_redirecting *redirecting);
 
 /* Set CRV reference for GR-303 calls */
 
@@ -764,9 +793,11 @@
 int pri_sr_set_channel(struct pri_sr *sr, int channel, int exclusive, int nonisdn);
 int pri_sr_set_bearer(struct pri_sr *sr, int transmode, int userl1);
 int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int complete);
+/*! \note Use pri_connected_line_update() instead to pass more precise caller information. */
 int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres);
+/*! \note Use pri_redirecting_update() instead to pass more precise redirecting information. */
 int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason);
-void pri_sr_set_redirecting_name(struct pri_sr *sr, char *name);
+
 #define PRI_USER_USER_TX
 /* Set the user user field.  Warning!  don't send binary data accross this field */
 void pri_sr_set_useruser(struct pri_sr *sr, const char *userchars);

Modified: team/group/issue14068/pri.c
URL: http://svn.asterisk.org/svn-view/libpri/team/group/issue14068/pri.c?view=diff&rev=854&r1=853&r2=854
==============================================================================
--- team/group/issue14068/pri.c (original)
+++ team/group/issue14068/pri.c Thu Jun  4 11:46:19 2009
@@ -560,142 +560,181 @@
 	return q931_connect(pri, call, channel, nonisdn);
 }
 
-int pri_connected_line_update(struct pri *pri, q931_call *call, struct pri_party_connected_line *connected)
-{
-	if (!pri || !call)
-		return -1;
-
-	call->local_id.number.status = Q931_PARTY_DATA_STATUS_CHANGED;
-	call->local_id.number.presentation = connected->id.number_presentation;
-	call->local_id.number.plan = connected->id.number_type;
-	libpri_copy_string(call->local_id.number.str, connected->id.number,
-		sizeof(call->local_id.number.str));
-
-	if (connected->id.name[0]) {
-		call->local_id.name.status = Q931_PARTY_DATA_STATUS_CHANGED;
-		call->local_id.name.presentation = connected->id.number_presentation;
-		call->local_id.name.char_set = 1;	/* iso8859-1 */
-		libpri_copy_string(call->local_id.name.str, connected->id.name,
-			sizeof(call->local_id.name.str));
-	} else {
-		q931_party_name_init(&call->local_id.name);
-	}
-
-	if (pri->switchtype == PRI_SWITCH_QSIG) {
-		switch (call->ourcallstate) {
-		case Q931_CALL_STATE_ACTIVE:
-			/* immediately send callTransferComplete APDU, callStatus=answered(0) */
-			qsig_initiate_call_transfer_complete(pri, call, 0);
-			break;
-		case Q931_CALL_STATE_OVERLAP_RECEIVING:
-		case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
-			/* queue updates for next ALERTING */
-			if (call->local_id.name.str[0]) {
-				/* queue connectedName to be send with next Q931_ALERTING */
-				rose_called_name_encode(pri, call, Q931_ALERTING);
-			}
-
-			if (call->redirecting.state != DIVERTEDSTATE_NONE) {
-				call->redirecting.to = call->local_id;
-
-				if ((call->redirecting.state == DIVERTEDSTATE_DIVERTED) && call->redirecting.to.number.str[0]) {
-					/* immediately send divertingLegInformation1 APDU  */
-					qsig_initiate_diverting_leg_information1(pri, call);
-					call->redirecting.state = DIVERTEDSTATE_DIVLEGINFO1SEND;
-				}
-				if ((call->redirecting.state == DIVERTEDSTATE_DIVLEGINFO1SEND) && call->redirecting.to.name.str[0]) {
-					/* queue divertingLegInformation3 to be send with next Q931_ALERTING */
-					rose_diverting_leg_information3_encode(pri, call, Q931_ALERTING);
-					call->redirecting.state = DIVERTEDSTATE_DIVLEGINFO3SEND;
-				}
-			}
-			break;
-		case Q931_CALL_STATE_CALL_RECEIVED:
-			/* queue updates for next CONNECT */
-			if (call->local_id.name.str[0] && ((call->redirecting.state == DIVERTEDSTATE_NONE) || (call->redirecting.state == DIVERTEDSTATE_DIVLEGINFO3SEND))) {
-				/* queue connectedName to be send with next Q931_CONNECT */
-				rose_connected_name_encode(pri, call, Q931_CONNECT);
-			}
-
-			if (call->redirecting.state != DIVERTEDSTATE_NONE) {
-				call->redirecting.to = call->local_id;
-
-				if ((call->redirecting.state == DIVERTEDSTATE_DIVERTED) && call->redirecting.to.number.str[0]) {
-					/* queue divertingLegInformation1 to be send with next Q931_FACILITY */
-					rose_diverting_leg_information1_encode(pri, call);
-					call->redirecting.state = DIVERTEDSTATE_DIVLEGINFO1SEND;
-
-					if (call->redirecting.to.name.str[0]) {
-						/* queue divertingLegInformation3 to be send with next Q931_FACILITY */
-						rose_diverting_leg_information3_encode(pri, call, Q931_FACILITY);
-						call->redirecting.state = DIVERTEDSTATE_DIVLEGINFO3SEND;
-					}
-
-					/* immediately send Q931_FACILITY */
-					if (q931_facility(pri, call)) {
-						pri_message(pri, "Could not schedule facility message for divertingLegInfo1+3\n");
-					}
-				}
-				if ((call->redirecting.state == DIVERTEDSTATE_DIVLEGINFO1SEND) && call->redirecting.to.name.str[0]) {
-					/* queue divertingLegInformation3 to be send with next Q931_CONNECT */
-					rose_diverting_leg_information3_encode(pri, call, Q931_CONNECT);
-					call->redirecting.state = DIVERTEDSTATE_DIVLEGINFO3SEND;
-				}
-			}
-			break;
-		}
-	}
-
-	return 0;
-}
-
-int pri_redirecting_update(struct pri *pri, q931_call *call, struct pri_party_redirecting *redirecting)
-{
-	if (!pri || !call)
-		return -1;
-
-	call->redirecting.to.number.status = Q931_PARTY_DATA_STATUS_CHANGED;
-	call->redirecting.to.number.presentation = redirecting->to.number_presentation;
-	call->redirecting.to.number.plan = redirecting->to.number_type;
-	libpri_copy_string(call->redirecting.to.number.str, redirecting->to.number,
-		sizeof(call->redirecting.to.number.str));
-
-	if (redirecting->to.name[0]) {
-		call->redirecting.to.name.status = Q931_PARTY_DATA_STATUS_CHANGED;
-		call->redirecting.to.name.presentation = redirecting->to.number_presentation;
-		call->redirecting.to.name.char_set = 1;	/* iso8859-1 */
-		libpri_copy_string(call->redirecting.to.name.str, redirecting->to.name,
-			sizeof(call->redirecting.to.name.str));
-	} else {
-		q931_party_name_init(&call->redirecting.to.name);
-	}
-	call->redirecting.reason = redirecting->reason;
-
-	if (pri->switchtype == PRI_SWITCH_QSIG) {
-		switch (call->ourcallstate) {
-		case Q931_CALL_STATE_ACTIVE:
-			/* immediately send callTransferComplete APDU, callStatus=alerting(1) */
-			qsig_initiate_call_transfer_complete(pri, call, 1);
-			break;
-		case Q931_CALL_STATE_OVERLAP_RECEIVING:
-		case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
-			call->redirecting.state = DIVERTEDSTATE_DIVERTED;
-
-			if (call->redirecting.to.number.str[0]) {
-				/* immediately send divertingLegInformation1 APDU */
-				qsig_initiate_diverting_leg_information1(pri, call);
-				call->redirecting.state = DIVERTEDSTATE_DIVLEGINFO1SEND;
-			}
-			if ((call->redirecting.state == DIVERTEDSTATE_DIVLEGINFO1SEND) && call->redirecting.to.name.str[0]) {
-				/* queue divertingLegInformation3 to be send with next Q931_ALERTING */
-				rose_diverting_leg_information3_encode(pri, call, Q931_ALERTING);
-				call->redirecting.state = DIVERTEDSTATE_DIVLEGINFO3SEND;
+/*!
+ * \internal
+ * \brief Copy the PRI party name to the Q.931 party name structure.
+ *
+ * \param q931_name Q.931 party name structure
+ * \param pri_name PRI party name structure
+ *
+ * \return Nothing
+ */
+static void pri_copy_party_name_to_q931(struct q931_party_name *q931_name, const struct pri_party_name *pri_name)
+{
+	q931_party_name_init(q931_name);
+	if (pri_name->valid) {
+		q931_name->valid = 1;
+		q931_name->presentation = pri_name->presentation;
+		q931_name->char_set = pri_name->char_set;
+		libpri_copy_string(q931_name->str, pri_name->str, sizeof(q931_name->str));
+	}
+}
+
+/*!
+ * \internal
+ * \brief Copy the PRI party number to the Q.931 party number structure.
+ *
+ * \param ctrl D channel controller.
+ * \param q931_number Q.931 party number structure
+ * \param pri_number PRI party number structure
+ *
+ * \return Nothing
+ */
+static void pri_copy_party_number_to_q931(struct pri *ctrl, struct q931_party_number *q931_number, const struct pri_party_number *pri_number)
+{
+	q931_party_number_init(q931_number);
+	if (pri_number->valid) {
+		q931_number->valid = 1;
+		q931_number->presentation = pri_number->presentation;
+		switch (ctrl->switchtype) {
+		case PRI_SWITCH_DMS100:
+		case PRI_SWITCH_ATT4ESS:
+			/* Doesn't like certain presentation types */
+			if (!(q931_number->presentation & 0x7c)) {
+				q931_number->presentation = PRES_ALLOWED_NETWORK_NUMBER;
 			}
 			break;
 		default:
-			pri_message(pri, "Redirecting update in state %d\n", call->ourcallstate);
 			break;
 		}
+		q931_number->plan = pri_number->plan;
+		libpri_copy_string(q931_number->str, pri_number->str, sizeof(q931_number->str));
+	}
+}
+
+/*!
+ * \internal
+ * \brief Copy the PRI party id to the Q.931 party id structure.
+ *
+ * \param ctrl D channel controller.
+ * \param q931_id Q.931 party id structure
+ * \param pri_id PRI party id structure
+ *
+ * \return Nothing
+ */
+static void pri_copy_party_id_to_q931(struct pri *ctrl, struct q931_party_id *q931_id, const struct pri_party_id *pri_id)
+{
+	pri_copy_party_name_to_q931(&q931_id->name, &pri_id->name);
+	pri_copy_party_number_to_q931(ctrl, &q931_id->number, &pri_id->number);
+}
+
+int pri_connected_line_update(struct pri *ctrl, q931_call *call, const struct pri_party_connected_line *connected)
+{
+	struct q931_party_id party_id;
+
+	if (!ctrl || !call) {
+		return -1;
+	}
+
+	pri_copy_party_id_to_q931(ctrl, &party_id, &connected->id);
+	if (!q931_party_id_cmp(&party_id, &call->local_id)) {
+		/* The local party information did not change so do nothing. */
+		return 0;
+	}
+	call->local_id = party_id;
+
+	switch (ctrl->switchtype) {
+	case PRI_SWITCH_QSIG:
+		switch (call->ourcallstate) {
+		case Q931_CALL_STATE_CALL_INITIATED:
+		case Q931_CALL_STATE_OVERLAP_SENDING:
+		case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
+		case Q931_CALL_STATE_CALL_DELIVERED:
+			/*
+			 * The local party transferred to someone else before
+			 * the remote end answered.
+			 */
+		case Q931_CALL_STATE_ACTIVE:
+			/* Immediately send CallTransferComplete APDU, callStatus=answered(0) */
+			qsig_initiate_call_transfer_complete(ctrl, call, 0);
+			break;
+		default:
+			/* Just save the data for further developments. */
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+int pri_redirecting_update(struct pri *ctrl, q931_call *call, const struct pri_party_redirecting *redirecting)
+{
+	if (!ctrl || !call) {
+		return -1;
+	}
+
+	/* Save redirecting.to information and reason. */
+	pri_copy_party_id_to_q931(ctrl, &call->redirecting.to, &redirecting->to);
+	call->redirecting.reason = redirecting->reason;
+
+	switch (call->ourcallstate) {
+	case Q931_CALL_STATE_NULL:
+		/* Save the remaining redirecting information before we place a call. */
+		pri_copy_party_id_to_q931(ctrl, &call->redirecting.from, &redirecting->from);
+		pri_copy_party_id_to_q931(ctrl, &call->redirecting.orig_called, &redirecting->orig_called);
+		call->redirecting.orig_reason = redirecting->orig_reason;
+		if (redirecting->count <= 0) {
+			if (call->redirecting.from.number.valid) {
+				call->redirecting.count = 1;
+			} else {
+				call->redirecting.count = 0;
+			}
+		} else if (redirecting->count < PRI_MAX_REDIRECTS) {
+			call->redirecting.count = redirecting->count;
+		} else {
+			call->redirecting.count = PRI_MAX_REDIRECTS;
+		}
+		break;
+	case Q931_CALL_STATE_OVERLAP_RECEIVING:
+	case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
+	case Q931_CALL_STATE_CALL_RECEIVED:
+		/* This is an incoming call that has not connected yet. */
+		if (!call->redirecting.to.number.valid) {
+			/* Not being redirected toward valid number data. Ignore. */
+			break;
+		}
+
+		switch (ctrl->switchtype) {
+		case PRI_SWITCH_QSIG:
+			if (call->redirecting.state != Q931_REDIRECTING_STATE_PENDING_TX_DIV_LEG_3
+				|| strcmp(call->redirecting.to.number.str, call->called_number.str) != 0) {
+				/* immediately send divertingLegInformation1 APDU */
+				if (rose_diverting_leg_information1_encode(ctrl, call)
+					|| q931_facility(ctrl, call)) {
+					pri_message(ctrl,
+						"Could not schedule facility message for divertingLegInfo1\n");
+				}
+			}
+			call->redirecting.state = Q931_REDIRECTING_STATE_IDLE;
+
+			/* immediately send divertingLegInformation3 APDU */
+			if (rose_diverting_leg_information3_encode(ctrl, call, Q931_FACILITY)
+				|| q931_facility(ctrl, call)) {
+				pri_message(ctrl,
+					"Could not schedule facility message for divertingLegInfo3\n");
+			}
+			break;
+		default:
+			break;
+		}
+		break;
+	default:
+		pri_message(ctrl, "Ignored redirecting update because call in state %s(%d).\n",
+			q931_call_state_str(call->ourcallstate), call->ourcallstate);
+		break;
 	}
 
 	return 0;
@@ -1094,8 +1133,3 @@
 	sr->redirectingreason = reason;
 	return 0;
 }
-
-void pri_sr_set_redirecting_name(struct pri_sr *sr, char *name)
-{
-	sr->redirectingname = name;
-}

Modified: team/group/issue14068/pri_facility.c
URL: http://svn.asterisk.org/svn-view/libpri/team/group/issue14068/pri_facility.c?view=diff&rev=854&r1=853&r2=854
==============================================================================
--- team/group/issue14068/pri_facility.c (original)
+++ team/group/issue14068/pri_facility.c Thu Jun  4 11:46:19 2009
@@ -597,31 +597,34 @@
 	msg.operation = ROSE_QSIG_DivertingLegInformation2;
 	msg.invoke_id = get_invokeid(ctrl);
 
-	/* diversionCounter always is 1 because other isn't available in the current design */
-	msg.args.qsig.DivertingLegInformation2.diversion_counter = 1;
+	/* diversionCounter is the redirecting.count */
+	msg.args.qsig.DivertingLegInformation2.diversion_counter = call->redirecting.count;
 
 	msg.args.qsig.DivertingLegInformation2.diversion_reason =
 		redirectingreason_from_q931(ctrl, call->redirecting.reason);
 
 	/* divertingNr is the redirecting.from.number */
 	msg.args.qsig.DivertingLegInformation2.diverting_present = 1;
-	msg.args.qsig.DivertingLegInformation2.diverting.presentation =
-		presentation_from_q931(ctrl, call->redirecting.from.number.presentation,
-			call->redirecting.from.number.str[0]);
-	msg.args.qsig.DivertingLegInformation2.diverting.number.plan =
-		numbering_plan_from_q931(ctrl, call->redirecting.from.number.plan);
-	msg.args.qsig.DivertingLegInformation2.diverting.number.ton =
-		typeofnumber_from_q931(ctrl, call->redirecting.from.number.plan);
-	libpri_copy_string((char *)
-		msg.args.qsig.DivertingLegInformation2.diverting.number.str,
-		call->redirecting.from.number.str,
-		sizeof(msg.args.qsig.DivertingLegInformation2.diverting.number.str));
-	msg.args.qsig.DivertingLegInformation2.diverting.number.length =
-		strlen((char *) msg.args.qsig.DivertingLegInformation2.diverting.number.str);
+	if (call->redirecting.from.number.valid) {
+		msg.args.qsig.DivertingLegInformation2.diverting.presentation =
+			presentation_from_q931(ctrl, call->redirecting.from.number.presentation,
+				call->redirecting.from.number.str[0]);
+		msg.args.qsig.DivertingLegInformation2.diverting.number.plan =
+			numbering_plan_from_q931(ctrl, call->redirecting.from.number.plan);
+		msg.args.qsig.DivertingLegInformation2.diverting.number.ton =
+			typeofnumber_from_q931(ctrl, call->redirecting.from.number.plan);
+		libpri_copy_string((char *)
+			msg.args.qsig.DivertingLegInformation2.diverting.number.str,
+			call->redirecting.from.number.str,
+			sizeof(msg.args.qsig.DivertingLegInformation2.diverting.number.str));
+		msg.args.qsig.DivertingLegInformation2.diverting.number.length =
+			strlen((char *) msg.args.qsig.DivertingLegInformation2.diverting.number.str);
+	} else {
+		msg.args.qsig.DivertingLegInformation2.diverting.presentation = 2;/* numberNotAvailableDueToInterworking */
+	}
 
 	/* redirectingName is the redirecting.from.name */
-	if (call->redirecting.from.name.status != Q931_PARTY_DATA_STATUS_INVALID) {
-		call->redirecting.from.name.status = Q931_PARTY_DATA_STATUS_VALID;
+	if (call->redirecting.from.name.valid) {
 		msg.args.qsig.DivertingLegInformation2.redirecting_name_present = 1;
 		msg.args.qsig.DivertingLegInformation2.redirecting_name.presentation =
 			qsig_name_presentation_from_q931(ctrl,
@@ -637,6 +640,53 @@
 			msg.args.qsig.DivertingLegInformation2.redirecting_name.data);
 	}
 
+	if (1 < call->redirecting.count) {
+		msg.args.qsig.DivertingLegInformation2.original_diversion_reason_present = 1;
+		msg.args.qsig.DivertingLegInformation2.original_called_present = 1;
+		if (call->redirecting.orig_called.number.valid) {
+			msg.args.qsig.DivertingLegInformation2.original_diversion_reason =
+				redirectingreason_from_q931(ctrl, call->redirecting.orig_reason);
+
+			/* originalCalledNr is the redirecting.orig_called.number */
+			msg.args.qsig.DivertingLegInformation2.original_called.presentation =
+				presentation_from_q931(ctrl, call->redirecting.orig_called.number.presentation,
+					call->redirecting.orig_called.number.str[0]);
+			msg.args.qsig.DivertingLegInformation2.original_called.number.plan =
+				numbering_plan_from_q931(ctrl, call->redirecting.orig_called.number.plan);
+			msg.args.qsig.DivertingLegInformation2.original_called.number.ton =
+				typeofnumber_from_q931(ctrl, call->redirecting.orig_called.number.plan);
+			libpri_copy_string((char *)
+				msg.args.qsig.DivertingLegInformation2.original_called.number.str,
+				call->redirecting.orig_called.number.str,
+				sizeof(msg.args.qsig.DivertingLegInformation2.original_called.number.str));
+			msg.args.qsig.DivertingLegInformation2.original_called.number.length =
+				strlen((char *)
+					msg.args.qsig.DivertingLegInformation2.original_called.number.str);
+		} else {
+			msg.args.qsig.DivertingLegInformation2.original_diversion_reason =
+				QSIG_DIVERT_REASON_UNKNOWN;
+			msg.args.qsig.DivertingLegInformation2.original_called.presentation = 2;/* numberNotAvailableDueToInterworking */
+		}
+
+		/* originalCalledName is the redirecting.orig_called.name */
+		if (call->redirecting.orig_called.name.valid) {
+			msg.args.qsig.DivertingLegInformation2.original_called_name_present = 1;
+			msg.args.qsig.DivertingLegInformation2.original_called_name.presentation =
+				qsig_name_presentation_from_q931(ctrl,
+					call->redirecting.orig_called.name.presentation,
+					call->redirecting.orig_called.name.str[0]);
+			msg.args.qsig.DivertingLegInformation2.original_called_name.char_set =
+				call->redirecting.orig_called.name.char_set;
+			libpri_copy_string((char *)
+				msg.args.qsig.DivertingLegInformation2.original_called_name.data,
+				call->redirecting.orig_called.name.str,
+				sizeof(msg.args.qsig.DivertingLegInformation2.original_called_name.data));
+			msg.args.qsig.DivertingLegInformation2.original_called_name.length =
+				strlen((char *)
+					msg.args.qsig.DivertingLegInformation2.original_called_name.data);
+		}
+	}
+
 	pos = rose_encode_invoke(ctrl, pos, end, &msg);
 
 	return pos;
@@ -704,8 +754,7 @@
 		msg.args.qsig.DivertingLegInformation3.presentation_allowed_indicator = 1;	/* TRUE */
 
 		/* redirectionName is the redirecting.to.name */
-		if (call->redirecting.to.name.status != Q931_PARTY_DATA_STATUS_INVALID) {
-			call->redirecting.to.name.status = Q931_PARTY_DATA_STATUS_VALID;
+		if (call->redirecting.to.name.valid) {
 			msg.args.qsig.DivertingLegInformation3.redirection_name_present = 1;
 			msg.args.qsig.DivertingLegInformation3.redirection_name.presentation =
 				qsig_name_presentation_from_q931(ctrl,
@@ -979,7 +1028,7 @@
 	unsigned char *end;
 	int mymessage;
 
-	if (call->local_id.name.status == Q931_PARTY_DATA_STATUS_INVALID) {
+	if (!call->local_id.name.valid) {
 		return 0;
 	}
 
@@ -1000,7 +1049,6 @@
 	}
 
 	/* CallingName is the local_id.name */
-	call->local_id.name.status = Q931_PARTY_DATA_STATUS_VALID;
 	end = enc_qsig_calling_name(ctrl, buffer, buffer + sizeof(buffer),
 		&call->local_id.name);
 	if (!end) {
@@ -1647,8 +1695,8 @@
 		msg.args.qsig.CallTransferComplete.redirection.screened.number.str);
 
 	/* redirectionName is the local_id.name */
-	if (call->local_id.name.status != Q931_PARTY_DATA_STATUS_INVALID) {
-		call->local_id.name.status = Q931_PARTY_DATA_STATUS_VALID;
+	if (call->local_id.name.valid) {
+		msg.args.qsig.CallTransferComplete.redirection_name_present = 1;
 		msg.args.qsig.CallTransferComplete.redirection_name.presentation =
 			qsig_name_presentation_from_q931(ctrl,
 				call->local_id.name.presentation,
@@ -1917,9 +1965,14 @@
 
 	if (pri->switchtype == PRI_SWITCH_QSIG) {
 		/* For Q.SIG it does network and cpe operations */
-		if (call->redirecting.from.number.status != Q931_PARTY_DATA_STATUS_INVALID) {
-			call->redirecting.from.number.status = Q931_PARTY_DATA_STATUS_VALID;
+		if (call->redirecting.count) {
 			rose_diverting_leg_information2_encode(pri, call);
+
+			/*
+			 * Expect a DivertingLegInformation3 to update the COLR of the
+			 * redirecting-to party we are attempting to call now.
+			 */
+			call->redirecting.state = Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3;
 		}
 		add_callername_facility_ies(pri, call, 1);
 		return 0;
@@ -2186,6 +2239,9 @@
 void rose_handle_invoke(struct pri *ctrl, q931_call *call, q931_ie *ie,
 	const struct fac_extension_header *header, const struct rose_msg_invoke *invoke)
 {
+	struct pri_subcommand *subcmd;
+	struct q931_party_id party_id;
+
 	switch (invoke->operation) {
 #if 0	/* Not handled yet */
 	case ROSE_ETSI_ActivationDiversion:
@@ -2273,7 +2329,8 @@
 #endif	/* Not handled yet */
 	case ROSE_QSIG_CallingName:
 		/* CallingName is put in remote_id.name */
-		call->remote_id.name.status = Q931_PARTY_DATA_STATUS_CHANGED;
+		q931_party_name_init(&call->remote_id.name);
+		call->remote_id.name.valid = 1;
 		call->remote_id.name.presentation = qsig_name_presentation_for_q931(ctrl,
 			invoke->args.qsig.CallingName.name.presentation);
 		call->remote_id.name.char_set = invoke->args.qsig.CallingName.name.char_set;
@@ -2283,17 +2340,28 @@
 		break;
 	case ROSE_QSIG_CalledName:
 		/* CalledName is put in remote_id.name */
-		call->remote_id.name.status = Q931_PARTY_DATA_STATUS_CHANGED;
+		q931_party_name_init(&call->remote_id.name);
+		call->remote_id.name.valid = 1;
 		call->remote_id.name.presentation = qsig_name_presentation_for_q931(ctrl,
 			invoke->args.qsig.CalledName.name.presentation);
 		call->remote_id.name.char_set = invoke->args.qsig.CalledName.name.char_set;
 		libpri_copy_string(call->remote_id.name.str,
 			(char *) invoke->args.qsig.CalledName.name.data,
 			sizeof(call->remote_id.name.str));
+
+		/* Setup connected line subcommand */
+		subcmd = q931_alloc_subcommand(ctrl);
+		if (!subcmd) {
+			pri_error(ctrl, "ERROR: Too many facility subcommands\n");
+			break;
+		}
+		subcmd->cmd = PRI_SUBCMD_CONNECTED_LINE;
+		q931_party_id_copy_to_pri(&subcmd->u.connected_line.party.id, &call->remote_id);
 		break;
 	case ROSE_QSIG_ConnectedName:
 		/* ConnectedName is put in remote_id.name */
-		call->remote_id.name.status = Q931_PARTY_DATA_STATUS_CHANGED;
+		q931_party_name_init(&call->remote_id.name);
+		call->remote_id.name.valid = 1;
 		call->remote_id.name.presentation = qsig_name_presentation_for_q931(ctrl,
 			invoke->args.qsig.ConnectedName.name.presentation);
 		call->remote_id.name.char_set =
@@ -2333,64 +2401,63 @@
 		break;
 #endif	/* Not handled yet */
 	case ROSE_QSIG_CallTransferActive:
-		call->ctactiveflag = 1;
-
-		/* connectedAddress is put in ct_active.number */
-		call->ct_active.number.status = Q931_PARTY_DATA_STATUS_CHANGED;
-		call->ct_active.number.presentation =
+		call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
+
+		/* connectedAddress is put in remote_id.number */
+		q931_party_number_init(&call->remote_id.number);
+		call->remote_id.number.valid = 1;
+		call->remote_id.number.presentation =
 			presentation_for_q931(ctrl,
 				invoke->args.qsig.CallTransferActive.connected.presentation);
 		switch (invoke->args.qsig.CallTransferActive.connected.presentation) {
 		case 0:	/* presentationAllowedAddress */
 		case 3:	/* presentationRestrictedAddress */
-			libpri_copy_string(call->ct_active.number.str, (char *)
+			libpri_copy_string(call->remote_id.number.str, (char *)
 				invoke->args.qsig.CallTransferActive.connected.screened.number.str,
-				sizeof(call->ct_active.number.str));
-			call->ct_active.number.presentation |=
+				sizeof(call->remote_id.number.str));
+			call->remote_id.number.presentation |=
 				invoke->args.qsig.CallTransferActive.connected.screened.
 				screening_indicator;
-			call->ct_active.number.plan =
+			call->remote_id.number.plan =
 				numbering_plan_for_q931(ctrl,
 					invoke->args.qsig.CallTransferActive.connected.screened.number.plan)
 				| typeofnumber_for_q931(ctrl,
 					invoke->args.qsig.CallTransferActive.connected.screened.number.ton);
 			break;
 		default:
-			call->ct_active.number.str[0] = '\0';
-			call->ct_active.number.plan = PRI_UNKNOWN;
-			break;
-		}
-
-		/* connectedName is put in ct_active.name */
-		call->ct_active.name.str[0] = '\0';
+			break;
+		}
+
+		/* connectedName is put in remote_id.name */
 		if (invoke->args.qsig.CallTransferActive.connected_name_present) {
-			call->ct_active.name.status = Q931_PARTY_DATA_STATUS_CHANGED;
-			call->ct_active.name.presentation = qsig_name_presentation_for_q931(ctrl,
+			q931_party_name_init(&call->remote_id.name);
+			call->remote_id.name.valid = 1;
+			call->remote_id.name.presentation = qsig_name_presentation_for_q931(ctrl,
 				invoke->args.qsig.CallTransferActive.connected_name.presentation);
-			call->ct_active.name.char_set =
+			call->remote_id.name.char_set =
 				invoke->args.qsig.CallTransferActive.connected_name.char_set;
-			libpri_copy_string(call->ct_active.name.str,
+			libpri_copy_string(call->remote_id.name.str,
 				(char *) invoke->args.qsig.CallTransferActive.connected_name.data,
-				sizeof(call->ct_active.name.str));
+				sizeof(call->remote_id.name.str));
 		}
 		break;
 	case ROSE_QSIG_CallTransferComplete:
-		call->ctcompleteflag = 1;
-
-		/* redirectionNumber is put in ct_complete.number */
-		call->ct_complete.number.presentation =
+		/* redirectionNumber is put in remote_id.number */
+		q931_party_number_init(&call->remote_id.number);
+		call->remote_id.number.valid = 1;
+		call->remote_id.number.presentation =
 			presentation_for_q931(ctrl,
 				invoke->args.qsig.CallTransferComplete.redirection.presentation);
 		switch (invoke->args.qsig.CallTransferComplete.redirection.presentation) {
 		case 0:	/* presentationAllowedNumber */
 		case 3:	/* presentationRestrictedNumber */
-			libpri_copy_string(call->ct_complete.number.str, (char *)
+			libpri_copy_string(call->remote_id.number.str, (char *)
 				invoke->args.qsig.CallTransferComplete.redirection.screened.number.str,
-				sizeof(call->ct_complete.number.str));
-			call->ct_complete.number.presentation |=
+				sizeof(call->remote_id.number.str));
+			call->remote_id.number.presentation |=
 				invoke->args.qsig.CallTransferComplete.redirection.screened.
 				screening_indicator;
-			call->ct_complete.number.plan =
+			call->remote_id.number.plan =
 				numbering_plan_for_q931(ctrl,
 					invoke->args.qsig.CallTransferComplete.redirection.screened.number.
 					plan)
@@ -2399,54 +2466,82 @@
 					ton);
 			break;
 		default:
-			call->ct_complete.number.str[0] = '\0';
-			call->ct_complete.number.plan = PRI_UNKNOWN;
-			break;
-		}
-
-		call->ctcompletecallstatus = invoke->args.qsig.CallTransferComplete.call_status;
-
-		/* redirectionName is put in ct_complete.name */
-		call->ct_complete.name.str[0] = '\0';
+			break;
+		}
+
+		/* redirectionName is put in remote_id.name */
 		if (invoke->args.qsig.CallTransferComplete.redirection_name_present) {
-			call->ct_complete.name.status = Q931_PARTY_DATA_STATUS_CHANGED;
-			call->ct_complete.name.presentation = qsig_name_presentation_for_q931(ctrl,
+			q931_party_name_init(&call->remote_id.name);
+			call->remote_id.name.valid = 1;
+			call->remote_id.name.presentation = qsig_name_presentation_for_q931(ctrl,
 				invoke->args.qsig.CallTransferComplete.redirection_name.presentation);
-			call->ct_complete.name.char_set =
+			call->remote_id.name.char_set =
 				invoke->args.qsig.CallTransferComplete.redirection_name.char_set;
-			libpri_copy_string(call->ct_complete.name.str,
+			libpri_copy_string(call->remote_id.name.str,
 				(char *) invoke->args.qsig.CallTransferComplete.redirection_name.data,
-				sizeof(call->ct_complete.name.str));
-		}
-		break;
-#if 0	/* This was incomplete */
+				sizeof(call->remote_id.name.str));
+		}
+
+		if (invoke->args.qsig.CallTransferComplete.call_status == 1) {
+			/* The remote party for the transfer has not answered yet. */
+			call->incoming_ct_state = INCOMING_CT_STATE_EXPECT_CT_ACTIVE;
+		} else {
+			call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
+		}
+		break;
 	case ROSE_QSIG_CallTransferUpdate:
+		party_id = call->remote_id;
+
+		/* redirectionNumber is put in party_id.number */
+		q931_party_number_init(&party_id.number);
+		party_id.number.valid = 1;
+		party_id.number.presentation =
+			presentation_for_q931(ctrl,
+				invoke->args.qsig.CallTransferUpdate.redirection.presentation);
 		switch (invoke->args.qsig.CallTransferUpdate.redirection.presentation) {
 		case 0:	/* presentationAllowedNumber */
 		case 3:	/* presentationRestrictedNumber */
-			libpri_copy_string(call->remote_id.number.str, (char *)
+			libpri_copy_string(party_id.number.str, (char *)
 				invoke->args.qsig.CallTransferUpdate.redirection.screened.number.str,
-				sizeof(call->remote_id.number.str));
+				sizeof(party_id.number.str));
+			party_id.number.presentation |=
+				invoke->args.qsig.CallTransferUpdate.redirection.screened.
+				screening_indicator;
+			party_id.number.plan =
+				numbering_plan_for_q931(ctrl,
+					invoke->args.qsig.CallTransferUpdate.redirection.screened.number.plan)
+				| typeofnumber_for_q931(ctrl,
+					invoke->args.qsig.CallTransferUpdate.redirection.screened.number.ton);
 			break;
 		default:
-			call->remote_id.number.str[0] = '\0';
-			break;
-		}
-		call->remote_id.name.str[0] = '\0';
+			break;
+		}
+
+		/* redirectionName is put in party_id.name */
 		if (invoke->args.qsig.CallTransferUpdate.redirection_name_present) {
-			switch (invoke->args.qsig.CallTransferUpdate.redirection_name.presentation) {
-			case 1:	/* presentation_allowed */
-			case 2:	/* presentation_restricted */
-				libpri_copy_string(call->remote_id.name.str,
-					(char *) invoke->args.qsig.CallTransferUpdate.redirection_name.data,
-					sizeof(call->remote_id.name.str));
+			q931_party_name_init(&party_id.name);
+			party_id.name.valid = 1;
+			party_id.name.presentation = qsig_name_presentation_for_q931(ctrl,
+				invoke->args.qsig.CallTransferUpdate.redirection_name.presentation);
+			party_id.name.char_set =
+				invoke->args.qsig.CallTransferUpdate.redirection_name.char_set;
+			libpri_copy_string(party_id.name.str,
+				(char *) invoke->args.qsig.CallTransferUpdate.redirection_name.data,
+				sizeof(party_id.name.str));
+		}
+
+		if (q931_party_id_cmp(&party_id, &call->remote_id)) {
+			/* The remote_id data has changed. */
+			call->remote_id = party_id;
+			switch (call->incoming_ct_state) {
+			case INCOMING_CT_STATE_IDLE:
+				call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
 				break;
 			default:
 				break;
 			}
 		}
 		break;
-#endif	/* This was incomplete */
 #if 0	/* Not handled yet */
 	case ROSE_QSIG_SubaddressTransfer:
 		break;
@@ -2467,10 +2562,9 @@
 		break;
 #endif	/* Not handled yet */
 	case ROSE_QSIG_DivertingLegInformation1:
-		call->divleginfo1activeflag = 1;
-
 		/* nominatedNr is put in redirecting.to.number */
-		call->redirecting.to.number.status = Q931_PARTY_DATA_STATUS_CHANGED;
+		q931_party_number_init(&call->redirecting.to.number);
+		call->redirecting.to.number.valid = 1;
 		if (invoke->args.qsig.DivertingLegInformation1.subscription_option ==
 			QSIG_NOTIFICATION_WITH_DIVERTED_TO_NR) {
 			call->redirecting.to.number.presentation =
@@ -2481,7 +2575,6 @@
 		} else {
 			call->redirecting.to.number.presentation =
 				PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
-			call->redirecting.to.number.str[0] = '\0';
 		}
 		call->redirecting.to.number.plan =
 			numbering_plan_for_q931(ctrl,
@@ -2491,24 +2584,25 @@
 
 		call->redirecting.reason = redirectingreason_for_q931(ctrl,

[... 1238 lines stripped ...]



More information about the svn-commits mailing list