[libpri-commits] rmudgett: branch group/issue14292 r673 - /team/group/issue14292/

SVN commits to the libpri project libpri-commits at lists.digium.com
Wed Jan 21 16:11:44 CST 2009


Author: rmudgett
Date: Wed Jan 21 16:11:44 2009
New Revision: 673

URL: http://svn.digium.com/svn-view/libpri?view=rev&rev=673
Log:
Applied the libpri-1.4-2008-12-10-ccbsccnr-0.1.0.patch
to the new team/group/issue14292 branched from the team/group/issue14068 branch.
(issue 0014292)

Modified:
    team/group/issue14292/libpri.h
    team/group/issue14292/pri.c
    team/group/issue14292/pri_facility.c
    team/group/issue14292/pri_facility.h
    team/group/issue14292/pri_internal.h
    team/group/issue14292/pri_timers.h
    team/group/issue14292/q931.c

Modified: team/group/issue14292/libpri.h
URL: http://svn.digium.com/svn-view/libpri/team/group/issue14292/libpri.h?view=diff&rev=673&r1=672&r2=673
==============================================================================
--- team/group/issue14292/libpri.h (original)
+++ team/group/issue14292/libpri.h Wed Jan 21 16:11:44 2009
@@ -333,6 +333,11 @@
 #define PRI_NSF_ATT_MULTIQUEST         0xF0
 #define PRI_NSF_CALL_REDIRECTION_SERVICE       0xF7
 
+/* ECMA 186 */
+#define PRI_CC_CCNRREQUEST		27
+#define PRI_CC_CANCEL			28
+#define PRI_CC_CCBSREQUEST		40
+
 typedef struct q931_call q931_call;
 
 /* Connected line update source code */
@@ -369,9 +374,39 @@
 	int reason;					/* Redirection reasons */
 };
 
+/* Structures for qsig_cc_facilities */
+struct qsig_cc_extension {
+	int	cc_extension_tag;
+	char	extension[256];
+};
+
+struct qsig_cc_optional_arg {
+	char	number_A[256];
+	char	number_B[256];
+	int	service;
+	struct qsig_cc_extension	cc_extension;
+};
+
+struct qsig_cc_request_res {
+	int	no_path_reservation;
+	int	retain_service;
+	struct qsig_cc_extension	cc_extension;
+};
+
 /* Command derived from Facility */
 #define CMD_REDIRECTING         1
 #define CMD_CONNECTEDLINE       2
+#define CMD_CC_CCBSREQUEST_RR   3
+#define CMD_CC_CCNRREQUEST_RR   4
+#define CMD_CC_CANCEL_INV       5
+#define CMD_CC_EXECPOSIBLE_INV  6
+#define CMD_CC_RINGOUT_INV      7
+#define CMD_CC_SUSPEND_INV      8
+#define CMD_CC_ERROR            9
+
+#define CCERROR_UNSPECIFIED		1008
+#define CCERROR_REMOTE_USER_BUSY_AGAIN	1012
+#define CCERROR_FAILURE_TO_MATCH	1013
 
 
 typedef struct cmd_connectedline {
@@ -387,12 +422,47 @@
 	q931_call *call;
 	struct pri_party_redirecting redirecting;
 } cmd_redirecting;
+
+typedef struct cmd_cc_ccbs_rr {
+	struct qsig_cc_request_res	cc_request_res;
+} cmd_cc_ccbs_rr;
+
+typedef struct cmd_cc_ccnr_rr {
+	struct qsig_cc_request_res	cc_request_res;
+} cmd_cc_ccnr_rr;
+
+typedef struct cmd_cc_cancel_inv {
+	struct qsig_cc_optional_arg	cc_optional_arg;
+} cmd_cc_cancel_inv;
+
+typedef struct cmd_cc_execposible_inv {
+	struct qsig_cc_optional_arg	cc_optional_arg;
+} cmd_cc_execposible_inv;
+
+typedef struct cmd_cc_suspend_inv {
+	struct qsig_cc_extension	cc_extension;
+} cmd_cc_suspend_inv;
+
+typedef struct cmd_cc_ringout_inv {
+	struct qsig_cc_extension	cc_extension;
+} cmd_cc_ringout_inv;
+
+typedef struct cmd_cc_error {
+	int	error_value;
+} cmd_cc_error;
 
 typedef	struct subcommand {
 	int cmd;
 	union {
 		cmd_connectedline      connectedline;
 		cmd_redirecting        redirecting;
+		cmd_cc_ccbs_rr         cc_ccbs_rr;
+		cmd_cc_ccnr_rr         cc_ccnr_rr;
+		cmd_cc_cancel_inv      cc_cancel_inv;
+		cmd_cc_execposible_inv cc_execposible_inv;
+		cmd_cc_suspend_inv     cc_suspend_inv;
+		cmd_cc_ringout_inv     cc_ringout_inv;
+		cmd_cc_error           cc_error;
 	};
 } subcommand;
 
@@ -432,6 +502,7 @@
 	char callednum[256];
 	int calledpres;
 	int calledplan;
+	struct subcommands subcmds;
 } pri_event_ringing;
 
 typedef struct pri_event_answer {
@@ -447,6 +518,7 @@
 	char connectednum[256];
 	char connectedname[256];
 	int source;
+	struct subcommands subcmds;
 } pri_event_answer;
 
 typedef struct pri_event_facname {
@@ -502,6 +574,7 @@
 	char origcallednum[256];
 	int callingplanorigcalled;		/* Dialing plan of Originally Called Number */
 	int origredirectingreason;
+	struct subcommands subcmds;
 } pri_event_ring;
 
 typedef struct pri_event_hangup {
@@ -512,6 +585,7 @@
 	q931_call *call;			/* Opaque call pointer */
 	long aoc_units;				/* Advise of Charge number of charged units */
 	char useruserinfo[260];		/* User->User info */
+	struct subcommands subcmds;
 } pri_event_hangup;	
 
 typedef struct pri_event_restart_ack {
@@ -684,6 +758,11 @@
 
 /* Create a new call */
 q931_call *pri_new_call(struct pri *pri);
+q931_call *pri_new_nochannel_call(struct pri *pri, int *cr);
+
+q931_call *pri_find_call(struct pri *pri, int cr);
+
+void pri_call_set_cc_operation(q931_call *call, int cc_operation);
 
 /* Retrieve CRV reference for GR-303 calls.  Returns >0 on success. */
 int pri_get_crv(struct pri *pri, q931_call *call, int *callmode);
@@ -710,6 +789,10 @@
 int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int complete);
 int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres);
 int pri_sr_set_redirecting(struct pri_sr *sr, char *name, char *num, int plan, int pres, int reason);
+
+int pri_sr_set_ccringout(struct pri_sr *sr, int ccringout);
+int pri_sr_set_ccbsnr(struct pri_sr *sr, int ccbsnr);
+
 #define PRI_USER_USER_TX
 /* Set the user user field.  Warning!  don't send binary data accross this field */
 void pri_sr_set_useruser(struct pri_sr *sr, const char *userchars);
@@ -720,6 +803,9 @@
 
 /* Set a call has a call indpendent signalling connection (i.e. no bchan) */
 int pri_sr_set_connection_call_independent(struct pri_sr *req);
+
+/* Set a no channel call (i.e. QSIG-CCBS/CCNR) */
+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, decativates */
 int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
@@ -824,6 +910,7 @@
 #define PRI_TIMER_TM20	28	/* maximum time avaiting XID response */
 #define PRI_TIMER_NM20	29	/* number of XID retransmits */
 
+#define PRI_TIMER_CCBST2	30	/* maximum time on completion of CC Call */
 /* Get PRI version */
 const char *pri_get_version(void);
 

Modified: team/group/issue14292/pri.c
URL: http://svn.digium.com/svn-view/libpri/team/group/issue14292/pri.c?view=diff&rev=673&r1=672&r2=673
==============================================================================
--- team/group/issue14292/pri.c (original)
+++ team/group/issue14292/pri.c Wed Jan 21 16:11:44 2009
@@ -166,6 +166,8 @@
 		return PRI_TIMER_T321;
 	else if (!strcasecmp(timer, "T322"))
 		return PRI_TIMER_T322;
+	else if (!strcasecmp(timer, "CCT2"))
+		return PRI_TIMER_CCBST2;
 	else
 		return -1;
 }
@@ -752,6 +754,17 @@
 	return q931_new_call(pri);
 }
 
+q931_call *pri_new_nochannel_call(struct pri *pri, int *cr)
+{
+	q931_call *call;
+	if (!pri)
+		return NULL;
+	call = q931_new_call(pri);
+	if (cr)
+		*cr = call->cr;
+	return call;
+}
+
 void pri_dump_event(struct pri *pri, pri_event *e)
 {
 	if (!pri || !e)
@@ -794,6 +807,15 @@
 	return 0;
 }
 
+int pri_sr_set_no_channel_call(struct pri_sr *req)
+{
+	if (!req)
+		return -1;
+
+	req->nochannelsignalling = 1;
+	return 0;
+}
+
 /* Don't call any other pri functions on this */
 int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called,
 					int calledplan)
@@ -944,6 +966,10 @@
 	struct q921_frame *f;
 	int q921outstanding = 0;
 #endif
+	q931_call *cur, *prev;
+	struct pri *master;
+	int counter = 0;
+
 	if (!pri)
 		return NULL;
 
@@ -977,8 +1003,55 @@
 	len += sprintf(buf + len, "T309 Timer: %d\n", pri->timers[PRI_TIMER_T309]);
 	len += sprintf(buf + len, "T313 Timer: %d\n", pri->timers[PRI_TIMER_T313]);
 	len += sprintf(buf + len, "N200 Counter: %d\n", pri->timers[PRI_TIMER_N200]);
+	len += sprintf(buf + len, "CCT2 Timer: %d\n", pri->timers[PRI_TIMER_CCBST2]);
+	/* Find the master  - He has the call pool */
+	if (pri->master)
+		master = pri->master;
+	else
+		master = pri;
+
+	cur = *master->callpool;
+	prev = NULL;
+	while(cur) {
+		if (cur->cctimer2) {
+			struct timeval tv;
+			int time_ms_to_go, time_to_go_min, time_to_go_sec;
+			gettimeofday(&tv, NULL);
+			time_ms_to_go = (pri->pri_sched[cur->cctimer2].when.tv_sec - tv.tv_sec)*1000;
+			time_to_go_min = time_ms_to_go/1000/60;
+			time_to_go_sec = (time_ms_to_go-(time_to_go_min*60*1000))/1000;
+
+			len += sprintf(buf + len, "%d. Active Q.931 Call: %x cr=%d: (%dmin %dsec)\n",
+								++counter, (int)cur, cur->cr,
+								time_to_go_min, time_to_go_sec);
+		} else {
+			len += sprintf(buf + len, "%d. Active Q.931 Call: %x cr=%d\n", ++counter, (int)cur, cur->cr);
+		}
+		cur = cur->next;
+	}
 
 	return strdup(buf);
+}
+
+q931_call *pri_find_call(struct pri *pri, int cr)
+{
+	q931_call *cur;
+	struct pri *master;
+
+	/* Find the master  - He has the call pool */
+	if (pri->master)
+		master = pri->master;
+	else
+		master = pri;
+	
+	cur = *master->callpool;
+	while(cur) {
+		if (cur->cr == cr)
+			return cur;
+		cur = cur->next;
+	}
+
+	return NULL;
 }
 
 int pri_get_crv(struct pri *pri, q931_call *call, int *callmode)
@@ -1052,3 +1125,20 @@
 	sr->redirectingreason = reason;
 	return 0;
 }
+
+int pri_sr_set_ccringout(struct pri_sr *sr, int ccringout)
+{
+	sr->ccringout = ccringout;
+	return 0;
+}
+
+int pri_sr_set_ccbsnr(struct pri_sr *sr, int ccbsnr)
+{
+	sr->ccbsnr = ccbsnr;
+	return 0;
+}
+
+void pri_call_set_cc_operation(q931_call *call, int cc_operation)
+{
+	call->ccoperation = cc_operation;
+}

Modified: team/group/issue14292/pri_facility.c
URL: http://svn.digium.com/svn-view/libpri/team/group/issue14292/pri_facility.c?view=diff&rev=673&r1=672&r2=673
==============================================================================
--- team/group/issue14292/pri_facility.c (original)
+++ team/group/issue14292/pri_facility.c Wed Jan 21 16:11:44 2009
@@ -3589,6 +3589,289 @@
 	return 0;
 }
 
+/* ===== Begin Call Completion Supplementary Service (ETS 300 366/ECMA 186) ===== */
+/* operationId e.g. QSIG_CCBSRINGOUT, QSIG_CC_CANCEL */
+int add_qsigCcInv_facility_ie (struct pri *pri, q931_call *c, int messagetype)
+{
+	int i = 0;
+	unsigned char buffer[256];
+	struct rose_component *comp = NULL, *compstk[10];
+	int compsp = 0;
+	u_int8_t operationId = c->ccoperation;
+
+	/* 1 Byte 	   0x80 | 0x1F = 9F	 Protocol Profile */
+	buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
+
+	/* Interpretation component */
+	ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i); /* 2. Byte NEtwork Facility Extension 0xAA = ASN1_CONTEXT_SPECIFIC(0x80) | (ASN1_CONSTRUCTOR 0x20)  0x0A (Tag laut Standard) */
+	ASN1_PUSH(compstk, compsp, comp);
+	ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);	/* (0x80, 0x01(len), 0x00) endPTNX */
+	ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);	/* (0x82, 0x01(len), 0x00) endPTNX */
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+
+	ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);   /* 0x8B, 0x01(len), 0x00 discard */
+	ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);			 /* 0xA1, 0xXX (len of Invoke Sequenz) invoke APDU */
+	ASN1_PUSH(compstk, compsp, comp);
+
+	/* Invoke ID */
+	ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));   /* 0x02 0x01 0xXX */
+
+	/* Operation ID: QSIG_CCBSRINGOUT, QSIG_CC_CANCEL */
+	ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, operationId); /* 0x02 0x01 0x1f/0x1c */
+
+	/* CcExtension */
+	ASN1_ADD_SIMPLE(comp, ASN1_NULL, buffer, i); /* 0x05 0x00 */
+
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+
+	if (pri_call_apdu_queue(c, messagetype, buffer, i, NULL, NULL))
+		return -1;
+	
+	return 0;
+}
+
+static int rose_cc_ringout_inv_decode(struct pri *pri, struct qsig_cc_extension *cc_extension, struct rose_component *choice, int len) {
+	int i = 0;
+	cc_extension->cc_extension_tag = 0;
+
+	do {
+		switch(choice->type) {
+		case (ASN1_NULL):   /* none NULL */
+			cc_extension->cc_extension_tag = ASN1_NULL;
+			return 0;
+
+		case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_14):   /* single [14] IMPLICIT Extension */
+			cc_extension->cc_extension_tag = ASN1_TAG_14;
+			return 0;
+
+
+		case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_15):   /* multiple [15] IMPLICIT SEQUENCE OF Extension */
+			cc_extension->cc_extension_tag = ASN1_TAG_15;
+			return 0;
+
+		default:
+			if (choice->type == 0 && choice->len == 0) {
+				return 0;
+			}
+			pri_message(pri, "!! Invalid ss-cc-optional-Arg component received 0x%X\n", choice->type);
+			return -1;
+		}
+
+		if (i < len)
+			pri_message(pri, "     ss-cc-extension: !! not all information is handled !! i=%d / len=%d\n", i, len);
+
+		return 0;
+	}
+	while (0);
+
+	return -1;
+}
+
+static int rose_cc_optional_arg_decode(struct pri *pri, q931_call *call, struct qsig_cc_optional_arg *cc_optional_arg , struct rose_component *choice, int len) {
+	int i = 0;
+	int res = 0;
+	struct rose_component *comp = NULL;
+	unsigned char *vdata = choice->data;
+	struct addressingdataelements_presentednumberunscreened numberA;
+	struct addressingdataelements_presentednumberunscreened numberB;
+
+	cc_optional_arg->cc_extension.cc_extension_tag = 0;
+	cc_optional_arg->number_A[0] = '\0';
+	cc_optional_arg->number_B[0] = '\0';
+
+	do {
+		switch(choice->type) {
+		case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0):   /* fullArg [0] IMPLICIT SEQUENCE */
+			if (pri->debug & PRI_DEBUG_APDU)
+				pri_message(pri, "     ss-cc-optional-Arg: len=%d\n", len);
+
+			numberA.partyaddress[0] = '\0';
+
+			/* numberA */
+			GET_COMPONENT(comp, i, vdata, len);
+			res += rose_party_number_decode(pri, (u_int8_t *)comp, comp->len + 2, &numberA);
+			if (res < 0)
+				return -1;
+			comp->len = res;
+			if (res > 2) {
+				if (pri->debug & PRI_DEBUG_APDU)
+					pri_message(pri, "     ss-cc-optional-Arg: Received numberA=%s\n", numberA.partyaddress);
+				strncpy(cc_optional_arg->number_A, numberA.partyaddress, 20);
+				cc_optional_arg->number_A[20] = '\0';
+			}
+			NEXT_COMPONENT(comp, i);
+
+			numberB.partyaddress[0] = '\0';
+
+			/* numberB */
+			GET_COMPONENT(comp, i, vdata, len);
+			res = rose_party_number_decode(pri, (u_int8_t *)comp, comp->len + 2, &numberB);
+			if (res < 0)
+				return -1;
+			comp->len = res;
+			if (res > 2) {
+				if (pri->debug & PRI_DEBUG_APDU)
+					pri_message(pri, "     ss-cc-optional-Arg: Received numberB=%s\n", numberB.partyaddress);
+				strncpy(cc_optional_arg->number_B, numberB.partyaddress, 20);
+				cc_optional_arg->number_B[20] = '\0';
+			}
+			NEXT_COMPONENT(comp, i);
+
+			/* service */ /* PSS1InformationElement */
+			GET_COMPONENT(comp, i, vdata, len);
+			NEXT_COMPONENT(comp, i);
+
+			/* optional */
+			for (; i < len; NEXT_COMPONENT(comp, i)) {
+				GET_COMPONENT(comp, i, vdata, len);
+				switch(comp->type) {
+				case (ASN1_NULL):   /*  */
+					cc_optional_arg->cc_extension.cc_extension_tag = ASN1_NULL;
+					NEXT_COMPONENT(comp, i);
+					break;
+				case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_14):   /*  */
+					NEXT_COMPONENT(comp, i);
+					break;
+				case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_15):   /*  */
+					NEXT_COMPONENT(comp, i);
+					break;
+				default:
+					if (comp->type == 0 && comp->len == 0) {
+						return 0;
+						break; /* Found termination characters */
+					}
+					pri_message(pri, "!! Invalid ss-cc-optional-Arg component received 0x%X\n", comp->type);
+					return -1;
+				}
+			}
+
+			if (i < len)
+				pri_message(pri, "     ss-cc-optional-Arg: !! not all information is handled !! i=%d / len=%d\n", i, len);
+
+			return 0;
+
+		/* extArg CcExtension */
+		case (ASN1_NULL):   /* none NULL */
+			cc_optional_arg->cc_extension.cc_extension_tag = ASN1_NULL;
+			return 0;
+
+		case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_14):   /* single [14] IMPLICIT Extension */
+			cc_optional_arg->cc_extension.cc_extension_tag = ASN1_TAG_14;
+			return 0;
+
+
+		case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_15):   /* multiple [15] IMPLICIT SEQUENCE OF Extension */
+			cc_optional_arg->cc_extension.cc_extension_tag = ASN1_TAG_15;
+			return 0;
+
+		default:
+			if (choice->type == 0 && choice->len == 0) {
+				return 0;
+			}
+			pri_message(pri, "!! Invalid ss-cc-optional-Arg component received 0x%X\n", choice->type);
+			return -1;
+		}
+
+		if (i < len)
+			pri_message(pri, "     ss-cc-optional-Arg: !! not all information is handled !! i=%d / len=%d\n", i, len);
+
+		return 0;
+	}
+	while (0);
+
+	return -1;
+}
+
+static int rose_cc_request_result_decode(struct pri *pri, struct qsig_cc_request_res *cc_request_res , struct rose_component *sequence, int len)
+{
+	int i = 0;
+	struct rose_component *comp = NULL;
+	unsigned char *vdata = sequence->data;
+
+	cc_request_res->no_path_reservation           = 0;  /* Default FALSE */
+	cc_request_res->retain_service                = 0;  /* Default FALSE */
+	cc_request_res->cc_extension.cc_extension_tag = 0;
+
+	/* Data checks */
+	if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
+		pri_message(pri, "Invalid cc request result argument. (Not a sequence)\n");
+		return -1;
+	}
+
+	if (sequence->len == ASN1_LEN_INDEF) {
+		len -= 4; /* For the 2 extra characters at the end
+					   * and two characters of header */
+	} else
+		len -= 2;
+
+	if (pri->debug & PRI_DEBUG_APDU)
+		pri_message(pri, "     CC-request-Return-Result: len=%d\n", len);
+
+	do {
+		/* defaults and optional */
+		for (; i < len; NEXT_COMPONENT(comp, i)) {
+			GET_COMPONENT(comp, i, vdata, len);
+			switch(comp->type) {
+			case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0):
+				/* no-path-reservation */
+				ASN1_GET_INTEGER(comp, cc_request_res->no_path_reservation);
+				NEXT_COMPONENT(comp, i);
+				if (pri->debug & PRI_DEBUG_APDU)
+					pri_message(pri, "     cc request result: Received noPathReservation=%d\n", cc_request_res->no_path_reservation);
+				break;
+
+			case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1):
+				/* retain_service */
+				ASN1_GET_INTEGER(comp, cc_request_res->retain_service);
+				NEXT_COMPONENT(comp, i);
+				if (pri->debug & PRI_DEBUG_APDU)
+					pri_message(pri, "     cc request result: Received retainService=%d\n", cc_request_res->retain_service);
+				break;
+
+			case (ASN1_NULL):   /*  */
+				cc_request_res->cc_extension.cc_extension_tag = ASN1_NULL;
+				NEXT_COMPONENT(comp, i);
+				break;
+
+			case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_14):
+				cc_request_res->cc_extension.cc_extension_tag = ASN1_TAG_14;
+				NEXT_COMPONENT(comp, i);
+				break;
+
+			case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_15):
+				cc_request_res->cc_extension.cc_extension_tag = ASN1_TAG_15;
+				NEXT_COMPONENT(comp, i);
+				break;
+
+			default:
+				if (comp->type == 0 && comp->len == 0) {
+					break; /* Found termination characters */
+				}
+				pri_message(pri, "!! Invalid ss-cc-optional-Arg component received 0x%X\n", comp->type);
+				return -1;
+			}
+		}
+
+		if (i < len)
+			pri_message(pri, "     ss-cc-optional-Arg: !! not all information is handled !! i=%d / len=%d\n", i, len);
+		return 0;
+	}
+	while (0);
+
+	return -1;
+}
+
+static int rose_ccbs_request_result_decode(struct pri *pri, struct qsig_cc_request_res *cc_request_res , struct rose_component *sequence, int len)
+{
+	return rose_cc_request_result_decode(pri, cc_request_res , sequence, len);
+}
+
+static int rose_ccnr_request_result_decode(struct pri *pri, struct qsig_cc_request_res *cc_request_res , struct rose_component *sequence, int len)
+{
+	return rose_cc_request_result_decode(pri, cc_request_res , sequence, len);
+}
+/* ===== End Call Completion Supplementary Service (ETS 300 366/ECMA 186) ===== */
+
 
 int rose_reject_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
 {
@@ -3660,6 +3943,18 @@
 }
 
 
+static subcommand *get_ptr_subcommand(subcommands *sub)
+{
+	if (sub->counter_subcmd < MAX_SUBCOMMANDS) {
+		int count = sub->counter_subcmd;
+		sub->counter_subcmd++;
+		return &sub->subcmd[count];
+	}
+
+	return NULL;
+}
+
+
 int rose_return_error_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
 {
 	int i = 0;
@@ -3668,6 +3963,7 @@
 	unsigned char *vdata = data;
 	struct rose_component *comp = NULL;
 	char *invokeidstr, *errorstr;
+	struct subcommand *c_subcmd;
 	
 	do {
 		/* Invoke ID stuff */
@@ -3714,9 +4010,39 @@
 			pri_error(pri, "\tERROR: %s\n", errorstr);
 
 			return 0;
+		} else if (pri->switchtype == PRI_SWITCH_QSIG) {
+			switch (errorvalue) {
+			case 1008:
+				errorstr = "Unspecified";
+				break;
+			case 1012:
+				errorstr = "Remote user busy again";
+				break;
+			case 1013:
+				errorstr = "Failure to match";
+				break;
+			default:
+				errorstr = "Unknown";
+			}
+
+			c_subcmd = get_ptr_subcommand(&call->subcmds);
+			if (!c_subcmd) {
+				if (pri->debug & PRI_DEBUG_APDU)
+					pri_message(pri, "ROSE RETURN ERROR %i - more than %d facilities !\n", errorvalue, MAX_SUBCOMMANDS);
+				dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+				return -1;
+			}
+
+			if (pri->debug & PRI_DEBUG_APDU)
+			{
+				pri_message(pri, "ROSE RETURN RESULT %i:   %s\n", errorvalue, errorstr);
+				dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+			}
+			c_subcmd->cmd = CMD_CC_ERROR;
+			c_subcmd->cc_error.error_value = errorvalue;
+			return 0;
 		} else {
-			pri_message(pri, "Unable to handle return result on switchtype %d!\n", pri->switchtype);
-			return -1;
+			pri_message(pri, "Unable to handle return error on switchtype %d!\n", pri->switchtype);
 		}
 
 	} while(0);
@@ -3731,6 +4057,8 @@
 	int invokeidvalue = -1;
 	unsigned char *vdata = data;
 	struct rose_component *comp = NULL;
+	int res;
+	struct subcommand *c_subcmd;
 	
 	do {
 		/* Invoke ID stuff */
@@ -3777,10 +4105,89 @@
 				return -1;
 			}
 		} else if (pri->switchtype == PRI_SWITCH_QSIG) {
-			switch (invokeidvalue) {
+			int operation_tag;
+
+			/* sequence is optional */
+			if (i >= len) 
+				return 0;
+
+			/* Data checks, sequence is optional */
+			GET_COMPONENT(comp, i, vdata, len);
+			if (comp->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
+				pri_message(pri, "No arguments on cc-return result\n");
+				return 0;
+			}
+
+			if (comp->len == ASN1_LEN_INDEF) {
+				len -= 2; /* For the 2 extra characters at the end*/
+			}
+
+			/* Traverse the contents of this sequence */
+			SUB_COMPONENT(comp, i);
+
+			/* Operation Tag */
+			GET_COMPONENT(comp, i, vdata, len);
+			CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if second ROSE component is of type 0x%x\n");
+			ASN1_GET_INTEGER(comp, operation_tag);
+			NEXT_COMPONENT(comp, i);
+
+			/* No argument - return with error */
+			if (i >= len) 
+				return -1;
+
+			/* Arguement Tag */
+			GET_COMPONENT(comp, i, vdata, len);
+			if (!comp->type)
+				return -1;
+
+			if (pri->debug & PRI_DEBUG_APDU)
+				pri_message(pri, "  [ Handling operation %d ]\n", operation_tag);
+			switch (operation_tag) {
 			case QSIG_CF_CALLREROUTING:
-				if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Successfully completed QSIG CF callRerouting!\n");
+				if (pri->debug & PRI_DEBUG_APDU)
+					pri_message(pri, "Successfully completed QSIG CF callRerouting!\n");
 				return 0;
+
+			case QSIG_CC_CCBSREQUEST:
+				c_subcmd = get_ptr_subcommand(&call->subcmds);
+				if (!c_subcmd) {
+					if (pri->debug & PRI_DEBUG_APDU)
+						pri_message(pri, "ROSE %i:  return_result CcCcbsRequest - more than %d facilities !\n", operation_tag, MAX_SUBCOMMANDS);
+					dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+					return -1;
+				}
+				if (pri->debug & PRI_DEBUG_APDU)
+				{
+					pri_message(pri, "ROSE %i:   Handle CcCcbsRequest\n", operation_tag);
+					dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+				}
+				c_subcmd->cmd = CMD_CC_CCBSREQUEST_RR;
+				res = rose_ccbs_request_result_decode(pri, &c_subcmd->cc_ccbs_rr.cc_request_res, comp, len-i);
+				return res;
+
+			case QSIG_CC_CCNRREQUEST:
+				c_subcmd = get_ptr_subcommand(&call->subcmds);
+				if (!c_subcmd) {
+					if (pri->debug & PRI_DEBUG_APDU)
+						pri_message(pri, "ROSE %i:  return_result CcCcnrRequest - more than %d facilities !\n", operation_tag, MAX_SUBCOMMANDS);
+					dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+					return -1;
+				}
+				if (pri->debug & PRI_DEBUG_APDU)
+				{
+					pri_message(pri, "ROSE %i:   Handle CcCcnrRequest\n", operation_tag);
+					dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+				}
+				c_subcmd->cmd = CMD_CC_CCNRREQUEST_RR;
+				res = rose_ccnr_request_result_decode(pri, &c_subcmd->cc_ccnr_rr.cc_request_res, comp, len-i);
+				return res;
+
+			default:
+				if (pri->debug & PRI_DEBUG_APDU) {
+					pri_message(pri, "!! Unable to handle ROSE operation %d", operation_tag);
+					dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+				}
+				return -1;
 			}
 		} else {
 			pri_message(pri, "Unable to handle return result on switchtype %d!\n", pri->switchtype);
@@ -3799,6 +4206,7 @@
 	int operation_tag;
 	unsigned char *vdata = data;
 	struct rose_component *comp = NULL, *invokeid = NULL, *operationid = NULL;
+	struct subcommand *c_subcmd;
 	
 	do {
 		/* Invoke ID stuff */
@@ -3914,6 +4322,81 @@
 				}
 				anfpr_pathreplacement_respond(pri, call, ie);
 				break;
+			case QSIG_CC_CCBSREQUEST:
+				if (pri->debug & PRI_DEBUG_APDU)
+					pri_message(pri, "ROSE %i:  invoke CcbsRequest - not handled!\n", operation_tag);
+				dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+				return -1;
+			case QSIG_CC_CCNRREQUEST:
+				if (pri->debug & PRI_DEBUG_APDU)
+					pri_message(pri, "ROSE %i:  invoke CcnrRequest - not handled!\n", operation_tag);
+				dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+				return -1;
+			case QSIG_CC_CANCEL:
+				c_subcmd = get_ptr_subcommand(&call->subcmds);
+				if (!c_subcmd) {
+					if (pri->debug & PRI_DEBUG_APDU)
+						pri_message(pri, "ROSE %i:  invoke CcCancel - more than %d facilities !\n", operation_tag, MAX_SUBCOMMANDS);
+					dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+					return -1;
+				}
+				if (pri->debug & PRI_DEBUG_APDU)
+				{
+					pri_message(pri, "ROSE %i:   Handle CcCancel\n", operation_tag);
+					dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+				}
+				c_subcmd->cmd = CMD_CC_CANCEL_INV;
+				res = rose_cc_optional_arg_decode(pri, call, &c_subcmd->cc_cancel_inv.cc_optional_arg, comp, len-i);
+				return res;
+			case QSIG_CC_EXECPOSIBLE:
+				c_subcmd = get_ptr_subcommand(&call->subcmds);
+				if (!c_subcmd) {
+					if (pri->debug & PRI_DEBUG_APDU)
+						pri_message(pri, "ROSE %i:  invoke CcExecposible - more than %d facilities !\n", operation_tag, MAX_SUBCOMMANDS);
+					dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+					return -1;
+				}
+				if (pri->debug & PRI_DEBUG_APDU)
+				{
+					pri_message(pri, "ROSE %i:   Handle CcExecposible\n", operation_tag);
+					dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+				}
+				c_subcmd->cmd = CMD_CC_EXECPOSIBLE_INV;
+				res = rose_cc_optional_arg_decode(pri, call, &c_subcmd->cc_execposible_inv.cc_optional_arg, comp, len-i);
+				return res;
+			case QSIG_CC_PATHRESERVE:
+				if (pri->debug & PRI_DEBUG_APDU)
+					pri_message(pri, "ROSE %i:  invoke CcPathreserve - not handled!\n", operation_tag);
+				dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+				return -1;
+			case QSIG_CC_RINGOUT:
+				c_subcmd = get_ptr_subcommand(&call->subcmds);
+				if (!c_subcmd) {
+					if (pri->debug & PRI_DEBUG_APDU)
+						pri_message(pri, "ROSE %i:  invoke CcRingout - more than %d facilities !\n", operation_tag, MAX_SUBCOMMANDS);
+					dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+					return -1;
+				}
+				if (pri->debug & PRI_DEBUG_APDU)
+				{
+					pri_message(pri, "ROSE %i:   Handle CcRingout\n", operation_tag);
+					dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+				}
+				c_subcmd->cmd = CMD_CC_RINGOUT_INV;
+				res = rose_cc_ringout_inv_decode(pri, &c_subcmd->cc_ringout_inv.cc_extension, comp, len-i);
+				return res;
+			case QSIG_CC_SUSPEND:
+				if (pri->debug & PRI_DEBUG_APDU)
+				{
+					pri_message(pri, "ROSE %i:   Handle CcSuspend\n", operation_tag);
+					dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+				}
+				return 0;
+			case QSIG_CC_RESUME:
+				if (pri->debug & PRI_DEBUG_APDU)
+					pri_message(pri, "ROSE %i:  invoke CcResume - not handled!\n", operation_tag);
+				dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+				return -1;
 			default:
 				if (pri->debug & PRI_DEBUG_APDU) {
 					pri_message(pri, "!! Unable to handle ROSE operation %d", operation_tag);
@@ -4097,6 +4580,95 @@
 	return 0;
 }
 
+/* ===== Begin Call Completion Supplementary Service (ETS 300 366/ECMA 186) ===== */
+/* operationId e.g. QSIG_CC_CCBS_REQUEST and QSIG_CC_CCNR_REQUEST */
+static int add_qsigCcRequestArg_facility_ie (struct pri *pri, q931_call *c)
+{
+	int size = 0;
+	int i = 0;
+	unsigned char buffer[256];
+	struct rose_component *comp = NULL, *compstk[10];
+	int compsp = 0;
+	u_int8_t operationId = c->ccoperation;
+	char *numberA = c->callernum;
+	char *numberB = c->callednum;
+ 
+	/* 1 Byte 	   0x80 | 0x1F = 9F	 Protocol Profile (0x93 wäre altes QSIG oder DDS1) */
+	buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
+
+	/* Interpretation component */
+	ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i); /* 2. Byte NEtwork Facility Extension 0xAA = ASN1_CONTEXT_SPECIFIC(0x80) | (ASN1_CONSTRUCTOR 0x20)  0x0A (Tag laut Standard) */
+	ASN1_PUSH(compstk, compsp, comp);
+
+	ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);	/* (0x80, 0x01(len), 0x00) endPTNX */
+	ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);	/* (0x82, 0x01(len), 0x00) endPTNX */
+
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+
+#if 0
+	ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);   /* 0x8B, 0x01(len), 0x00 discard */
+#endif
+	ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);			 /* 0xA1, 0xXX (len of Invoke Sequenz) invoke APDU */
+	ASN1_PUSH(compstk, compsp, comp);
+
+	/* Invoke ID */
+	ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));   /* InvokeID 0x02 0x01 0xXX */
+
+	/*CcbsRequest ::= 40 or CcnrRequest ::= 27 */
+	/* Operation ID: CCBS/CCNR */
+	ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, operationId); /* 0x02 0x01 0x28/0x1b */
+
+	/* ccbs/ccnr request argument */
+	/* PresentedNumberUnscreened */
+	ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i); /*0x30 0xXX (len)*/
+	ASN1_PUSH(compstk, compsp, comp);
+	/* (0xA0, 0x01(len)) presentationAlloweAddress  [0] PartyNumber */
+	/* (0xA1, 0xXX (len) publicPartyNumber [1] IMPLICIT PublicPartyNumber */
+	/* (0x0A, 0x01, 0x00 ) type of public party number = subscriber number */
+	/* (0x12, 0xXX (len), 0xXX .. 0xXX) numeric string */
+	size = rose_presented_number_unscreened_encode(pri, &buffer[i], PRES_ALLOWED, Q932_TON_UNKNOWN, numberA);
+	if (size < 0)
+		return -1;
+	i += size;
+
+	/* (0xA1, 0xXX (len) [1] IMPLICIT PublicPartyNumber */
+	ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
+	ASN1_PUSH(compstk, compsp, comp);
+	/* (0x0A, 0x01, 0x00 ) type of public party number = subscriber number */
+	/* (0x12, 0xXX (len), 0xXX .. 0xXX) numeric string */
+	size = rose_public_party_number_encode(pri, comp->data, 1, Q932_TON_UNKNOWN, numberB);
+	if (size < 0)
+		return -1;
+	i += size;
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+
+	/* (0x40, 0xXX (len), 0xXX .. 0xXX) pSS1InfoElement */
+	ASN1_ADD_SIMPLE(comp, (ASN1_APPLICATION | ASN1_TAG_0 ), buffer, i);
+	ASN1_PUSH(compstk, compsp, comp);
+	buffer[i++] = (0x04);	/*  add Bearer Capability IE */
+	buffer[i++] = (0x03);	/* len*/
+	buffer[i++] = (0x80);	/* ETSI Standard, Speech */
+	buffer[i++] = (0x90);	/* circuit mode, 64kbit/s */
+	buffer[i++] = (0xa3);	/* level1 protocol, a-law */
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+#if 0
+	/* can-retain-service [12] IMPLICIT BOOLEAN DEFAULT FALSE,*/
+	ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_12), buffer, i, 0);   /* 0x1C, 0x01(len), 0x00 false */
+#endif
+	/* retain-sig-connection [13] IMPLICIT BOOLEAN OPTIONAL, --TRUE: sign. connection to be retained */	 
+	ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_13), buffer, i, 1);   /* 0x1D, 0x01(len), 0x01 true */
+
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+
+	if (pri_call_apdu_queue(c, Q931_SETUP, buffer, i, NULL, NULL))
+		return -1;
+	
+	return 0;
+}
+/* ===== End Call Completion Supplementary Service (ETS 300 366/ECMA 186) ===== */
+
 int pri_call_add_standard_apdus(struct pri *pri, q931_call *call)
 {
 	if (!pri->sendfacility)
@@ -4106,6 +4678,21 @@
 		if (call->redirectingnum[0])
 			rose_diverting_leg_information2_encode(pri, call);
 		add_callername_facility_ies(pri, call, 1);
+		if (call->ccoperation) {
+			switch(call->ccoperation) {
+			case 0:
+				break;
+			case QSIG_CC_CCBSREQUEST:
+			case QSIG_CC_CCNRREQUEST:
+				add_qsigCcRequestArg_facility_ie(pri, call);
+				break;
+			case QSIG_CC_RINGOUT:
+				add_qsigCcInv_facility_ie(pri, call, Q931_SETUP);
+				break;
+			default:
+				break;
+			}
+		}
 		return 0;
 	}
 

Modified: team/group/issue14292/pri_facility.h
URL: http://svn.digium.com/svn-view/libpri/team/group/issue14292/pri_facility.h?view=diff&rev=673&r1=672&r2=673
==============================================================================
--- team/group/issue14292/pri_facility.h (original)
+++ team/group/issue14292/pri_facility.h Wed Jan 21 16:11:44 2009
@@ -81,6 +81,20 @@
 #define SS_MWI_DEACTIVATE					81
 #define SS_MWI_INTERROGATE					82
 
+/* ECMA 186 */
+#define QSIG_CC_CCNRREQUEST		PRI_CC_CCNRREQUEST /* 27 */
+#define QSIG_CC_CANCEL				PRI_CC_CANCEL      /* 28 */
+#define QSIG_CC_EXECPOSIBLE		29
+#define QSIG_CC_PATHRESERVE		30
+#define QSIG_CC_RINGOUT				31
+#define QSIG_CC_SUSPEND				32
+#define QSIG_CC_RESUME				33
+#define QSIG_CC_CCBSREQUEST		PRI_CC_CCBSREQUEST /* 40 */
+
+#define QSIG_CC_UNSPECIFIED				1008
+#define QSIG_CC_REMOTE_USER_BUSY_AGAIN	1012
+#define QSIG_CC_FAILURE_TO_MATCH			1013
+
 /* ROSE definitions and data structures */
 #define INVOKE_IDENTIFIER			0x02
 #define INVOKE_LINKED_IDENTIFIER	0x80
@@ -126,6 +140,8 @@
 #define ASN1_TAG_11				0x0b
 #define ASN1_TAG_12				0x0c
 #define ASN1_TAG_13				0x0d
+#define ASN1_TAG_14				0x0e
+#define ASN1_TAG_15				0x0f
 
 /* ASN.1 Identifier Octet - Primitive/Constructor Bit */
 #define ASN1_PC_MASK			0x20
@@ -349,6 +365,8 @@
 /* Adds the "standard" APDUs to a call */
 int pri_call_add_standard_apdus(struct pri *pri, q931_call *call);
 
+int add_qsigCcInv_facility_ie (struct pri *pri, q931_call *c, int messagetype);
+
 int asn1_dump(struct pri *pri, void *comp, int len);
 
 #endif /* _PRI_FACILITY_H */

Modified: team/group/issue14292/pri_internal.h
URL: http://svn.digium.com/svn-view/libpri/team/group/issue14292/pri_internal.h?view=diff&rev=673&r1=672&r2=673
==============================================================================
--- team/group/issue14292/pri_internal.h (original)
+++ team/group/issue14292/pri_internal.h Wed Jan 21 16:11:44 2009
@@ -53,7 +53,7 @@
 enum q931_mode;
 
 /* No more than 128 scheduled events */
-#define MAX_SCHED 128
+#define MAX_SCHED 128+256 /* 256 ccT2 timer events*/
 
 #define MAX_TIMERS 32
 
@@ -154,8 +154,11 @@
 	int redirectingpres;
 	int redirectingreason;
 	int justsignalling;
+	int nochannelsignalling;
+	int ccbsnr;
 	const char *useruserinfo;
 	int transferable;
+	int ccringout;
 };
 
 /* Internal switch types */
@@ -209,6 +212,7 @@
 	
 	int sentchannel;
 	int justsignalling;		/* for a signalling-only connection */
+	int nochannelsignalling;
 
 	int progcode;			/* Progress coding */
 	int progloc;			/* Progress Location */	
@@ -231,6 +235,12 @@
 	char callerani[256];	/* Caller */
 	char callernum[256];
 	char callername[256];
+
+	int ccoperation;		/* QSIG_CCBSREQUEST/QSIG_CCNRREQUEST */
+	int ccrequestresult;
+	int cctimer2;			/* Timer for QSIG-timer2 */
+	/* QSIG cc infos (receive) */
+	struct subcommands subcmds;
 
 	char keypad_digits[64];		/* Buffer for digits that come in KEYPAD_FACILITY */
 

Modified: team/group/issue14292/pri_timers.h
URL: http://svn.digium.com/svn-view/libpri/team/group/issue14292/pri_timers.h?view=diff&rev=673&r1=672&r2=673
==============================================================================
--- team/group/issue14292/pri_timers.h (original)
+++ team/group/issue14292/pri_timers.h Wed Jan 21 16:11:44 2009
@@ -62,6 +62,7 @@
 				-1,		/* T322 */ \
 				2500,	/* TM20 - Q.921 Appendix IV */ \
 				3,		/* NM20 - Q.921 Appendix IV */ \
+				45*60*1000	/* CC-Timer2 45 min */\
 			}
 
 /* XXX Only our default timers are setup now XXX */

Modified: team/group/issue14292/q931.c
URL: http://svn.digium.com/svn-view/libpri/team/group/issue14292/q931.c?view=diff&rev=673&r1=672&r2=673
==============================================================================
--- team/group/issue14292/q931.c (original)
+++ team/group/issue14292/q931.c Wed Jan 21 16:11:44 2009
@@ -362,6 +362,11 @@
 	/* We are ready to transmit single IE only */
 	if (order > 1)
 		return 0;
+
+	if (call->nochannelsignalling) {
+		ie->data[pos++] = 0xac;
+		return pos + 2;
+	}
 	
 	if (call->justsignalling) {
 		ie->data[pos++] = 0xac; /* Read the standards docs to figure this out
@@ -804,7 +809,13 @@
 		ie->data[1] = 0x90;
 		return 4;
 	}
-	
+
+	if (call->nochannelsignalling) {
+		ie->data[0] = 0xa8;
+		ie->data[1] = 0x80;
+		return 4;
+	}
+
 	if (call->justsignalling) {
 		ie->data[0] = 0xa8;
 		ie->data[1] = 0x80;
@@ -2958,6 +2969,18 @@
 	q931_release(pri, c, PRI_CAUSE_NORMAL_CLEARING);
 }
 
+static void pri_cctimer2_timeout(void *data)
+{
+	int cause = 16;
+	struct q931_call *c = data;
+	struct pri *pri = c->pri;
+	if (pri->debug & PRI_DEBUG_Q931_STATE)
+		pri_message(pri, "Timed out no-channel call\n");
+	c->ccoperation = QSIG_CC_CANCEL;
+	/* normal clear cause */
+	q931_hangup(pri, c, cause);
+}
+
 int q931_connect(struct pri *pri, q931_call *c, int channel, int nonisdn)
 {
 	if (channel) { 
@@ -2989,7 +3012,7 @@
 	return send_message(pri, c, Q931_CONNECT, connect_ies);
 }
 
-static int release_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, -1 };
+static int release_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, Q931_IE_FACILITY, -1 };
 
 int q931_release(struct pri *pri, q931_call *c, int cause)
 {
@@ -3037,7 +3060,7 @@
 	return send_message(pri, c, Q931_RESTART, restart_ies);
 }
 
-static int disconnect_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, -1 };
+static int disconnect_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, Q931_IE_FACILITY, -1 };
 
 int q931_disconnect(struct pri *pri, q931_call *c, int cause)
 {
@@ -3064,6 +3087,8 @@
 static int gr303_setup_ies[] =  { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, -1 };
 
 static int cis_setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_CALLED_PARTY_NUMBER, -1 };
+
+static int nochannel_setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_SENDING_COMPLETE, -1 };
 
 int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
 {
@@ -3090,6 +3115,7 @@
 	c->nonisdn = req->nonisdn;
 	c->newcall = 0;
 	c->justsignalling = req->justsignalling;		
+	c->nochannelsignalling = req->nochannelsignalling;		
 	c->complete = req->numcomplete; 
 	if (req->exclusive) 
 		c->chanflags = FLAG_EXCLUSIVE;
@@ -3150,12 +3176,19 @@
 	else
 		c->progressmask = 0;
 
+	if (req->ccringout)
+		c->ccoperation = QSIG_CC_RINGOUT;
+	if (req->ccbsnr)
+		c->ccoperation = req->ccbsnr;
+
 	pri_call_add_standard_apdus(pri, c);
 
 	if (pri->subchannel && !pri->bri)
 		res = send_message(pri, c, Q931_SETUP, gr303_setup_ies);
 	else if (c->justsignalling)
 		res = send_message(pri, c, Q931_SETUP, cis_setup_ies);
+	else if (c->nochannelsignalling)
+		res = send_message(pri, c, Q931_SETUP, nochannel_setup_ies);

[... 348 lines stripped ...]



More information about the libpri-commits mailing list