[libpri-commits] mattf: branch mattf/libpri-1.4-q921-rewrite r1292 - /team/mattf/libpri-1.4-q9...

SVN commits to the libpri project libpri-commits at lists.digium.com
Tue Nov 10 18:23:12 CST 2009


Author: mattf
Date: Tue Nov 10 18:23:09 2009
New Revision: 1292

URL: http://svnview.digium.com/svn/libpri?view=rev&rev=1292
Log:
Merged revisions 1151-1152,1169,1177,1191,1205,1212,1219-1220,1230,1242,1249,1255,1261,1268,1275-1276,1283 via svnmerge from 
https://origsvn.digium.com/svn/libpri/branches/1.4

........
r1151 | rmudgett | 2009-10-07 13:33:09 -0500 (Wed, 07 Oct 2009) | 13 lines

Merged revisions 1143, 1144 from
https://origsvn.digium.com/svn/libpri/tags/1.4.10.2

  ..........
  r1144 | mattf | 2009-09-29 10:32:23 -0500 (Tue, 29 Sep 2009) | 1 line

  This fix is more like the fix that was used to resolve the issue for the PRI case
  ..........
  r1143 | mattf | 2009-09-28 14:07:01 -0500 (Mon, 28 Sep 2009) | 1 line

  Changes for 1.4.10.2
  ..........

........
r1152 | rmudgett | 2009-10-07 13:34:06 -0500 (Wed, 07 Oct 2009) | 19 lines

Sent Q.SIG call rerouting message fixes.

a) Account for pSS1InfoElement where the bearer capability for the new
rerouted call is described.  The call could be a fax or data call, let's
use the appropriate signaling to avoid call rejects on the other end.
b) Handle calling number appropriately, number can be prohibited or
non-existent.
c) Add calling name if available.
d) Use the diversion counter from DivLegInfo2 (if was present in the
incoming Setup) and increment.

(issue #14292)
Reported by: tomaso
Patches:
      libpri-1.4-2009-01-29-rerouting-0.1.9.patch uploaded by tomaso (license 564)
      (Used as a guide since it no longer will apply.)
      (This patch is unrelated to the issue.)


........
r1169 | rmudgett | 2009-10-09 18:20:37 -0500 (Fri, 09 Oct 2009) | 7 lines

Conditional out noisy and redundant ASN.1 parse dump of facility ie contents.

1) Outgoing messages have the facility ie ASN.1 decoded and dumped when the
ie is added to the message.  The whole message is then dumped.
2) Incoming messages have the facility ie ASN.1 decoded and dumped when the
ie is processed.  The whole message has already been dumped.

........
r1177 | rmudgett | 2009-10-12 12:17:48 -0500 (Mon, 12 Oct 2009) | 8 lines

Miscellaneous changes:

*  Removed unnecessary Q931_IE_CONNECTED_NUM ie from setup_ack_ies[].
*  Added internal state Q931_CALL_STATE_NOT_SET to Q.931 state enum.
*  Made q931_is_ptmp() take a const pointer.
*  pri_facility.c: Some preparations for subaddressing.
*  pri.c: Eliminate use of a magic number.

........
r1191 | rmudgett | 2009-10-13 14:06:26 -0500 (Tue, 13 Oct 2009) | 1 line

Reduce future conflicts when adding ie's to the SETUP message.
........
r1205 | rmudgett | 2009-10-14 14:03:49 -0500 (Wed, 14 Oct 2009) | 1 line

In q931_getcall(): Simplify test and add related switch types.
........
r1212 | rmudgett | 2009-10-15 17:34:52 -0500 (Thu, 15 Oct 2009) | 12 lines

Take diverted-to-number from DivLegInfo1 and use it as connected number.

If no connected number is signaled in the CONNECT message we will use the
last diverted to number.

(issue #14292)
Reported by: tomaso
Patches:
      divleginfo1_to_connectednum.patch uploaded by tomaso (license 564)
      (Used as a guide since it no longer will apply.)
      (This patch is unrelated to the issue.)

........
r1219 | rmudgett | 2009-10-19 17:38:32 -0500 (Mon, 19 Oct 2009) | 1 line

Fix comparision of invalid party name and number structs in comparison functions.
........
r1220 | rmudgett | 2009-10-19 17:49:59 -0500 (Mon, 19 Oct 2009) | 6 lines

Fix call state ie transmission.

Sending a STATUS message failed to include the call state ie for some
reason.  We will now always send a call state ie when a message ie list
includes one.

........
r1230 | rmudgett | 2009-10-22 11:16:50 -0500 (Thu, 22 Oct 2009) | 15 lines

Add support for calling and called subaddress.  Partial support for COLP subaddress.

The Telecom Specs in NZ suggests that SUB ADDRESS is always on, so doing
"desk to desk" between offices each with an asterisk box over the ISDN
should then be possible, without a whole load of DDI numbers required.

(closes issue #15604)
Reported by: alecdavis
Patches:
      libpri_subaddr_trunk.diff11.txt uploaded by alecdavis (license 585)
      Some minor modificatons were made.
Tested by: alecdavis, rmudgett

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

........
r1242 | rmudgett | 2009-10-23 14:50:45 -0500 (Fri, 23 Oct 2009) | 16 lines

Add BRI PTMP NT mode, HOLD/RETRIEVE, Call rerouting/deflection, and keypad facility support.

* Added support for BRI PTMP NT mode.  (Overlap dialing NT -> TE not supported.)
* Added handling of received HOLD/RETRIEVE messages and the optional ability
  to transfer a held call on disconnect similar to an analog phone.
* Added CallRerouting/CallDeflection support for Q.SIG, ETSI PTP, ETSI PTMP.
  Will reroute/deflect an outgoing call when receive the message.
  Can use the DAHDISendCallreroutingFacility to send the message for the
  supported switches.
* Added ability to send/receive keypad digits in the SETUP message.
  Send keypad digits in SETUP message: Dial(DAHDI/g1[/K<keypad_digits>][/extension])
  Access any received keypad digits in SETUP message by: ${CHANNEL(keypad_digits)}

(closes issue #15048)
Tested by: rmudgett, mattf

........
r1249 | rmudgett | 2009-10-23 18:47:58 -0500 (Fri, 23 Oct 2009) | 5 lines

Add subaddress handling to existing messages and functions.

Connected line updates when transfering calls does not completely support
subaddresses yet.

........
r1255 | rmudgett | 2009-11-02 17:28:59 -0600 (Mon, 02 Nov 2009) | 7 lines

NT PTMP did not report busy when calling a busy phone.

The caller would not get a busy indication when calling a busy phone.
Timer T303 is not supposed to be stopped when RELEASE_COMPLETE received.
When T303 expires we will now report the last clearing cause code to the
caller if we received one.

........
r1261 | rmudgett | 2009-11-03 11:19:20 -0600 (Tue, 03 Nov 2009) | 11 lines

Unknown IE 50 (cs5, Unknown Information Element)

Add code to recognize the code set 5 ie 50 (calling party category) to
suppress the unknown IE message.

(closes issue #13828)
Reported by: fdecher
Patches:
      libpri_ie50_cs5-trunk.diff3.txt uploaded by alecdavis (license 585)
Tested by: alecdavis

........
r1268 | rmudgett | 2009-11-09 14:53:10 -0600 (Mon, 09 Nov 2009) | 1 line

Remove unused callingsubaddr[].
........
r1275 | rmudgett | 2009-11-10 13:27:34 -0600 (Tue, 10 Nov 2009) | 7 lines

Add dummy call reference support.

Fixes problem where PTMP NT mode responds erroneously to a FACILITY
message from a phone on the dummy call reference.  LibPRI behaved as if
the dummy call reference were an invalid call reference and proceeded to
respond on the global call reference.

........
r1276 | mattf | 2009-11-10 14:25:02 -0600 (Tue, 10 Nov 2009) | 1 line

Re-add back in support for TE initiated layer 2 activation
........
r1283 | rmudgett | 2009-11-10 15:51:26 -0600 (Tue, 10 Nov 2009) | 11 lines

The facility ie queue needs to remove facilities that have been sent.

The facility ie queue needs to remove facilities that have been sent.
Otherwise, the queue just grows until the call is terminated.  AOC
messages can clog the queue during a long call and the dummy call
reference may never be deleted.

Also removed unneeded elements of struct apdu_event.  The callback
function was not a good idea since many facility messages do not have
responses and the callback would prevents removal of events from the list.

........

Modified:
    team/mattf/libpri-1.4-q921-rewrite/   (props changed)
    team/mattf/libpri-1.4-q921-rewrite/libpri.h
    team/mattf/libpri-1.4-q921-rewrite/pri.c
    team/mattf/libpri-1.4-q921-rewrite/pri_facility.c
    team/mattf/libpri-1.4-q921-rewrite/pri_facility.h
    team/mattf/libpri-1.4-q921-rewrite/pri_internal.h
    team/mattf/libpri-1.4-q921-rewrite/pri_q921.h
    team/mattf/libpri-1.4-q921-rewrite/pri_q931.h
    team/mattf/libpri-1.4-q921-rewrite/q921.c
    team/mattf/libpri-1.4-q921-rewrite/q931.c

Propchange: team/mattf/libpri-1.4-q921-rewrite/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Tue Nov 10 18:23:09 2009
@@ -1,1 +1,1 @@
-/branches/1.4:1-1127
+/branches/1.4:1-1290

Modified: team/mattf/libpri-1.4-q921-rewrite/libpri.h
URL: http://svnview.digium.com/svn/libpri/team/mattf/libpri-1.4-q921-rewrite/libpri.h?view=diff&rev=1292&r1=1291&r2=1292
==============================================================================
--- team/mattf/libpri-1.4-q921-rewrite/libpri.h (original)
+++ team/mattf/libpri-1.4-q921-rewrite/libpri.h Tue Nov 10 18:23:09 2009
@@ -91,6 +91,12 @@
 #define PRI_EVENT_KEYPAD_DIGIT	18	/* When we receive during ACTIVE state (INFORMATION) */
 #define PRI_EVENT_SERVICE       19	/* SERVICE maintenance message */
 #define PRI_EVENT_SERVICE_ACK   20	/* SERVICE maintenance acknowledgement message */
+#define PRI_EVENT_HOLD			21	/* HOLD request received */
+#define PRI_EVENT_HOLD_ACK		22	/* HOLD_ACKNOWLEDGE received */
+#define PRI_EVENT_HOLD_REJ		23	/* HOLD_REJECT received */
+#define PRI_EVENT_RETRIEVE		24	/* RETRIEVE request received */
+#define PRI_EVENT_RETRIEVE_ACK	25	/* RETRIEVE_ACKNOWLEDGE received */
+#define PRI_EVENT_RETRIEVE_REJ	26	/* RETRIEVE_REJECT received */
 
 /* Simple states */
 #define PRI_STATE_DOWN		0
@@ -200,6 +206,7 @@
 #define PRI_CAUSE_NO_ANSWER						19
 #define PRI_CAUSE_CALL_REJECTED					21
 #define PRI_CAUSE_NUMBER_CHANGED				22
+#define PRI_CAUSE_NONSELECTED_USER_CLEARING		26
 #define PRI_CAUSE_DESTINATION_OUT_OF_ORDER		27
 #define PRI_CAUSE_INVALID_NUMBER_FORMAT			28
 #define PRI_CAUSE_FACILITY_REJECTED				29	/* !Q.SIG */
@@ -212,6 +219,7 @@
 #define PRI_CAUSE_ACCESS_INFO_DISCARDED			43	/* !Q.SIG */
 #define PRI_CAUSE_REQUESTED_CHAN_UNAVAIL		44
 #define PRI_CAUSE_PRE_EMPTED					45	/* !Q.SIG */
+#define PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED	47
 #define PRI_CAUSE_FACILITY_NOT_SUBSCRIBED  		50	/* !Q.SIG */
 #define PRI_CAUSE_OUTGOING_CALL_BARRED     		52	/* !Q.SIG */
 #define PRI_CAUSE_INCOMING_CALL_BARRED     		54	/* !Q.SIG */
@@ -428,7 +436,7 @@
 	 * \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];
+	unsigned char data[32];
 };
 
 /*! \brief Information needed to identify an endpoint in a call. */
@@ -468,9 +476,37 @@
 	int reason;
 };
 
+/*!
+ * \brief Information for rerouting/deflecting the call.
+ */
+struct pri_rerouting_data {
+	/*!
+	 * \brief Updated caller-id information.
+	 * \note The information may have been altered by procedure in the private network.
+	 */
+	struct pri_party_id caller;
+	/*!
+	 * \note
+	 * deflection.to is the new called number and must always be present.
+	 */
+	struct pri_party_redirecting deflection;
+	/*!
+	 * \brief Diverting user subscription option to specify if caller is notified.
+	 * \details
+	 * noNotification(0),
+	 * notificationWithoutDivertedToNr(1),
+	 * notificationWithDivertedToNr(2),
+	 * notApplicable(3) (Status only.)
+	 */
+	int subscription_option;
+	/*! Invocation ID to use when sending a reply to the call rerouting/deflection request. */
+	int invoke_id;
+};
+
 /* Subcommands derived from supplementary services. */
 #define PRI_SUBCMD_REDIRECTING		1
 #define PRI_SUBCMD_CONNECTED_LINE	2
+#define PRI_SUBCMD_REROUTING		3
 
 
 struct pri_subcommand {
@@ -481,6 +517,7 @@
 		char reserve_space[512];
 		struct pri_party_connected_line connected_line;
 		struct pri_party_redirecting redirecting;
+		struct pri_rerouting_data rerouting;
 	} u;
 };
 
@@ -497,13 +534,14 @@
  * Event channel parameter encoding:
  * 3322 2222 2222 1111 1111 1100 0000 0000
  * 1098 7654 3210 9876 5432 1098 7654 3210
- * xxxx xxxx xxxx xxDC BBBBBBBBB AAAAAAAAA
+ * xxxx xxxx xxxx xEDC BBBBBBBBB AAAAAAAAA
  *
  * Bit field
  * A - B channel
  * B - Span (DS1) (0 - 127)
  * C - DS1 Explicit bit
  * D - D channel (cis_call) bit (status only)
+ * E - Call is held bit (status only)
  *
  * B channel values:
  * 0     - No channel (ISDN uses for call waiting feature)
@@ -567,10 +605,16 @@
 	char callingnum[256];		/*!< Deprecated, preserved for struct pri_event_facname compatibility */
 	int channel;
 	int cref;
+	/*!
+	 * \brief Master call or normal call.
+	 * \note Call pointer known about by upper layer.
+	 * \note NULL if dummy call reference.
+	 */
 	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;
+	q931_call *subcall;			/*!< Subcall to send any reply toward. */
 };
 
 #define PRI_CALLINGPLANANI
@@ -598,7 +642,7 @@
 	int layer1;					/* User layer 1 */
 	int complete;				/* Have we seen "Complete" i.e. no more number? */
 	q931_call *call;			/* Opaque call pointer */
-	char callingsubaddr[256];	/* Calling parties subaddress */
+	char callingsubaddr[256];	/* Calling parties subaddress, backwards compatibility */
 	int progress;
 	int progressmask;
 	char origcalledname[256];
@@ -607,6 +651,9 @@
 	int origredirectingreason;
 	int reversecharge;
 	struct pri_subcommands *subcmds;
+	struct pri_party_id calling;			/* Calling Party's info, initially subaddress' */
+	struct pri_party_subaddress called_subaddress;	/* Called party's subaddress */
+	char keypad_digits[64];		/* Keypad digits in the SETUP message. */
 } pri_event_ring;
 
 typedef struct pri_event_hangup {
@@ -614,10 +661,22 @@
 	int channel;				/* Channel requested */
 	int cause;
 	int cref;
-	q931_call *call;			/* Opaque call pointer */
+	q931_call *call;			/* Opaque call pointer of call hanging up. */
 	long aoc_units;				/* Advise of Charge number of charged units */
 	char useruserinfo[260];		/* User->User info */
 	struct pri_subcommands *subcmds;
+	/*!
+	 * \brief Opaque held call pointer for possible transfer to active call.
+	 * \note The call_held and call_active pointers must not be NULL if
+	 * transfer held call on disconnect is available.
+	 */
+	q931_call *call_held;
+	/*!
+	 * \brief Opaque active call pointer for possible transfer with held call.
+	 * \note The call_held and call_active pointers must not be NULL if
+	 * transfer held call on disconnect is available.
+	 */
+	q931_call *call_active;
 } pri_event_hangup;
 
 typedef struct pri_event_restart_ack {
@@ -649,6 +708,7 @@
 	int channel;
 	int info;
 	struct pri_subcommands *subcmds;
+	q931_call *call;
 } pri_event_notify;
 
 typedef struct pri_event_keypad_digit {
@@ -670,6 +730,51 @@
 	int channel;
 	int changestatus;
 } pri_event_service_ack;
+
+struct pri_event_hold {
+	int e;
+	int channel;
+	q931_call *call;
+	struct pri_subcommands *subcmds;
+};
+
+struct pri_event_hold_ack {
+	int e;
+	int channel;
+	q931_call *call;
+	struct pri_subcommands *subcmds;
+};
+
+struct pri_event_hold_rej {
+	int e;
+	int channel;
+	q931_call *call;
+	int cause;
+	struct pri_subcommands *subcmds;
+};
+
+struct pri_event_retrieve {
+	int e;
+	int channel;
+	q931_call *call;
+	int flexible;				/* Are we flexible with our channel selection? */
+	struct pri_subcommands *subcmds;
+};
+
+struct pri_event_retrieve_ack {
+	int e;
+	int channel;
+	q931_call *call;
+	struct pri_subcommands *subcmds;
+};
+
+struct pri_event_retrieve_rej {
+	int e;
+	int channel;
+	q931_call *call;
+	int cause;
+	struct pri_subcommands *subcmds;
+};
 
 typedef union {
 	int e;
@@ -689,6 +794,12 @@
 	pri_event_service service;				/* service message */
 	pri_event_service_ack service_ack;		/* service acknowledgement message */
 	struct pri_event_facility facility;
+	struct pri_event_hold hold;
+	struct pri_event_hold_ack hold_ack;
+	struct pri_event_hold_rej hold_rej;
+	struct pri_event_retrieve retrieve;
+	struct pri_event_retrieve_ack retrieve_ack;
+	struct pri_event_retrieve_rej retrieve_rej;
 } pri_event;
 
 struct pri;
@@ -818,6 +929,14 @@
 /* Create a new call */
 q931_call *pri_new_call(struct pri *pri);
 
+/*!
+ * \brief Deterimine if the given call control pointer is a dummy call.
+ *
+ * \retval TRUE if given call is a dummy call.
+ * \retval FALSE otherwise.
+ */
+int pri_is_dummy_call(q931_call *call);
+
 /* Retrieve CRV reference for GR-303 calls.  Returns >0 on success. */
 int pri_get_crv(struct pri *pri, q931_call *call, int *callmode);
 
@@ -832,8 +951,8 @@
 extern pri_event *pri_schedule_run_tv(struct pri *pri, const struct timeval *now);
 
 int pri_call(struct pri *pri, q931_call *c, int transmode, int channel,
-   int exclusive, int nonisdn, char *caller, int callerplan, char *callername, int callerpres,
-	 char *called,int calledplan, int ulayer1);
+    int exclusive, int nonisdn, char *caller, int callerplan, char *callername, int callerpres,
+    char *called, int calledplan, int ulayer1);
 
 struct pri_sr *pri_sr_new(void);
 void pri_sr_free(struct pri_sr *sr);
@@ -855,6 +974,26 @@
 int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres);
 
 /*!
+ * \brief Set the calling subaddress information in the call SETUP record.
+ *
+ * \param sr New call SETUP record.
+ * \param subaddress information to set.
+ *
+ * \return Nothing
+ */
+void pri_sr_set_caller_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress);
+
+/*!
+ * \brief Set the called subaddress information in the call SETUP record.
+ *
+ * \param sr New call SETUP record.
+ * \param subaddress information to set.
+ *
+ * \return Nothing
+ */
+void pri_sr_set_called_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress);
+
+/*!
  * \brief Set the redirecting information in the call SETUP record.
  *
  * \param sr New call SETUP record.
@@ -865,6 +1004,16 @@
 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);
+
+/*!
+ * \brief Set the keypad digits in the call SETUP record.
+ *
+ * \param sr New call SETUP record.
+ * \param keypad_digits Keypad digits to send.
+ *
+ * \return Nothing
+ */
+void pri_sr_set_keypad_digits(struct pri_sr *sr, const char *keypad_digits);
 
 #define PRI_USER_USER_TX
 /* Set the user user field.  Warning!  don't send binary data accross this field */
@@ -950,6 +1099,157 @@
 int pri_notify(struct pri *pri, q931_call *c, int channel, int info);
 
 int pri_callrerouting_facility(struct pri *pri, q931_call *call, const char *dest, const char* original, const char* reason);
+
+/*!
+ * \brief Set the call deflection/rerouting feature enable flag.
+ *
+ * \param ctrl D channel controller.
+ * \param enable TRUE to enable call deflection/rerouting feature.
+ *
+ * \return Nothing
+ */
+void pri_reroute_enable(struct pri *ctrl, int enable);
+
+/*!
+ * \brief Send the CallRerouting/CallDeflection message.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg.
+ * \param caller Call rerouting/deflecting updated caller data. (NULL if data not updated.)
+ * \param deflection Call rerouting/deflecting redirection data.
+ * \param subscription_option Diverting user subscription option to specify if caller is notified.
+ *
+ * \note
+ * deflection->to is the new called number and must always be present.
+ * \note
+ * subscription option:
+ * noNotification(0),
+ * notificationWithoutDivertedToNr(1),
+ * notificationWithDivertedToNr(2)
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int pri_reroute_call(struct pri *ctrl, q931_call *call, const struct pri_party_id *caller, const struct pri_party_redirecting *deflection, int subscription_option);
+
+enum PRI_REROUTING_RSP_CODE {
+	/*!
+	 * Rerouting invocation accepted and the network provider option
+	 * "served user call retention on invocation of diversion"
+	 * is "clear call on invocation".
+	 */
+	PRI_REROUTING_RSP_OK_CLEAR,
+	/*!
+	 * Rerouting invocation accepted and the network provider option
+	 * "served user call retention on invocation of diversion"
+	 * is "retain call until alerting begins at the deflected-to user".
+	 */
+	PRI_REROUTING_RSP_OK_RETAIN,
+	PRI_REROUTING_RSP_NOT_SUBSCRIBED,
+	PRI_REROUTING_RSP_NOT_AVAILABLE,
+	/*! Supplementary service interaction not allowed. */
+	PRI_REROUTING_RSP_NOT_ALLOWED,
+	PRI_REROUTING_RSP_INVALID_NUMBER,
+	/*! Deflection to prohibited number (e.g., operator, police, emergency). */
+	PRI_REROUTING_RSP_SPECIAL_SERVICE_NUMBER,
+	/*! Deflection to served user number. */
+	PRI_REROUTING_RSP_DIVERSION_TO_SELF,
+	PRI_REROUTING_RSP_MAX_DIVERSIONS_EXCEEDED,
+	PRI_REROUTING_RSP_RESOURCE_UNAVAILABLE,
+};
+
+/*!
+ * \brief Send the CallRerouteing/CallDeflection response message.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg.
+ * \param invoke_id Value given by the initiating request.
+ * \param code The result to send.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int pri_rerouting_rsp(struct pri *ctrl, q931_call *call, int invoke_id, enum PRI_REROUTING_RSP_CODE code);
+
+/*!
+ * \brief Set the call hold feature enable flag.
+ *
+ * \param ctrl D channel controller.
+ * \param enable TRUE to enable call hold feature.
+ *
+ * \return Nothing
+ */
+void pri_hold_enable(struct pri *ctrl, int enable);
+
+/*!
+ * \brief Send the HOLD message.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int pri_hold(struct pri *ctrl, q931_call *call);
+
+/*!
+ * \brief Send the HOLD ACKNOWLEDGE message.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int pri_hold_ack(struct pri *ctrl, q931_call *call);
+
+/*!
+ * \brief Send the HOLD REJECT message.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg
+ * \param cause Q.931 cause code for rejecting the hold request.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int pri_hold_rej(struct pri *ctrl, q931_call *call, int cause);
+
+/*!
+ * \brief Send the RETRIEVE message.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg
+ * \param channel Encoded channel id to use.  If zero do not send channel id.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int pri_retrieve(struct pri *ctrl, q931_call *call, int channel);
+
+/*!
+ * \brief Send the RETRIEVE ACKNOWLEDGE message.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg
+ * \param channel Encoded channel id to use.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int pri_retrieve_ack(struct pri *ctrl, q931_call *call, int channel);
+
+/*!
+ * \brief Send the RETRIEVE REJECT message.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg
+ * \param cause Q.931 cause code for rejecting the retrieve request.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int pri_retrieve_rej(struct pri *ctrl, q931_call *call, int cause);
 
 /* Get/Set PRI Timers  */
 #define PRI_GETSET_TIMERS
@@ -993,6 +1293,9 @@
 	PRI_TIMER_TM20,	/*!< Maximum time awaiting XID response */
 	PRI_TIMER_NM20,	/*!< Number of XID retransmits */
 
+	PRI_TIMER_T_HOLD,	/*!< Maximum time to wait for HOLD request response. */
+	PRI_TIMER_T_RETRIEVE,	/*!< Maximum time to wait for RETRIEVE request response. */
+
 	/* Must be last in the enum list */
 	_PRI_MAX_TIMERS,
 	PRI_MAX_TIMERS = (_PRI_MAX_TIMERS < 32) ? 32 : _PRI_MAX_TIMERS

Modified: team/mattf/libpri-1.4-q921-rewrite/pri.c
URL: http://svnview.digium.com/svn/libpri/team/mattf/libpri-1.4-q921-rewrite/pri.c?view=diff&rev=1292&r1=1291&r2=1292
==============================================================================
--- team/mattf/libpri-1.4-q921-rewrite/pri.c (original)
+++ team/mattf/libpri-1.4-q921-rewrite/pri.c Tue Nov 10 18:23:09 2009
@@ -86,6 +86,8 @@
 	{ "T320",           PRI_TIMER_T320,             PRI_ALL_SWITCHES },
 	{ "T321",           PRI_TIMER_T321,             PRI_ALL_SWITCHES },
 	{ "T322",           PRI_TIMER_T322,             PRI_ALL_SWITCHES },
+	{ "T-HOLD",         PRI_TIMER_T_HOLD,           PRI_ALL_SWITCHES },
+	{ "T-RETRIEVE",     PRI_TIMER_T_RETRIEVE,       PRI_ALL_SWITCHES },
 /* *INDENT-ON* */
 };
 
@@ -150,6 +152,10 @@
 	ctrl->timers[PRI_TIMER_T313] = 4 * 1000;	/* Wait for CONNECT acknowledge, CPE side only */
 	ctrl->timers[PRI_TIMER_TM20] = 2500;		/* Max time awaiting XID response - Q.921 Appendix IV */
 	ctrl->timers[PRI_TIMER_NM20] = 3;			/* Number of XID retransmits - Q.921 Appendix IV */
+	ctrl->timers[PRI_TIMER_T303] = 4 * 1000;			/* Length between SETUP retransmissions and timeout */
+
+	ctrl->timers[PRI_TIMER_T_HOLD] = 4 * 1000;	/* Wait for HOLD request response. */
+	ctrl->timers[PRI_TIMER_T_RETRIEVE] = 4 * 1000;/* Wait for RETRIEVE request response. */
 
 	/* Set any switch specific override default values */
 	switch (switchtype) {
@@ -220,18 +226,44 @@
 	return res;
 }
 
-/* Pass in the master for this function */
 void __pri_free_tei(struct pri * p)
 {
-	free (p);
+	if (p) {
+		struct q931_call *call;
+
+		call = p->dummy_call;
+		if (call) {
+			pri_schedule_del(call->pri, call->retranstimer);
+			pri_call_apdu_queue_cleanup(call);
+		}
+		free(p);
+	}
 }
 
 struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int tei, int bri)
 {
+	struct d_ctrl_dummy *dummy_ctrl;
 	struct pri *p;
 
-	if (!(p = calloc(1, sizeof(*p))))
-		return NULL;
+	switch (switchtype) {
+	case PRI_SWITCH_GR303_EOC:
+	case PRI_SWITCH_GR303_TMC:
+	case PRI_SWITCH_GR303_TMC_SWITCHING:
+	case PRI_SWITCH_GR303_EOC_PATH:
+		p = calloc(1, sizeof(*p));
+		if (!p) {
+			return NULL;
+		}
+		dummy_ctrl = NULL;
+		break;
+	default:
+		dummy_ctrl = calloc(1, sizeof(*dummy_ctrl));
+		if (!dummy_ctrl) {
+			return NULL;
+		}
+		p = &dummy_ctrl->ctrl;
+		break;
+	}
 
 	p->bri = bri;
 	p->fd = fd;
@@ -259,7 +291,14 @@
 	p->q931_rxcount = 0;
 	p->q931_txcount = 0;
 #endif
-	if (switchtype == PRI_SWITCH_GR303_EOC) {
+	if (dummy_ctrl) {
+		/* Initialize the dummy call reference call record. */
+		dummy_ctrl->ctrl.dummy_call = &dummy_ctrl->dummy_call;
+		q931_init_call_record(&dummy_ctrl->ctrl, dummy_ctrl->ctrl.dummy_call,
+			Q931_DUMMY_CALL_REFERENCE);
+	}
+	switch (switchtype) {
+	case PRI_SWITCH_GR303_EOC:
 		p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
 		p->sapi = Q921_SAPI_GR303_EOC;
 		p->tei = Q921_TEI_GR303_EOC_OPS;
@@ -268,7 +307,8 @@
 			free(p);
 			p = NULL;
 		}
-	} else if (switchtype == PRI_SWITCH_GR303_TMC) {
+		break;
+	case PRI_SWITCH_GR303_TMC:
 		p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
 		p->sapi = Q921_SAPI_GR303_TMC_CALLPROC;
 		p->tei = Q921_TEI_GR303_TMC_CALLPROC;
@@ -277,14 +317,19 @@
 			free(p);
 			p = NULL;
 		}
-	} else if (switchtype == PRI_SWITCH_GR303_TMC_SWITCHING) {
+		break;
+	case PRI_SWITCH_GR303_TMC_SWITCHING:
 		p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
 		p->sapi = Q921_SAPI_GR303_TMC_SWITCHING;
 		p->tei = Q921_TEI_GR303_TMC_SWITCHING;
-	} else if (switchtype == PRI_SWITCH_GR303_EOC_PATH) {
+		break;
+	case PRI_SWITCH_GR303_EOC_PATH:
 		p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
 		p->sapi = Q921_SAPI_GR303_EOC;
 		p->tei = Q921_TEI_GR303_EOC_PATH;
+		break;
+	default:
+		break;
 	}
 	/* Start Q.921 layer, Wait if we're the network */
 	if (p)
@@ -309,7 +354,7 @@
 #if 0
 	/* Restart Q.921 layer */
 	if (pri) {
-		q921_reset(pri);
+		q921_reset(pri, 1);
 		q921_start(pri, pri->localtype == PRI_CPE);	
 	}
 #else
@@ -385,6 +430,12 @@
 		{ PRI_EVENT_KEYPAD_DIGIT,   "Keypad Digit" },
 		{ PRI_EVENT_SERVICE,        "Service" },
 		{ PRI_EVENT_SERVICE_ACK,    "Service ACK" },
+		{ PRI_EVENT_HOLD,           "Hold" },
+		{ PRI_EVENT_HOLD_ACK,       "Hold Ack" },
+		{ PRI_EVENT_HOLD_REJ,       "Hold Rej" },
+		{ PRI_EVENT_RETRIEVE,       "Retrieve" },
+		{ PRI_EVENT_RETRIEVE_ACK,   "Retrieve ACK" },
+		{ PRI_EVENT_RETRIEVE_REJ,   "Retrieve Rej" },
 /* *INDENT-ON* */
 	};
 
@@ -543,26 +594,17 @@
 	return q931_keypad_facility(pri, call, digits);
 }
 
-
-int pri_callrerouting_facility(struct pri *pri, q931_call *call, const char *dest, const char* original, const char* reason)
+int pri_notify(struct pri *pri, q931_call *call, int channel, int info)
 {
 	if (!pri || !call)
 		return -1;
-
-	return qsig_cf_callrerouting(pri, call, dest, original, reason);
-}
-
-int pri_notify(struct pri *pri, q931_call *call, int channel, int info)
-{
-	if (!pri || !call)
-		return -1;
 	return q931_notify(pri, call, channel, info);
 }
 
 void pri_destroycall(struct pri *pri, q931_call *call)
 {
 	if (pri && call)
-		__q931_destroycall(pri, call);
+		q931_destroycall(pri, call);
 	return;
 }
 
@@ -622,6 +664,40 @@
 
 /*!
  * \internal
+ * \brief Copy the PRI party subaddress to the Q.931 party subaddress structure.
+ *
+ * \param q931_subaddress Q.931 party subaddress structure
+ * \param pri_subaddress PRI party subaddress structure
+ *
+ * \return Nothing
+ */
+static void pri_copy_party_subaddress_to_q931(struct q931_party_subaddress *q931_subaddress, const struct pri_party_subaddress *pri_subaddress)
+{
+	int length;
+	int maxlen = sizeof(q931_subaddress->data) - 1;
+
+	q931_party_subaddress_init(q931_subaddress);
+
+	if (!pri_subaddress->valid) {
+		return;
+	}
+
+	q931_subaddress->valid = 1;
+	q931_subaddress->type = pri_subaddress->type;
+
+	length = pri_subaddress->length;
+	if (length > maxlen){
+		length = maxlen;
+	} else {
+		q931_subaddress->odd_even_indicator = pri_subaddress->odd_even_indicator;
+	}
+	q931_subaddress->length = length;
+	memcpy(q931_subaddress->data, pri_subaddress->data, length);
+	q931_subaddress->data[length] = '\0';
+}
+
+/*!
+ * \internal
  * \brief Copy the PRI party id to the Q.931 party id structure.
  *
  * \param q931_id Q.931 party id structure
@@ -633,11 +709,14 @@
 {
 	pri_copy_party_name_to_q931(&q931_id->name, &pri_id->name);
 	pri_copy_party_number_to_q931(&q931_id->number, &pri_id->number);
+	pri_copy_party_subaddress_to_q931(&q931_id->subaddress, &pri_id->subaddress);
 }
 
 int pri_connected_line_update(struct pri *ctrl, q931_call *call, const struct pri_party_connected_line *connected)
 {
 	struct q931_party_id party_id;
+	unsigned idx;
+	struct q931_call *subcall;
 
 	if (!ctrl || !call) {
 		return -1;
@@ -650,6 +729,16 @@
 		return 0;
 	}
 	call->local_id = party_id;
+
+	/* Update all subcalls with new local_id. */
+	if (call->outboundbroadcast && call->master_call == call) {
+		for (idx = 0; idx < Q931_MAX_TEI; ++idx) {
+			subcall = call->subcalls[idx];
+			if (subcall) {
+				subcall->local_id = party_id;
+			}
+		}
+	}
 
 	switch (call->ourcallstate) {
 	case Q931_CALL_STATE_CALL_INITIATED:
@@ -692,6 +781,9 @@
 
 int pri_redirecting_update(struct pri *ctrl, q931_call *call, const struct pri_party_redirecting *redirecting)
 {
+	unsigned idx;
+	struct q931_call *subcall;
+
 	if (!ctrl || !call) {
 		return -1;
 	}
@@ -700,6 +792,21 @@
 	pri_copy_party_id_to_q931(&call->redirecting.to, &redirecting->to);
 	q931_party_id_fixup(ctrl, &call->redirecting.to);
 	call->redirecting.reason = redirecting->reason;
+
+	/*
+	 * Update all subcalls with new redirecting.to information and reason.
+	 * I do not think we will ever have any subcalls when this data is relevant,
+	 * but update it just in case.
+	 */
+	if (call->outboundbroadcast && call->master_call == call) {
+		for (idx = 0; idx < Q931_MAX_TEI; ++idx) {
+			subcall = call->subcalls[idx];
+			if (subcall) {
+				subcall->redirecting.to = call->redirecting.to;
+				subcall->redirecting.reason = redirecting->reason;
+			}
+		}
+	}
 
 	switch (call->ourcallstate) {
 	case Q931_CALL_STATE_NULL:
@@ -845,7 +952,7 @@
 		return -1;
 	if (cause == -1)
 		/* normal clear cause */
-		cause = 16;
+		cause = PRI_CAUSE_NORMAL_CLEARING;
 	return q931_hangup(pri, call, cause);
 }
 
@@ -869,6 +976,14 @@
 	if (!pri)
 		return NULL;
 	return q931_new_call(pri);
+}
+
+int pri_is_dummy_call(q931_call *call)
+{
+	if (!call) {
+		return 0;
+	}
+	return q931_is_dummy_call(call);
 }
 
 void pri_dump_event(struct pri *pri, pri_event *e)
@@ -978,7 +1093,7 @@
 
 int pri_call(struct pri *pri, q931_call *c, int transmode, int channel, int exclusive, 
 					int nonisdn, char *caller, int callerplan, char *callername, int callerpres, char *called,
-					int calledplan,int ulayer1)
+					int calledplan, int ulayer1)
 {
 	struct pri_sr req;
 	if (!pri || !c)
@@ -1015,7 +1130,7 @@
 	vsnprintf(tmp, sizeof(tmp), fmt, ap);
 	va_end(ap);
 	if (__pri_message)
-		__pri_message(pri, tmp);
+		__pri_message(PRI_MASTER(pri), tmp);
 	else
 		fputs(tmp, stdout);
 }
@@ -1028,7 +1143,7 @@
 	vsnprintf(tmp, sizeof(tmp), fmt, ap);
 	va_end(ap);
 	if (__pri_error)
-		__pri_error(pri, tmp);
+		__pri_error(PRI_MASTER(pri), tmp);
 	else
 		fputs(tmp, stderr);
 }
@@ -1210,6 +1325,11 @@
 	return 0;
 }
 
+void pri_sr_set_called_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress)
+{
+	pri_copy_party_subaddress_to_q931(&sr->called.subaddress, subaddress);
+}
+
 int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres)
 {
 	q931_party_id_init(&sr->caller);
@@ -1228,6 +1348,11 @@
 		}
 	}
 	return 0;
+}
+
+void pri_sr_set_caller_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress)
+{
+	pri_copy_party_subaddress_to_q931(&sr->caller.subaddress, subaddress);
 }
 
 void pri_sr_set_caller_party(struct pri_sr *sr, const struct pri_party_id *caller)
@@ -1279,3 +1404,124 @@
 {
 	sr->reversecharge = requested;
 }
+
+void pri_sr_set_keypad_digits(struct pri_sr *sr, const char *keypad_digits)
+{
+	sr->keypad_digits = keypad_digits;
+}
+
+void pri_hold_enable(struct pri *ctrl, int enable)
+{
+	ctrl = PRI_MASTER(ctrl);
+	if (ctrl) {
+		ctrl->hold_support = enable ? 1 : 0;
+	}
+}
+
+int pri_hold(struct pri *ctrl, q931_call *call)
+{
+	if (!ctrl || !call) {
+		return -1;
+	}
+	return q931_send_hold(ctrl, call);
+}
+
+int pri_hold_ack(struct pri *ctrl, q931_call *call)
+{
+	if (!ctrl || !call) {
+		return -1;
+	}
+	return q931_send_hold_ack(ctrl, call);
+}
+
+int pri_hold_rej(struct pri *ctrl, q931_call *call, int cause)
+{
+	if (!ctrl || !call) {
+		return -1;
+	}
+	return q931_send_hold_rej(ctrl, call, cause);
+}
+
+int pri_retrieve(struct pri *ctrl, q931_call *call, int channel)
+{
+	if (!ctrl || !call) {
+		return -1;
+	}
+	return q931_send_retrieve(ctrl, call, channel);
+}
+
+int pri_retrieve_ack(struct pri *ctrl, q931_call *call, int channel)
+{
+	if (!ctrl || !call) {
+		return -1;
+	}
+	return q931_send_retrieve_ack(ctrl, call, channel);
+}
+
+int pri_retrieve_rej(struct pri *ctrl, q931_call *call, int cause)
+{
+	if (!ctrl || !call) {
+		return -1;
+	}
+	return q931_send_retrieve_rej(ctrl, call, cause);
+}
+
+int pri_callrerouting_facility(struct pri *pri, q931_call *call, const char *dest, const char* original, const char* reason)
+{
+	if (!pri || !call || !dest)
+		return -1;
+
+	return qsig_cf_callrerouting(pri, call, dest, original, reason);
+}
+
+void pri_reroute_enable(struct pri *ctrl, int enable)
+{
+	ctrl = PRI_MASTER(ctrl);
+	if (ctrl) {
+		ctrl->deflection_support = enable ? 1 : 0;
+	}
+}
+
+int pri_reroute_call(struct pri *ctrl, q931_call *call, const struct pri_party_id *caller, const struct pri_party_redirecting *deflection, int subscription_option)
+{
+	const struct q931_party_id *caller_id;
+	struct q931_party_id local_caller;
+	struct q931_party_redirecting reroute;
+
+	if (!ctrl || !call || !deflection) {
+		return -1;
+	}
+
+	if (caller) {
+		/* Convert the caller update information. */
+		pri_copy_party_id_to_q931(&local_caller, caller);
+		q931_party_id_fixup(ctrl, &local_caller);
+		caller_id = &local_caller;
+	} else {
+		caller_id = NULL;
+	}
+
+	/* Convert the deflection information. */
+	q931_party_redirecting_init(&reroute);
+	pri_copy_party_id_to_q931(&reroute.from, &deflection->from);
+	q931_party_id_fixup(ctrl, &reroute.from);
+	pri_copy_party_id_to_q931(&reroute.to, &deflection->to);
+	q931_party_id_fixup(ctrl, &reroute.to);
+	pri_copy_party_id_to_q931(&reroute.orig_called, &deflection->orig_called);
+	q931_party_id_fixup(ctrl, &reroute.orig_called);
+	reroute.reason = deflection->reason;
+	reroute.orig_reason = deflection->orig_reason;
+	if (deflection->count <= 0) {
+		/*
+		 * We are deflecting with an unknown count
+		 * so assume the count is one.
+		 */
+		reroute.count = 1;
+	} else if (deflection->count < PRI_MAX_REDIRECTS) {
+		reroute.count = deflection->count;
+	} else {
+		reroute.count = PRI_MAX_REDIRECTS;
+	}
+
+	return send_reroute_request(ctrl, call, caller_id, &reroute, subscription_option);
+}

Modified: team/mattf/libpri-1.4-q921-rewrite/pri_facility.c
URL: http://svnview.digium.com/svn/libpri/team/mattf/libpri-1.4-q921-rewrite/pri_facility.c?view=diff&rev=1292&r1=1291&r2=1292
==============================================================================
--- team/mattf/libpri-1.4-q921-rewrite/pri_facility.c (original)
+++ team/mattf/libpri-1.4-q921-rewrite/pri_facility.c Tue Nov 10 18:23:09 2009
@@ -510,10 +510,83 @@
 static void rose_copy_number_to_q931(struct pri *ctrl,
 	struct q931_party_number *q931_number, const struct rosePartyNumber *rose_number)
 {
+	//q931_party_number_init(q931_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);
+	q931_number->valid = 1;
+}
+
+/*!
+ * \internal
+ * \brief Copy the given rose subaddress to the q931_party_subaddress.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param q931_subaddress Q.931 party subaddress structure
+ * \param rose_subaddress ROSE subaddress structure
+ *
+ * \note It is assumed that the q931_subaddress has been initialized before calling.
+ *
+ * \return Nothing
+ */
+static void rose_copy_subaddress_to_q931(struct pri *ctrl,
+	struct q931_party_subaddress *q931_subaddress,
+	const struct rosePartySubaddress *rose_subaddress)
+{
+	//q931_party_subaddress_init(q931_subaddress);
+	if (!rose_subaddress->length) {
+		/* Subaddress is not present. */
+		return;
+	}
+
+	switch (rose_subaddress->type) {
+	case 0:/* UserSpecified */
+		q931_subaddress->type = 2;/* user_specified */
+		q931_subaddress->valid = 1;
+		q931_subaddress->length = rose_subaddress->length;
+		if (sizeof(q931_subaddress->data) <= q931_subaddress->length) {
+			q931_subaddress->length = sizeof(q931_subaddress->data) - 1;
+		}
+		memcpy(q931_subaddress->data, rose_subaddress->u.user_specified.information,
+			q931_subaddress->length);
+		q931_subaddress->data[q931_subaddress->length] = '\0';
+		if (rose_subaddress->u.user_specified.odd_count_present) {
+			q931_subaddress->odd_even_indicator =
+				rose_subaddress->u.user_specified.odd_count;
+		}
+		break;
+	case 1:/* NSAP */
+		q931_subaddress->type = 0;/* nsap */
+		q931_subaddress->valid = 1;
+		libpri_copy_string((char *) q931_subaddress->data,
+			(char *) rose_subaddress->u.nsap, sizeof(q931_subaddress->data));
+		q931_subaddress->length = strlen((char *) q931_subaddress->data);
+		break;
+	default:
+		/* Don't know how to encode so assume it is not present. */
+		break;
+	}
+}
+
+/*!
+ * \internal
+ * \brief Copy the given rose address to the q931_party_id address.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param q931_address Q.931 party id structure to fill address
+ * \param rose_address ROSE address structure
+ *
+ * \note It is assumed that the q931_address has been initialized before calling.
+ *
+ * \return Nothing
+ */
+static void rose_copy_address_to_q931(struct pri *ctrl,
+	struct q931_party_id *q931_address, const struct roseAddress *rose_address)
+{
+	rose_copy_number_to_q931(ctrl, &q931_address->number, &rose_address->number);

[... 5857 lines stripped ...]



More information about the libpri-commits mailing list