[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