[svn-commits] rmudgett: branch 1.4 r982 - /branches/1.4/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Aug 18 18:53:40 CDT 2009


Author: rmudgett
Date: Tue Aug 18 18:53:32 2009
New Revision: 982

URL: http://svn.asterisk.org/svn-view/libpri?view=rev&rev=982
Log:
Add COLP support to libpri for ETSI PTP, ETSI PTMP, and Q.SIG.

Add Connected Line Presentation (COLP) support to chan_dahdi/libpri as an
addition to issue 8824.  This is the libpri portion.  COLP support is now
available for ETSI PTP, ETSI PTMP, and Q.SIG with this patch.

(closes issue #14068)
Tested by: rmudgett

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

Added:
    branches/1.4/rose_etsi_diversion.c
      - copied unchanged from r981, team/group/issue14068/rose_etsi_diversion.c
    branches/1.4/rose_etsi_ect.c
      - copied unchanged from r981, team/group/issue14068/rose_etsi_ect.c
Modified:
    branches/1.4/Makefile
    branches/1.4/libpri.h
    branches/1.4/pri.c
    branches/1.4/pri_facility.c
    branches/1.4/pri_facility.h
    branches/1.4/pri_internal.h
    branches/1.4/q931.c
    branches/1.4/rose.c
    branches/1.4/rose.h
    branches/1.4/rose_internal.h
    branches/1.4/rosetest.c

Modified: branches/1.4/Makefile
URL: http://svn.asterisk.org/svn-view/libpri/branches/1.4/Makefile?view=diff&rev=982&r1=981&r2=982
==============================================================================
--- branches/1.4/Makefile (original)
+++ branches/1.4/Makefile Tue Aug 18 18:53:32 2009
@@ -52,6 +52,8 @@
 	rose.o \
 	rose_address.o \
 	rose_etsi_aoc.o \
+	rose_etsi_diversion.o \
+	rose_etsi_ect.o \
 	rose_other.o \
 	rose_q931.o \
 	rose_qsig_aoc.o \
@@ -71,6 +73,8 @@
 	rose.lo \
 	rose_address.lo \
 	rose_etsi_aoc.lo \
+	rose_etsi_diversion.lo \
+	rose_etsi_ect.lo \
 	rose_other.lo \
 	rose_q931.lo \
 	rose_qsig_aoc.lo \

Modified: branches/1.4/libpri.h
URL: http://svn.asterisk.org/svn-view/libpri/branches/1.4/libpri.h?view=diff&rev=982&r1=981&r2=982
==============================================================================
--- branches/1.4/libpri.h (original)
+++ branches/1.4/libpri.h Tue Aug 18 18:53:32 2009
@@ -80,7 +80,8 @@
 #define PRI_EVENT_ANSWER		 8	/* Call has been answered (CONNECT) */
 #define PRI_EVENT_HANGUP_ACK	 9	/* Call hangup has been acknowledged */
 #define PRI_EVENT_RESTART_ACK	10	/* Restart complete on a given channel (RESTART_ACKNOWLEDGE) */
-#define PRI_EVENT_FACNAME		11	/* Caller*ID Name received on Facility */
+#define PRI_EVENT_FACNAME		11	/* Caller*ID Name received on Facility (DEPRECATED) */
+#define PRI_EVENT_FACILITY		11	/* Facility received (FACILITY) */
 #define PRI_EVENT_INFO_RECEIVED 12	/* Additional info (digits) received (INFORMATION) */
 #define PRI_EVENT_PROCEEDING	13	/* When we get CALL_PROCEEDING */
 #define PRI_EVENT_SETUP_ACK		14	/* When we get SETUP_ACKNOWLEDGE */
@@ -301,8 +302,8 @@
 #define PRI_RATE_ADAPT_ASYNC		0x40
 
 /* Notifications */
-#define PRI_NOTIFY_USER_SUSPENDED		0x00	/* User suspended */
-#define PRI_NOTIFY_USER_RESUMED			0x01	/* User resumed */
+#define PRI_NOTIFY_USER_SUSPENDED		0x00	/* User suspended (Q.931) (Call is placed on hold) */
+#define PRI_NOTIFY_USER_RESUMED			0x01	/* User resumed (Q.931) (Call is taken off hold) */
 #define PRI_NOTIFY_BEARER_CHANGE		0x02	/* Bearer service change (DSS1) */
 #define PRI_NOTIFY_ASN1_COMPONENT		0x03	/* ASN.1 encoded component (DSS1) */
 #define PRI_NOTIFY_COMPLETION_DELAY		0x04	/* Call completion delay */
@@ -317,12 +318,12 @@
 #define PRI_NOTIFY_CONF_OTHER_DISCONNECTED	0x4a	/* Other party disconnected */
 #define PRI_NOTIFY_CONF_FLOATING		0x4b	/* Conference floating */
 #define PRI_NOTIFY_WAITING_CALL			0x60	/* Call is waiting call */
-#define PRI_NOTIFY_DIVERSION_ACTIVATED		0x68	/* Diversion activated (DSS1) */
-#define PRI_NOTIFY_TRANSFER_ALERTING		0x69	/* Call transfer, alerting */
-#define PRI_NOTIFY_TRANSFER_ACTIVE		0x6a	/* Call transfer, active */
+#define PRI_NOTIFY_DIVERSION_ACTIVATED		0x68	/* Diversion activated (DSS1) (cfu, cfb, cfnr) (EN 300 207-1 Section 7.2.1) */
+#define PRI_NOTIFY_TRANSFER_ALERTING		0x69	/* Call transfer, alerting (EN 300 369-1 Section 7.2) */
+#define PRI_NOTIFY_TRANSFER_ACTIVE		0x6a	/* Call transfer, active(answered) (EN 300 369-1 Section 7.2) */
 #define PRI_NOTIFY_REMOTE_HOLD			0x79	/* Remote hold */
 #define PRI_NOTIFY_REMOTE_RETRIEVAL		0x7a	/* Remote retrieval */
-#define PRI_NOTIFY_CALL_DIVERTING		0x7b	/* Call is diverting */
+#define PRI_NOTIFY_CALL_DIVERTING		0x7b	/* Call is diverting (EN 300 207-1 Section 7.2.1) */
 
 #define PRI_COPY_DIGITS_CALLED_NUMBER
 
@@ -347,6 +348,151 @@
 
 typedef struct q931_call q931_call;
 
+/* 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];
+};
+
+/*!
+ * \note This structure is a place holder for possible future subaddress support
+ * to maintain ABI compatibility.
+ */
+struct pri_party_subaddress {
+	/*! \brief TRUE if the subaddress information is valid/present */
+	int valid;
+	/*!
+	 * \brief Subaddress type.
+	 * \details
+	 * nsap(0),
+	 * user_specified(2)
+	 */
+	int type;
+	/*!
+	 * \brief TRUE if odd number of address signals
+	 * \note The odd/even indicator is used when the type of subaddress is
+	 * user_specified and the coding is BCD.
+	 */
+	int odd_even_indicator;
+	/*! \brief Length of the subaddress data */
+	int length;
+	/*!
+	 * \brief Subaddress data with null terminator.
+	 * \note The null terminator is a convenience only since the data could be
+	 * BCD/binary and thus have a null byte as part of the contents.
+	 */
+	char data[32];
+};
+
+/*! \brief Information needed to identify an endpoint in a call. */
+struct pri_party_id {
+	/*! \brief Subscriber name */
+	struct pri_party_name name;
+	/*! \brief Subscriber phone number */
+	struct pri_party_number number;
+	/*! \brief Subscriber subaddress */
+	struct pri_party_subaddress subaddress;
+};
+
+/*! \brief Connected Line/Party information */
+struct pri_party_connected_line {
+	/*! Connected party ID */
+	struct pri_party_id id;
+};
+
+/*!
+ * \brief Redirecting Line information.
+ * \details
+ * RDNIS (Redirecting Directory Number Information Service)
+ * Where a call diversion or transfer was invoked.
+ */
+struct pri_party_redirecting {
+	/*! Who is redirecting the call (Sent to the party the call is redirected toward) */
+	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;
+	/*! Original reason for redirect (in cases of multiple redirects) */
+	int orig_reason;
+	/*! Redirection reason */
+	int reason;
+};
+
+/* Subcommands derived from supplementary services. */
+#define PRI_SUBCMD_REDIRECTING		1
+#define PRI_SUBCMD_CONNECTED_LINE	2
+
+
+struct pri_subcommand {
+	/*! PRI_SUBCMD_xxx defined values */
+	int cmd;
+	union {
+		/*! Reserve room for possible expansion to maintain ABI compatibility. */
+		char reserve_space[512];
+		struct pri_party_connected_line connected_line;
+		struct pri_party_redirecting redirecting;
+	} u;
+};
+
+/* Max number of subcommands per event message */
+#define PRI_MAX_SUBCOMMANDS	8
+
+struct pri_subcommands {
+	int counter_subcmd;
+	struct pri_subcommand subcmd[PRI_MAX_SUBCOMMANDS];
+};
+
+
 typedef struct pri_event_generic {
 	/* Events with no additional information fall in this category */
 	int e;
@@ -370,6 +516,7 @@
 	int progressmask;
 	q931_call *call;
 	char useruserinfo[260];		/* User->User info */
+	struct pri_subcommands *subcmds;
 } pri_event_ringing;
 
 typedef struct pri_event_answer {
@@ -380,8 +527,10 @@
 	int progressmask;
 	q931_call *call;
 	char useruserinfo[260];		/* User->User info */
+	struct pri_subcommands *subcmds;
 } pri_event_answer;
 
+/*! Deprecated replaced by struct pri_event_facility. */
 typedef struct pri_event_facname {
 	int e;
 	char callingname[256];
@@ -392,6 +541,18 @@
 	int callingpres;			/* Presentation of Calling CallerID */
 	int callingplan;			/* Dialing plan of Calling entity */
 } pri_event_facname;
+
+struct pri_event_facility {
+	int e;
+	char callingname[256];		/*!< Deprecated, preserved for struct pri_event_facname compatibility */
+	char callingnum[256];		/*!< Deprecated, preserved for struct pri_event_facname compatibility */
+	int channel;
+	int cref;
+	q931_call *call;
+	int callingpres;			/*!< Presentation of Calling CallerID (Deprecated, preserved for struct pri_event_facname compatibility) */
+	int callingplan;			/*!< Dialing plan of Calling entity (Deprecated, preserved for struct pri_event_facname compatibility) */
+	struct pri_subcommands *subcmds;
+};
 
 #define PRI_CALLINGPLANANI
 #define PRI_CALLINGPLANRDNIS
@@ -426,6 +587,7 @@
 	int callingplanorigcalled;		/* Dialing plan of Originally Called Number */
 	int origredirectingreason;
 	int reversecharge;
+	struct pri_subcommands *subcmds;
 } pri_event_ring;
 
 typedef struct pri_event_hangup {
@@ -436,6 +598,7 @@
 	q931_call *call;			/* Opaque call pointer */
 	long aoc_units;				/* Advise of Charge number of charged units */
 	char useruserinfo[260];		/* User->User info */
+	struct pri_subcommands *subcmds;
 } pri_event_hangup;	
 
 typedef struct pri_event_restart_ack {
@@ -452,18 +615,21 @@
 	int progressmask;
 	int cause;
 	q931_call *call;
+	struct pri_subcommands *subcmds;
 } pri_event_proceeding;
  
 typedef struct pri_event_setup_ack {
 	int e;
 	int channel;
 	q931_call *call;
+	struct pri_subcommands *subcmds;
 } pri_event_setup_ack;
 
 typedef struct pri_event_notify {
 	int e;
 	int channel;
 	int info;
+	struct pri_subcommands *subcmds;
 } pri_event_notify;
 
 typedef struct pri_event_keypad_digit {
@@ -471,6 +637,7 @@
 	int channel;
 	q931_call *call;
 	char digits[64];
+	struct pri_subcommands *subcmds;
 } pri_event_keypad_digit;
 
 typedef struct pri_event_service {
@@ -490,7 +657,7 @@
 	pri_event_generic gen;		/* Generic view */
 	pri_event_restart restart;	/* Restart view */
 	pri_event_error	  err;		/* Error view */
-	pri_event_facname facname;	/* Caller*ID Name on Facility */
+	pri_event_facname facname;	/* Caller*ID Name on Facility (Deprecated, use pri_event.facility) */
 	pri_event_ring	  ring;		/* Ring */
 	pri_event_hangup  hangup;	/* Hang up */
 	pri_event_ringing ringing;	/* Ringing */
@@ -502,6 +669,7 @@
 	pri_event_keypad_digit digit;			/* Digits that come during a call */
 	pri_event_service service;				/* service message */
 	pri_event_service_ack service_ack;		/* service acknowledgement message */
+	struct pri_event_facility facility;
 } pri_event;
 
 struct pri;
@@ -588,6 +756,18 @@
    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
+ * \note Could be used instead of pri_sr_set_caller_party() 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 Could be used instead of pri_sr_set_redirecting_parties() 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 */
 
 
@@ -642,8 +822,31 @@
 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);
+
+/*!
+ * \brief Set the caller party ID information in the call SETUP record.
+ *
+ * \param sr New call SETUP record.
+ * \param caller Caller party ID information to set.
+ *
+ * \return Nothing
+ */
+void pri_sr_set_caller_party(struct pri_sr *sr, const struct pri_party_id *caller);
+/*! \note Use pri_sr_set_caller_party() instead to pass more precise caller information. */
 int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres);
+
+/*!
+ * \brief Set the redirecting information in the call SETUP record.
+ *
+ * \param sr New call SETUP record.
+ * \param caller Redirecting information to set.
+ *
+ * \return Nothing
+ */
+void pri_sr_set_redirecting_parties(struct pri_sr *sr, const struct pri_party_redirecting *redirecting);
+/*! \note Use pri_sr_set_redirecting_parties() instead to pass more precise redirecting information. */
 int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason);
+
 #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: branches/1.4/pri.c
URL: http://svn.asterisk.org/svn-view/libpri/branches/1.4/pri.c?view=diff&rev=982&r1=981&r2=982
==============================================================================
--- branches/1.4/pri.c (original)
+++ branches/1.4/pri.c Tue Aug 18 18:53:32 2009
@@ -374,8 +374,8 @@
 		return "Hangup ACK";
 	case PRI_EVENT_RESTART_ACK:
 		return "Restart ACK";
-	case PRI_EVENT_FACNAME:
-		return "FacName";
+	case PRI_EVENT_FACILITY:
+		return "Facility";
 	case PRI_EVENT_INFO_RECEIVED:
 		return "Info Received";
 	case PRI_EVENT_PROCEEDING:
@@ -577,6 +577,203 @@
 	if (!pri || !call)
 		return -1;
 	return q931_connect(pri, call, channel, nonisdn);
+}
+
+/*!
+ * \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 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 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;
+		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 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 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(&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(&party_id, &connected->id);
+	q931_party_id_fixup(ctrl, &party_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 (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:
+		switch (ctrl->switchtype) {
+		case PRI_SWITCH_EUROISDN_E1:
+		case PRI_SWITCH_EUROISDN_T1:
+			if (q931_is_ptmp(ctrl)) {
+				/* PTMP mode */
+				q931_notify_redirection(ctrl, call, PRI_NOTIFY_TRANSFER_ACTIVE,
+					&call->local_id.number);
+			} else {
+				/* PTP mode */
+				/* Immediately send EctInform APDU, callStatus=answered(0) */
+				send_call_transfer_complete(ctrl, call, 0);
+			}
+			break;
+		case PRI_SWITCH_QSIG:
+			/* Immediately send CallTransferComplete APDU, callStatus=answered(0) */
+			send_call_transfer_complete(ctrl, call, 0);
+			break;
+		default:
+			break;
+		}
+		break;
+	default:
+		/* Just save the data for further developments. */
+		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(&call->redirecting.to, &redirecting->to);
+	q931_party_id_fixup(ctrl, &call->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(&call->redirecting.from, &redirecting->from);
+		q931_party_id_fixup(ctrl, &call->redirecting.from);
+		pri_copy_party_id_to_q931(&call->redirecting.orig_called, &redirecting->orig_called);
+		q931_party_id_fixup(ctrl, &call->redirecting.orig_called);
+		call->redirecting.orig_reason = redirecting->orig_reason;
+		if (redirecting->count <= 0) {
+			if (call->redirecting.from.number.valid) {
+				/*
+				 * We are redirecting with an unknown count
+				 * so assume the count is one.
+				 */
+				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_EUROISDN_E1:
+		case PRI_SWITCH_EUROISDN_T1:
+			if (q931_is_ptmp(ctrl)) {
+				/* PTMP mode */
+				q931_notify_redirection(ctrl, call, PRI_NOTIFY_CALL_DIVERTING,
+					&call->redirecting.to.number);
+				break;
+			}
+			/* PTP mode - same behaviour as Q.SIG */
+			/* fall through */
+		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;
 }
 
 #if 0
@@ -703,6 +900,9 @@
 static void pri_sr_init(struct pri_sr *req)
 {
 	memset(req, 0, sizeof(struct pri_sr));
+	q931_party_redirecting_init(&req->redirecting);
+	q931_party_id_init(&req->caller);
+	q931_party_address_init(&req->called);
 	req->reversecharge = PRI_REVERSECHARGE_NONE;
 }
 
@@ -725,13 +925,8 @@
 
 	pri_sr_init(&req);
 	pri_sr_set_connection_call_independent(&req);
-
-	req.caller = caller;
-	req.callerplan = callerplan;
-	req.callername = callername;
-	req.callerpres = callerpres;
-	req.called = called;
-	req.calledplan = calledplan;
+	pri_sr_set_caller(&req, caller, callername, callerplan, callerpres);
+	pri_sr_set_called(&req, called, calledplan, 0);
 
 	if (mwi_message_send(pri, c, &req, 1) < 0) {
 		pri_message(pri, "Unable to send MWI activate message\n");
@@ -750,13 +945,8 @@
 
 	pri_sr_init(&req);
 	pri_sr_set_connection_call_independent(&req);
-
-	req.caller = caller;
-	req.callerplan = callerplan;
-	req.callername = callername;
-	req.callerpres = callerpres;
-	req.called = called;
-	req.calledplan = calledplan;
+	pri_sr_set_caller(&req, caller, callername, callerplan, callerpres);
+	pri_sr_set_called(&req, called, calledplan, 0);
 
 	if(mwi_message_send(pri, c, &req, 0) < 0) {
 		pri_message(pri, "Unable to send MWI deactivate message\n");
@@ -782,16 +972,12 @@
 	if (!pri || !c)
 		return -1;
 	pri_sr_init(&req);
+	pri_sr_set_caller(&req, caller, callername, callerplan, callerpres);
+	pri_sr_set_called(&req, called, calledplan, 0);
 	req.transmode = transmode;
 	req.channel = channel;
 	req.exclusive = exclusive;
 	req.nonisdn =  nonisdn;
-	req.caller = caller;
-	req.callerplan = callerplan;
-	req.callername = callername;
-	req.callerpres = callerpres;
-	req.called = called;
-	req.calledplan = calledplan;
 	req.userl1 = ulayer1;
 	return q931_setup(pri, c, &req);
 }	
@@ -1002,30 +1188,81 @@
 
 int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int numcomplete)
 {
-	sr->called = called;
-	sr->calledplan = calledplan;
+	q931_party_address_init(&sr->called);
+	if (called) {
+		sr->called.number.valid = 1;
+		sr->called.number.plan = calledplan;
+		libpri_copy_string(sr->called.number.str, called, sizeof(sr->called.number.str));
+	}
 	sr->numcomplete = numcomplete;
 	return 0;
 }
 
 int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres)
 {
-	sr->caller = caller;
-	sr->callername = callername;
-	sr->callerplan = callerplan;
-	sr->callerpres = callerpres;
+	q931_party_id_init(&sr->caller);
+	if (caller) {
+		sr->caller.number.valid = 1;
+		sr->caller.number.presentation = callerpres;
+		sr->caller.number.plan = callerplan;
+		libpri_copy_string(sr->caller.number.str, caller, sizeof(sr->caller.number.str));
+
+		if (callername) {
+			sr->caller.name.valid = 1;
+			sr->caller.name.presentation = callerpres;
+			sr->caller.name.char_set = PRI_CHAR_SET_ISO8859_1;
+			libpri_copy_string(sr->caller.name.str, callername,
+				sizeof(sr->caller.name.str));
+		}
+	}
 	return 0;
 }
 
+void pri_sr_set_caller_party(struct pri_sr *sr, const struct pri_party_id *caller)
+{
+	pri_copy_party_id_to_q931(&sr->caller, caller);
+}
+
 int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason)
 {
-	sr->redirectingnum = num;
-	sr->redirectingplan = plan;
-	sr->redirectingpres = pres;
-	sr->redirectingreason = reason;
+	q931_party_redirecting_init(&sr->redirecting);
+	if (num && num[0]) {
+		sr->redirecting.from.number.valid = 1;
+		sr->redirecting.from.number.presentation = pres;
+		sr->redirecting.from.number.plan = plan;
+		libpri_copy_string(sr->redirecting.from.number.str, num,
+			sizeof(sr->redirecting.from.number.str));
+
+		sr->redirecting.count = 1;
+		sr->redirecting.reason = reason;
+	}
 	return 0;
 }
 
+void pri_sr_set_redirecting_parties(struct pri_sr *sr, const struct pri_party_redirecting *redirecting)
+{
+	pri_copy_party_id_to_q931(&sr->redirecting.from, &redirecting->from);
+	pri_copy_party_id_to_q931(&sr->redirecting.to, &redirecting->to);
+	pri_copy_party_id_to_q931(&sr->redirecting.orig_called, &redirecting->orig_called);
+	sr->redirecting.orig_reason = redirecting->orig_reason;
+	sr->redirecting.reason = redirecting->reason;
+	if (redirecting->count <= 0) {
+		if (sr->redirecting.from.number.valid) {
+			/*
+			 * We are redirecting with an unknown count
+			 * so assume the count is one.
+			 */
+			sr->redirecting.count = 1;
+		} else {
+			sr->redirecting.count = 0;
+		}
+	} else if (redirecting->count < PRI_MAX_REDIRECTS) {
+		sr->redirecting.count = redirecting->count;
+	} else {
+		sr->redirecting.count = PRI_MAX_REDIRECTS;
+	}
+}
+
 void pri_sr_set_reversecharge(struct pri_sr *sr, int requested)
 {
 	sr->reversecharge = requested;

Modified: branches/1.4/pri_facility.c
URL: http://svn.asterisk.org/svn-view/libpri/branches/1.4/pri_facility.c?view=diff&rev=982&r1=981&r2=982
==============================================================================
--- branches/1.4/pri_facility.c (original)
+++ branches/1.4/pri_facility.c Tue Aug 18 18:53:32 2009
@@ -394,17 +394,374 @@
 
 /*!
  * \internal
- * \brief Encode the Q.SIG DivertingLegInformation2 invoke message.
+ * \brief Convert the Q.931 number presentation field to Q.SIG name presentation.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param presentation Q.931 presentation/screening octet.
+ * \param name_present Non-zero if the name is available.
+ *
+ * \return Name presentation enumeration value.
+ */
+static int qsig_name_presentation_from_q931(struct pri *ctrl, int presentation, int name_present)
+{
+	int value;
+
+	switch (presentation & PRI_PRES_RESTRICTION) {
+	case PRI_PRES_ALLOWED:
+		if (name_present) {
+			value = 1;	/* presentation_allowed */
+		} else {
+			value = 4;	/* name_not_available */
+		}
+		break;
+	default:
+		pri_message(ctrl, "!! Unsupported Q.931 number presentation value (%d)\n",
+			presentation);
+		/* fall through */
+	case PRI_PRES_RESTRICTED:
+		if (name_present) {
+			value = 2;	/* presentation_restricted */
+		} else {
+			value = 3;	/* presentation_restricted_null */
+		}
+		break;
+	case PRI_PRES_UNAVAILABLE:
+		value = 4;	/* name_not_available */
+		break;
+	}
+
+	return value;
+}
+
+/*!
+ * \internal
+ * \brief Convert the Q.SIG name presentation to Q.931 presentation field value.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param presentation Q.SIG name presentation value.
+ *
+ * \return Q.931 presentation field value.
+ */
+static int qsig_name_presentation_for_q931(struct pri *ctrl, int presentation)
+{
+	int value;
+
+	switch (presentation) {
+	case 1:	/* presentation_allowed */
+		value = PRI_PRES_ALLOWED;
+		break;
+	default:
+		pri_message(ctrl,
+			"!! Unsupported Q.SIG name presentation to Q.931 value (%d)\n",
+			presentation);
+		/* fall through */
+	case 2:	/* presentation_restricted */
+	case 3:	/* presentation_restricted_null */
+		value = PRI_PRES_RESTRICTED;
+		break;
+	case 0:	/* optional_name_not_present */
+	case 4:	/* name_not_available */
+		value = PRI_PRES_UNAVAILABLE;
+		break;
+	}
+
+	return value;
+}
+
+/*!
+ * \internal
+ * \brief Convert number presentation to Q.SIG diversion subscription notification.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param presentation Number presentation value.
+ *
+ * \return Q.SIG diversion subscription notification value.
+ */
+static int presentation_to_subscription(struct pri *ctrl, int presentation)
+{
+	/* derive subscription value from presentation value */
+
+	switch (presentation & PRI_PRES_RESTRICTION) {
+	case PRI_PRES_ALLOWED:
+		return QSIG_NOTIFICATION_WITH_DIVERTED_TO_NR;
+	case PRI_PRES_RESTRICTED:
+		return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR;
+	case PRI_PRES_UNAVAILABLE:	/* Number not available due to interworking */
+		return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR;	/* ?? QSIG_NO_NOTIFICATION */
+	default:
+		pri_message(ctrl, "!! Unknown Q.SIG presentationIndicator 0x%02x\n",
+			presentation);
+		return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR;
+	}
+}
+
+/*!
+ * \internal
+ * \brief Copy the given rose party number to the q931_party_number
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param q931_number Q.931 party number structure
+ * \param rose_number ROSE party number structure
+ *
+ * \note It is assumed that the q931_number has been initialized before calling.
+ *
+ * \return Nothing
+ */
+static void rose_copy_number_to_q931(struct pri *ctrl,
+	struct q931_party_number *q931_number, const struct rosePartyNumber *rose_number)
+{
+	libpri_copy_string(q931_number->str, (char *) rose_number->str,
+		sizeof(q931_number->str));
+	q931_number->plan = numbering_plan_for_q931(ctrl, rose_number->plan)
+		| typeofnumber_for_q931(ctrl, rose_number->ton);
+}
+
+/*!
+ * \internal
+ * \brief Copy the given rose presented screened party number to the q931_party_number
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param q931_number Q.931 party number structure
+ * \param rose_presented ROSE presented screened party number structure
+ *
+ * \return Nothing
+ */
+static void rose_copy_presented_number_screened_to_q931(struct pri *ctrl,
+	struct q931_party_number *q931_number,
+	const struct rosePresentedNumberScreened *rose_presented)
+{
+	q931_party_number_init(q931_number);
+	q931_number->valid = 1;
+	q931_number->presentation = presentation_for_q931(ctrl, rose_presented->presentation);
+	switch (rose_presented->presentation) {
+	case 0:	/* presentationAllowedNumber */
+	case 3:	/* presentationRestrictedNumber */
+		q931_number->presentation |=
+			(rose_presented->screened.screening_indicator & PRI_PRES_NUMBER_TYPE);
+		rose_copy_number_to_q931(ctrl, q931_number,
+			&rose_presented->screened.number);
+		break;
+	default:
+		q931_number->presentation |= PRI_PRES_USER_NUMBER_UNSCREENED;
+		break;
+	}
+}
+
+/*!
+ * \internal
+ * \brief Copy the given rose presented unscreened party number to the q931_party_number
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param q931_number Q.931 party number structure
+ * \param rose_presented ROSE presented unscreened party number structure
+ *
+ * \return Nothing
+ */
+static void rose_copy_presented_number_unscreened_to_q931(struct pri *ctrl,
+	struct q931_party_number *q931_number,
+	const struct rosePresentedNumberUnscreened *rose_presented)
+{
+	q931_party_number_init(q931_number);
+	q931_number->valid = 1;
+	q931_number->presentation = presentation_for_q931(ctrl,
+		rose_presented->presentation) | PRI_PRES_USER_NUMBER_UNSCREENED;
+	switch (rose_presented->presentation) {
+	case 0:	/* presentationAllowedNumber */
+	case 3:	/* presentationRestrictedNumber */
+		rose_copy_number_to_q931(ctrl, q931_number, &rose_presented->number);
+		break;
+	default:
+		break;
+	}
+}
+
+/*!
+ * \internal
+ * \brief Copy the given rose presented screened party address to the q931_party_number
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param q931_number Q.931 party number structure
+ * \param rose_presented ROSE presented screened party address structure
+ *
+ * \return Nothing
+ */
+static void rose_copy_presented_address_screened_to_q931(struct pri *ctrl,
+	struct q931_party_number *q931_number,
+	const struct rosePresentedAddressScreened *rose_presented)
+{
+	q931_party_number_init(q931_number);
+	q931_number->valid = 1;
+	q931_number->presentation = presentation_for_q931(ctrl, rose_presented->presentation);
+	switch (rose_presented->presentation) {
+	case 0:	/* presentationAllowedAddress */
+	case 3:	/* presentationRestrictedAddress */
+		q931_number->presentation |=
+			(rose_presented->screened.screening_indicator & PRI_PRES_NUMBER_TYPE);
+		rose_copy_number_to_q931(ctrl, q931_number,
+			&rose_presented->screened.number);
+		break;
+	default:
+		q931_number->presentation |= PRI_PRES_USER_NUMBER_UNSCREENED;
+		break;
+	}
+}
+
+/*!
+ * \internal
+ * \brief Copy the given rose party name to the q931_party_name
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param qsig_name Q.SIG party name structure
+ * \param rose_name Q.SIG ROSE party name structure
+ *
+ * \return Nothing
+ */
+static void rose_copy_name_to_q931(struct pri *ctrl,
+	struct q931_party_name *qsig_name, const struct roseQsigName *rose_name)
+{
+	//q931_party_name_init(qsig_name);
+	qsig_name->valid = 1;
+	qsig_name->presentation = qsig_name_presentation_for_q931(ctrl,
+		rose_name->presentation);
+	qsig_name->char_set = rose_name->char_set;
+	libpri_copy_string(qsig_name->str, (char *) rose_name->data, sizeof(qsig_name->str));
+}
+
+/*!
+ * \internal
+ * \brief Copy the given q931_party_number to the rose party number
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param rose_number ROSE party number structure
+ * \param q931_number Q.931 party number structure
+ *
+ * \return Nothing
+ */
+static void q931_copy_number_to_rose(struct pri *ctrl,
+	struct rosePartyNumber *rose_number, const struct q931_party_number *q931_number)
+{
+	rose_number->plan = numbering_plan_from_q931(ctrl, q931_number->plan);
+	rose_number->ton = typeofnumber_from_q931(ctrl, q931_number->plan);
+	/* Truncate the q931_number->str if necessary. */
+	libpri_copy_string((char *) rose_number->str, q931_number->str,
+		sizeof(rose_number->str));
+	rose_number->length = strlen((char *) rose_number->str);
+}
+
+/*!
+ * \internal
+ * \brief Copy the given q931_party_number to the rose presented screened party number
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param rose_presented ROSE presented screened party number structure
+ * \param q931_number Q.931 party number structure
+ *
+ * \return Nothing
+ */
+static void q931_copy_presented_number_screened_to_rose(struct pri *ctrl,
+	struct rosePresentedNumberScreened *rose_presented,
+	const struct q931_party_number *q931_number)
+{
+	if (q931_number->valid) {
+		rose_presented->presentation =
+			presentation_from_q931(ctrl, q931_number->presentation, q931_number->str[0]);
+		rose_presented->screened.screening_indicator =
+			q931_number->presentation & PRI_PRES_NUMBER_TYPE;
+		q931_copy_number_to_rose(ctrl, &rose_presented->screened.number, q931_number);
+	} else {
+		rose_presented->presentation = 2;/* numberNotAvailableDueToInterworking */
+	}
+}
+
+/*!
+ * \internal
+ * \brief Copy the given q931_party_number to the rose presented unscreened party number
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param rose_presented ROSE presented unscreened party number structure
+ * \param q931_number Q.931 party number structure
+ *
+ * \return Nothing
+ */
+static void q931_copy_presented_number_unscreened_to_rose(struct pri *ctrl,
+	struct rosePresentedNumberUnscreened *rose_presented,
+	const struct q931_party_number *q931_number)
+{
+	if (q931_number->valid) {
+		rose_presented->presentation =
+			presentation_from_q931(ctrl, q931_number->presentation, q931_number->str[0]);
+		q931_copy_number_to_rose(ctrl, &rose_presented->number, q931_number);
+	} else {
+		rose_presented->presentation = 2;/* numberNotAvailableDueToInterworking */
+	}
+}
+
+#if 0	/* In case it is needed in the future */
+/*!
+ * \internal
+ * \brief Copy the given q931_party_number to the rose presented screened party address
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param rose_presented ROSE presented screened party address structure
+ * \param q931_number Q.931 party number structure
+ *
+ * \return Nothing
+ */
+static void q931_copy_presented_address_screened_to_rose(struct pri *ctrl,
+	struct rosePresentedAddressScreened *rose_presented,
+	const struct q931_party_number *q931_number)
+{
+	if (q931_number->valid) {
+		rose_presented->presentation =
+			presentation_from_q931(ctrl, q931_number->presentation, q931_number->str[0]);
+		rose_presented->screened.screening_indicator =
+			q931_number->presentation & PRI_PRES_NUMBER_TYPE;
+		q931_copy_number_to_rose(ctrl, &rose_presented->screened.number, q931_number);
+		rose_presented->screened.subaddress.length = 0;
+	} else {
+		rose_presented->presentation = 2;/* numberNotAvailableDueToInterworking */
+	}
+}
+#endif	/* In case it is needed in the future */
+
+/*!
+ * \internal
+ * \brief Copy the given q931_party_name to the rose party name
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param rose_name Q.SIG ROSE party name structure
+ * \param qsig_name Q.SIG party name structure
+ *
+ * \return Nothing
+ */
+static void q931_copy_name_to_rose(struct pri *ctrl,
+	struct roseQsigName *rose_name, const struct q931_party_name *qsig_name)
+{
+	if (qsig_name->valid) {
+		rose_name->presentation = qsig_name_presentation_from_q931(ctrl,
+			qsig_name->presentation, qsig_name->str[0]);
+		rose_name->char_set = qsig_name->char_set;
+		/* Truncate the qsig_name->str if necessary. */
+		libpri_copy_string((char *) rose_name->data, qsig_name->str, sizeof(rose_name->data));
+		rose_name->length = strlen((char *) rose_name->data);
+	} else {
+		rose_name->presentation = 4;/* name_not_available */
+	}
+}
+
+/*!
+ * \internal
+ * \brief Encode the Q.SIG DivertingLegInformation1 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 call Call leg from which to encode diversion leg 2.
+ * \param call Call leg from which to encode diversion leg 1.
  *
  * \retval Start of the next ASN.1 component to encode on success.
  * \retval NULL on error.
  */
-static unsigned char *enc_qsig_diverting_leg_information2(struct pri *ctrl,
+static unsigned char *enc_qsig_diverting_leg_information1(struct pri *ctrl,
 	unsigned char *pos, unsigned char *end, q931_call *call)
 {
 	struct fac_extension_header header;
@@ -422,42 +779,19 @@
 	}
 
 	memset(&msg, 0, sizeof(msg));
-	msg.operation = ROSE_QSIG_DivertingLegInformation2;
+	msg.operation = ROSE_QSIG_DivertingLegInformation1;
 	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;
-
-	msg.args.qsig.DivertingLegInformation2.diversion_reason =
-		redirectingreason_from_q931(ctrl, call->redirectingreason);
-
-	/* divertingNr */
-	msg.args.qsig.DivertingLegInformation2.diverting_present = 1;
-	msg.args.qsig.DivertingLegInformation2.diverting.presentation =
-		presentation_from_q931(ctrl, call->redirectingpres, call->redirectingnum[0]);
-	msg.args.qsig.DivertingLegInformation2.diverting.number.plan =

[... 5455 lines stripped ...]



More information about the svn-commits mailing list