Simplified some protocol discriminator handling code.

git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1675 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
Richard Mudgett 2010-04-26 19:54:00 +00:00
parent bfcab2eabe
commit 14c3616e02

102
q931.c
View File

@ -3890,12 +3890,23 @@ static char *disc2str(int disc)
static struct msgtype discs[] = {
{ Q931_PROTOCOL_DISCRIMINATOR, "Q.931" },
{ GR303_PROTOCOL_DISCRIMINATOR, "GR-303" },
{ 0x3, "AT&T Maintenance" },
{ 0x43, "New AT&T Maintenance" },
{ MAINTENANCE_PROTOCOL_DISCRIMINATOR_1, "AT&T Maintenance" },
{ MAINTENANCE_PROTOCOL_DISCRIMINATOR_2, "New AT&T Maintenance" },
};
return code2str(disc, discs, sizeof(discs) / sizeof(discs[0]));
}
/*!
* \brief Debug dump the given Q.931 packet.
*
* \param ctrl D channel controller.
* \param tei TEI the packet is associated with.
* \param h Q.931 packet contents/header.
* \param len Received length of the Q.931 packet
* \param txrx TRUE if packet is transmitted/outgoing
*
* \return Nothing
*/
void q931_dump(struct pri *ctrl, int tei, q931_h *h, int len, int txrx)
{
q931_mh *mh;
@ -3907,6 +3918,7 @@ void q931_dump(struct pri *ctrl, int tei, q931_h *h, int len, int txrx)
int cref;
c = txrx ? '>' : '<';
pri_message(ctrl, "%c Protocol Discriminator: %s (%d) len=%d\n", c, disc2str(h->pd), h->pd, len);
if (len < 2 || len < 2 + h->crlen) {
@ -3930,10 +3942,17 @@ void q931_dump(struct pri *ctrl, int tei, q931_h *h, int len, int txrx)
/* Message header begins at the end of the call reference number */
mh = (q931_mh *)(h->contents + h->crlen);
if ((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) {
switch (h->pd) {
case MAINTENANCE_PROTOCOL_DISCRIMINATOR_1:
case MAINTENANCE_PROTOCOL_DISCRIMINATOR_2:
pri_message(ctrl, "%c Message Type: %s (%d)\n", c, maintenance_msg2str(mh->msg, h->pd), mh->msg);
} else {
break;
default:
/* Unknown protocol discriminator but we will treat it as Q.931 anyway. */
case GR303_PROTOCOL_DISCRIMINATOR:
case Q931_PROTOCOL_DISCRIMINATOR:
pri_message(ctrl, "%c Message Type: %s (%d)\n", c, msg2str(mh->msg), mh->msg);
break;
}
/* Drop length of header, including call reference */
len -= (h->crlen + 3);
@ -3958,6 +3977,7 @@ void q931_dump(struct pri *ctrl, int tei, q931_h *h, int len, int txrx)
default:
/* Reset temporary codeset change */
cur_codeset = codeset;
break;
}
}
}
@ -5882,6 +5902,8 @@ int q931_receive(struct pri *ctrl, int tei, q931_h *h, int len)
int codeset, cur_codeset;
int last_ie[8];
int cref;
int allow_event;
int allow_posthandle;
memset(last_ie, 0, sizeof(last_ie));
if (ctrl->debug & PRI_DEBUG_Q931_DUMP)
@ -5893,21 +5915,29 @@ int q931_receive(struct pri *ctrl, int tei, q931_h *h, int len)
/* Message too short for supported protocols. */
return -1;
}
mh = (q931_mh *)(h->contents + h->crlen);
if ((h->pd != ctrl->protodisc) && (h->pd != MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) && (h->pd != MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) {
pri_error(ctrl, "Warning: unknown/inappropriate protocol discriminator received (%02x/%d)\n", h->pd, h->pd);
return 0;
}
if (((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) && (!ctrl->service_message_support)) {
/* Real service message support has not been enabled (and is OFF in libpri by default),
* so we have to revert to the 'traditional' KLUDGE of changing byte 4 from a 0xf (SERVICE)
* to a 0x7 (SERVICE ACKNOWLEDGE) */
/* This is the weird maintenance stuff. We majorly
KLUDGE this by changing byte 4 from a 0xf (SERVICE)
to a 0x7 (SERVICE ACKNOWLEDGE) */
h->raw[h->crlen + 2] -= 0x8;
q931_xmit(ctrl, ctrl->tei, h, len, 1, 0);
return 0;
switch (h->pd) {
case MAINTENANCE_PROTOCOL_DISCRIMINATOR_1:
case MAINTENANCE_PROTOCOL_DISCRIMINATOR_2:
if (!ctrl->service_message_support) {
/* Real service message support has not been enabled (and is OFF in libpri by default),
* so we have to revert to the 'traditional' KLUDGE of changing byte 4 from a 0xf (SERVICE)
* to a 0x7 (SERVICE ACKNOWLEDGE) */
/* This is the weird maintenance stuff. We majorly
KLUDGE this by changing byte 4 from a 0xf (SERVICE)
to a 0x7 (SERVICE ACKNOWLEDGE) */
h->raw[h->crlen + 2] -= 0x8;
q931_xmit(ctrl, ctrl->tei, h, len, 1, 0);
return 0;
}
break;
default:
if (h->pd != ctrl->protodisc) {
pri_error(ctrl,
"Warning: unknown/inappropriate protocol discriminator received (%02x/%d)\n",
h->pd, h->pd);
return 0;
}
break;
}
cref = q931_cr(h);
@ -5936,19 +5966,27 @@ int q931_receive(struct pri *ctrl, int tei, q931_h *h, int len)
ctrl->facility.count = 0;
c->connected_number_in_message = 0;
c->redirecting_number_in_message = 0;
if ((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) {
mh = (q931_mh *)(h->contents + h->crlen);
switch (h->pd) {
case MAINTENANCE_PROTOCOL_DISCRIMINATOR_1:
case MAINTENANCE_PROTOCOL_DISCRIMINATOR_2:
prepare_to_handle_maintenance_message(ctrl, mh, c);
} else {
break;
default:
/* Unknown protocol discriminator but we will treat it as Q.931 anyway. */
case GR303_PROTOCOL_DISCRIMINATOR:
case Q931_PROTOCOL_DISCRIMINATOR:
prepare_to_handle_q931_message(ctrl, mh, c);
break;
}
q931_clr_subcommands(ctrl);
/* Handle IEs */
memset(mandies, 0, sizeof(mandies));
missingmand = 0;
for (x=0;x<sizeof(msgs) / sizeof(msgs[0]); x++) {
for (x = 0; x < ARRAY_LEN(msgs); ++x) {
if (msgs[x].msgnum == mh->msg) {
memcpy(mandies, msgs[x].mandies, sizeof(mandies));
break;
}
}
/* Do real IE processing */
@ -5966,7 +6004,7 @@ int q931_receive(struct pri *ctrl, int tei, q931_h *h, int len)
}
return -1;
}
for (y=0;y<MAX_MAND_IES;y++) {
for (y = 0; y < ARRAY_LEN(mandies); ++y) {
if (mandies[y] == Q931_FULL_IE(cur_codeset, ie->ie))
mandies[y] = 0;
}
@ -6015,13 +6053,15 @@ int q931_receive(struct pri *ctrl, int tei, q931_h *h, int len)
/* XXX Applicable to codeset 0 only? XXX */
if (!cur_codeset && !(ie->ie & 0xf0) && (y < 0))
mandies[MAX_MAND_IES - 1] = Q931_FULL_IE(cur_codeset, ie->ie);
break;
}
/* Reset current codeset */
cur_codeset = codeset;
break;
}
}
missingmand = 0;
for (x=0;x<MAX_MAND_IES;x++) {
for (x = 0; x < ARRAY_LEN(mandies); ++x) {
if (mandies[x]) {
/* check if there is no channel identification when we're configured as network -> that's not an error */
if (((ctrl->localtype != PRI_NETWORK) || (mh->msg != Q931_SETUP) || (mandies[x] != Q931_CHANNEL_IDENT)) &&
@ -6036,10 +6076,14 @@ int q931_receive(struct pri *ctrl, int tei, q931_h *h, int len)
q931_handle_facilities(ctrl, c, mh->msg);
/* Post handling */
if ((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) {
switch (h->pd) {
case MAINTENANCE_PROTOCOL_DISCRIMINATOR_1:
case MAINTENANCE_PROTOCOL_DISCRIMINATOR_2:
res = post_handle_maintenance_message(ctrl, h->pd, mh, c);
} else {
int allow_event = 1, allow_posthandle = 1;
break;
default:
allow_event = 1;
allow_posthandle = 1;
if (c->master_call->outboundbroadcast) {
nt_ptmp_handle_q931_message(ctrl, mh, c, &allow_event, &allow_posthandle);
@ -6047,13 +6091,13 @@ int q931_receive(struct pri *ctrl, int tei, q931_h *h, int len)
if (allow_posthandle) {
res = post_handle_q931_message(ctrl, mh, c, missingmand);
if (res == Q931_RES_HAVEEVENT && !allow_event) {
res = 0;
}
} else {
res = 0;
}
break;
}
return res;
}