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

SVN commits to the libpri project libpri-commits at lists.digium.com
Fri Feb 4 13:59:50 CST 2011


Author: rmudgett
Date: Fri Feb  4 13:59:45 2011
New Revision: 2190

URL: http://svnview.digium.com/svn/libpri?view=rev&rev=2190
Log:
Add display ie text handling options.

The display ie handling can be controlled independently in the send and
receive directions with the following options:

* Block display text data.

* Use display text in SETUP/CONNECT messages for name.

* Use display text for COLP name updates (FACILITY/NOTIFY as appropriate).

* Pass arbitrary display text during a call.  Sent in INFORMATION
messages.  Received from any message that the display text was not used as
a name.

If the display options are not set then the options default to legacy
behavior.

Modified:
    branches/1.4/libpri.h
    branches/1.4/pri.c
    branches/1.4/pri_facility.c
    branches/1.4/pri_internal.h
    branches/1.4/q931.c

Modified: branches/1.4/libpri.h
URL: http://svnview.digium.com/svn/libpri/branches/1.4/libpri.h?view=diff&rev=2190&r1=2189&r2=2190
==============================================================================
--- branches/1.4/libpri.h (original)
+++ branches/1.4/libpri.h Fri Feb  4 13:59:45 2011
@@ -547,6 +547,7 @@
 #define PRI_SUBCMD_AOC_CHARGING_REQ_RSP		22	/*!< Advice Of Charge Request Response information */
 #define PRI_SUBCMD_MCID_REQ					23	/*!< Malicious Call ID Request */
 #define PRI_SUBCMD_MCID_RSP					24	/*!< Malicious Call ID Request response */
+#define PRI_SUBCMD_DISPLAY_TEXT				25	/*!< Received display ie text */
 
 #if defined(STATUS_REQUEST_PLACE_HOLDER)
 struct pri_subcmd_status_request {
@@ -965,6 +966,35 @@
 	 * \note Use pri_facility_reject2str() to convert the reject_code.
 	 */
 	int fail_code;
+};
+
+struct pri_subcmd_display_txt {
+	/*!
+	 * \brief Character set the text 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)
+	 */
+	int char_set;
+	/*!
+	 * \brief Number of octets in the display message.
+	 * \note Not including any added null terminator.
+	 */
+	int length;
+	/*!
+	 * \brief Display text data.
+	 * \note Null terminated on receive.
+	 * \note Does not need to be null terminated on send.
+	 */
+	char text[128];
 };
 
 struct pri_subcommand {
@@ -999,6 +1029,7 @@
 		struct pri_subcmd_aoc_e aoc_e;
 		struct pri_subcmd_mcid_req mcid_req;
 		struct pri_subcmd_mcid_rsp mcid_rsp;
+		struct pri_subcmd_display_txt display;
 	} u;
 };
 
@@ -1840,6 +1871,55 @@
  */
 void pri_aoc_events_enable(struct pri *ctrl, int enable);
 
+#define PRI_DISPLAY_OPTION_BLOCK		(1 << 0)	/*!< Do not pass display text. */
+#define PRI_DISPLAY_OPTION_NAME_INITIAL	(1 << 1)	/*!< Use display in SETUP/CONNECT for name. */
+#define PRI_DISPLAY_OPTION_NAME_UPDATE	(1 << 2)	/*!< Use display in FACILITY/NOTIFY for COLP name if appropriate. */
+#define PRI_DISPLAY_OPTION_TEXT			(1 << 3)	/*!< Pass arbitrary display text in INFORMATION messages during call. */
+
+/*!
+ * \brief Set the display ie send policy options.
+ *
+ * \param ctrl D channel controller.
+ * \param flags Option flags to apply.
+ *
+ * \note
+ * If no flags set then legacy default behaviour.
+ *
+ * \note
+ * Not all options are supported by all switches.
+ *
+ * \return Nothing
+ */
+void pri_display_options_send(struct pri *ctrl, unsigned long flags);
+
+/*!
+ * \brief Set the display ie receive policy options.
+ *
+ * \param ctrl D channel controller.
+ * \param flags Option flags to apply.
+ *
+ * \note
+ * If no flags set then legacy default behaviour.
+ *
+ * \note
+ * Not all options are supported by all switches.
+ *
+ * \return Nothing
+ */
+void pri_display_options_receive(struct pri *ctrl, unsigned long flags);
+
+/*!
+ * \brief Send display text during a call.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg
+ * \param display Display text to send.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int pri_display_text(struct pri *ctrl, q931_call *call, const struct pri_subcmd_display_txt *display);
+
 /*!
  * \brief Set the call hold feature enable flag.
  *

Modified: branches/1.4/pri.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri.c?view=diff&rev=2190&r1=2189&r2=2190
==============================================================================
--- branches/1.4/pri.c (original)
+++ branches/1.4/pri.c Fri Feb  4 13:59:45 2011
@@ -289,6 +289,60 @@
 }
 
 /*!
+ * \internal
+ * \brief Determine the default display text send options.
+ *
+ * \param ctrl D channel controller.
+ *
+ * \return Default display text send options. (legacy behaviour defaults)
+ */
+static unsigned long pri_display_options_send_default(struct pri *ctrl)
+{
+	unsigned long flags;
+
+	switch (ctrl->switchtype) {
+	case PRI_SWITCH_QSIG:
+		flags = PRI_DISPLAY_OPTION_BLOCK;
+		break;
+	case PRI_SWITCH_EUROISDN_E1:
+	case PRI_SWITCH_EUROISDN_T1:
+		if (ctrl->localtype == PRI_CPE) {
+			flags = PRI_DISPLAY_OPTION_BLOCK;
+			break;
+		}
+		flags = PRI_DISPLAY_OPTION_NAME_INITIAL;
+		break;
+	default:
+		flags = PRI_DISPLAY_OPTION_NAME_INITIAL;
+		break;
+	}
+	return flags;
+}
+
+/*!
+ * \internal
+ * \brief Determine the default display text receive options.
+ *
+ * \param ctrl D channel controller.
+ *
+ * \return Default display text receive options. (legacy behaviour defaults)
+ */
+static unsigned long pri_display_options_receive_default(struct pri *ctrl)
+{
+	unsigned long flags;
+
+	switch (ctrl->switchtype) {
+	case PRI_SWITCH_QSIG:
+		flags = PRI_DISPLAY_OPTION_BLOCK;
+		break;
+	default:
+		flags = PRI_DISPLAY_OPTION_NAME_INITIAL;
+		break;
+	}
+	return flags;
+}
+
+/*!
  * \brief Destroy the given link.
  *
  * \param link Q.921 link to destroy.
@@ -481,6 +535,8 @@
 	ctrl->q931_rxcount = 0;
 	ctrl->q931_txcount = 0;
 
+	ctrl->display_flags.send = pri_display_options_send_default(ctrl);
+	ctrl->display_flags.receive = pri_display_options_receive_default(ctrl);
 	switch (switchtype) {
 	case PRI_SWITCH_GR303_EOC:
 		ctrl->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
@@ -999,7 +1055,7 @@
 				 */
 				if (new_number) {
 					q931_notify_redirection(ctrl, call, PRI_NOTIFY_TRANSFER_ACTIVE,
-						&party_id.number);
+						&party_id.name, &party_id.number);
 				}
 				if (new_subaddress || (party_id.subaddress.valid && new_number)) {
 					q931_subaddress_transfer(ctrl, call);
@@ -1050,10 +1106,10 @@
 					 * connected yet.
 					 */
 					q931_notify_redirection(ctrl, call, PRI_NOTIFY_TRANSFER_ACTIVE,
-						&party_id.number);
+						&party_id.name, &party_id.number);
 #else
 					q931_request_subaddress(ctrl, call, PRI_NOTIFY_TRANSFER_ACTIVE,
-						&party_id.number);
+						&party_id.name, &party_id.number);
 #endif	/* defined(USE_NOTIFY_FOR_ECT) */
 				}
 				if (new_subaddress || (party_id.subaddress.valid && new_number)) {
@@ -1167,7 +1223,7 @@
 					 * themselves.  Well... If you consider someone else picking up
 					 * the handset a redirection then how is the network to know?
 					 */
-					q931_notify_redirection(ctrl, call, PRI_NOTIFY_CALL_DIVERTING,
+					q931_notify_redirection(ctrl, call, PRI_NOTIFY_CALL_DIVERTING, NULL,
 						&call->redirecting.to.number);
 				}
 				break;
@@ -2050,3 +2106,35 @@
 		ctrl->cc.option.signaling_retention_rsp = signaling_retention ? 1 : 0;
 	}
 }
+
+void pri_display_options_send(struct pri *ctrl, unsigned long flags)
+{
+	if (!ctrl) {
+		return;
+	}
+	if (!flags) {
+		flags = pri_display_options_send_default(ctrl);
+	}
+	ctrl->display_flags.send = flags;
+}
+
+void pri_display_options_receive(struct pri *ctrl, unsigned long flags)
+{
+	if (!ctrl) {
+		return;
+	}
+	if (!flags) {
+		flags = pri_display_options_receive_default(ctrl);
+	}
+	ctrl->display_flags.receive = flags;
+}
+
+int pri_display_text(struct pri *ctrl, q931_call *call, const struct pri_subcmd_display_txt *display)
+{
+	if (!ctrl || !display || display->length <= 0
+		|| sizeof(display->text) < display->length || !pri_is_call_valid(ctrl, call)) {
+		/* Parameter sanity checks failed. */
+		return -1;
+	}
+	return q931_display_text(ctrl, call, display);
+}

Modified: branches/1.4/pri_facility.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri_facility.c?view=diff&rev=2190&r1=2189&r2=2190
==============================================================================
--- branches/1.4/pri_facility.c (original)
+++ branches/1.4/pri_facility.c Fri Feb  4 13:59:45 2011
@@ -3355,8 +3355,18 @@
  */
 int send_call_transfer_complete(struct pri *ctrl, q931_call *call, int call_status)
 {
-	if (rose_call_transfer_complete_encode(ctrl, call, call_status)
-		|| q931_facility(ctrl, call)) {
+	int status;
+
+	status = rose_call_transfer_complete_encode(ctrl, call, call_status);
+	if (!status) {
+		if (!call_status && call->local_id.number.valid
+			&& (ctrl->display_flags.send & PRI_DISPLAY_OPTION_NAME_UPDATE)) {
+			status = q931_facility_display_name(ctrl, call, &call->local_id.name);
+		} else {
+			status = q931_facility(ctrl, call);
+		}
+	}
+	if (status) {
 		pri_message(ctrl,
 			"Could not schedule facility message for call transfer completed.\n");
 		return -1;
@@ -3574,6 +3584,7 @@
  */
 static void etsi_request_subaddress(struct pri *ctrl, struct q931_call *call)
 {
+	struct q931_party_name name;
 	int changed = 0;
 
 	switch (call->notify) {
@@ -3585,6 +3596,15 @@
 		}
 		/* Fall through */
 	case PRI_NOTIFY_TRANSFER_ALERTING:
+		if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+			if (q931_display_name_get(call, &name)) {
+				if (q931_party_name_cmp(&call->remote_id.name, &name)) {
+					/* The remote party name information changed. */
+					call->remote_id.name = name;
+					changed = 1;
+				}
+			}
+		}
 		if (call->redirection_number.valid
 			&& q931_party_number_cmp(&call->remote_id.number, &call->redirection_number)) {
 			/* The remote party number information changed. */
@@ -3626,6 +3646,7 @@
 static void handle_subaddress_transfer(struct pri *ctrl, struct q931_call *call, const struct rosePartySubaddress *subaddr)
 {
 	int changed = 0;
+	struct q931_party_name name;
 	struct q931_party_subaddress q931_subaddress;
 
 	q931_party_subaddress_init(&q931_subaddress);
@@ -3639,6 +3660,15 @@
 		/* The remote party number information changed. */
 		call->remote_id.number = call->redirection_number;
 		changed = 1;
+	}
+	if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+		if (q931_display_name_get(call, &name)) {
+			if (q931_party_name_cmp(&call->remote_id.name, &name)) {
+				/* The remote party name information changed. */
+				call->remote_id.name = name;
+				changed = 1;
+			}
+		}
 	}
 	if (changed) {
 		call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
@@ -4684,6 +4714,10 @@
 		send_ect_link_id_rsp(ctrl, call, invoke->invoke_id);
 		break;
 	case ROSE_ETSI_EctInform:
+		if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+			q931_display_name_get(call, &call->remote_id.name);
+		}
+
 		/* redirectionNumber is put in remote_id.number */
 		if (invoke->args.etsi.EctInform.redirection_present) {
 			rose_copy_presented_number_unscreened_to_q931(ctrl,
@@ -5002,6 +5036,10 @@
 		break;
 #endif	/* Not handled yet */
 	case ROSE_QSIG_CallingName:
+		if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+			q931_display_name_get(call, &call->remote_id.name);
+		}
+
 		/* CallingName is put in remote_id.name */
 		rose_copy_name_to_q931(ctrl, &call->remote_id.name,
 			&invoke->args.qsig.CallingName.name);
@@ -5023,6 +5061,10 @@
 		}
 		break;
 	case ROSE_QSIG_CalledName:
+		if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+			q931_display_name_get(call, &call->remote_id.name);
+		}
+
 		/* CalledName is put in remote_id.name */
 		rose_copy_name_to_q931(ctrl, &call->remote_id.name,
 			&invoke->args.qsig.CalledName.name);
@@ -5044,6 +5086,10 @@
 		}
 		break;
 	case ROSE_QSIG_ConnectedName:
+		if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+			q931_display_name_get(call, &call->remote_id.name);
+		}
+
 		/* ConnectedName is put in remote_id.name */
 		rose_copy_name_to_q931(ctrl, &call->remote_id.name,
 			&invoke->args.qsig.ConnectedName.name);
@@ -5095,6 +5141,10 @@
 		break;
 #endif	/* Not handled yet */
 	case ROSE_QSIG_CallTransferActive:
+		if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+			q931_display_name_get(call, &call->remote_id.name);
+		}
+
 		call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
 
 		/* connectedAddress is put in remote_id */
@@ -5108,6 +5158,10 @@
 		}
 		break;
 	case ROSE_QSIG_CallTransferComplete:
+		if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+			q931_display_name_get(call, &call->remote_id.name);
+		}
+
 		/* redirectionNumber is put in remote_id.number */
 		rose_copy_presented_number_screened_to_q931(ctrl, &call->remote_id.number,
 			&invoke->args.qsig.CallTransferComplete.redirection);
@@ -5138,6 +5192,10 @@
 		break;
 	case ROSE_QSIG_CallTransferUpdate:
 		party_id = call->remote_id;
+
+		if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+			q931_display_name_get(call, &party_id.name);
+		}
 
 		/* redirectionNumber is put in party_id.number */
 		rose_copy_presented_number_screened_to_q931(ctrl, &party_id.number,

Modified: branches/1.4/pri_internal.h
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri_internal.h?view=diff&rev=2190&r1=2189&r2=2190
==============================================================================
--- branches/1.4/pri_internal.h (original)
+++ branches/1.4/pri_internal.h Fri Feb  4 13:59:45 2011
@@ -59,6 +59,9 @@
 
 /*! Maximum number of facility ie's to handle per incoming message. */
 #define MAX_FACILITY_IES	8
+
+/*! Maximum length of sent display text string.  (No null terminator.) */
+#define MAX_DISPLAY_TEXT	80
 
 /*! Accumulated pri_message() line until a '\n' is seen on the end. */
 struct pri_msg_line {
@@ -177,6 +180,13 @@
 		/*! Number of facility ie's in the array from the current received message. */
 		unsigned char count;
 	} facility;
+	/*! Display text policy handling options. */
+	struct {
+		/*! Send display text policy option flags. */
+		unsigned long send;
+		/*! Receive display text policy option flags. */
+		unsigned long receive;
+	} display_flags;
 };
 
 /*! \brief Maximum name length plus null terminator (From ECMA-164) */
@@ -602,6 +612,29 @@
 		/*! TRUE if outgoing call was already redirected. */
 		unsigned char initially_redirected;
 	} cc;
+
+	/*! Display text ie contents. */
+	struct {
+		/*! Display ie text.  NULL if not present or consumed as remote name. */
+		const char *text;
+		/*! Length of display text. */
+		unsigned char length;
+		/*!
+		 * \brief Character set the text 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)
+		 */
+		unsigned char char_set;
+	} display;
 
 	/* AOC charge requesting on Setup */
 	int aoc_charging_request;
@@ -938,6 +971,11 @@
 void q931_party_id_fixup(const struct pri *ctrl, struct q931_party_id *id);
 int q931_party_id_presentation(const struct q931_party_id *id);
 
+int q931_display_name_get(struct q931_call *call, struct q931_party_name *name);
+int q931_display_text(struct pri *ctrl, struct q931_call *call, const struct pri_subcmd_display_txt *display);
+
+int q931_facility_display_name(struct pri *ctrl, struct q931_call *call, const struct q931_party_name *name);
+
 const char *q931_call_state_str(enum Q931_CALL_STATE callstate);
 const char *msg2str(int msg);
 
@@ -948,9 +986,9 @@
 struct q931_call *q931_find_link_id_call(struct pri *ctrl, int link_id);
 struct q931_call *q931_find_held_active_call(struct pri *ctrl, struct q931_call *held_call);
 
-int q931_request_subaddress(struct pri *ctrl, struct q931_call *call, int notify, const struct q931_party_number *number);
+int q931_request_subaddress(struct pri *ctrl, struct q931_call *call, int notify, const struct q931_party_name *name, const struct q931_party_number *number);
 int q931_subaddress_transfer(struct pri *ctrl, struct q931_call *call);
-int q931_notify_redirection(struct pri *ctrl, q931_call *call, int notify, const struct q931_party_number *number);
+int q931_notify_redirection(struct pri *ctrl, struct q931_call *call, int notify, const struct q931_party_name *name, const struct q931_party_number *number);
 
 struct pri_cc_record *pri_cc_find_by_reference(struct pri *ctrl, unsigned reference_id);
 struct pri_cc_record *pri_cc_find_by_linkage(struct pri *ctrl, unsigned linkage_id);

Modified: branches/1.4/q931.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/q931.c?view=diff&rev=2190&r1=2189&r2=2190
==============================================================================
--- branches/1.4/q931.c (original)
+++ branches/1.4/q931.c Fri Feb  4 13:59:45 2011
@@ -937,6 +937,125 @@
 }
 
 /*!
+ * \internal
+ * \brief Clear the display text.
+ *
+ * \param call Q.931 call to clear display text.
+ *
+ * \return Nothing
+ */
+static void q931_display_clear(struct q931_call *call)
+{
+	call->display.text = NULL;
+}
+
+/*!
+ * \internal
+ * \brief Set the display text for the party name.
+ *
+ * \param call Q.931 call to set display text to the party name.
+ *
+ * \return Nothing
+ */
+static void q931_display_name_send(struct q931_call *call, const struct q931_party_name *name)
+{
+	if (name->valid) {
+		switch (name->presentation & PRI_PRES_RESTRICTION) {
+		case PRI_PRES_ALLOWED:
+			call->display.text = (char *) name->str;
+			call->display.length = strlen(name->str);
+			call->display.char_set = name->char_set;
+			break;
+		default:
+			call->display.text = NULL;
+			break;
+		}
+	} else {
+		call->display.text = NULL;
+	}
+}
+
+/*!
+ * \brief Get the display text into the party name.
+ *
+ * \param call Q.931 call to get the display text into the party name.
+ * \param name Party name to fill if there is display text.
+ *
+ * \note
+ * The party name is not touched if there is no display text.
+ *
+ * \note
+ * The display text is consumed.
+ *
+ * \return TRUE if party name filled.
+ */
+int q931_display_name_get(struct q931_call *call, struct q931_party_name *name)
+{
+	if (!call->display.text) {
+		return 0;
+	}
+
+	name->valid = 1;
+	name->char_set = call->display.char_set;
+	if (call->display.length < sizeof(name->str)) {
+		memcpy(name->str, call->display.text, call->display.length);
+		name->str[call->display.length] = '\0';
+	} else {
+		name->str[0] = '\0';
+	}
+	if (name->str[0]) {
+		name->presentation = PRI_PRES_ALLOWED;
+	} else {
+		name->presentation = PRI_PRES_RESTRICTED;
+	}
+
+	/* Mark the display text as consumed. */
+	call->display.text = NULL;
+
+	return 1;
+}
+
+/*!
+ * \internal
+ * \brief Fill a subcmd with any display text.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg.
+ *
+ * \note
+ * The display text is consumed.
+ *
+ * \return Nothing
+ */
+static void q931_display_subcmd(struct pri *ctrl, struct q931_call *call)
+{
+	struct pri_subcommand *subcmd;
+
+	if (call->display.text && call->display.length
+		&& (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_TEXT)) {
+		subcmd = q931_alloc_subcommand(ctrl);
+		if (subcmd) {
+			/* Setup display text subcommand */
+			subcmd->cmd = PRI_SUBCMD_DISPLAY_TEXT;
+			subcmd->u.display.char_set = call->display.char_set;
+			if (call->display.length < sizeof(subcmd->u.display.text)) {
+				subcmd->u.display.length = call->display.length;
+			} else {
+				/* Truncate display text and leave room for a null terminator. */
+				subcmd->u.display.length = sizeof(subcmd->u.display.text) - 1;
+			}
+			memcpy(subcmd->u.display.text, call->display.text, subcmd->u.display.length);
+
+			/* Make sure display text is null terminated. */
+			subcmd->u.display.text[subcmd->u.display.length] = '\0';
+		}
+	}
+
+	/* Mark the display text as consumed. */
+	call->display.text = NULL;
+}
+
+/*!
  * \brief Find the winning subcall if it exists or current call if not outboundbroadcast.
  *
  * \param call Starting Q.931 call record of search.
@@ -2435,21 +2554,11 @@
 
 static int receive_display(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
 {
-	unsigned char *data;
-
-	switch (msgtype) {
-	case Q931_SETUP:
-	case Q931_CONNECT:
-		/*
-		 * Only keep the display message on SETUP and CONNECT messages
-		 * as the remote name.
-		 */
-		break;
-	default:
+	u_int8_t *data;
+
+	if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_BLOCK) {
 		return 0;
 	}
-
-	call->remote_id.name.valid = 1;
 
 	data = ie->data;
 	if (data[0] & 0x80) {
@@ -2457,14 +2566,10 @@
 		data++;
 		len--;
 	}
-	call->remote_id.name.char_set = PRI_CHAR_SET_ISO8859_1;
-
-	q931_get_number((unsigned char *) call->remote_id.name.str, sizeof(call->remote_id.name.str), data, len - 2);
-	if (call->remote_id.name.str[0]) {
-		call->remote_id.name.presentation = PRI_PRES_ALLOWED;
-	} else {
-		call->remote_id.name.presentation = PRI_PRES_RESTRICTED;
-	}
+
+	call->display.text = (char *) data;
+	call->display.length = len - 2;
+	call->display.char_set = PRI_CHAR_SET_ISO8859_1;
 	return 0;
 }
 
@@ -2473,30 +2578,31 @@
 	size_t datalen;
 	int i;
 
+	if (!call->display.text || !call->display.length) {
+		return 0;
+	}
+	if (ctrl->display_flags.send & PRI_DISPLAY_OPTION_BLOCK) {
+		return 0;
+	}
+
 	i = 0;
-
-	if (!call->local_id.name.valid || !call->local_id.name.str[0]) {
-		return 0;
-	}
 	switch (ctrl->switchtype) {
 	case PRI_SWITCH_QSIG:
-		/* Q.SIG supports names */
-		return 0;
 	case PRI_SWITCH_EUROISDN_E1:
 	case PRI_SWITCH_EUROISDN_T1:
-		if (ctrl->localtype == PRI_CPE) {
-			return 0;
-		}
 		break;
 	default:
-		/* Prefix name with character set indicator. */
+		/* Prefix text with character set indicator. */
 		ie->data[0] = 0xb1;
 		++i;
 		break;
 	}
 
-	datalen = strlen(call->local_id.name.str);
-	memcpy(ie->data + i, call->local_id.name.str, datalen);
+	datalen = call->display.length;
+	if (MAX_DISPLAY_TEXT < datalen + i) {
+		datalen = MAX_DISPLAY_TEXT - i;
+	}
+	memcpy(ie->data + i, call->display.text, datalen);
 	return 2 + i + datalen;
 }
 
@@ -4742,20 +4848,27 @@
 	return send_message(ctrl, c, (pd << 8) | mt, maintenance_service_ies);
 }
 
-static int status_ies[] = { Q931_CAUSE, Q931_IE_CALL_STATE, -1 };
-
 static int q931_status(struct pri *ctrl, q931_call *call, int cause)
 {
+	static int status_ies[] = {
+		Q931_CAUSE,
+		Q931_IE_CALL_STATE,
+		-1
+	};
+
 	call->cause = cause;
 	call->causecode = CODE_CCITT;
 	call->causeloc = LOC_USER;
 	return send_message(ctrl, call, Q931_STATUS, status_ies);
 }
 
-static int information_ies[] = { Q931_CALLED_PARTY_NUMBER, -1 };
-
 int q931_information(struct pri *ctrl, q931_call *c, char digit)
 {
+	static int information_ies[] = {
+		Q931_CALLED_PARTY_NUMBER,
+		-1
+	};
+
 	c->overlap_digits[0] = digit;
 	c->overlap_digits[1] = '\0';
 
@@ -4772,6 +4885,84 @@
 	return send_message(ctrl, c, Q931_INFORMATION, information_ies);
 }
 
+/*!
+ * \internal
+ * \brief Actually send display text if in the right call state.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg
+ * \param display Display text to send.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int q931_display_text_helper(struct pri *ctrl, struct q931_call *call, const struct pri_subcmd_display_txt *display)
+{
+	int status;
+	static int information_display_ies[] = {
+		Q931_DISPLAY,
+		-1
+	};
+
+	switch (call->ourcallstate) {
+	case Q931_CALL_STATE_OVERLAP_SENDING:
+	case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
+	case Q931_CALL_STATE_CALL_DELIVERED:
+	case Q931_CALL_STATE_CALL_RECEIVED:
+	case Q931_CALL_STATE_CONNECT_REQUEST:
+	case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
+	case Q931_CALL_STATE_ACTIVE:
+	case Q931_CALL_STATE_OVERLAP_RECEIVING:
+		call->display.text = display->text;
+		call->display.length = display->length;
+		call->display.char_set = display->char_set;
+		status = send_message(ctrl, call, Q931_INFORMATION, information_display_ies);
+		q931_display_clear(call);
+		break;
+	default:
+		status = 0;
+		break;
+	}
+
+	return status;
+}
+
+/*!
+ * \brief Send display text during a call.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg
+ * \param display Display text to send.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int q931_display_text(struct pri *ctrl, struct q931_call *call, const struct pri_subcmd_display_txt *display)
+{
+	int status;
+	unsigned idx;
+	struct q931_call *subcall;
+
+	if ((ctrl->display_flags.send & (PRI_DISPLAY_OPTION_BLOCK | PRI_DISPLAY_OPTION_TEXT))
+		!= PRI_DISPLAY_OPTION_TEXT) {
+		/* Not enabled */
+		return 0;
+	}
+	if (call->outboundbroadcast && call->master_call == call) {
+		status = 0;
+		for (idx = 0; idx < ARRAY_LEN(call->subcalls); ++idx) {
+			subcall = call->subcalls[idx];
+			if (subcall && q931_display_text_helper(ctrl, subcall, display)) {
+				status = -1;
+			}
+		}
+	} else {
+		status = q931_display_text_helper(ctrl, call, display);
+	}
+	return status;
+}
+
+
 static int keypad_facility_ies[] = { Q931_IE_KEYPAD_FACILITY, -1 };
 
 int q931_keypad_facility(struct pri *ctrl, q931_call *call, const char *digits)
@@ -4789,41 +4980,66 @@
 	return send_message(ctrl, c, Q931_RESTART_ACKNOWLEDGE, restart_ack_ies);
 }
 
-static int facility_ies[] = { Q931_IE_FACILITY, -1 };
-
-int q931_facility(struct pri*ctrl, q931_call *c)
-{
-	return send_message(ctrl, c, Q931_FACILITY, facility_ies);
-}
-
-static int facility_notify_ies[] = {
-	Q931_IE_FACILITY,
-	Q931_IE_NOTIFY_IND,
-	Q931_IE_REDIRECTION_NUMBER,
-	-1
-};
+int q931_facility(struct pri *ctrl, struct q931_call *call)
+{
+	static int facility_ies[] = {
+		Q931_IE_FACILITY,
+		-1
+	};
+
+	return send_message(ctrl, call, Q931_FACILITY, facility_ies);
+}
+
+int q931_facility_display_name(struct pri *ctrl, struct q931_call *call, const struct q931_party_name *name)
+{
+	int status;
+	static int facility_display_ies[] = {
+		Q931_IE_FACILITY,
+		Q931_DISPLAY,
+		-1
+	};
+
+	q931_display_name_send(call, name);
+	status = send_message(ctrl, call, Q931_FACILITY, facility_display_ies);
+	q931_display_clear(call);
+	return status;
+}
 
 /*!
- * \brief Send a FACILITY RequestSubaddress with optional redirection number.
+ * \brief Send a FACILITY RequestSubaddress with optional redirection name and number.
  *
  * \param ctrl D channel controller.
  * \param call Q.931 call leg
  * \param notify Notification indicator
+ * \param name Redirection name to send if not NULL.
  * \param number Redirection number to send if not NULL.
  *
  * \retval 0 on success.
  * \retval -1 on error.
  */
-int q931_request_subaddress(struct pri *ctrl, struct q931_call *call, int notify, const struct q931_party_number *number)
-{
+int q931_request_subaddress(struct pri *ctrl, struct q931_call *call, int notify, const struct q931_party_name *name, const struct q931_party_number *number)
+{
+	int status;
 	struct q931_call *winner;
+	static int facility_notify_ies[] = {
+		Q931_IE_FACILITY,
+		Q931_IE_NOTIFY_IND,
+		Q931_DISPLAY,
+		Q931_IE_REDIRECTION_NUMBER,
+		-1
+	};
 
 	winner = q931_find_winning_call(call);
 	if (!winner) {
 		return -1;
 	}
+	q931_display_clear(winner);
 	if (number) {
 		winner->redirection_number = *number;
+		if (number->valid && name
+			&& (ctrl->display_flags.send & PRI_DISPLAY_OPTION_NAME_UPDATE)) {
+			q931_display_name_send(winner, name);
+		}
 	} else {
 		q931_party_number_init(&winner->redirection_number);
 	}
@@ -4832,10 +5048,13 @@
 		|| send_message(ctrl, winner, Q931_FACILITY, facility_notify_ies)) {
 		pri_message(ctrl,
 			"Could not schedule facility message for request subaddress.\n");
-		return -1;
-	}
-
-	return 0;
+		status = -1;
+	} else {
+		status = 0;
+	}
+	q931_display_clear(winner);
+
+	return status;
 }
 
 /*!
@@ -4878,43 +5097,58 @@
 	return status;
 }
 
-static int notify_ies[] = { Q931_IE_NOTIFY_IND, Q931_IE_REDIRECTION_NUMBER, -1 };
-
 /*!
  * \internal
- * \brief Actually send a NOTIFY message with optional redirection number.
+ * \brief Actually send a NOTIFY message with optional redirection name and number.
  *
  * \param ctrl D channel controller.
  * \param call Q.931 call leg
  * \param notify Notification indicator
+ * \param name Redirection display name to send if not NULL.
  * \param number Redirection number to send if not NULL.
  *
  * \retval 0 on success.
  * \retval -1 on error.
  */
-static int q931_notify_redirection_helper(struct pri *ctrl, q931_call *call, int notify, const struct q931_party_number *number)
-{
+static int q931_notify_redirection_helper(struct pri *ctrl, struct q931_call *call, int notify, const struct q931_party_name *name, const struct q931_party_number *number)
+{
+	int status;
+	static int notify_ies[] = {
+		Q931_IE_NOTIFY_IND,
+		Q931_DISPLAY,
+		Q931_IE_REDIRECTION_NUMBER,
+		-1
+	};
+
+	q931_display_clear(call);
 	if (number) {
 		call->redirection_number = *number;
+		if (number->valid && name
+			&& (ctrl->display_flags.send & PRI_DISPLAY_OPTION_NAME_UPDATE)) {
+			q931_display_name_send(call, name);
+		}
 	} else {
 		q931_party_number_init(&call->redirection_number);
 	}
 	call->notify = notify;
-	return send_message(ctrl, call, Q931_NOTIFY, notify_ies);
+	status = send_message(ctrl, call, Q931_NOTIFY, notify_ies);
+	q931_display_clear(call);
+	return status;
 }
 
 /*!
- * \brief Send a NOTIFY message with optional redirection number.
+ * \brief Send a NOTIFY message with optional redirection name and number.
  *
  * \param ctrl D channel controller.
  * \param call Q.931 call leg
  * \param notify Notification indicator
+ * \param name Redirection display name to send if not NULL.
  * \param number Redirection number to send if not NULL.
  *
  * \retval 0 on success.
  * \retval -1 on error.
  */
-int q931_notify_redirection(struct pri *ctrl, q931_call *call, int notify, const struct q931_party_number *number)
+int q931_notify_redirection(struct pri *ctrl, struct q931_call *call, int notify, const struct q931_party_name *name, const struct q931_party_number *number)
 {
 	int status;
 	unsigned idx;
@@ -4930,7 +5164,7 @@
 				case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
 				case Q931_CALL_STATE_CALL_DELIVERED:
 				case Q931_CALL_STATE_ACTIVE:
-					if (q931_notify_redirection_helper(ctrl, subcall, notify, number)) {
+					if (q931_notify_redirection_helper(ctrl, subcall, notify, name, number)) {
 						status = -1;
 					}
 					break;
@@ -4940,7 +5174,7 @@
 			}
 		}
 	} else {
-		status = q931_notify_redirection_helper(ctrl, call, notify, number);
+		status = q931_notify_redirection_helper(ctrl, call, notify, name, number);
 	}
 	return status;
 }
@@ -4964,7 +5198,7 @@
 		/* Cannot send NOTIFY message if the mandatory ie is not going to be present. */
 		return -1;
 	}
-	return q931_notify_redirection(ctrl, c, info, NULL);
+	return q931_notify_redirection(ctrl, c, info, NULL, NULL);
 }
 
 #ifdef ALERTING_NO_PROGRESS
@@ -5278,6 +5512,11 @@
 	default:
 		break;
 	}
+	if (ctrl->display_flags.send & PRI_DISPLAY_OPTION_NAME_INITIAL) {
+		q931_display_name_send(c, &c->local_id.name);
+	} else {
+		q931_display_clear(c);
+	}
 	if (ctrl->localtype == PRI_NETWORK) {
 	    /* networks may send date/time */
 	    return send_message(ctrl, c, Q931_CONNECT, connect_net_ies);
@@ -5473,6 +5712,11 @@
 		 * retransmits will lose the facility ies.
 		 */
 		pri_call_add_standard_apdus(ctrl, c);
+		if (ctrl->display_flags.send & PRI_DISPLAY_OPTION_NAME_INITIAL) {
+			q931_display_name_send(c, &c->local_id.name);
+		} else {
+			q931_display_clear(c);
+		}
 		c->cc.saved_ie_contents.length = 0;
 		c->cc.saved_ie_flags = 0;
 		if (ctrl->link.next && !ctrl->bri)
@@ -5567,6 +5811,11 @@
 	c->aoc_charging_request = req->aoc_charging_request;
 
 	pri_call_add_standard_apdus(ctrl, c);
+	if (ctrl->display_flags.send & PRI_DISPLAY_OPTION_NAME_INITIAL) {
+		q931_display_name_send(c, &c->local_id.name);
+	} else {
+		q931_display_clear(c);
+	}
 
 	/* Save the initial cc-parties. */
 	c->cc.party_a = c->local_id;
@@ -6808,7 +7057,8 @@
 		break;
 	}
 	q931_clr_subcommands(ctrl);
-	
+	q931_display_clear(c);
+
 	/* Handle IEs */
 	memset(mandies, 0, sizeof(mandies));
 	for (x = 0; x < ARRAY_LEN(msgs); ++x)  {
@@ -6830,6 +7080,7 @@
 				/* Allow the message anyway.  We have already processed an ie. */
 				break;
 			}
+			q931_display_clear(c);
 			return -1;
 		}
 		for (y = 0; y < ARRAY_LEN(mandies); ++y) {
@@ -6907,6 +7158,17 @@
 	}
 
 	if (!missingmand) {
+		switch (mh->msg) {
+		case Q931_SETUP:
+		case Q931_CONNECT:
+			if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_INITIAL) {
+				q931_display_name_get(c, &c->remote_id.name);
+			}
+			break;
+		default:
+			break;
+		}
+
 		/* Now handle the facility ie's after all the other ie's were processed. */
 		q931_handle_facilities(ctrl, c, mh->msg);
 	}
@@ -6939,6 +7201,8 @@
 		}
 		break;
 	}
+	q931_display_subcmd(ctrl, c);
+	q931_display_clear(c);
 	return res;
 }
 
@@ -7888,6 +8152,7 @@
 		default:
 			break;
 		}
+		q931_display_subcmd(ctrl, c);
 		if (ctrl->subcmds.counter_subcmd) {
 			q931_fill_facility_event(ctrl, c);
 			return Q931_RES_HAVEEVENT;
@@ -8294,6 +8559,7 @@
 				}
 			}
 
+			q931_display_subcmd(ctrl, c);
 			if (ctrl->subcmds.counter_subcmd) {
 				q931_fill_facility_event(ctrl, c);
 				res = Q931_RES_HAVEEVENT;
@@ -8307,6 +8573,17 @@
 			}
 			/* Fall through */
 		case PRI_NOTIFY_TRANSFER_ALERTING:
+			if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+				struct q931_party_name name;
+
+				if (q931_display_name_get(c, &name)) {
+					if (q931_party_name_cmp(&c->remote_id.name, &name)) {
+						/* The remote party name information changed. */
+						c->remote_id.name = name;
+						changed = 1;
+					}
+				}
+			}
 			if (c->redirection_number.valid
 				&& q931_party_number_cmp(&c->remote_id.number, &c->redirection_number)) {
 				/* The remote party number information changed. */
@@ -8331,6 +8608,7 @@
 				}
 			}
 
+			q931_display_subcmd(ctrl, c);
 			if (ctrl->subcmds.counter_subcmd) {
 				q931_fill_facility_event(ctrl, c);
 				res = Q931_RES_HAVEEVENT;




More information about the libpri-commits mailing list