[libpri-commits] rmudgett: branch group/ccss r993 - /team/group/ccss/
SVN commits to the libpri project
libpri-commits at lists.digium.com
Thu Aug 20 09:38:46 CDT 2009
Author: rmudgett
Date: Thu Aug 20 09:38:42 2009
New Revision: 993
URL: http://svn.asterisk.org/svn-view/libpri?view=rev&rev=993
Log:
Work so far. Certainly not functional.
Added:
team/group/ccss/pri_cc.c (with props)
Modified:
team/group/ccss/Makefile
team/group/ccss/libpri.h
team/group/ccss/pri.c
team/group/ccss/pri_facility.c
team/group/ccss/pri_internal.h
team/group/ccss/q931.c
Modified: team/group/ccss/Makefile
URL: http://svn.asterisk.org/svn-view/libpri/team/group/ccss/Makefile?view=diff&rev=993&r1=992&r2=993
==============================================================================
--- team/group/ccss/Makefile (original)
+++ team/group/ccss/Makefile Thu Aug 20 09:38:42 2009
@@ -47,6 +47,7 @@
q921.o \
prisched.o \
q931.o \
+ pri_cc.o \
pri_facility.o \
asn1_primitive.o \
rose.o \
@@ -70,6 +71,7 @@
q921.lo \
prisched.lo \
q931.lo \
+ pri_cc.lo \
pri_facility.lo \
asn1_primitive.lo \
rose.lo \
Modified: team/group/ccss/libpri.h
URL: http://svn.asterisk.org/svn-view/libpri/team/group/ccss/libpri.h?view=diff&rev=993&r1=992&r2=993
==============================================================================
--- team/group/ccss/libpri.h (original)
+++ team/group/ccss/libpri.h Thu Aug 20 09:38:42 2009
@@ -346,7 +346,7 @@
#define PRI_NSF_ATT_MULTIQUEST 0xF0
#define PRI_NSF_CALL_REDIRECTION_SERVICE 0xF7
-/* ECMA 186 */
+/* BUGBUG eliminate these defines ECMA 186 */
#define PRI_CC_CCNRREQUEST 27
#define PRI_CC_CANCEL 28
#define PRI_CC_RINGOUT 31
@@ -435,6 +435,14 @@
* BCD/binary and thus have a null byte as part of the contents.
*/
char data[32];
+};
+
+/*! \brief Addressing information needed to identify an endpoint in a call. */
+struct pri_party_address {
+ /*! \brief Subscriber phone number */
+ struct pri_party_number number;
+ /*! \brief Subscriber subaddress */
+ struct pri_party_subaddress subaddress;
};
/*! \brief Information needed to identify an endpoint in a call. */
@@ -474,12 +482,14 @@
int reason;
};
+/* BUGBUG eliminate this struct definition. */
/* Structures for qsig_cc_facilities */
struct pri_qsig_cc_extension {
int cc_extension_tag;
char extension[256];
};
+/* BUGBUG eliminate this struct definition. */
struct pri_qsig_cc_optional_arg {
char number_A[256];
char number_B[256];
@@ -487,6 +497,7 @@
struct pri_qsig_cc_extension cc_extension;
};
+/* BUGBUG eliminate this struct definition. */
struct pri_qsig_cc_request_res {
int no_path_reservation;
int retain_service;
@@ -494,44 +505,168 @@
};
/* Subcommands derived from supplementary services. */
-#define PRI_SUBCMD_REDIRECTING 1
-#define PRI_SUBCMD_CONNECTED_LINE 2
-#define PRI_SUBCMD_CC_CCBSREQUEST_RR 3
-#define PRI_SUBCMD_CC_CCNRREQUEST_RR 4
-#define PRI_SUBCMD_CC_CANCEL_INV 5
-#define PRI_SUBCMD_CC_EXECPOSSIBLE_INV 6
-#define PRI_SUBCMD_CC_RINGOUT_INV 7
-#define PRI_SUBCMD_CC_SUSPEND_INV 8
-#define PRI_SUBCMD_CC_ERROR 9
-
+#define PRI_SUBCMD_REDIRECTING 1 /*!< Redirecting information update */
+#define PRI_SUBCMD_CONNECTED_LINE 2 /*!< Connected line information update */
+#define PRI_SUBCMD_STATUS_REQ 3 /*!< Determine the status of the given party. */
+#define PRI_SUBCMD_STATUS_REQ_RSP 4 /*!< Status request response */
+#define PRI_SUBCMD_CC_RECORD_RETENTION 5 /*!< Give cc_id to upper layer */
+#define PRI_SUBCMD_CC_AVAILABLE 6 /*!< Indicate that CC is available */
+#define PRI_SUBCMD_CC_REQ 7 /*!< CC activation request */
+#define PRI_SUBCMD_CC_REQ_RSP 8 /*!< CC activation request response */
+#define PRI_SUBCMD_CC_REMOTE_USER_FREE 9 /*!< Indicate that CC party B is available */
+#define PRI_SUBCMD_CC_STATUS_REQ 10 /*!< Request/prod to receive updates of CC party A status */
+#define PRI_SUBCMD_CC_STATUS 11 /*!< Unsolicited update of CC party A status */
+#define PRI_SUBCMD_CC_CALL 12 /*!< Indicate that this call is a CC callback */
+#define PRI_SUBCMD_CC_CANCEL 13 /*!< Unsolicited indication that CC is canceled */
+#define PRI_SUBCMD_CC_DEACTIVATE_REQ 14 /*!< CC deactivation request */
+#define PRI_SUBCMD_CC_DEACTIVATE_RSP 15 /*!< CC deactivation request response */
+
+struct pri_subcmd_status_request {
+ /*!
+ * \brief Invoke id in case there are multiple outstanding requests.
+ * \note Used to match any responses with the original invoke in case
+ * there are several requests active.
+ */
+ int invoke_id;
+ /*! \brief Party address requesting status about. */
+ struct pri_party_address party;
+};
+
+struct pri_subcmd_status_request_rsp {
+ /*!
+ * \brief Request id in case there are multiple outstanding requests.
+ * \note Used to match any responses with the request in case there
+ * are several requests active.
+ */
+ int request_id;
+ /*!
+ * \brief Response status to the status request.
+ * \details
+ * free(0),
+ * busy(1),
+ * incompatible(2)
+ * unknown(3),
+ * timeout(4),
+ */
+ int status;
+};
+
+struct pri_subcmd_cc_id {
+ /*! \brief Call-Completion record id */
+ long cc_id;
+};
+
+struct pri_subcmd_cc_request {
+ /*! \brief Call-Completion record id */
+ long cc_id;
+ /*!
+ * \brief Mode of call-completion requested.
+ * \details
+ * ccbs(0),
+ * ccnr(1)
+ */
+ int mode;
+};
+
+struct pri_subcmd_cc_request_rsp {
+ /*! \brief Call-Completion record id */
+ long cc_id;
+ /*!
+ * \brief Status of the requested call-completion activation.
+ * \details
+ * success(0),
+ * timeout(1),
+ * short_term_denial(2),
+ * long_term_denial(3),
+ * not_subscribed(4)
+ */
+ int status;
+ /*!
+ * \brief Error code that can be converted to a string to further
+ * explain the non-timeout failure.
+ * \note Valid when non-zero.
+ * \note Use pri_facility_error2str() to convert the error_code.
+ */
+ int error_code;
+};
+
+struct pri_subcmd_cc_status {
+ /*! \brief Call-Completion record id */
+ long cc_id;
+ /*!
+ * \brief Party A status.
+ * \details
+ * free(0),
+ * busy(1)
+ */
+ int status;
+};
+
+struct pri_subcmd_cc_deactivate_rsp {
+ /*! \brief Call-Completion record id */
+ long cc_id;
+ /*!
+ * \brief Status of the requested call-completion deactivation.
+ * \details
+ * success(0),
+ * timeout(1),
+ * fail(2)
+ */
+ int status;
+ /*!
+ * \brief Error code that can be converted to a string to further
+ * explain the non-timeout failure.
+ * \note Valid when non-zero.
+ * \note Use pri_facility_error2str() to convert the error_code.
+ */
+ int error_code;
+};
+
+/* BUGBUG eliminate the following defines */
+#define PRI_SUBCMD_CC_CCBSREQUEST_RR 93
+#define PRI_SUBCMD_CC_CCNRREQUEST_RR 94
+#define PRI_SUBCMD_CC_CANCEL_INV 95
+#define PRI_SUBCMD_CC_EXECPOSSIBLE_INV 96
+#define PRI_SUBCMD_CC_RINGOUT_INV 97
+#define PRI_SUBCMD_CC_SUSPEND_INV 98
+#define PRI_SUBCMD_CC_ERROR 99
+
+/* BUGBUG eliminate the following defines */
#define PRI_CCERROR_UNSPECIFIED 1008
#define PRI_CCERROR_REMOTE_USER_BUSY_AGAIN 1012
#define PRI_CCERROR_FAILURE_TO_MATCH 1013
+/* BUGBUG eliminate this struct definition. */
struct pri_subcmd_cc_ccbs_rr {
struct pri_qsig_cc_request_res cc_request_res;
};
+/* BUGBUG eliminate this struct definition. */
struct pri_subcmd_cc_ccnr_rr {
struct pri_qsig_cc_request_res cc_request_res;
};
+/* BUGBUG eliminate this struct definition. */
struct pri_subcmd_cc_cancel_inv {
struct pri_qsig_cc_optional_arg cc_optional_arg;
};
+/* BUGBUG eliminate this struct definition. */
struct pri_subcmd_cc_execpossible_inv {
struct pri_qsig_cc_optional_arg cc_optional_arg;
};
+/* BUGBUG eliminate this struct definition. */
struct pri_subcmd_cc_suspend_inv {
struct pri_qsig_cc_extension cc_extension;
};
+/* BUGBUG eliminate this struct definition. */
struct pri_subcmd_cc_ringout_inv {
struct pri_qsig_cc_extension cc_extension;
};
+/* BUGBUG eliminate this struct definition. */
struct pri_subcmd_cc_error {
int error_value;
};
@@ -544,6 +679,20 @@
char reserve_space[512];
struct pri_party_connected_line connected_line;
struct pri_party_redirecting redirecting;
+ struct pri_subcmd_status_request status_request;
+ struct pri_subcmd_status_request_rsp status_request_rsp;
+ struct pri_subcmd_cc_id cc_available;
+ struct pri_subcmd_cc_request cc_request;
+ struct pri_subcmd_cc_request_rsp cc_request_rsp;
+ struct pri_subcmd_cc_id cc_remote_user_free;
+ struct pri_subcmd_cc_id cc_status_req;
+ struct pri_subcmd_cc_status cc_status;
+ struct pri_subcmd_cc_id cc_call;
+ struct pri_subcmd_cc_id cc_cancel;
+ struct pri_subcmd_cc_id cc_deactivate_req;
+ struct pri_subcmd_cc_deactivate_rsp cc_deactivate_rsp;
+
+/* BUGBUG eliminate these struct members. */
struct pri_subcmd_cc_ccbs_rr cc_ccbs_rr;
struct pri_subcmd_cc_ccnr_rr cc_ccnr_rr;
struct pri_subcmd_cc_cancel_inv cc_cancel_inv;
@@ -669,7 +818,7 @@
long aoc_units; /* Advise of Charge number of charged units */
char useruserinfo[260]; /* User->User info */
struct pri_subcommands *subcmds;
-} pri_event_hangup;
+} pri_event_hangup;
typedef struct pri_event_restart_ack {
int e;
@@ -687,7 +836,7 @@
q931_call *call;
struct pri_subcommands *subcmds;
} pri_event_proceeding;
-
+
typedef struct pri_event_setup_ack {
int e;
int channel;
@@ -751,7 +900,7 @@
/* Create a D-channel on a given file descriptor. The file descriptor must be a
channel operating in HDLC mode with FCS computed by the fd's driver. Also it
- must be NON-BLOCKING! Frames received on the fd should include FCS. Nodetype
+ must be NON-BLOCKING! Frames received on the fd should include FCS. Nodetype
must be one of PRI_NETWORK or PRI_CPE. switchtype should be PRI_SWITCH_* */
struct pri *pri_new(int fd, int nodetype, int switchtype);
struct pri *pri_new_bri(int fd, int ptpmode, int nodetype, int switchtype);
@@ -806,6 +955,15 @@
/* Turn cause into a string */
char *pri_cause2str(int cause);
+
+/*!
+ * \brief Convert the given facility error code to a descriptive string.
+ *
+ * \param facility_error_code Error code to convert to a string.
+ *
+ * \return Descriptive error string.
+ */
+const char *pri_facility_error2str(int facility_error_code);
/* Acknowledge a call and place it on the given channel. Set info to non-zero if there
is in-band data available on the channel */
@@ -868,10 +1026,14 @@
/* Create a new call */
q931_call *pri_new_call(struct pri *pri);
+
+/* BUGBUG eliminate this prototype. */
q931_call *pri_new_nochannel_call(struct pri *pri, int *cr);
+/* BUGBUG eliminate this prototype. */
q931_call *pri_find_call(struct pri *pri, int cr);
+/* BUGBUG eliminate this prototype. */
void pri_call_set_cc_operation(q931_call *call, int cc_operation);
/* Retrieve CRV reference for GR-303 calls. Returns >0 on success. */
@@ -922,8 +1084,9 @@
/*! \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);
-
+/* BUGBUG eliminate this prototype. */
int pri_sr_set_ccringout(struct pri_sr *sr, int ccringout);
+/* BUGBUG eliminate this prototype. */
int pri_sr_set_ccbsnr(struct pri_sr *sr, int ccbsnr);
#define PRI_USER_USER_TX
@@ -935,10 +1098,16 @@
int pri_setup(struct pri *pri, q931_call *call, struct pri_sr *req);
-/* Set a call has a call indpendent signalling connection (i.e. no bchan) */
+/*!
+ * \brief Set a call has a call indpendent signalling connection (i.e. no bchan)
+ * \note Call will automaticlly disconnect after signalling sent.
+ */
int pri_sr_set_connection_call_independent(struct pri_sr *req);
-/* Set a no channel call (i.e. QSIG-CCBS/CCNR) */
+/*!
+ * \brief Set a call has a call indpendent signalling connection (i.e. no bchan)
+ * \note Call will stay connected until explicitly disconnected.
+ */
int pri_sr_set_no_channel_call(struct pri_sr *req);
/* Send an MWI indication to a remote location. If activate is non zero, activates, if zero, deactivates */
@@ -1004,6 +1173,20 @@
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);
+
+int pri_status_request(struct pri *ctrl, int request_id, const struct pri_sr *req);
+void pri_status_request_response(struct pri *ctrl, int invoke_id, int status);
+
+/* Call-completion function prototypes */
+void pri_cc_available(struct pri *ctrl, q931_call *call);
+int pri_cc_request(struct pri *ctrl, long cc_id, int mode);
+void pri_cc_request_response(struct pri *ctrl, long cc_id, int status);
+void pri_cc_remote_user_free(struct pri *ctrl, long cc_id);
+int pri_cc_status_request(struct pri *ctrl, long cc_id);
+void pri_cc_status(struct pri *ctrl, long cc_id, int status);
+int pri_cc_call(struct pri *ctrl, long cc_id, q931_call *call, int channel, int exclusive);
+void pri_cc_cancel(struct pri *ctrl, long cc_id);
+int pri_cc_deactivate_request(struct pri *ctrl, long cc_id);
/* Get/Set PRI Timers */
#define PRI_GETSET_TIMERS
@@ -1047,11 +1230,33 @@
PRI_TIMER_TM20, /*!< Maximum time awaiting XID response */
PRI_TIMER_NM20, /*!< Number of XID retransmits */
- PRI_TIMER_CCBST2,/*!< maximum time on completion of CC Call */
+ PRI_TIMER_T_STATUS, /*!< Max time to wait for all replies to check for compatible terminals */
+
+ PRI_TIMER_T_ACTIVATE, /*!< Request supervision timeout. */
+ PRI_TIMER_T_DEACTIVATE, /*!< Deactivate supervision timeout. */
+ PRI_TIMER_T_INTERROGATE,/*!< Interrogation supervision timeout. */
+
+ /* ETSI call-completion timers */
+ PRI_TIMER_T_RETENTION, /*!< Max time to wait for user A to activate call-completion. */
+ PRI_TIMER_T_CCBS1, /*!< T-STATUS timer equivalent for CC user A status. */
+ PRI_TIMER_T_CCBS2, /*!< Max time the CCBS service will be active */
+ PRI_TIMER_T_CCBS3, /*!< Max time to wait for user A to respond to user B availability. */
+ PRI_TIMER_T_CCBS4, /*!< CC user B guard time before sending CC recall indication. */
+ PRI_TIMER_T_CCBS5, /*!< Network B CCBS supervision timeout. */
+ PRI_TIMER_T_CCBS6, /*!< Network A CCBS supervision timeout. */
+ PRI_TIMER_T_CCNR2, /*!< Max time the CCNR service will be active */
+ PRI_TIMER_T_CCNR5, /*!< Network B CCNR supervision timeout. */
+ PRI_TIMER_T_CCNR6, /*!< Network A CCNR supervision timeout. */
+
+ /* Q.SIG call-completion timers */
+ PRI_TIMER_QSIG_CC_T1, /*!< CC request supervision timeout. */
+ PRI_TIMER_QSIG_CCBS_T2, /*!< CCBS supervision timeout. */
+ PRI_TIMER_QSIG_CCNR_T2, /*!< CCNR supervision timeout. */
+ PRI_TIMER_QSIG_CC_T3, /*!< Max time to wait for user A to respond to user B availability. */
+ PRI_TIMER_QSIG_CC_T4, /*!< Path reservation supervision timeout. */
/* Must be last in the enum list */
- _PRI_MAX_TIMERS,
- PRI_MAX_TIMERS = (_PRI_MAX_TIMERS < 32) ? 32 : _PRI_MAX_TIMERS
+ PRI_MAX_TIMERS
};
/* Get PRI version */
Modified: team/group/ccss/pri.c
URL: http://svn.asterisk.org/svn-view/libpri/team/group/ccss/pri.c?view=diff&rev=993&r1=992&r2=993
==============================================================================
--- team/group/ccss/pri.c (original)
+++ team/group/ccss/pri.c Thu Aug 20 09:38:42 2009
@@ -45,6 +45,7 @@
#define PRI_BIT(a_bit) (1UL << (a_bit))
#define PRI_ALL_SWITCHES 0xFFFFFFFF
+#define PRI_ETSI_SWITCHES (PRI_BIT(PRI_SWITCH_EUROISDN_E1) | PRI_BIT(PRI_SWITCH_EUROISDN_T1))
struct pri_timer_table {
const char *name;
@@ -86,7 +87,24 @@
{ "T320", PRI_TIMER_T320, PRI_ALL_SWITCHES },
{ "T321", PRI_TIMER_T321, PRI_ALL_SWITCHES },
{ "T322", PRI_TIMER_T322, PRI_ALL_SWITCHES },
- { "CCT2", PRI_TIMER_CCBST2, PRI_BIT(PRI_SWITCH_QSIG) },
+ { "T-STATUS", PRI_TIMER_T_STATUS, PRI_ETSI_SWITCHES },
+ { "T-ACTIVATE", PRI_TIMER_T_ACTIVATE, PRI_ETSI_SWITCHES },
+ { "T-DEACTIVATE", PRI_TIMER_T_DEACTIVATE, PRI_ETSI_SWITCHES },
+ { "T-INTERROGATE", PRI_TIMER_T_INTERROGATE, PRI_ETSI_SWITCHES },
+ { "T-RETENTION", PRI_TIMER_T_RETENTION, PRI_ETSI_SWITCHES },
+ { "T-CCBS1", PRI_TIMER_T_CCBS1, PRI_ETSI_SWITCHES },
+ { "T-CCBS2", PRI_TIMER_T_CCBS2, PRI_ETSI_SWITCHES },
+ { "T-CCBS3", PRI_TIMER_T_CCBS3, PRI_ETSI_SWITCHES },
+ { "T-CCBS4", PRI_TIMER_T_CCBS4, PRI_ETSI_SWITCHES },
+ { "T-CCBS5", PRI_TIMER_T_CCBS5, PRI_ETSI_SWITCHES },
+ { "T-CCBS6", PRI_TIMER_T_CCBS6, PRI_ETSI_SWITCHES },
+ { "T-CCNR2", PRI_TIMER_T_CCNR2, PRI_ETSI_SWITCHES },
+ { "T-CCNR5", PRI_TIMER_T_CCNR5, PRI_ETSI_SWITCHES },
+ { "T-CCNR6", PRI_TIMER_T_CCNR6, PRI_ETSI_SWITCHES },
+ { "CC-T1", PRI_TIMER_QSIG_CC_T1, PRI_BIT(PRI_SWITCH_QSIG) },
+ { "CCBS-T2", PRI_TIMER_QSIG_CCBS_T2, PRI_BIT(PRI_SWITCH_QSIG) },
+ { "CCNR-T2", PRI_TIMER_QSIG_CCNR_T2, PRI_BIT(PRI_SWITCH_QSIG) },
+ { "CC-T3", PRI_TIMER_QSIG_CC_T3, PRI_BIT(PRI_SWITCH_QSIG) },
/* *INDENT-ON* */
};
@@ -151,7 +169,30 @@
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_CCBST2] = 45 * 60 * 1000;/* Q.SIG CC-Timer2 45 min */
+
+ /* ETSI timers */
+ ctrl->timers[PRI_TIMER_T_STATUS] = 4 * 1000; /* Max time to wait for all replies to check for compatible terminals */
+ ctrl->timers[PRI_TIMER_T_ACTIVATE] = 10 * 1000; /* Request supervision timeout. */
+ ctrl->timers[PRI_TIMER_T_DEACTIVATE] = 4 * 1000;/* Deactivate supervision timeout. */
+ ctrl->timers[PRI_TIMER_T_INTERROGATE] = 4 * 1000;/* Interrogation supervision timeout. */
+
+ /* ETSI call-completion timers */
+ ctrl->timers[PRI_TIMER_T_RETENTION] = 30 * 1000;/* Max time to wait for user A to activate call-completion. */
+ ctrl->timers[PRI_TIMER_T_CCBS1] = 4 * 1000; /* T-STATUS timer equivalent for CC user A status. */
+ ctrl->timers[PRI_TIMER_T_CCBS2] = 45 * 60 * 1000;/* Max time the CCBS service will be active */
+ ctrl->timers[PRI_TIMER_T_CCBS3] = 20 * 1000; /* Max time to wait for user A to respond to user B availability. */
+ ctrl->timers[PRI_TIMER_T_CCBS4] = 5 * 1000; /* CC user B guard time before sending CC recall indication. */
+ ctrl->timers[PRI_TIMER_T_CCBS5] = 60 * 60 * 1000;/* Network B CCBS supervision timeout. */
+ ctrl->timers[PRI_TIMER_T_CCBS6] = 60 * 60 * 1000;/* Network A CCBS supervision timeout. */
+ ctrl->timers[PRI_TIMER_T_CCNR2] = 180 * 60 * 1000;/* Max time the CCNR service will be active */
+ ctrl->timers[PRI_TIMER_T_CCNR5] = 195 * 60 * 1000;/* Network B CCNR supervision timeout. */
+ ctrl->timers[PRI_TIMER_T_CCNR6] = 195 * 60 * 1000;/* Network A CCNR supervision timeout. */
+
+ /* Q.SIG call-completion timers */
+ ctrl->timers[PRI_TIMER_QSIG_CC_T1] = 30 * 1000;/* CC request supervision timeout. */
+ ctrl->timers[PRI_TIMER_QSIG_CCBS_T2] = 60 * 60 * 1000;/* CCBS supervision timeout. */
+ ctrl->timers[PRI_TIMER_QSIG_CCNR_T2] = 195 * 60 * 1000;/* CCNR supervision timeout. */
+ ctrl->timers[PRI_TIMER_QSIG_CC_T3] = 30 * 1000;/* Max time to wait for user A to respond to user B availability. */
/* Set any switch specific override default values */
switch (switchtype) {
@@ -778,6 +819,53 @@
return 0;
}
+/*!
+ * \brief Poll/ping for the status of any "called" party.
+ *
+ * \param ctrl D channel controller.
+ * \param request_id The upper layer's ID number to match with the response in case
+ * there are several requests at the same time.
+ * \param req Setup request for "called" party to determine the status.
+ *
+ * \note
+ * There could be one or more PRI_SUBCMD_STATUS_REQ_RSP to the status request
+ * depending upon how many endpoints respond to the request.
+ * (This includes the timeout or unknown termination response.)
+ * \note
+ * If the switch type is not ETSI BRI PTMP NT then the status will always be
+ * an immediate unknown.
+ * \note
+ * Could be used to poll for the status of call-completion party B.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int pri_status_request(struct pri *ctrl, int request_id, const struct pri_sr *req)
+{
+ /*! \todo BUGBUG pri_status_request() not written */
+ return -1;
+}
+
+/*!
+ * \brief Response to a poll/ping request for status of any "called" party by libpri.
+ *
+ * \param ctrl D channel controller.
+ * \param invoke_id ID given by libpri when it requested the party status.
+ * \param status free(0)/busy(1)/incompatible(2)
+ *
+ * \note
+ * There could be zero, one, or more responses to the original
+ * status request depending upon how many endpoints respond to the request.
+ * \note
+ * Could be used to poll for the status of call-completion party B.
+ *
+ * \return Nothing
+ */
+void pri_status_request_response(struct pri *ctrl, int invoke_id, int status)
+{
+ /*! \todo BUGBUG pri_status_request_response() not written */
+}
+
#if 0
/* deprecated routines, use pri_hangup */
int pri_release(struct pri *pri, q931_call *call, int cause)
@@ -910,7 +998,7 @@
}
}
-static void pri_sr_init(struct pri_sr *req)
+void pri_sr_init(struct pri_sr *req)
{
memset(req, 0, sizeof(struct pri_sr));
q931_party_redirecting_init(&req->redirecting);
@@ -924,7 +1012,8 @@
if (!req)
return -1;
- req->justsignalling = 1; /* have to set justsignalling for all those pesky IEs we need to setup */
+ req->cis_call = 1; /* have to set cis_call for all those pesky IEs we need to setup */
+ req->cis_auto_disconnect = 1;
return 0;
}
@@ -933,7 +1022,7 @@
if (!req)
return -1;
- req->nochannelsignalling = 1;
+ req->cis_call = 1;
return 0;
}
Added: team/group/ccss/pri_cc.c
URL: http://svn.asterisk.org/svn-view/libpri/team/group/ccss/pri_cc.c?view=auto&rev=993
==============================================================================
--- team/group/ccss/pri_cc.c (added)
+++ team/group/ccss/pri_cc.c Thu Aug 20 09:38:42 2009
@@ -1,0 +1,566 @@
+/*
+ * libpri: An implementation of Primary Rate ISDN
+ *
+ * Copyright (C) 2009 Digium, Inc.
+ *
+ * Richard Mudgett <rmudgett at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2 as published by the
+ * Free Software Foundation. See the LICENSE file included with
+ * this program for more details.
+ *
+ * In addition, when this program is distributed with Asterisk in
+ * any form that would qualify as a 'combined work' or as a
+ * 'derivative work' (but not mere aggregation), you can redistribute
+ * and/or modify the combination under the terms of the license
+ * provided with that copy of Asterisk, instead of the license
+ * terms granted here.
+ */
+
+/*!
+ * \file
+ * \brief Call Completion controller
+ *
+ * \author Richard Mudgett <rmudgett at digium.com>
+ */
+
+
+#include "compat.h"
+#include "libpri.h"
+#include "pri_internal.h"
+#include "pri_q921.h"
+#include "pri_q931.h"
+
+#include <stdlib.h>
+
+
+/* ------------------------------------------------------------------- */
+
+#if defined(BUGBUG_NOT_USED_YET)
+/*!
+ * \internal
+ * \brief Find a cc_record by the PTMP reference_id.
+ *
+ * \param ctrl D channel controller.
+ * \param reference_id CCBS reference ID to look for in cc_record pool.
+ *
+ * \retval cc_record on success.
+ * \retval NULL on error.
+ */
+static struct pri_cc_record *pri_cc_find_by_reference(struct pri *ctrl, unsigned reference_id)
+{
+ struct pri_cc_record *cc_record;
+
+ for (cc_record = ctrl->cc_pool; cc_record; cc_record = cc_record->next) {
+ if (cc_record->ccbs_reference_id == reference_id) {
+ /* Found the record */
+ break;
+ }
+ }
+
+ return cc_record;
+}
+#endif
+
+#if defined(BUGBUG_NOT_USED_YET)
+/*!
+ * \internal
+ * \brief Find a cc_record by the PTMP linkage_id.
+ *
+ * \param ctrl D channel controller.
+ * \param linkage_id Call linkage ID to look for in cc_record pool.
+ *
+ * \retval cc_record on success.
+ * \retval NULL on error.
+ */
+static struct pri_cc_record *pri_cc_find_by_linkage(struct pri *ctrl, unsigned linkage_id)
+{
+ struct pri_cc_record *cc_record;
+
+ for (cc_record = ctrl->cc_pool; cc_record; cc_record = cc_record->next) {
+ if (cc_record->call_linkage_id == linkage_id) {
+ /* Found the record */
+ break;
+ }
+ }
+
+ return cc_record;
+}
+#endif
+
+/*!
+ * \internal
+ * \brief Find a cc_record by the cc_id.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_id ID to look for in cc_record pool.
+ *
+ * \retval cc_record on success.
+ * \retval NULL on error.
+ */
+static struct pri_cc_record *pri_cc_find_by_id(struct pri *ctrl, long cc_id)
+{
+ struct pri_cc_record *cc_record;
+
+ for (cc_record = ctrl->cc_pool; cc_record; cc_record = cc_record->next) {
+ if (cc_record->record_id == cc_id) {
+ /* Found the record */
+ break;
+ }
+ }
+
+ return cc_record;
+}
+
+#if defined(BUGBUG_NOT_USED_YET)
+/*!
+ * \internal
+ * \brief Find a cc_record by an incoming call addressing data.
+ *
+ * \param ctrl D channel controller.
+ * \param party_a Party A address.
+ * \param party_b Party B address.
+ *
+ * \retval cc_record on success.
+ * \retval NULL on error.
+ */
+static struct pri_cc_record *pri_cc_find_by_addressing(struct pri *ctrl, const struct q931_party_address *party_a, const struct q931_party_address *party_b)
+{
+ struct pri_cc_record *cc_record;
+
+ for (cc_record = ctrl->cc_pool; cc_record; cc_record = cc_record->next) {
+ if (!q931_cmp_party_id_to_address(&cc_record->party_a, party_a)
+ && !q931_party_address_cmp(&cc_record->party_b, party_b)) {
+ /* Found the record */
+ break;
+ }
+ }
+
+ return cc_record;
+
+ /*! \todo BUGBUG pri_cc_find_by_addressing() not written */
+}
+#endif
+
+#if defined(BUGBUG_NOT_USED_YET)
+/*!
+ * \internal
+ * \brief Allocate a new cc_record id.
+ *
+ * \param ctrl D channel controller.
+ *
+ * \retval cc_id on success.
+ * \retval -1 on error.
+ */
+static long pri_cc_new_id(struct pri *ctrl)
+{
+ long record_id;
+ long first_id;
+
+ record_id = ++ctrl->last_cc_id;
+ first_id = record_id;
+ while (pri_cc_find_by_id(ctrl, record_id)) {
+ record_id = ++ctrl->last_cc_id;
+ if (record_id == first_id) {
+ /*
+ * We have a resource leak.
+ * We should never need to allocate 64k records on a D channel.
+ */
+ pri_error(ctrl, "ERROR Too many call completion records!\n");
+ record_id = -1;
+ break;
+ }
+ }
+
+ return record_id;
+}
+#endif
+
+#if defined(BUGBUG_NOT_USED_YET)
+/*!
+ * \internal
+ * \brief Delete the given call completion record
+ *
+ * \param ctrl D channel controller.
+ * \param doomed Call completion record to destroy
+ *
+ * \return Nothing
+ */
+static void pri_cc_delete_record(struct pri *ctrl, struct pri_cc_record *doomed)
+{
+ struct pri_cc_record **prev;
+ struct pri_cc_record *current;
+
+ for (prev = &ctrl->cc_pool, current = ctrl->cc_pool; current;
+ prev = ¤t->next, current = current->next) {
+ if (current == doomed) {
+ *prev = current->next;
+ free(doomed);
+ return;
+ }
+ }
+
+ /* The doomed node is not in the call completion database */
+}
+#endif
+
+#if defined(BUGBUG_NOT_USED_YET)
+/*!
+ * \internal
+ * \brief Allocate a new cc_record.
+ *
+ * \param ctrl D channel controller.
+ *
+ * \retval cc_id on success.
+ * \retval -1 on error.
+ */
+static long pri_cc_new_record(struct pri *ctrl)
+{
+ struct pri_cc_record *cc_record;
+ long record_id;
+
+ cc_record = calloc(1, sizeof(*cc_record));
+ if (!cc_record) {
+ return -1;
+ }
+ record_id = pri_cc_new_id(ctrl);
+ if (record_id < 0) {
+ free(cc_record);
+ return -1;
+ }
+
+ /* Initialize the new record */
+ cc_record->record_id = record_id;
+ cc_record->call_linkage_id = 0xFF;/* Invalid so it will never be found this way */
+ cc_record->ccbs_reference_id = 0xFF;/* Invalid so it will never be found this way */
+ q931_party_id_init(&cc_record->party_a);
+ q931_party_address_init(&cc_record->party_b);
+/*! \todo BUGBUG need more initialization?? */
+
+ /* Insert the new record into the database */
+ cc_record->next = ctrl->cc_pool;
+ ctrl->cc_pool = cc_record;
+
+ return record_id;
+}
+#endif
+
+/*!
+ * \brief Indicate to the far end that CCBS/CCNR is available.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg.
+ *
+ * \details
+ * The CC available indication will go out with the next
+ * DISCONNECT(busy/congested)/ALERTING message.
+ *
+ * \return Nothing
+ */
+void pri_cc_available(struct pri *ctrl, q931_call *call)
+{
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_QSIG:
+ /*
+ * Q.SIG has no message to send when CC is available.
+ * Q.SIG assumes CC is always available and is denied when
+ * requested if CC is not possible or allowed.
+ */
+ break;
+ case PRI_SWITCH_EUROISDN_E1:
+ case PRI_SWITCH_EUROISDN_T1:
+ if (q931_is_ptmp(ctrl)) {
+ } else {
+ }
+ /*! \todo BUGBUG pri_cc_available() not written */
+ break;
+ default:
+ break;
+ }
+}
+
+/*!
+ * \brief Request to activate CC.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_id CC record ID to activate.
+ * \param mode Which CC mode to use CCBS(0)/CCNR(1)
+ *
+ * \note
+ * Will always get a reply from libpri. libpri will start a timer to guarantee
+ * that a reply will be passed back to the upper layer.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int pri_cc_request(struct pri *ctrl, long cc_id, int mode)
+{
+ struct pri_sr req;
+ q931_call *call;
+ struct pri_cc_record *cc_record;
+
+ cc_record = pri_cc_find_by_id(ctrl, cc_id);
+ if (!cc_record) {
+ return -1;
+ }
+
+ if (cc_record->state == CC_STATE_IDLE) {
+ cc_record->party_b_is_remote = 1;
+ }
+
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_QSIG:
+ call = q931_new_call(ctrl);
+ if (!call) {
+ return -1;
+ }
+
+/* BUGBUG */
+ //add_qsigCcRequestArg_facility_ie(ctrl, call, Q931_SETUP, cc_record, mode);
+
+ pri_sr_init(&req);
+ req.caller = cc_record->party_a;
+ req.called = cc_record->party_b;
+ req.numcomplete = 1;
+ req.cis_auto_disconnect = 0;
+ req.cis_call = 1;
+ if (q931_setup(ctrl, call, &req)) {
+ return -1;
+ }
+ break;
+ case PRI_SWITCH_EUROISDN_E1:
+ case PRI_SWITCH_EUROISDN_T1:
+ if (q931_is_ptmp(ctrl)) {
+ } else {
+ }
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+
+ cc_record->state = CC_STATE_REQUESTED;
+
+ return 0;
+
+ /*! \todo BUGBUG pri_cc_request() not written */
+}
+
+/*!
+ * \brief Response to an incoming CC activation request.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_id CC record ID to activate.
+ * \param status success(0)/timeout(1)/
+ * short_term_denial(2)/long_term_denial(3)/not_subscribed(4)
+ *
+ * \return Nothing
+ */
+void pri_cc_request_response(struct pri *ctrl, long cc_id, int status)
+{
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_QSIG:
+ break;
+ case PRI_SWITCH_EUROISDN_E1:
+ case PRI_SWITCH_EUROISDN_T1:
+ if (q931_is_ptmp(ctrl)) {
+ } else {
+ }
+ break;
+ default:
+ break;
+ }
+
+ /*! \todo BUGBUG pri_cc_request_response() not written */
+}
+
+/*!
+ * \brief Indicate that the remote user (Party B) is free to call.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_id CC record ID to activate.
+ *
+ * \return Nothing
+ */
+void pri_cc_remote_user_free(struct pri *ctrl, long cc_id)
+{
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_QSIG:
+ break;
+ case PRI_SWITCH_EUROISDN_E1:
+ case PRI_SWITCH_EUROISDN_T1:
+ if (q931_is_ptmp(ctrl)) {
+ } else {
+ }
+ break;
+ default:
+ break;
+ }
+
+ /*! \todo BUGBUG pri_cc_remote_user_free() not written */
+}
+
+/*!
+ * \brief Poll/Ping for the status of CC party A.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_id CC record ID to activate.
+ *
+ * \note
+ * There could be zero, one, or more PRI_SUBCMD_CC_STATUS responses to the
+ * status request depending upon how many endpoints respond to the request.
+ * \note
+ * This is expected to be called only if there are two PTMP links between
+ * party A and the network. (e.g., A --> * --> PSTN)
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int pri_cc_status_request(struct pri *ctrl, long cc_id)
+{
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_QSIG:
+ break;
+ case PRI_SWITCH_EUROISDN_E1:
+ case PRI_SWITCH_EUROISDN_T1:
+ if (q931_is_ptmp(ctrl)) {
+ } else {
+ }
+ break;
+ default:
+ break;
+ }
+
+ /*! \todo BUGBUG pri_cc_status_request() not written */
+ return -1;
+}
+
+/*!
+ * \brief Update the busy status of CC party A.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_id CC record ID to activate.
+ * \param status Updated party A status free(0)/busy(1)
+ *
+ * \note
+ * Party A status is used to suspend/resume monitoring party B.
+ *
+ * \return Nothing
+ */
+void pri_cc_status(struct pri *ctrl, long cc_id, int status)
+{
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_QSIG:
+ break;
+ case PRI_SWITCH_EUROISDN_E1:
+ case PRI_SWITCH_EUROISDN_T1:
+ if (q931_is_ptmp(ctrl)) {
+ } else {
+ }
+ break;
+ default:
+ break;
+ }
+
+ /*! \todo BUGBUG pri_cc_status() not written */
+}
+
+/*!
+ * \brief Initiate the CC callback call.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_id CC record ID to activate.
+ * \param call Q.931 call leg.
+ * \param channel Encoded B channel to use.
+ * \param exclusive TRUE if the specified B channel must be used.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int pri_cc_call(struct pri *ctrl, long cc_id, q931_call *call, int channel, int exclusive)
+{
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_QSIG:
+ break;
+ case PRI_SWITCH_EUROISDN_E1:
+ case PRI_SWITCH_EUROISDN_T1:
+ if (q931_is_ptmp(ctrl)) {
+ } else {
+ }
+ break;
+ default:
+ break;
+ }
+
+ /*! \todo BUGBUG pri_cc_call() not written */
+ return -1;
+}
+
+/*!
+ * \brief Unsolicited indication that CC is cancelled.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_id CC record ID to deactivate.
+ *
+ * \return Nothing. The cc_id is no longer valid.
+ */
+void pri_cc_cancel(struct pri *ctrl, long cc_id)
+{
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_QSIG:
+ break;
+ case PRI_SWITCH_EUROISDN_E1:
+ case PRI_SWITCH_EUROISDN_T1:
+ if (q931_is_ptmp(ctrl)) {
+ } else {
+ }
+ break;
+ default:
+ break;
+ }
+
+ /*! \todo BUGBUG pri_cc_cancel() not written */
+}
+
+/*!
+ * \brief Request that the CC be canceled.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_id CC record ID to request deactivation.
+ *
+ * \note
+ * Will always get a PRI_SUBCMD_CC_DEACTIVATE_RSP from libpri.
+ * \note
+ * Deactivate is used in the party A to party B direction.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int pri_cc_deactivate_request(struct pri *ctrl, long cc_id)
+{
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_QSIG:
+ break;
+ case PRI_SWITCH_EUROISDN_E1:
+ case PRI_SWITCH_EUROISDN_T1:
+ if (q931_is_ptmp(ctrl)) {
+ } else {
+ }
+ break;
+ default:
+ break;
+ }
+
+ /*! \todo BUGBUG pri_cc_deactivate_request() not written */
+ return -1;
+}
+
+/* ------------------------------------------------------------------- */
+/* end pri_cc.c */
Propchange: team/group/ccss/pri_cc.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/group/ccss/pri_cc.c
------------------------------------------------------------------------------
svn:keywords = 'Author Date Id Revision'
Propchange: team/group/ccss/pri_cc.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: team/group/ccss/pri_facility.c
URL: http://svn.asterisk.org/svn-view/libpri/team/group/ccss/pri_facility.c?view=diff&rev=993&r1=992&r2=993
==============================================================================
--- team/group/ccss/pri_facility.c (original)
+++ team/group/ccss/pri_facility.c Thu Aug 20 09:38:42 2009
@@ -39,6 +39,11 @@
#include <stdlib.h>
#include <string.h>
#include <limits.h>
+
+const char *pri_facility_error2str(int facility_error_code)
+{
+ return rose_error2str(facility_error_code);
+}
static short get_invokeid(struct pri *ctrl)
{
@@ -170,6 +175,7 @@
}
/*!
+ * \internal
* \brief Convert the Q.931 type-of-number field to facility.
*
* \param ctrl D channel controller for diagnostic messages or global options.
Modified: team/group/ccss/pri_internal.h
URL: http://svn.asterisk.org/svn-view/libpri/team/group/ccss/pri_internal.h?view=diff&rev=993&r1=992&r2=993
==============================================================================
--- team/group/ccss/pri_internal.h (original)
+++ team/group/ccss/pri_internal.h Thu Aug 20 09:38:42 2009
@@ -47,9 +47,10 @@
struct q921_frame;
enum q931_state;
enum q931_mode;
+struct pri_cc_record;
/*! Maximum number of scheduled events active at the same time. */
-#define MAX_SCHED (128 + 256) /* 256 ccT2 timer events*/
+#define MAX_SCHED (128 + 256) /* 256 CC supervision timer events */
/*! \brief D channel controller structure */
struct pri {
@@ -114,6 +115,9 @@
q931_call **callpool;
q931_call *localpool;
+ /*! Active call-completion records */
+ struct pri_cc_record *cc_pool;
+
/* do we do overlap dialing */
int overlapdial;
@@ -131,6 +135,8 @@
unsigned int q931_rxcount;
#endif
+ /*! Last CC id allocated. */
+ unsigned short last_cc_id;
short last_invoke; /* Last ROSE invoke ID */
unsigned char sendfacility;
};
@@ -292,8 +298,8 @@
struct q931_party_address called;
int userl1;
int numcomplete;
- int justsignalling;
- int nochannelsignalling;
+ int cis_call;
+ int cis_auto_disconnect;
const char *useruserinfo;
int transferable;
int reversecharge;
@@ -370,8 +376,13 @@
int userl3;
int rateadaption;
- int justsignalling; /* for a signalling-only connection */
- int nochannelsignalling;
+ /*!
+ * \brief TRUE if the call is a Call Independent Signalling connection.
+ * \note The call has no B channel associated with it. (Just signalling)
+ */
+ int cis_call;
+ /*! \brief TRUE if we will auto disconnect the cis_call we originated. */
+ int cis_auto_disconnect;
int progcode; /* Progress coding */
int progloc; /* Progress Location */
@@ -388,6 +399,7 @@
int ourcallstate; /* Our call state */
int sugcallstate; /* Status call state */
+/* BUGBUG These CC elements may not be retained. */
int ccoperation; /* QSIG_CCBSREQUEST/QSIG_CCNRREQUEST */
int ccrequestresult;
int cctimer2; /* Timer for QSIG-timer2 */
@@ -473,6 +485,46 @@
0,2-7 - Reserved for future use */
};
+enum CC_STATES {
+ /*! CC is not active. */
+ CC_STATE_IDLE,
+ /*! CC has recorded call information in anticipation of CC availability. */
+ CC_STATE_RECORD_RETENTION,
+ /*! CC is available and waiting on possible CC request. */
+ CC_STATE_AVAILABLE,
+ /*! CC is requested to be activated and waiting on party B to acknowledge. */
+ CC_STATE_REQUESTED,
+ /*! CC is activated and waiting for party B to become available. */
+ CC_STATE_ACTIVATED,
+ /*! CC party B is available and waiting for status of party A. */
+ CC_STATE_B_AVAILABLE,
+ /*! CC is suspended because party A is not available. */
+ CC_STATE_SUSPENDED,
+ /*! CC is waiting for party A to initiate CC callback. */
+ CC_STATE_WAIT_CALLBACK,
+};
+
+/*! \brief Call-completion record */
+struct pri_cc_record {
+ /*! Next call-completion record in the list */
+ struct pri_cc_record *next;
+ /*! Call-completion record id */
+ long record_id;
+ /*! Call-completion state */
+ enum CC_STATES state;
+ /*! Original calling party. */
+ struct q931_party_id party_a;
+ /*! Original called party. */
+ struct q931_party_address party_b;
+
[... 357 lines stripped ...]
More information about the libpri-commits
mailing list