Split justsignalling into cis_call and cis_auto_disconnect functionality.

git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1042 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
Richard Mudgett 2009-08-31 17:24:19 +00:00
parent 61f7a372d9
commit e7c9ecb1b2
4 changed files with 88 additions and 27 deletions

View File

@ -599,7 +599,7 @@ typedef struct pri_event_hangup {
long aoc_units; /* Advise of Charge number of charged units */
char useruserinfo[260]; /* User->User info */
struct pri_subcommands *subcmds;
} pri_event_hangup;
} pri_event_hangup;
typedef struct pri_event_restart_ack {
int e;
@ -617,7 +617,7 @@ typedef struct pri_event_proceeding {
q931_call *call;
struct pri_subcommands *subcmds;
} pri_event_proceeding;
typedef struct pri_event_setup_ack {
int e;
int channel;
@ -681,7 +681,7 @@ typedef int (*pri_io_cb)(struct pri *pri, void *buf, int buflen);
/* Create a D-channel on a given file descriptor. The file descriptor must be a
channel operating in HDLC mode with FCS computed by the fd's driver. Also it
must be NON-BLOCKING! Frames received on the fd should include FCS. Nodetype
must be NON-BLOCKING! Frames received on the fd should include FCS. Nodetype
must be one of PRI_NETWORK or PRI_CPE. switchtype should be PRI_SWITCH_* */
struct pri *pri_new(int fd, int nodetype, int switchtype);
struct pri *pri_new_bri(int fd, int ptpmode, int nodetype, int switchtype);
@ -856,9 +856,18 @@ void pri_call_set_useruser(q931_call *sr, const char *userchars);
int pri_setup(struct pri *pri, q931_call *call, struct pri_sr *req);
/* Set a call has a call indpendent signalling connection (i.e. no bchan) */
/*!
* \brief Set a call as a call indpendent signalling connection (i.e. no bchan)
* \note Call will automaticlly disconnect after signalling sent.
*/
int pri_sr_set_connection_call_independent(struct pri_sr *req);
/*!
* \brief Set a call as a call indpendent signalling connection (i.e. no bchan)
* \note Call will stay connected until explicitly disconnected.
*/
int pri_sr_set_no_channel_call(struct pri_sr *req);
/* Send an MWI indication to a remote location. If activate is non zero, activates, if zero, deactivates */
int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);

13
pri.c
View File

@ -911,7 +911,18 @@ int pri_sr_set_connection_call_independent(struct pri_sr *req)
if (!req)
return -1;
req->justsignalling = 1; /* have to set justsignalling for all those pesky IEs we need to setup */
req->cis_call = 1; /* have to set cis_call for all those pesky IEs we need to setup */
req->cis_auto_disconnect = 1;
return 0;
}
int pri_sr_set_no_channel_call(struct pri_sr *req)
{
if (!req) {
return -1;
}
req->cis_call = 1;
return 0;
}

View File

@ -292,7 +292,8 @@ struct pri_sr {
struct q931_party_address called;
int userl1;
int numcomplete;
int justsignalling;
int cis_call;
int cis_auto_disconnect;
const char *useruserinfo;
int transferable;
int reversecharge;
@ -367,7 +368,13 @@ struct q931_call {
int userl3;
int rateadaption;
int justsignalling; /* for a signalling-only connection */
/*!
* \brief TRUE if the call is a Call Independent Signalling connection.
* \note The call has no B channel associated with it. (Just signalling)
*/
int cis_call;
/*! \brief TRUE if we will auto disconnect the cis_call we originated. */
int cis_auto_disconnect;
int progcode; /* Progress coding */
int progloc; /* Progress Location */

74
q931.c
View File

@ -650,13 +650,13 @@ static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, in
#ifndef NOAUTO_CHANNEL_SELECTION_SUPPORT
if (ctrl->bri) {
if (!(ie->data[0] & 3))
call->justsignalling = 1;
call->cis_call = 1;
else
call->channelno = ie->data[0] & 3;
} else {
switch (ie->data[0] & 3) {
case 0:
call->justsignalling = 1;
call->cis_call = 1;
break;
case 1:
break;
@ -719,10 +719,14 @@ static int transmit_channel_id(int full_ie, struct pri *ctrl, q931_call *call, i
/* We are ready to transmit single IE only */
if (order > 1)
return 0;
if (call->justsignalling) {
ie->data[pos++] = 0xac; /* Read the standards docs to figure this out
ECMA-165 section 7.3 */
if (call->cis_call) {
/*
* Read the standards docs to figure this out.
* Q.SIG ECMA-165 section 7.3
* ITU Q.931 section 4.5.13
*/
ie->data[pos++] = ctrl->bri ? 0x8c : 0xac;
return pos + 2;
}
@ -1178,20 +1182,20 @@ static int transmit_bearer_capability(int full_ie, struct pri *ctrl, q931_call *
if(order > 1)
return 0;
tc = call->transcapability;
if (ctrl->subchannel && !ctrl->bri) {
/* Bearer capability is *hard coded* in GR-303 */
ie->data[0] = 0x88;
ie->data[1] = 0x90;
return 4;
}
if (call->justsignalling) {
if (call->cis_call) {
ie->data[0] = 0xa8;
ie->data[1] = 0x80;
return 4;
}
tc = call->transcapability;
ie->data[0] = 0x80 | tc;
ie->data[1] = call->transmoderate | 0x80;
@ -3804,7 +3808,8 @@ static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_F
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 };
/*! Call Independent Signalling SETUP ie's */
static int cis_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 *ctrl, q931_call *c, struct pri_sr *req)
{
@ -3830,7 +3835,8 @@ int q931_setup(struct pri *ctrl, q931_call *c, struct pri_sr *req)
c->slotmap = -1;
c->nonisdn = req->nonisdn;
c->newcall = 0;
c->justsignalling = req->justsignalling;
c->cis_call = req->cis_call;
c->cis_auto_disconnect = req->cis_auto_disconnect;
c->complete = req->numcomplete;
if (req->exclusive)
c->chanflags = FLAG_EXCLUSIVE;
@ -3871,7 +3877,7 @@ int q931_setup(struct pri *ctrl, q931_call *c, struct pri_sr *req)
if (ctrl->subchannel && !ctrl->bri)
res = send_message(ctrl, c, Q931_SETUP, gr303_setup_ies);
else if (c->justsignalling)
else if (c->cis_call)
res = send_message(ctrl, c, Q931_SETUP, cis_setup_ies);
else
res = send_message(ctrl, c, Q931_SETUP, setup_ies);
@ -3936,15 +3942,29 @@ int q931_hangup(struct pri *ctrl, q931_call *c, int cause)
/* If mandatory IE was missing, insist upon that cause code */
if (c->cause == PRI_CAUSE_MANDATORY_IE_MISSING)
cause = c->cause;
if (cause == 34 || cause == 44 || cause == 82 || cause == 1 || cause == 81) {
switch (cause) {
case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
case PRI_CAUSE_REQUESTED_CHAN_UNAVAIL:
case PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST:
case PRI_CAUSE_UNALLOCATED:
case PRI_CAUSE_INVALID_CALL_REFERENCE:
/* We'll send RELEASE_COMPLETE with these causes */
disconnect = 0;
release_compl = 1;
}
if (cause == 6 || cause == 7 || cause == 26) {
break;
case PRI_CAUSE_CHANNEL_UNACCEPTABLE:
case PRI_CAUSE_CALL_AWARDED_DELIVERED:
case 26:
/* We'll send RELEASE with these causes */
disconnect = 0;
break;
default:
break;
}
if (c->cis_call) {
disconnect = 0;
}
/* All other causes we send with DISCONNECT */
switch(c->ourcallstate) {
case Q931_CALL_STATE_NULL:
@ -3973,21 +3993,34 @@ int q931_hangup(struct pri *ctrl, q931_call *c, int cause)
case Q931_CALL_STATE_OVERLAP_RECEIVING:
/* received SETUP_ACKNOWLEDGE */
/* send DISCONNECT in general */
if (c->peercallstate != Q931_CALL_STATE_NULL && c->peercallstate != Q931_CALL_STATE_DISCONNECT_REQUEST && c->peercallstate != Q931_CALL_STATE_DISCONNECT_INDICATION && c->peercallstate != Q931_CALL_STATE_RELEASE_REQUEST && c->peercallstate != Q931_CALL_STATE_RESTART_REQUEST && c->peercallstate != Q931_CALL_STATE_RESTART) {
switch (c->peercallstate) {
default:
if (disconnect)
q931_disconnect(ctrl,c,cause);
else if (release_compl)
q931_release_complete(ctrl,c,cause);
else
q931_release(ctrl,c,cause);
} else
break;
case Q931_CALL_STATE_NULL:
case Q931_CALL_STATE_DISCONNECT_REQUEST:
case Q931_CALL_STATE_DISCONNECT_INDICATION:
case Q931_CALL_STATE_RELEASE_REQUEST:
case Q931_CALL_STATE_RESTART_REQUEST:
case Q931_CALL_STATE_RESTART:
pri_error(ctrl,
"Wierd, doing nothing but this shouldn't happen, ourstate %s, peerstate %s\n",
q931_call_state_str(c->ourcallstate),
q931_call_state_str(c->peercallstate));
break;
}
break;
case Q931_CALL_STATE_ACTIVE:
/* received CONNECT */
if (c->cis_call) {
q931_release(ctrl, c, cause);
break;
}
q931_disconnect(ctrl,c,cause);
break;
case Q931_CALL_STATE_DISCONNECT_REQUEST:
@ -4621,8 +4654,9 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
q931_connect_acknowledge(ctrl, c);
if (c->justsignalling) { /* Make sure WE release when we initiatie a signalling only connection */
q931_release(ctrl, c, PRI_CAUSE_NORMAL_CLEARING);
if (c->cis_auto_disconnect && c->cis_call) {
/* Make sure WE release when we initiate a signalling only connection */
q931_hangup(ctrl, c, PRI_CAUSE_NORMAL_CLEARING);
break;
} else {
c->incoming_ct_state = INCOMING_CT_STATE_IDLE;