[svn-commits] rmudgett: branch group/ccss r1274 - /team/group/ccss/
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Mon Nov 9 16:37:46 CST 2009
Author: rmudgett
Date: Mon Nov 9 16:37:42 2009
New Revision: 1274
URL: http://svnview.digium.com/svn/libpri?view=rev&rev=1274
Log:
Current call completion work in progress.
* Preliminary support for sending cc-available messages.
* Collected struct pri and struct q931_call cc elements into a substruct.
Modified:
team/group/ccss/libpri.h
team/group/ccss/pri_cc.c
team/group/ccss/pri_facility.c
team/group/ccss/pri_facility.h
team/group/ccss/pri_internal.h
team/group/ccss/q931.c
Modified: team/group/ccss/libpri.h
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/libpri.h?view=diff&rev=1274&r1=1273&r2=1274
==============================================================================
--- team/group/ccss/libpri.h (original)
+++ team/group/ccss/libpri.h Mon Nov 9 16:37:42 2009
@@ -1490,7 +1490,7 @@
void pri_status_req_rsp(struct pri *ctrl, int invoke_id, int status);
/* Call-completion function prototypes */
-void pri_cc_available(struct pri *ctrl, q931_call *call);
+long pri_cc_available(struct pri *ctrl, q931_call *call);
int pri_cc_req(struct pri *ctrl, long cc_id, int mode);
void pri_cc_req_rsp(struct pri *ctrl, long cc_id, int status);
void pri_cc_remote_user_free(struct pri *ctrl, long cc_id);
Modified: team/group/ccss/pri_cc.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_cc.c?view=diff&rev=1274&r1=1273&r2=1274
==============================================================================
--- team/group/ccss/pri_cc.c (original)
+++ team/group/ccss/pri_cc.c Mon Nov 9 16:37:42 2009
@@ -58,7 +58,7 @@
{
struct pri_cc_record *cc_record;
- for (cc_record = ctrl->cc_pool; cc_record; cc_record = cc_record->next) {
+ 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;
@@ -69,7 +69,6 @@
}
#endif
-#if defined(BUGBUG_NOT_USED_YET)
/*!
* \internal
* \brief Find a cc_record by the PTMP linkage_id.
@@ -84,7 +83,7 @@
{
struct pri_cc_record *cc_record;
- for (cc_record = ctrl->cc_pool; cc_record; cc_record = cc_record->next) {
+ 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;
@@ -93,7 +92,6 @@
return cc_record;
}
-#endif
/*!
* \internal
@@ -109,7 +107,7 @@
{
struct pri_cc_record *cc_record;
- for (cc_record = ctrl->cc_pool; cc_record; cc_record = cc_record->next) {
+ for (cc_record = ctrl->cc.pool; cc_record; cc_record = cc_record->next) {
if (cc_record->record_id == cc_id) {
/* Found the record */
break;
@@ -135,7 +133,7 @@
{
struct pri_cc_record *cc_record;
- for (cc_record = ctrl->cc_pool; cc_record; cc_record = cc_record->next) {
+ 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 */
@@ -152,6 +150,69 @@
#if defined(BUGBUG_NOT_USED_YET)
/*!
* \internal
+ * \brief Allocate a new cc_record reference id.
+ *
+ * \param ctrl D channel controller.
+ *
+ * \retval reference_id on success.
+ * \retval -1 on error.
+ */
+static int pri_cc_new_reference_id(struct pri *ctrl)
+{
+ long reference_id;
+ long first_id;
+
+ ctrl->cc.last_reference_id = (ctrl->cc.last_reference_id + 1) & 0x7F;
+ reference_id = ctrl->cc.last_reference_id;
+ first_id = reference_id;
+ while (pri_cc_find_by_reference(ctrl, reference_id)) {
+ ctrl->cc.last_reference_id = (ctrl->cc.last_reference_id + 1) & 0x7F;
+ reference_id = ctrl->cc.last_reference_id;
+ if (reference_id == first_id) {
+ /* We probably have a resource leak. */
+ pri_error(ctrl, "PTMP call completion reference id exhaustion!\n");
+ reference_id = -1;
+ break;
+ }
+ }
+
+ return reference_id;
+}
+#endif
+
+/*!
+ * \internal
+ * \brief Allocate a new cc_record linkage id.
+ *
+ * \param ctrl D channel controller.
+ *
+ * \retval linkage_id on success.
+ * \retval -1 on error.
+ */
+static int pri_cc_new_linkage_id(struct pri *ctrl)
+{
+ long linkage_id;
+ long first_id;
+
+ ctrl->cc.last_linkage_id = (ctrl->cc.last_linkage_id + 1) & 0x7F;
+ linkage_id = ctrl->cc.last_linkage_id;
+ first_id = linkage_id;
+ while (pri_cc_find_by_linkage(ctrl, linkage_id)) {
+ ctrl->cc.last_linkage_id = (ctrl->cc.last_linkage_id + 1) & 0x7F;
+ linkage_id = ctrl->cc.last_linkage_id;
+ if (linkage_id == first_id) {
+ /* We probably have a resource leak. */
+ pri_error(ctrl, "PTMP call completion linkage id exhaustion!\n");
+ linkage_id = -1;
+ break;
+ }
+ }
+
+ return linkage_id;
+}
+
+/*!
+ * \internal
* \brief Allocate a new cc_record id.
*
* \param ctrl D channel controller.
@@ -164,16 +225,16 @@
long record_id;
long first_id;
- record_id = ++ctrl->last_cc_id;
+ record_id = ++ctrl->cc.last_record_id;
first_id = record_id;
while (pri_cc_find_by_id(ctrl, record_id)) {
- record_id = ++ctrl->last_cc_id;
+ record_id = ++ctrl->cc.last_record_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");
+ pri_error(ctrl, "Too many call completion records!\n");
record_id = -1;
break;
}
@@ -181,7 +242,6 @@
return record_id;
}
-#endif
#if defined(BUGBUG_NOT_USED_YET)
/*!
@@ -198,7 +258,7 @@
struct pri_cc_record **prev;
struct pri_cc_record *current;
- for (prev = &ctrl->cc_pool, current = ctrl->cc_pool; current;
+ for (prev = &ctrl->cc.pool, current = ctrl->cc.pool; current;
prev = ¤t->next, current = current->next) {
if (current == doomed) {
*prev = current->next;
@@ -211,46 +271,46 @@
}
#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)
+ * \param call Q.931 call leg.
+ *
+ * \retval pointer to new call completion record
+ * \retval NULL if failed
+ */
+static struct pri_cc_record *pri_cc_new_record(struct pri *ctrl, q931_call *call)
{
struct pri_cc_record *cc_record;
long record_id;
+ record_id = pri_cc_new_id(ctrl);
+ if (record_id < 0) {
+ return NULL;
+ }
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;
+ return NULL;
}
/* 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);
+ cc_record->call_linkage_id = CC_PTMP_INVALID_ID;/* So it will never be found this way */
+ cc_record->ccbs_reference_id = CC_PTMP_INVALID_ID;/* So it will never be found this way */
+ cc_record->party_a = call->cc.party_a;
+ cc_record->party_b = call->cc.party_b;
+ cc_record->party_b_is_remote = call->cc.party_b_is_remote;
+/* BUGBUG need to record BC, HLC, and LLC from initial SETUP */
/*! \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
+ cc_record->next = ctrl->cc.pool;
+ ctrl->cc.pool = cc_record;
+
+ return cc_record;
+}
/*!
* \brief Indicate to the far end that CCBS/CCNR is available.
@@ -262,28 +322,68 @@
* 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:
+ * \retval cc_id on success for subsequent reference.
+ * \retval -1 on error.
+ */
+long pri_cc_available(struct pri *ctrl, q931_call *call)
+{
+ struct pri_cc_record *cc_record;
+ long cc_id;
+
+ if (call->cc.record) {
+ /* This call is already associated with call completion. */
+ return -1;
+ }
+
+ cc_record = NULL;
+
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_QSIG:
+ cc_record = pri_cc_new_record(ctrl, call);
+ if (!cc_record) {
+ break;
+ }
+
/*
* 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;
- }
+ cc_record->state = CC_STATE_AVAILABLE;
+ break;
+ case PRI_SWITCH_EUROISDN_E1:
+ case PRI_SWITCH_EUROISDN_T1:
+ if (q931_is_ptmp(ctrl)) {
+ int linkage_id;
+
+ linkage_id = pri_cc_new_linkage_id(ctrl);
+ if (linkage_id < 0) {
+ break;
+ }
+ cc_record = pri_cc_new_record(ctrl, call);
+ if (!cc_record) {
+ break;
+ }
+ cc_record->call_linkage_id = linkage_id;
+ } else {
+ cc_record = pri_cc_new_record(ctrl, call);
+ if (!cc_record) {
+ break;
+ }
+ }
+ cc_record->state = CC_STATE_PENDING_AVAILABLE;
+ break;
+ default:
+ break;
+ }
+
+ call->cc.record = cc_record;
+ if (cc_record) {
+ cc_id = cc_record->record_id;
+ } else {
+ cc_id = -1;
+ }
+ return cc_id;
}
/*!
@@ -309,10 +409,6 @@
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) {
Modified: team/group/ccss/pri_facility.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_facility.c?view=diff&rev=1274&r1=1273&r2=1274
==============================================================================
--- team/group/ccss/pri_facility.c (original)
+++ team/group/ccss/pri_facility.c Mon Nov 9 16:37:42 2009
@@ -3336,6 +3336,111 @@
break;
}
return send_facility_error(ctrl, call, invoke_id, rose_err);
+}
+
+/*!
+ * \internal
+ * \brief Encode ETSI PTP call completion event operation message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param pos Starting position to encode the facility ie contents.
+ * \param end End of facility ie contents encoding data buffer.
+ * \param call Call leg from which to encode message.
+ * \param operation PTP call completion event operation to encode.
+ *
+ * \retval Start of the next ASN.1 component to encode on success.
+ * \retval NULL on error.
+ */
+static unsigned char *enc_etsi_ptp_cc_operation(struct pri *ctrl, unsigned char *pos,
+ unsigned char *end, q931_call *call, enum rose_operation operation)
+{
+ struct rose_msg_invoke msg;
+
+ pos = facility_encode_header(ctrl, pos, end, NULL);
+ if (!pos) {
+ return NULL;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ msg.invoke_id = get_invokeid(ctrl);
+ msg.operation = operation;
+
+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+ return pos;
+}
+
+/*!
+ * \internal
+ * \brief Encode ETSI PTMP call completion available message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param pos Starting position to encode the facility ie contents.
+ * \param end End of facility ie contents encoding data buffer.
+ * \param call Call leg from which to encode message.
+ *
+ * \retval Start of the next ASN.1 component to encode on success.
+ * \retval NULL on error.
+ */
+static unsigned char *enc_etsi_ptmp_cc_available(struct pri *ctrl, unsigned char *pos,
+ unsigned char *end, q931_call *call)
+{
+ struct rose_msg_invoke msg;
+
+ pos = facility_encode_header(ctrl, pos, end, NULL);
+ if (!pos) {
+ return NULL;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ msg.invoke_id = get_invokeid(ctrl);
+ msg.operation = ROSE_ETSI_CallInfoRetain;
+
+ msg.args.etsi.CallInfoRetain.call_linkage_id = call->cc.record->call_linkage_id;
+
+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+ return pos;
+}
+
+/*!
+ * \brief Encode and queue a cc-available message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param call Call leg from which to encode call completion available.
+ * \param msgtype Q.931 message type to put facility ie in.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int rose_cc_available_encode(struct pri *ctrl, q931_call *call, int msgtype)
+{
+ unsigned char buffer[256];
+ unsigned char *end;
+
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_EUROISDN_E1:
+ case PRI_SWITCH_EUROISDN_T1:
+ if (q931_is_ptmp(ctrl)) {
+ end =
+ enc_etsi_ptmp_cc_available(ctrl, buffer, buffer + sizeof(buffer), call);
+ } else {
+ end =
+ enc_etsi_ptp_cc_operation(ctrl, buffer, buffer + sizeof(buffer), call,
+ ROSE_ETSI_CCBS_T_Available);
+ }
+ break;
+ case PRI_SWITCH_QSIG:
+ /* Q.SIG does not have a cc-available type message. */
+ return 0;
+ default:
+ return -1;
+ }
+ if (!end) {
+ return -1;
+ }
+
+ return pri_call_apdu_queue(call, msgtype, buffer, end - buffer, NULL, NULL);
}
/*!
Modified: team/group/ccss/pri_facility.h
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_facility.h?view=diff&rev=1274&r1=1273&r2=1274
==============================================================================
--- team/group/ccss/pri_facility.h (original)
+++ team/group/ccss/pri_facility.h Mon Nov 9 16:37:42 2009
@@ -87,6 +87,8 @@
int rose_connected_name_encode(struct pri *pri, q931_call *call, int messagetype);
int rose_called_name_encode(struct pri *pri, q931_call *call, int messagetype);
+int rose_cc_available_encode(struct pri *ctrl, q931_call *call, int msgtype);
+
/* Use this function to queue a facility-IE born APDU onto a call
* call is the call to use, messagetype is any one of the Q931 messages,
* apdu is the apdu data, apdu_len is the length of the apdu data */
Modified: team/group/ccss/pri_internal.h
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_internal.h?view=diff&rev=1274&r1=1273&r2=1274
==============================================================================
--- team/group/ccss/pri_internal.h (original)
+++ team/group/ccss/pri_internal.h Mon Nov 9 16:37:42 2009
@@ -116,9 +116,6 @@
q931_call **callpool;
q931_call *localpool;
- /*! Active call-completion records */
- struct pri_cc_record *cc_pool;
-
/* do we do overlap dialing */
int overlapdial;
@@ -136,10 +133,20 @@
unsigned int q931_rxcount;
#endif
- /*! Last CC id allocated. */
- unsigned short last_cc_id;
short last_invoke; /* Last ROSE invoke ID */
unsigned char sendfacility;
+
+ /*! Call completion */
+ struct {
+ /*! Active CC records */
+ struct pri_cc_record *pool;
+ /*! Last CC record id allocated. */
+ unsigned short last_record_id;
+ /*! Last CC PTMP reference id allocated. (0-127) */
+ unsigned char last_reference_id;
+ /*! Last CC PTMP linkage id allocated. (0-127) */
+ unsigned char last_linkage_id;
+ } cc;
};
/*! \brief Maximum name length plus null terminator (From ECMA-164) */
@@ -413,11 +420,6 @@
enum Q931_CALL_STATE ourcallstate; /* Our call state */
enum Q931_CALL_STATE 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 */
-
int ani2; /* ANI II */
/*! Buffer for digits that come in KEYPAD_FACILITY */
@@ -518,6 +520,24 @@
/* These valid in master call only */
struct q931_call *subcalls[Q931_MAX_TEI];
int pri_winner;
+
+/* BUGBUG These CC elements will not be retained. (At least in this form) */
+ int ccoperation; /* QSIG_CCBSREQUEST/QSIG_CCNRREQUEST */
+ int ccrequestresult;
+ int cctimer2; /* Timer for QSIG-timer2 */
+
+ /* Call completion */
+ struct {
+ /*! CC record associated with this call. */
+ struct pri_cc_record *record;
+ /*! Original calling party. */
+ struct q931_party_id party_a;
+ /*! Original called party. */
+ struct q931_party_address party_b;
+ /*! TRUE if the remote party is party B. */
+ unsigned char party_b_is_remote;
+/* BUGBUG need to record BC, HLC, and LLC from initial SETUP */
+ } cc;
};
enum CC_STATES {
@@ -525,6 +545,8 @@
CC_STATE_IDLE,
/*! CC has recorded call information in anticipation of CC availability. */
CC_STATE_RECORD_RETENTION,
+ /*! CC is available and waiting on ALERTING or DISCONNECT to go out. */
+ CC_STATE_PENDING_AVAILABLE,
/*! 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. */
@@ -539,6 +561,9 @@
CC_STATE_WAIT_CALLBACK,
};
+/* Invalid PTMP call completion reference and linkage id value. */
+#define CC_PTMP_INVALID_ID 0xFF
+
/*! \brief Call-completion record */
struct pri_cc_record {
/*! Next call-completion record in the list */
@@ -551,6 +576,7 @@
struct q931_party_id party_a;
/*! Original called party. */
struct q931_party_address party_b;
+/* BUGBUG need to record BC, HLC, and LLC from initial SETUP */
/*! TRUE if the remote party is party B. */
unsigned char party_b_is_remote;
Modified: team/group/ccss/q931.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/q931.c?view=diff&rev=1274&r1=1273&r2=1274
==============================================================================
--- team/group/ccss/q931.c (original)
+++ team/group/ccss/q931.c Mon Nov 9 16:37:42 2009
@@ -4328,6 +4328,17 @@
break;
}
+ if (c->cc.record) {
+ switch (c->cc.record->state) {
+ case CC_STATE_PENDING_AVAILABLE:
+ c->cc.record->state = CC_STATE_AVAILABLE;
+ rose_cc_available_encode(ctrl, c, Q931_ALERTING);
+ break;
+ default:
+ break;
+ }
+ }
+
return send_message(ctrl, c, Q931_ALERTING, alerting_ies);
}
@@ -4557,6 +4568,18 @@
c->causecode = CODE_CCITT;
c->causeloc = LOC_PRIV_NET_LOCAL_USER;
c->sendhangupack = 1;
+
+ if (c->cc.record) {
+ switch (c->cc.record->state) {
+ case CC_STATE_PENDING_AVAILABLE:
+ c->cc.record->state = CC_STATE_AVAILABLE;
+ rose_cc_available_encode(ctrl, c, Q931_DISCONNECT);
+ break;
+ default:
+ break;
+ }
+ }
+
pri_schedule_del(ctrl, c->retranstimer);
c->retranstimer = pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T305], pri_disconnect_timeout, c);
return send_message(ctrl, c, Q931_DISCONNECT, disconnect_ies);
@@ -4734,6 +4757,11 @@
c->ccoperation = req->ccbsnr;
pri_call_add_standard_apdus(ctrl, c);
+
+ /* Save the initial cc-parties. */
+ c->cc.party_a = c->local_id;
+ c->cc.party_b = c->called;
+ c->cc.party_b_is_remote = 1;
if (ctrl->subchannel && !ctrl->bri)
res = send_message(ctrl, c, Q931_SETUP, gr303_setup_ies);
@@ -6640,6 +6668,11 @@
q931_release_complete(ctrl, c, PRI_CAUSE_BEARERCAPABILITY_NOTIMPL);
break;
}
+
+ /* Save the initial cc-parties. (Incoming SETUP can only be a master call.) */
+ c->cc.party_a = c->remote_id;
+ c->cc.party_b = c->called;
+ c->cc.party_b_is_remote = 0;
q931_fill_ring_event(ctrl, c);
return Q931_RES_HAVEEVENT;
More information about the svn-commits
mailing list