Add dummy call reference support.
Fixes problem where PTMP NT mode responds erroneously to a FACILITY message from a phone on the dummy call reference. LibPRI behaved as if the dummy call reference were an invalid call reference and proceeded to respond on the global call reference. git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1275 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
parent
c7c670aa85
commit
e23ea9568c
8
libpri.h
8
libpri.h
@ -929,6 +929,14 @@ extern int pri_maintenance_service(struct pri *pri, int span, int channel, int c
|
|||||||
/* Create a new call */
|
/* Create a new call */
|
||||||
q931_call *pri_new_call(struct pri *pri);
|
q931_call *pri_new_call(struct pri *pri);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Deterimine if the given call control pointer is a dummy call.
|
||||||
|
*
|
||||||
|
* \retval TRUE if given call is a dummy call.
|
||||||
|
* \retval FALSE otherwise.
|
||||||
|
*/
|
||||||
|
int pri_is_dummy_call(q931_call *call);
|
||||||
|
|
||||||
/* Retrieve CRV reference for GR-303 calls. Returns >0 on success. */
|
/* Retrieve CRV reference for GR-303 calls. Returns >0 on success. */
|
||||||
int pri_get_crv(struct pri *pri, q931_call *call, int *callmode);
|
int pri_get_crv(struct pri *pri, q931_call *call, int *callmode);
|
||||||
|
|
||||||
|
63
pri.c
63
pri.c
@ -226,18 +226,44 @@ static int __pri_write(struct pri *pri, void *buf, int buflen)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pass in the master for this function */
|
|
||||||
void __pri_free_tei(struct pri * p)
|
void __pri_free_tei(struct pri * p)
|
||||||
{
|
{
|
||||||
free(p);
|
if (p) {
|
||||||
|
struct q931_call *call;
|
||||||
|
|
||||||
|
call = p->dummy_call;
|
||||||
|
if (call) {
|
||||||
|
pri_schedule_del(call->pri, call->retranstimer);
|
||||||
|
pri_call_apdu_queue_cleanup(call);
|
||||||
|
}
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int tei, int bri)
|
struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int tei, int bri)
|
||||||
{
|
{
|
||||||
|
struct d_ctrl_dummy *dummy_ctrl;
|
||||||
struct pri *p;
|
struct pri *p;
|
||||||
|
|
||||||
if (!(p = calloc(1, sizeof(*p))))
|
switch (switchtype) {
|
||||||
return NULL;
|
case PRI_SWITCH_GR303_EOC:
|
||||||
|
case PRI_SWITCH_GR303_TMC:
|
||||||
|
case PRI_SWITCH_GR303_TMC_SWITCHING:
|
||||||
|
case PRI_SWITCH_GR303_EOC_PATH:
|
||||||
|
p = calloc(1, sizeof(*p));
|
||||||
|
if (!p) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
dummy_ctrl = NULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dummy_ctrl = calloc(1, sizeof(*dummy_ctrl));
|
||||||
|
if (!dummy_ctrl) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
p = &dummy_ctrl->ctrl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
p->bri = bri;
|
p->bri = bri;
|
||||||
p->fd = fd;
|
p->fd = fd;
|
||||||
@ -265,7 +291,14 @@ struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master,
|
|||||||
p->q931_rxcount = 0;
|
p->q931_rxcount = 0;
|
||||||
p->q931_txcount = 0;
|
p->q931_txcount = 0;
|
||||||
#endif
|
#endif
|
||||||
if (switchtype == PRI_SWITCH_GR303_EOC) {
|
if (dummy_ctrl) {
|
||||||
|
/* Initialize the dummy call reference call record. */
|
||||||
|
dummy_ctrl->ctrl.dummy_call = &dummy_ctrl->dummy_call;
|
||||||
|
q931_init_call_record(&dummy_ctrl->ctrl, dummy_ctrl->ctrl.dummy_call,
|
||||||
|
Q931_DUMMY_CALL_REFERENCE);
|
||||||
|
}
|
||||||
|
switch (switchtype) {
|
||||||
|
case PRI_SWITCH_GR303_EOC:
|
||||||
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
|
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
|
||||||
p->sapi = Q921_SAPI_GR303_EOC;
|
p->sapi = Q921_SAPI_GR303_EOC;
|
||||||
p->tei = Q921_TEI_GR303_EOC_OPS;
|
p->tei = Q921_TEI_GR303_EOC_OPS;
|
||||||
@ -274,7 +307,8 @@ struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master,
|
|||||||
free(p);
|
free(p);
|
||||||
p = NULL;
|
p = NULL;
|
||||||
}
|
}
|
||||||
} else if (switchtype == PRI_SWITCH_GR303_TMC) {
|
break;
|
||||||
|
case PRI_SWITCH_GR303_TMC:
|
||||||
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
|
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
|
||||||
p->sapi = Q921_SAPI_GR303_TMC_CALLPROC;
|
p->sapi = Q921_SAPI_GR303_TMC_CALLPROC;
|
||||||
p->tei = Q921_TEI_GR303_TMC_CALLPROC;
|
p->tei = Q921_TEI_GR303_TMC_CALLPROC;
|
||||||
@ -283,14 +317,19 @@ struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master,
|
|||||||
free(p);
|
free(p);
|
||||||
p = NULL;
|
p = NULL;
|
||||||
}
|
}
|
||||||
} else if (switchtype == PRI_SWITCH_GR303_TMC_SWITCHING) {
|
break;
|
||||||
|
case PRI_SWITCH_GR303_TMC_SWITCHING:
|
||||||
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
|
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
|
||||||
p->sapi = Q921_SAPI_GR303_TMC_SWITCHING;
|
p->sapi = Q921_SAPI_GR303_TMC_SWITCHING;
|
||||||
p->tei = Q921_TEI_GR303_TMC_SWITCHING;
|
p->tei = Q921_TEI_GR303_TMC_SWITCHING;
|
||||||
} else if (switchtype == PRI_SWITCH_GR303_EOC_PATH) {
|
break;
|
||||||
|
case PRI_SWITCH_GR303_EOC_PATH:
|
||||||
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
|
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
|
||||||
p->sapi = Q921_SAPI_GR303_EOC;
|
p->sapi = Q921_SAPI_GR303_EOC;
|
||||||
p->tei = Q921_TEI_GR303_EOC_PATH;
|
p->tei = Q921_TEI_GR303_EOC_PATH;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
/* Start Q.921 layer, Wait if we're the network */
|
/* Start Q.921 layer, Wait if we're the network */
|
||||||
if (p)
|
if (p)
|
||||||
@ -935,6 +974,14 @@ q931_call *pri_new_call(struct pri *pri)
|
|||||||
return q931_new_call(pri);
|
return q931_new_call(pri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int pri_is_dummy_call(q931_call *call)
|
||||||
|
{
|
||||||
|
if (!call) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return q931_is_dummy_call(call);
|
||||||
|
}
|
||||||
|
|
||||||
void pri_dump_event(struct pri *pri, pri_event *e)
|
void pri_dump_event(struct pri *pri, pri_event *e)
|
||||||
{
|
{
|
||||||
if (!pri || !e)
|
if (!pri || !e)
|
||||||
|
@ -114,6 +114,13 @@ struct pri {
|
|||||||
q931_call **callpool;
|
q931_call **callpool;
|
||||||
q931_call *localpool;
|
q931_call *localpool;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Q.931 Dummy call reference call associated with this TEI.
|
||||||
|
* \note If present then this call is allocated as part of the
|
||||||
|
* D channel control structure.
|
||||||
|
*/
|
||||||
|
q931_call *dummy_call;
|
||||||
|
|
||||||
/* do we do overlap dialing */
|
/* do we do overlap dialing */
|
||||||
int overlapdial;
|
int overlapdial;
|
||||||
|
|
||||||
@ -506,6 +513,14 @@ struct q931_call {
|
|||||||
int pri_winner;
|
int pri_winner;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*! D channel control structure with associated dummy call reference record. */
|
||||||
|
struct d_ctrl_dummy {
|
||||||
|
/*! D channel control structure. */
|
||||||
|
struct pri ctrl;
|
||||||
|
/*! Dummy call reference call record. */
|
||||||
|
struct q931_call dummy_call;
|
||||||
|
};
|
||||||
|
|
||||||
extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);
|
extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);
|
||||||
|
|
||||||
extern pri_event *pri_schedule_run(struct pri *pri);
|
extern pri_event *pri_schedule_run(struct pri *pri);
|
||||||
@ -523,6 +538,8 @@ struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master,
|
|||||||
|
|
||||||
void __pri_free_tei(struct pri *p);
|
void __pri_free_tei(struct pri *p);
|
||||||
|
|
||||||
|
void q931_init_call_record(struct pri *ctrl, struct q931_call *call, int cr);
|
||||||
|
|
||||||
void q931_party_name_init(struct q931_party_name *name);
|
void q931_party_name_init(struct q931_party_name *name);
|
||||||
void q931_party_number_init(struct q931_party_number *number);
|
void q931_party_number_init(struct q931_party_number *number);
|
||||||
void q931_party_subaddress_init(struct q931_party_subaddress *subaddr);
|
void q931_party_subaddress_init(struct q931_party_subaddress *subaddr);
|
||||||
@ -589,4 +606,17 @@ static inline int BRI_TE_PTMP(struct pri *mypri)
|
|||||||
return pri->bri && (((pri)->localtype == PRI_CPE) && ((pri)->tei == Q921_TEI_GROUP));
|
return pri->bri && (((pri)->localtype == PRI_CPE) && ((pri)->tei == Q921_TEI_GROUP));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define Q931_DUMMY_CALL_REFERENCE -1
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Deterimine if the given call control pointer is a dummy call.
|
||||||
|
*
|
||||||
|
* \retval TRUE if given call is a dummy call.
|
||||||
|
* \retval FALSE otherwise.
|
||||||
|
*/
|
||||||
|
static inline int q931_is_dummy_call(const q931_call *call)
|
||||||
|
{
|
||||||
|
return (call->cr == Q931_DUMMY_CALL_REFERENCE) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
219
q931.c
219
q931.c
@ -3307,30 +3307,38 @@ static char *maintenance_msg2str(int msg, int pd)
|
|||||||
return "Unknown Message Type";
|
return "Unknown Message Type";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Decode the call reference */
|
||||||
static inline int q931_cr(q931_h *h)
|
static inline int q931_cr(q931_h *h)
|
||||||
{
|
{
|
||||||
int cr = 0;
|
int cr;
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
if (h->crlen > 3) {
|
if (h->crlen > 3) {
|
||||||
pri_error(NULL, "Call Reference Length Too long: %d\n", h->crlen);
|
pri_error(NULL, "Call Reference Length Too long: %d\n", h->crlen);
|
||||||
return -1;
|
return Q931_DUMMY_CALL_REFERENCE;
|
||||||
}
|
}
|
||||||
switch (h->crlen) {
|
switch (h->crlen) {
|
||||||
case 2:
|
case 2:
|
||||||
for (x=0;x<h->crlen;x++) {
|
cr = 0;
|
||||||
cr <<= 8;
|
for (x = 0; x < h->crlen; ++x) {
|
||||||
cr |= h->crv[x];
|
cr <<= 8;
|
||||||
}
|
cr |= h->crv[x];
|
||||||
break;
|
}
|
||||||
case 1:
|
break;
|
||||||
cr = h->crv[0];
|
case 1:
|
||||||
if (cr & 0x80) {
|
cr = h->crv[0];
|
||||||
cr &= ~0x80;
|
if (cr & 0x80) {
|
||||||
cr |= 0x8000;
|
cr &= ~0x80;
|
||||||
}
|
cr |= 0x8000;
|
||||||
break;
|
}
|
||||||
default:
|
break;
|
||||||
pri_error(NULL, "Call Reference Length not supported: %d\n", h->crlen);
|
case 0:
|
||||||
|
cr = Q931_DUMMY_CALL_REFERENCE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pri_error(NULL, "Call Reference Length not supported: %d\n", h->crlen);
|
||||||
|
cr = Q931_DUMMY_CALL_REFERENCE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return cr;
|
return cr;
|
||||||
}
|
}
|
||||||
@ -3370,12 +3378,73 @@ static inline void q931_dumpie(struct pri *ctrl, int codeset, q931_ie *ie, char
|
|||||||
pri_error(ctrl, "!! %c Unknown IE %d (cs%d, len = %d)\n", prefix, Q931_IE_IE(base_ie), Q931_IE_CODESET(base_ie), ielen(ie));
|
pri_error(ctrl, "!! %c Unknown IE %d (cs%d, len = %d)\n", prefix, Q931_IE_IE(base_ie), Q931_IE_CODESET(base_ie), ielen(ie));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Initialize the call record.
|
||||||
|
*
|
||||||
|
* \param ctrl D channel controller.
|
||||||
|
* \param call Q.931 call leg.
|
||||||
|
*
|
||||||
|
* \note The call record is assumed to already be memset() to zero.
|
||||||
|
*
|
||||||
|
* \return Nothing
|
||||||
|
*/
|
||||||
|
void q931_init_call_record(struct pri *ctrl, struct q931_call *call, int cr)
|
||||||
|
{
|
||||||
|
call->cr = cr;
|
||||||
|
call->slotmap = -1;
|
||||||
|
call->channelno = -1;
|
||||||
|
if (cr != Q931_DUMMY_CALL_REFERENCE) {
|
||||||
|
call->newcall = 1;
|
||||||
|
}
|
||||||
|
call->ourcallstate = Q931_CALL_STATE_NULL;
|
||||||
|
call->peercallstate = Q931_CALL_STATE_NULL;
|
||||||
|
call->sugcallstate = Q931_CALL_STATE_NOT_SET;
|
||||||
|
call->ri = -1;
|
||||||
|
call->transcapability = -1;
|
||||||
|
call->transmoderate = -1;
|
||||||
|
call->transmultiple = -1;
|
||||||
|
call->userl1 = -1;
|
||||||
|
call->userl2 = -1;
|
||||||
|
call->userl3 = -1;
|
||||||
|
call->rateadaption = -1;
|
||||||
|
call->progress = -1;
|
||||||
|
call->causecode = -1;
|
||||||
|
call->causeloc = -1;
|
||||||
|
call->cause = -1;
|
||||||
|
call->useruserprotocoldisc = -1;
|
||||||
|
call->aoc_units = -1;
|
||||||
|
call->changestatus = -1;
|
||||||
|
call->reversecharge = -1;
|
||||||
|
call->pri_winner = -1;
|
||||||
|
call->master_call = call;
|
||||||
|
q931_party_number_init(&call->redirection_number);
|
||||||
|
q931_party_address_init(&call->called);
|
||||||
|
q931_party_id_init(&call->local_id);
|
||||||
|
q931_party_id_init(&call->remote_id);
|
||||||
|
q931_party_redirecting_init(&call->redirecting);
|
||||||
|
|
||||||
|
/* PRI is set to whoever called us */
|
||||||
|
if (BRI_TE_PTMP(ctrl)) {
|
||||||
|
/*
|
||||||
|
* Point to the master to avoid stale pointer problems if
|
||||||
|
* the TEI is removed later.
|
||||||
|
*/
|
||||||
|
call->pri = PRI_MASTER(ctrl);
|
||||||
|
} else {
|
||||||
|
call->pri = ctrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static q931_call *q931_getcall(struct pri *ctrl, int cr)
|
static q931_call *q931_getcall(struct pri *ctrl, int cr)
|
||||||
{
|
{
|
||||||
q931_call *cur;
|
q931_call *cur;
|
||||||
q931_call *prev;
|
q931_call *prev;
|
||||||
struct pri *master;
|
struct pri *master;
|
||||||
|
|
||||||
|
if (cr == Q931_DUMMY_CALL_REFERENCE) {
|
||||||
|
return ctrl->dummy_call;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find the master - He has the call pool */
|
/* Find the master - He has the call pool */
|
||||||
master = PRI_MASTER(ctrl);
|
master = PRI_MASTER(ctrl);
|
||||||
|
|
||||||
@ -3414,47 +3483,7 @@ static q931_call *q931_getcall(struct pri *ctrl, int cr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize call structure. */
|
/* Initialize call structure. */
|
||||||
cur->cr = cr;
|
q931_init_call_record(ctrl, cur, cr);
|
||||||
cur->slotmap = -1;
|
|
||||||
cur->channelno = -1;
|
|
||||||
cur->newcall = 1;
|
|
||||||
cur->ourcallstate = Q931_CALL_STATE_NULL;
|
|
||||||
cur->peercallstate = Q931_CALL_STATE_NULL;
|
|
||||||
cur->sugcallstate = Q931_CALL_STATE_NOT_SET;
|
|
||||||
cur->ri = -1;
|
|
||||||
cur->transcapability = -1;
|
|
||||||
cur->transmoderate = -1;
|
|
||||||
cur->transmultiple = -1;
|
|
||||||
cur->userl1 = -1;
|
|
||||||
cur->userl2 = -1;
|
|
||||||
cur->userl3 = -1;
|
|
||||||
cur->rateadaption = -1;
|
|
||||||
cur->progress = -1;
|
|
||||||
cur->causecode = -1;
|
|
||||||
cur->causeloc = -1;
|
|
||||||
cur->cause = -1;
|
|
||||||
cur->useruserprotocoldisc = -1;
|
|
||||||
cur->aoc_units = -1;
|
|
||||||
cur->changestatus = -1;
|
|
||||||
cur->reversecharge = -1;
|
|
||||||
cur->pri_winner = -1;
|
|
||||||
cur->master_call = cur;
|
|
||||||
q931_party_number_init(&cur->redirection_number);
|
|
||||||
q931_party_address_init(&cur->called);
|
|
||||||
q931_party_id_init(&cur->local_id);
|
|
||||||
q931_party_id_init(&cur->remote_id);
|
|
||||||
q931_party_redirecting_init(&cur->redirecting);
|
|
||||||
|
|
||||||
/* PRI is set to whoever called us */
|
|
||||||
if (BRI_TE_PTMP(ctrl)) {
|
|
||||||
/*
|
|
||||||
* Point to the master to avoid stale pointer problems if
|
|
||||||
* the TEI is removed later.
|
|
||||||
*/
|
|
||||||
cur->pri = master;
|
|
||||||
} else {
|
|
||||||
cur->pri = ctrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Append to end of list */
|
/* Append to end of list */
|
||||||
if (prev) {
|
if (prev) {
|
||||||
@ -3511,6 +3540,10 @@ void q931_destroycall(struct pri *ctrl, q931_call *c)
|
|||||||
int slavesleft;
|
int slavesleft;
|
||||||
int slaveidx;
|
int slaveidx;
|
||||||
|
|
||||||
|
if (q931_is_dummy_call(c)) {
|
||||||
|
/* Cannot destroy the dummy call. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (c->master_call != c) {
|
if (c->master_call != c) {
|
||||||
slave = c;
|
slave = c;
|
||||||
c = slave->master_call;
|
c = slave->master_call;
|
||||||
@ -3711,7 +3744,9 @@ void q931_dump(struct pri *ctrl, q931_h *h, int len, int txrx)
|
|||||||
cref = q931_cr(h);
|
cref = q931_cr(h);
|
||||||
pri_message(ctrl, "%c Call Ref: len=%2d (reference %d/0x%X) (%s)\n",
|
pri_message(ctrl, "%c Call Ref: len=%2d (reference %d/0x%X) (%s)\n",
|
||||||
c, h->crlen, cref & 0x7FFF, cref & 0x7FFF,
|
c, h->crlen, cref & 0x7FFF, cref & 0x7FFF,
|
||||||
(cref & 0x8000) ? "Terminator" : "Originator");
|
(cref == Q931_DUMMY_CALL_REFERENCE)
|
||||||
|
? "Dummy"
|
||||||
|
: (cref & 0x8000) ? "Terminator" : "Originator");
|
||||||
|
|
||||||
/* Message header begins at the end of the call reference number */
|
/* Message header begins at the end of the call reference number */
|
||||||
mh = (q931_mh *)(h->contents + h->crlen);
|
mh = (q931_mh *)(h->contents + h->crlen);
|
||||||
@ -3778,7 +3813,9 @@ static void init_header(struct pri *ctrl, q931_call *call, unsigned char *buf, q
|
|||||||
h->pd = ctrl->protodisc;
|
h->pd = ctrl->protodisc;
|
||||||
}
|
}
|
||||||
h->x0 = 0; /* Reserved 0 */
|
h->x0 = 0; /* Reserved 0 */
|
||||||
if (!ctrl->bri) {
|
if (q931_is_dummy_call(call)) {
|
||||||
|
h->crlen = 0;
|
||||||
|
} else if (!ctrl->bri) {
|
||||||
/* Two bytes of Call Reference. */
|
/* Two bytes of Call Reference. */
|
||||||
h->crlen = 2;
|
h->crlen = 2;
|
||||||
/* Invert the top bit to make it from our sense */
|
/* Invert the top bit to make it from our sense */
|
||||||
@ -3807,18 +3844,11 @@ static void init_header(struct pri *ctrl, q931_call *call, unsigned char *buf, q
|
|||||||
|
|
||||||
static int q931_xmit(struct pri *ctrl, q931_h *h, int len, int cr, int uiframe)
|
static int q931_xmit(struct pri *ctrl, q931_h *h, int len, int cr, int uiframe)
|
||||||
{
|
{
|
||||||
/*
|
if (uiframe) {
|
||||||
* For NT-PTMP mode, we need to check the following:
|
|
||||||
* MODE = NT-PTMP
|
|
||||||
* MESSAGE = SETUP
|
|
||||||
*
|
|
||||||
* If those are true, we need to send the SETUP in a UI frame
|
|
||||||
* instead of an I-frame.
|
|
||||||
*/
|
|
||||||
if (BRI_NT_PTMP(ctrl) && uiframe)
|
|
||||||
q921_transmit_uiframe(ctrl, h, len);
|
q921_transmit_uiframe(ctrl, h, len);
|
||||||
else
|
} else {
|
||||||
q921_transmit_iframe(ctrl, h, len, cr);
|
q921_transmit_iframe(ctrl, h, len, cr);
|
||||||
|
}
|
||||||
/* The transmit operation might dump the q921 header, so logging the q931
|
/* The transmit operation might dump the q921 header, so logging the q931
|
||||||
message body after the transmit puts the sections of the message in the
|
message body after the transmit puts the sections of the message in the
|
||||||
right order in the log */
|
right order in the log */
|
||||||
@ -3893,6 +3923,43 @@ static int send_message(struct pri *ctrl, q931_call *call, int msgtype, int ies[
|
|||||||
ctrl = ctrl->subchannel;
|
ctrl = ctrl->subchannel;
|
||||||
}
|
}
|
||||||
if (ctrl) {
|
if (ctrl) {
|
||||||
|
int uiframe;
|
||||||
|
|
||||||
|
switch (msgtype) {
|
||||||
|
case Q931_SETUP:
|
||||||
|
/*
|
||||||
|
* For NT-PTMP mode, we need to check the following:
|
||||||
|
* MODE = NT-PTMP
|
||||||
|
* MESSAGE = SETUP
|
||||||
|
*
|
||||||
|
* If those are true, we need to send the SETUP in a UI frame
|
||||||
|
* instead of an I-frame.
|
||||||
|
*/
|
||||||
|
uiframe = call->outboundbroadcast;
|
||||||
|
break;
|
||||||
|
case Q931_FACILITY:
|
||||||
|
if (ctrl->tei == Q921_TEI_GROUP) {
|
||||||
|
/* Broadcast TEI. */
|
||||||
|
if (q931_is_dummy_call(call)) {
|
||||||
|
/*
|
||||||
|
* This is a FACILITY message on the dummy call reference
|
||||||
|
* for the broadcast TEI.
|
||||||
|
*/
|
||||||
|
uiframe = 1;
|
||||||
|
} else {
|
||||||
|
pri_error(ctrl,
|
||||||
|
"Attempting to broadcast %s on cref %d\n",
|
||||||
|
msg2str(msgtype), call->cr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uiframe = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
uiframe = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
|
if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
|
||||||
pri_message(ctrl,
|
pri_message(ctrl,
|
||||||
"Sending message for call %p on %p TEI/SAPI %d/%d, call->pri is %p, TEI/SAPI %d/%d\n",
|
"Sending message for call %p on %p TEI/SAPI %d/%d, call->pri is %p, TEI/SAPI %d/%d\n",
|
||||||
@ -3900,7 +3967,7 @@ static int send_message(struct pri *ctrl, q931_call *call, int msgtype, int ies[
|
|||||||
ctrl, ctrl->tei, ctrl->sapi,
|
ctrl, ctrl->tei, ctrl->sapi,
|
||||||
call->pri, call->pri->tei, call->pri->sapi);
|
call->pri, call->pri->tei, call->pri->sapi);
|
||||||
}
|
}
|
||||||
q931_xmit(ctrl, h, len, 1, (msgtype == Q931_SETUP) ? 1 : 0);
|
q931_xmit(ctrl, h, len, 1, uiframe);
|
||||||
}
|
}
|
||||||
call->acked = 1;
|
call->acked = 1;
|
||||||
return 0;
|
return 0;
|
||||||
@ -5375,6 +5442,9 @@ static int prepare_to_handle_q931_message(struct pri *ctrl, q931_mh *mh, q931_ca
|
|||||||
c->ri = -1;
|
c->ri = -1;
|
||||||
break;
|
break;
|
||||||
case Q931_FACILITY:
|
case Q931_FACILITY:
|
||||||
|
if (q931_is_dummy_call(c)) {
|
||||||
|
q931_party_address_init(&c->called);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Q931_SETUP:
|
case Q931_SETUP:
|
||||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE)
|
if (ctrl->debug & PRI_DEBUG_Q931_STATE)
|
||||||
@ -7288,7 +7358,10 @@ int q931_call_getcrv(struct pri *ctrl, q931_call *call, int *callmode)
|
|||||||
|
|
||||||
int q931_call_setcrv(struct pri *ctrl, q931_call *call, int crv, int callmode)
|
int q931_call_setcrv(struct pri *ctrl, q931_call *call, int crv, int callmode)
|
||||||
{
|
{
|
||||||
call->cr = (crv << 3) & 0x7fff;
|
/* Do not allow changing the dummy call reference */
|
||||||
call->cr |= (callmode & 0x7);
|
if (!q931_is_dummy_call(call)) {
|
||||||
|
call->cr = (crv << 3) & 0x7fff;
|
||||||
|
call->cr |= (callmode & 0x7);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user