[libpri-commits] moy: branch moy/tap-1.4 r1119 - /team/moy/tap-1.4/
SVN commits to the libpri project
libpri-commits at lists.digium.com
Tue Sep 22 11:48:57 CDT 2009
Author: moy
Date: Tue Sep 22 11:48:53 2009
New Revision: 1119
URL: http://svnview.digium.com/svn/libpri?view=rev&rev=1119
Log:
added pri_read_event API to read events passively from the PRI link
Modified:
team/moy/tap-1.4/libpri.h
team/moy/tap-1.4/pri.c
team/moy/tap-1.4/pri_q931.h
team/moy/tap-1.4/pridump.c
team/moy/tap-1.4/q931.c
Modified: team/moy/tap-1.4/libpri.h
URL: http://svnview.digium.com/svn/libpri/team/moy/tap-1.4/libpri.h?view=diff&rev=1119&r1=1118&r2=1119
==============================================================================
--- team/moy/tap-1.4/libpri.h (original)
+++ team/moy/tap-1.4/libpri.h Tue Sep 22 11:48:53 2009
@@ -735,6 +735,9 @@
/* Check for an outstanding event on the PRI */
pri_event *pri_check_event(struct pri *pri);
+/* Check for PRI events */
+pri_event *pri_read_event(struct pri *pri);
+
/* Give a name to a given event ID */
char *pri_event2str(int id);
Modified: team/moy/tap-1.4/pri.c
URL: http://svnview.digium.com/svn/libpri/team/moy/tap-1.4/pri.c?view=diff&rev=1119&r1=1118&r2=1119
==============================================================================
--- team/moy/tap-1.4/pri.c (original)
+++ team/moy/tap-1.4/pri.c Tue Sep 22 11:48:53 2009
@@ -405,6 +405,26 @@
return e;
}
+pri_event *pri_read_event(struct pri *pri)
+{
+ char buf[1024];
+ int res;
+ res = pri->read_func ? pri->read_func(pri, buf, sizeof(buf)) : 0;
+ /* this check should be at some routine in q921.c */
+ /* at least 4 bytes of Q921 and at check buf[4] for Q931 Network packet */
+ if (res < 5 || ((int)buf[4] != 8)) {
+ return NULL;
+ }
+ res = q931_read_event(pri, (q931_h*)(buf + 4), res - 4 - 2 /* remove 4 bytes of Q921 h and 2 of CRC */);
+ if (res == -1) {
+ return NULL;
+ }
+ if (res & Q931_RES_HAVEEVENT) {
+ return &pri->ev;
+ }
+ return NULL;
+}
+
static int wait_pri(struct pri *pri)
{
struct timeval *tv, real;
@@ -886,7 +906,15 @@
pri_message(pri, "Called number: %s (%s)\n", e->ring.callednum, pri_plan2str(e->ring.calledplan));
pri_message(pri, "Channel: %d (%s) Reference number: %d\n", e->ring.channel, e->ring.flexible ? "Flexible" : "Not Flexible", e->ring.cref);
break;
+ case PRI_EVENT_ANSWER:
+ pri_message(pri, "Channel: %d Reference number: %d\n", e->answer.channel, e->answer.cref);
+ break;
+ case PRI_EVENT_PROCEEDING:
+ pri_message(pri, "Channel: %d Reference number: %d\n", e->proceeding.channel, e->proceeding.cref);
case PRI_EVENT_HANGUP:
+ pri_message(pri, "Hangup, reference number: %d, reason: %s\n", e->hangup.cref, pri_cause2str(e->hangup.cause));
+ break;
+ case PRI_EVENT_HANGUP_ACK:
pri_message(pri, "Hangup, reference number: %d, reason: %s\n", e->hangup.cref, pri_cause2str(e->hangup.cause));
break;
default:
Modified: team/moy/tap-1.4/pri_q931.h
URL: http://svnview.digium.com/svn/libpri/team/moy/tap-1.4/pri_q931.h?view=diff&rev=1119&r1=1118&r2=1119
==============================================================================
--- team/moy/tap-1.4/pri_q931.h (original)
+++ team/moy/tap-1.4/pri_q931.h Tue Sep 22 11:48:53 2009
@@ -427,6 +427,8 @@
/* Q.SIG specific */
#define QSIG_IE_TRANSIT_COUNT 0x31
+extern int q931_read_event(struct pri *pri, q931_h *h, int len);
+
extern int q931_receive(struct pri *pri, q931_h *h, int len);
extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info);
Modified: team/moy/tap-1.4/pridump.c
URL: http://svnview.digium.com/svn/libpri/team/moy/tap-1.4/pridump.c?view=diff&rev=1119&r1=1118&r2=1119
==============================================================================
--- team/moy/tap-1.4/pridump.c (original)
+++ team/moy/tap-1.4/pridump.c Tue Sep 22 11:48:53 2009
@@ -42,7 +42,7 @@
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/types.h>
-#include <zaptel/zaptel.h>
+#include <dahdi/user.h>
#include "libpri.h"
#include "pri_q921.h"
#include "pri_q931.h"
@@ -50,18 +50,18 @@
static int pri_open(char *dev)
{
int dfd;
- struct zt_params p;
+ struct dahdi_params p;
dfd = open(dev, O_RDWR);
if (dfd < 0) {
fprintf(stderr, "Failed to open dchannel '%s': %s\n", dev, strerror(errno));
return -1;
}
- if (ioctl(dfd, ZT_GET_PARAMS, &p)) {
+ if (ioctl(dfd, DAHDI_GET_PARAMS, &p)) {
fprintf(stderr, "Unable to get parameters on '%s': %s\n", dev, strerror(errno));
return -1;
}
- if ((p.sigtype != ZT_SIG_HDLCRAW) && (p.sigtype != ZT_SIG_HDLCFCS)) {
+ if ((p.sigtype != DAHDI_SIG_HDLCRAW) && (p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
fprintf(stderr, "%s is in %d signalling, not FCS HDLC or RAW HDLC mode\n", dev, p.sigtype);
return -1;
}
@@ -70,11 +70,33 @@
static void dump_packet(struct pri *pri, char *buf, int len, int txrx)
{
- q921_h *h = (q921_h *)buf;
- q921_dump(pri, h, len, 1, txrx);
+ //q921_h *h = (q921_h *)buf;
+
+ //q921_dump(pri, h, len, 1, txrx);
+
+ // Check if data is long enough and if this is a Q931 frame
+ if ((len < 5) || ((int)buf[4] != 8)) {
+ return;
+ }
+ q931_dump(pri, (void*)(buf + 4), len - 4 - 2, txrx);
+
+#if 0
+ switch (h->h.data[0] & Q921_FRAMETYPE_MASK) {
+ case 0:
+ case 2:
+ q931_dump(pri, (q931_h *)(h->i.data), len - 4 - 2 /* FCS */, txrx);
+ break;
+ default:
+ break;
+ }
+
+ // serch for 0 in the first 2 bits (which __q921_receive_qualified handles just as 2, frame 3 can also have q931 msg though)
if (!((h->h.data[0] & Q921_FRAMETYPE_MASK) & 0x3)) {
+ // case 3 h->h.data[0] & Q921_FRAMETYPE_MASK, res = q931_receive(pri, (q931_h *) h->u.data, len - 3);
q931_dump(pri, (q931_h *)(h->i.data), len - 4 - 2 /* FCS */, txrx);
}
+#endif
+
fflush(stdout);
fflush(stderr);
}
@@ -94,8 +116,8 @@
max = d1;
if (max < d2)
max = d2;
- ioctl(d1, ZT_GETEVENT, &e);
- ioctl(d2, ZT_GETEVENT, &e);
+ ioctl(d1, DAHDI_GETEVENT, &e);
+ ioctl(d2, DAHDI_GETEVENT, &e);
res = select(max + 1, &fds, NULL, NULL, NULL);
if (res < 0) {
fprintf(stderr, "Select returned %d: %s\n", res, strerror(errno));
Modified: team/moy/tap-1.4/q931.c
URL: http://svnview.digium.com/svn/libpri/team/moy/tap-1.4/q931.c?view=diff&rev=1119&r1=1118&r2=1119
==============================================================================
--- team/moy/tap-1.4/q931.c (original)
+++ team/moy/tap-1.4/q931.c Tue Sep 22 11:48:53 2009
@@ -91,7 +91,7 @@
{ Q931_SUSPEND_ACKNOWLEDGE, "SUSPEND ACKNOWLEDGE" },
{ Q931_SUSPEND_REJECT, "SUSPEND REJECT" },
};
-static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, int missingmand);
+static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, int missingmand, int checkstate);
struct msgtype att_maintenance_msgs[] = {
{ ATT_SERVICE, "SERVICE", { Q931_CHANNEL_IDENT } },
@@ -171,6 +171,7 @@
{ PRI_NSF_ATT_MULTIQUEST, "AT&T MultiQuest" },
{ PRI_NSF_CALL_REDIRECTION_SERVICE, "Call Redirection Service" }
};
+static int q931_process_ies(struct pri *ctrl, q931_h *h, int len, q931_mh *mh, q931_call *c, int *missingmand);
#define FLAG_WHOLE_INTERFACE 0x01
#define FLAG_PREFERRED 0x02
@@ -4313,22 +4314,47 @@
return 0;
}
-int q931_receive(struct pri *ctrl, q931_h *h, int len)
+/* here we trust receiving q931 only (no maintenance or anything else)*/
+int q931_read_event(struct pri *ctrl, q931_h *h, int len)
{
q931_mh *mh;
q931_call *c;
- q931_ie *ie;
- unsigned int x;
- int y;
+ int cref;
+ int missingmand;
+
+ //q931_dump(ctrl, h, len, 0);
+
+ mh = (q931_mh *)(h->contents + h->crlen);
+
+ cref = q931_cr(h);
+
+ /* XXX FIXME: when does the call structure will be freed???? when!? XXX */
+ c = q931_getcall(ctrl, cref);
+ if (!c) {
+ pri_error(ctrl, "Unable to locate call %d\n", cref);
+ return -1;
+ }
+
+ if (prepare_to_handle_q931_message(ctrl, mh, c)) {
+ return 0;
+ }
+
+ missingmand = 0;
+ if (q931_process_ies(ctrl, h, len, mh, c, &missingmand)) {
+ return -1;
+ }
+
+ return post_handle_q931_message(ctrl, mh, c, missingmand, 0);
+}
+
+int q931_receive(struct pri *ctrl, q931_h *h, int len)
+{
+ q931_mh *mh;
+ q931_call *c;
+ int missingmand;
int res;
- int r;
- int mandies[MAX_MAND_IES];
- int missingmand;
- int codeset, cur_codeset;
- int last_ie[8];
int cref;
- memset(last_ie, 0, sizeof(last_ie));
if (ctrl->debug & PRI_DEBUG_Q931_DUMP)
q931_dump(ctrl, h, len, 0);
#ifdef LIBPRI_COUNTERS
@@ -4362,11 +4388,43 @@
} else {
prepare_to_handle_q931_message(ctrl, mh, c);
}
+
+ /* Handle IEs */
+ missingmand = 0;
+ if (q931_process_ies(ctrl, h, len, mh, c, &missingmand)) {
+ return -1;
+ }
+
+ /* Post handling */
+ if ((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) {
+ res = post_handle_maintenance_message(ctrl, h->pd, mh, c);
+ } else {
+ res = post_handle_q931_message(ctrl, mh, c, missingmand, 1);
+ }
+ return res;
+}
+
+/*!
+ * \internal
+ * \brief Process all IEs in a Q931 msg
+ */
+static int q931_process_ies(struct pri *ctrl, q931_h *h, int len, q931_mh *mh, q931_call *c, int *missingmand)
+{
+ int mandies[MAX_MAND_IES];
+ unsigned int x;
+ int y;
+ int r;
+ int codeset, cur_codeset;
+ int last_ie[8];
+ q931_ie *ie;
+
+ memset(last_ie, 0, sizeof(last_ie));
+
q931_clr_subcommands(ctrl);
/* Handle IEs */
memset(mandies, 0, sizeof(mandies));
- missingmand = 0;
+ *missingmand = 0;
for (x=0;x<sizeof(msgs) / sizeof(msgs[0]); x++) {
if (msgs[x].msgnum == mh->msg) {
memcpy(mandies, msgs[x].mandies, sizeof(mandies));
@@ -4439,25 +4497,18 @@
x += r;
len -= r;
}
- missingmand = 0;
+ *missingmand = 0;
for (x=0;x<MAX_MAND_IES;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)) &&
((mh->msg != Q931_PROGRESS) || (mandies[x] != Q931_PROGRESS_INDICATOR))) {
pri_error(ctrl, "XXX Missing handling for mandatory IE %d (cs%d, %s) XXX\n", Q931_IE_IE(mandies[x]), Q931_IE_CODESET(mandies[x]), ie2str(mandies[x]));
- missingmand++;
+ (*missingmand)++;
}
}
}
-
- /* Post handling */
- if ((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) {
- res = post_handle_maintenance_message(ctrl, h->pd, mh, c);
- } else {
- res = post_handle_q931_message(ctrl, mh, c, missingmand);
- }
- return res;
+ return 0;
}
static int post_handle_maintenance_message(struct pri *ctrl, int protodisc, struct q931_mh *mh, struct q931_call *c)
@@ -4549,12 +4600,13 @@
* \param mh Q.931 message header.
* \param c Q.931 call leg.
* \param missingmand Number of missing mandatory ie's.
+ * \param checkstate Whether or not to check the state of the call
*
* \retval 0 if no error or event.
* \retval Q931_RES_HAVEEVENT if have an event.
* \retval -1 on error.
*/
-static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, int missingmand)
+static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, int missingmand, int checkstate)
{
int res;
struct apdu_event *cur = NULL;
@@ -4580,8 +4632,9 @@
q931_release_complete(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
break;
}
+
/* Must be new call */
- if (!c->newcall) {
+ if (checkstate && !c->newcall) {
break;
}
if (c->progressmask & PRI_PROG_CALLER_NOT_ISDN)
@@ -4620,7 +4673,6 @@
c->redirecting.to.number.presentation =
PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
}
-
ctrl->ev.e = PRI_EVENT_RING;
ctrl->ev.ring.subcmds = &ctrl->subcmds;
ctrl->ev.ring.channel = q931_encode_channel(c);
@@ -4690,10 +4742,12 @@
return Q931_RES_HAVEEVENT;
case Q931_ALERTING:
- if (c->newcall) {
+
+ if (checkstate && c->newcall) {
q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
break;
}
+
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_CALL_DELIVERED);
c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED;
ctrl->ev.e = PRI_EVENT_RINGING;
@@ -4718,14 +4772,16 @@
return Q931_RES_HAVEEVENT;
case Q931_CONNECT:
- if (c->newcall) {
+
+ if (checkstate && c->newcall) {
q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
break;
}
- if (c->ourcallstate == Q931_CALL_STATE_ACTIVE) {
+ if (checkstate && c->ourcallstate == Q931_CALL_STATE_ACTIVE) {
q931_status(ctrl, c, PRI_CAUSE_WRONG_MESSAGE);
break;
}
+
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_ACTIVE);
c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST;
@@ -4790,17 +4846,18 @@
/* Fall through */
case Q931_CALL_PROCEEDING:
ctrl->ev.proceeding.subcmds = &ctrl->subcmds;
- if (c->newcall) {
+ if (checkstate && c->newcall) {
q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
break;
}
- if ((c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED) &&
+ if (checkstate && (c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED) &&
(c->ourcallstate != Q931_CALL_STATE_OVERLAP_SENDING) &&
(c->ourcallstate != Q931_CALL_STATE_CALL_DELIVERED) &&
(c->ourcallstate != Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING)) {
q931_status(ctrl,c,PRI_CAUSE_WRONG_MESSAGE);
break;
}
+
ctrl->ev.proceeding.channel = q931_encode_channel(c);
if (mh->msg == Q931_CALL_PROCEEDING) {
ctrl->ev.e = PRI_EVENT_PROCEEDING;
@@ -4822,18 +4879,21 @@
}
return Q931_RES_HAVEEVENT;
case Q931_CONNECT_ACKNOWLEDGE:
- if (c->newcall) {
+
+ if (checkstate && c->newcall) {
q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
break;
}
- if (!(c->ourcallstate == Q931_CALL_STATE_CONNECT_REQUEST) &&
+ if (checkstate && !(c->ourcallstate == Q931_CALL_STATE_CONNECT_REQUEST) &&
!(c->ourcallstate == Q931_CALL_STATE_ACTIVE &&
(ctrl->localtype == PRI_NETWORK || ctrl->switchtype == PRI_SWITCH_QSIG))) {
q931_status(ctrl,c,PRI_CAUSE_WRONG_MESSAGE);
break;
}
+
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_ACTIVE);
c->peercallstate = Q931_CALL_STATE_ACTIVE;
+
break;
case Q931_STATUS:
if (missingmand) {
@@ -4936,7 +4996,7 @@
c->useruserinfo[0] = '\0';
/* Don't send release complete if they send us release
while we sent it, assume a NULL state */
- if (c->newcall)
+ if (checkstate && c->newcall)
q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
else
return Q931_RES_HAVEEVENT;
@@ -4946,7 +5006,7 @@
/* Still let user call release */
c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
}
- if (c->newcall) {
+ if (checkstate && c->newcall) {
q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
break;
}
@@ -5012,7 +5072,7 @@
q931_status(ctrl,c, 0);
break;
case Q931_SETUP_ACKNOWLEDGE:
- if (c->newcall) {
+ if (checkstate && c->newcall) {
q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
break;
}
More information about the libpri-commits
mailing list