[libpri-commits] mattf: trunk r429 - /trunk/
SVN commits to the libpri project
libpri-commits at lists.digium.com
Tue Jun 19 15:31:55 CDT 2007
Author: mattf
Date: Tue Jun 19 15:31:54 2007
New Revision: 429
URL: http://svn.digium.com/view/libpri?view=rev&rev=429
Log:
Patch to add PTMP mode (BRI support)
Modified:
trunk/Makefile
trunk/libpri.h
trunk/pri.c
trunk/pri_internal.h
trunk/pri_q921.h
trunk/pri_timers.h
trunk/prisched.c
trunk/q921.c
trunk/q931.c
trunk/testprilib.c
Modified: trunk/Makefile
URL: http://svn.digium.com/view/libpri/trunk/Makefile?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/Makefile (original)
+++ trunk/Makefile Tue Jun 19 15:31:54 2007
@@ -39,7 +39,7 @@
CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g $(ALERTING) $(LIBPRI_COUNTERS)
INSTALL_PREFIX=$(DESTDIR)
INSTALL_BASE=/usr
-SOFLAGS = -Wl,-hlibpri.so.1.0
+SOFLAGS = -Wl,-h./libpri.so.1.0
LDCONFIG = /sbin/ldconfig
ifneq (,$(findstring X$(OSARCH)X, XLinuxX XGNU/kFreeBSDX))
LDCONFIG_FLAGS=-n
Modified: trunk/libpri.h
URL: http://svn.digium.com/view/libpri/trunk/libpri.h?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/libpri.h (original)
+++ trunk/libpri.h Tue Jun 19 15:31:54 2007
@@ -257,20 +257,24 @@
typedef struct pri_event_generic {
/* Events with no additional information fall in this category */
int e;
+ struct pri *pri;
} pri_event_generic;
typedef struct pri_event_error {
int e;
+ struct pri *pri;
char err[256];
} pri_event_error;
typedef struct pri_event_restart {
int e;
+ struct pri *pri;
int channel;
} pri_event_restart;
typedef struct pri_event_ringing {
int e;
+ struct pri *pri;
int channel;
int cref;
int progress;
@@ -281,6 +285,7 @@
typedef struct pri_event_answer {
int e;
+ struct pri *pri;
int channel;
int cref;
int progress;
@@ -291,6 +296,7 @@
typedef struct pri_event_facname {
int e;
+ struct pri *pri;
int callingpres; /* Presentation of Calling CallerID */
int callingplan; /* Dialing plan of Calling entity */
char callingname[256];
@@ -304,7 +310,9 @@
#define PRI_CALLINGPLANRDNIS
typedef struct pri_event_ring {
int e;
+ struct pri *pri;
int channel; /* Channel requested */
+ int cref; /* Call Reference Number */
int callingpres; /* Presentation of Calling CallerID */
int callingplanani; /* Dialing plan of Calling entity ANI */
int callingplan; /* Dialing plan of Calling entity */
@@ -320,7 +328,6 @@
int callingplanrdnis; /* Dialing plan of Redirecting Number */
char useruserinfo[260]; /* User->User info */
int flexible; /* Are we flexible with our channel selection? */
- int cref; /* Call Reference Number */
int ctype; /* Call type (see PRI_TRANS_CAP_* */
int layer1; /* User layer 1 */
int complete; /* Have we seen "Complete" i.e. no more number? */
@@ -336,9 +343,10 @@
typedef struct pri_event_hangup {
int e;
+ struct pri *pri;
int channel; /* Channel requested */
+ int cref;
int cause;
- int cref;
q931_call *call; /* Opaque call pointer */
long aoc_units; /* Advise of Charge number of charged units */
char useruserinfo[260]; /* User->User info */
@@ -346,12 +354,14 @@
typedef struct pri_event_restart_ack {
int e;
+ struct pri *pri;
int channel;
} pri_event_restart_ack;
#define PRI_PROGRESS_CAUSE
typedef struct pri_event_proceeding {
int e;
+ struct pri *pri;
int channel;
int cref;
int progress;
@@ -362,18 +372,21 @@
typedef struct pri_event_setup_ack {
int e;
+ struct pri *pri;
int channel;
q931_call *call;
} pri_event_setup_ack;
typedef struct pri_event_notify {
int e;
+ struct pri *pri;
int channel;
int info;
} pri_event_notify;
typedef struct pri_event_keypad_digit {
int e;
+ struct pri *pri;
int channel;
q931_call *call;
char digits[64];
@@ -408,6 +421,7 @@
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_* */
extern struct pri *pri_new(int fd, int nodetype, int switchtype);
+extern struct pri *pri_new_bri(int fd, int nodetype, int switchtype);
/* Create D-channel just as above with user defined I/O callbacks and data */
extern struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata);
@@ -602,7 +616,7 @@
#define PRI_TIMER_N200 0 /* Maximum numer of q921 retransmissions */
#define PRI_TIMER_N201 1 /* Maximum numer of octets in an information field */
#define PRI_TIMER_N202 2 /* Maximum numer of transmissions of the TEI identity request message */
-#define PRI_TIMER_K 3 /* Maximum number of outstanding I-frames */
+#define PRI_TIMER_K 3 /* Maximum number of outstanding I-frames */
#define PRI_TIMER_T200 4 /* time between SABME's */
#define PRI_TIMER_T201 5 /* minimum time between retransmissions of the TEI Identity check messages */
@@ -630,4 +644,7 @@
#define PRI_TIMER_T321 26
#define PRI_TIMER_T322 27
+#define PRI_TIMER_TM20 28 /* maximum time avaiting XID response */
+#define PRI_TIMER_NM20 29 /* number of XID retransmits */
+
#endif
Modified: trunk/pri.c
URL: http://svn.digium.com/view/libpri/trunk/pri.c?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/pri.c (original)
+++ trunk/pri.c Tue Jun 19 15:31:54 2007
@@ -187,7 +187,7 @@
return res;
}
-static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata)
+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)
{
struct pri *p;
p = malloc(sizeof(struct pri));
@@ -200,13 +200,19 @@
p->localtype = node;
p->switchtype = switchtype;
p->cref = 1;
- p->sapi = Q921_SAPI_CALL_CTRL;
- p->tei = 0;
+ p->sapi = (tei == Q921_TEI_GROUP) ? Q921_SAPI_LAYER2_MANAGEMENT : Q921_SAPI_CALL_CTRL;
+ p->tei = tei;
p->nsf = PRI_NSF_NONE;
p->protodisc = Q931_PROTOCOL_DISCRIMINATOR;
p->master = master;
p->callpool = &p->localpool;
+ p->ev.gen.pri = p;
pri_default_timers(p, switchtype);
+ if (master) {
+ pri_set_debug(p, master->debug);
+ if (master->sendfacility)
+ pri_facility_enable(p);
+ }
#ifdef LIBPRI_COUNTERS
p->q921_rxcount = 0;
p->q921_txcount = 0;
@@ -217,7 +223,7 @@
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
p->sapi = Q921_SAPI_GR303_EOC;
p->tei = Q921_TEI_GR303_EOC_OPS;
- p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_EOC_PATH, p, NULL, NULL, NULL);
+ p->subchannel = __pri_new_tei(-1, node, PRI_SWITCH_GR303_EOC_PATH, p, NULL, NULL, NULL, Q921_TEI_GR303_EOC_PATH);
if (!p->subchannel) {
free(p);
p = NULL;
@@ -226,7 +232,7 @@
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
p->sapi = Q921_SAPI_GR303_TMC_CALLPROC;
p->tei = Q921_TEI_GR303_TMC_CALLPROC;
- p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_TMC_SWITCHING, p, NULL, NULL, NULL);
+ p->subchannel = __pri_new_tei(-1, node, PRI_SWITCH_GR303_TMC_SWITCHING, p, NULL, NULL, NULL, Q921_TEI_GR303_TMC_SWITCHING);
if (!p->subchannel) {
free(p);
p = NULL;
@@ -270,7 +276,12 @@
struct pri *pri_new(int fd, int nodetype, int switchtype)
{
- return __pri_new(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL);
+ return __pri_new_tei(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL, Q921_TEI_PRI);
+}
+
+struct pri *pri_new_bri(int fd, int nodetype, int switchtype)
+{
+ return __pri_new_tei(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL, Q921_TEI_GROUP);
}
struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata)
@@ -279,7 +290,7 @@
io_read = __pri_read;
if (!io_write)
io_write = __pri_write;
- return __pri_new(fd, nodetype, switchtype, NULL, io_read, io_write, userdata);
+ return __pri_new_tei(fd, nodetype, switchtype, NULL, io_read, io_write, userdata, Q921_TEI_PRI);
}
void *pri_get_userdata(struct pri *pri)
Modified: trunk/pri_internal.h
URL: http://svn.digium.com/view/libpri/trunk/pri_internal.h?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/pri_internal.h (original)
+++ trunk/pri_internal.h Tue Jun 19 15:31:54 2007
@@ -83,6 +83,9 @@
/* Various timers */
int sabme_timer; /* SABME retransmit */
int t203_timer; /* Max idle time */
+ int t202_timer;
+ int n202_counter;
+ int ri;
int t200_timer; /* T-200 retransmission timer */
/* All ISDN Timer values */
int timers[MAX_TIMERS];
@@ -265,4 +268,6 @@
void libpri_copy_string(char *dst, const char *src, size_t size);
+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);
+
#endif
Modified: trunk/pri_q921.h
URL: http://svn.digium.com/view/libpri/trunk/pri_q921.h?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/pri_q921.h (original)
+++ trunk/pri_q921.h Tue Jun 19 15:31:54 2007
@@ -46,10 +46,11 @@
#define Q921_FRAMETYPE_I 0x0
#define Q921_FRAMETYPE_S 0x1
-#define Q921_TEI_GROUP 127
+#define Q921_TEI_GROUP 127
+#define Q921_TEI_PRI 0
#define Q921_TEI_GR303_EOC_PATH 0
#define Q921_TEI_GR303_EOC_OPS 4
-#define Q921_TEI_GR303_TMC_SWITCHING 0
+#define Q921_TEI_GR303_TMC_SWITCHING 0
#define Q921_TEI_GR303_TMC_CALLPROC 0
#define Q921_SAPI_CALL_CTRL 0
@@ -62,6 +63,14 @@
#define Q921_SAPI_X25_LAYER3 16
#define Q921_SAPI_LAYER2_MANAGEMENT 63
+
+#define Q921_TEI_IDENTITY_REQUEST 1
+#define Q921_TEI_IDENTITY_ASSIGNED 2
+#define Q921_TEI_IDENTITY_DENIED 3
+#define Q921_TEI_IDENTITY_CHECK_REQUEST 4
+#define Q921_TEI_IDENTITY_CHECK_RESPONSE 5
+#define Q921_TEI_IDENTITY_REMOVE 6
+#define Q921_TEI_IDENTITY_VERIFY 7
typedef struct q921_header {
#if __BYTE_ORDER == __BIG_ENDIAN
@@ -154,6 +163,12 @@
#define Q921_INC(j) (j) = (((j) + 1) % 128)
typedef enum q921_state {
+ Q921_DOWN,
+ Q921_TEI_UNASSIGNED,
+ Q921_TEI_AWAITING_ESTABLISH,
+ Q921_TEI_AWAITING_ASSIGN,
+ Q921_TEI_ASSIGNED,
+ Q921_NEGOTIATION,
Q921_LINK_CONNECTION_RELEASED, /* Also known as TEI_ASSIGNED */
Q921_LINK_CONNECTION_ESTABLISHED,
Q921_AWAITING_ESTABLISH,
Modified: trunk/pri_timers.h
URL: http://svn.digium.com/view/libpri/trunk/pri_timers.h?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/pri_timers.h (original)
+++ trunk/pri_timers.h Tue Jun 19 15:31:54 2007
@@ -26,34 +26,37 @@
#define _PRI_TIMERS_H
/* -1 means we dont currently support the timer/counter */
-#define PRI_TIMERS_DEFAULT { 3, /* N200 */ \
- -1, /* N201 */ \
- -1, /* N202 */ \
- 7, /* K */ \
+#define PRI_TIMERS_DEFAULT { \
+ 3, /* N200 */ \
+ -1, /* N201 */ \
+ 3, /* N202 */ \
+ 7, /* K */ \
1000, /* T200 */ \
- -1, /* T201 */ \
- -1, /* T202 */ \
+ -1, /* T201 */ \
+ 10000, /* T202 */ \
10000, /* T203 */ \
- -1, /* T300 */ \
- -1, /* T301 */ \
- -1, /* T302 */ \
- -1, /* T303 */ \
- -1, /* T304 */ \
+ -1, /* T300 */ \
+ -1, /* T301 */ \
+ -1, /* T302 */ \
+ -1, /* T303 */ \
+ -1, /* T304 */ \
30000, /* T305 */ \
- -1, /* T306 */ \
- -1, /* T307 */ \
+ -1, /* T306 */ \
+ -1, /* T307 */ \
4000, /* T308 */ \
- -1, /* T309 */ \
- -1, /* T310 */ \
+ -1, /* T309 */ \
+ -1, /* T310 */ \
4000, /* T313 */ \
- -1, /* T314 */ \
- -1, /* T316 */ \
- -1, /* T317 */ \
- -1, /* T318 */ \
- -1, /* T319 */ \
- -1, /* T320 */ \
- -1, /* T321 */ \
- -1 /* T322 */ \
+ -1, /* T314 */ \
+ -1, /* T316 */ \
+ -1, /* T317 */ \
+ -1, /* T318 */ \
+ -1, /* T319 */ \
+ -1, /* T320 */ \
+ -1, /* T321 */ \
+ -1, /* T322 */ \
+ 2500, /* TM20 - Q.921 Appendix IV */ \
+ 3, /* NM20 - Q.921 Appendix IV */ \
}
/* XXX Only our default timers are setup now XXX */
Modified: trunk/prisched.c
URL: http://svn.digium.com/view/libpri/trunk/prisched.c?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/prisched.c (original)
+++ trunk/prisched.c Tue Jun 19 15:31:54 2007
@@ -35,6 +35,9 @@
{
int x;
struct timeval tv;
+ /* Scheduling runs on master channels only */
+ while (pri->master)
+ pri = pri->master;
for (x=1;x<MAX_SCHED;x++)
if (!pri->pri_sched[x].callback)
break;
@@ -113,6 +116,8 @@
void pri_schedule_del(struct pri *pri,int id)
{
+ while (pri->master)
+ pri = pri->master;
if ((id >= MAX_SCHED) || (id < 0))
pri_error(pri, "Asked to delete sched id %d???\n", id);
pri->pri_sched[id].callback = NULL;
Modified: trunk/q921.c
URL: http://svn.digium.com/view/libpri/trunk/q921.c?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/q921.c (original)
+++ trunk/q921.c Tue Jun 19 15:31:54 2007
@@ -51,6 +51,7 @@
} while(0)
static void reschedule_t203(struct pri *pri);
+static void q921_restart(struct pri *pri, int now);
static void q921_discard_retransmissions(struct pri *pri)
{
@@ -92,6 +93,53 @@
}
reschedule_t203(pri);
return 0;
+}
+
+static void q921_send_tei(struct pri *pri, int message, int ri, int ai, int isreq)
+{
+ q921_u *f;
+
+ f = malloc(sizeof(*f) + 5);
+ if (f) {
+ memset(f, 0, sizeof(*f) + 5);
+ Q921_INIT(pri, *f);
+ f->h.c_r = isreq;
+ f->m3 = 0;
+ f->m2 = 0;
+ f->p_f = 0;
+ f->ft = Q921_FRAMETYPE_U;
+ f->data[0] = 0x0f; /* Management entity */
+ f->data[1] = (ri >> 8) & 0xff;
+ f->data[2] = ri & 0xff;
+ f->data[3] = message;
+ f->data[4] = (ai << 1) | 1;
+// if (pri->debug & PRI_DEBUG_Q921_STATE)
+ pri_message(pri, "Sending TEI management message %d, TEI=%d\n", message, ai);
+ q921_transmit(pri, (q921_h *)f, 8);
+ free(f);
+ }
+}
+
+static void q921_tei_request(void *vpri)
+{
+ struct pri *pri = (struct pri *)vpri;
+
+ if (pri->subchannel) {
+ pri_error(pri, "Cannot request TEI while its already assigned\n");
+ return;
+ }
+ pri->n202_counter++;
+#if 0
+ if (pri->n202_counter > pri->timers[PRI_TIMER_N202]) {
+ pri_error(pri, "Unable to assign TEI from network\n");
+ return;
+ }
+#endif
+ pri->ri = random() % 65535;
+ q921_send_tei(pri, Q921_TEI_IDENTITY_REQUEST, pri->ri, Q921_TEI_GROUP, 1);
+ if (pri->t202_timer)
+ pri_schedule_del(pri, pri->t202_timer);
+ pri->t202_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T202], q921_tei_request, pri);
}
static void q921_send_ua(struct pri *pri, int pfbit)
@@ -655,8 +703,10 @@
q921_reset(pri);
/* Stop any SABME retransmissions */
- pri_schedule_del(pri, pri->sabme_timer);
- pri->sabme_timer = 0;
+ if (pri->sabme_timer) {
+ pri_schedule_del(pri, pri->sabme_timer);
+ pri->sabme_timer = 0;
+ }
/* Reset any rejects */
pri->sentrej = 0;
@@ -699,9 +749,12 @@
pri->v_na = 0;
pri->window = pri->timers[PRI_TIMER_K];
pri->windowlen = 0;
- pri_schedule_del(pri, pri->sabme_timer);
- pri_schedule_del(pri, pri->t203_timer);
- pri_schedule_del(pri, pri->t200_timer);
+ if (pri->sabme_timer)
+ pri_schedule_del(pri, pri->sabme_timer);
+ if (pri->t203_timer)
+ pri_schedule_del(pri, pri->t203_timer);
+ if (pri->t200_timer)
+ pri_schedule_del(pri, pri->t200_timer);
pri->sabme_timer = 0;
pri->t203_timer = 0;
pri->t200_timer = 0;
@@ -715,6 +768,66 @@
/* Discard anything waiting to go out */
q921_discard_retransmissions(pri);
+}
+
+static pri_event *q921_receive_MDL(struct pri *pri, q921_u *h, int len)
+{
+ int ri;
+ struct pri *sub;
+ int tei;
+ pri_message(pri, "Received MDL message\n");
+ if (h->data[0] != 0x0f) {
+ pri_error(pri, "Received MDL with unsupported management entity %02x\n", h->data[0]);
+ return NULL;
+ }
+ if (!(h->data[4] & 0x01)) {
+ pri_error(pri, "Received MDL with multibyte TEI identifier\n");
+ return NULL;
+ }
+ ri = (h->data[1] << 8) | h->data[2];
+ tei = (h->data[4] >> 1);
+ switch(h->data[3]) {
+ case Q921_TEI_IDENTITY_REQUEST:
+ if (tei != 127) {
+ pri_error(pri, "Received TEI identity request with invalid TEI %d\n", tei);
+ q921_send_tei(pri, Q921_TEI_IDENTITY_DENIED, ri, tei, 0);
+ }
+ /* Go to master */
+ for (sub = pri; sub->master; sub = sub->master);
+ tei = 64;
+ while(sub->subchannel) {
+ if(sub->subchannel->tei == tei)
+ ++tei;
+ }
+ sub->subchannel = __pri_new_tei(-1, pri->localtype, pri->switchtype, pri, NULL, NULL, NULL, tei);
+ if (!sub->subchannel) {
+ pri_error(pri, "Unable to allocate D-channel for new TEI %d\n", tei);
+ return NULL;
+ }
+ q921_send_tei(pri, Q921_TEI_IDENTITY_ASSIGNED, ri, tei, 0);
+ break;
+ case Q921_TEI_IDENTITY_ASSIGNED:
+ if (ri != pri->ri) {
+ pri_message(pri, "TEI assignment received for invalid Ri %02x (our is %02x)\n", ri, pri->ri);
+ return NULL;
+ }
+ if (pri->t202_timer) {
+ pri_schedule_del(pri, pri->t202_timer);
+ pri->t202_timer = 0;
+ }
+ if (pri->subchannel) {
+ pri_error(pri, "TEI already assigned (new is %d, current is %d)\n", tei, pri->subchannel->tei);
+ }
+ pri_message(pri, "TEI assiged to %d\n", tei);
+ pri->subchannel = __pri_new_tei(-1, pri->localtype, pri->switchtype, pri, NULL, NULL, NULL, tei);
+ if (!pri->subchannel) {
+ pri_error(pri, "Unable to allocate D-channel for new TEI %d\n", tei);
+ return NULL;
+ }
+ pri->q921_state = Q921_TEI_ASSIGNED;
+ break;
+ }
+ return NULL; /* Do we need to return something??? */
}
static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
@@ -767,59 +880,59 @@
pri->solicitfbit = 0;
}
break;
- case 1:
- /* Receiver not ready */
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "-- Got receiver not ready\n");
- if(h->s.p_f) {
- /* Send RR if poll bit set */
- q921_rr(pri, h->s.p_f, 0);
- }
- pri->busy = 1;
- break;
- case 2:
- /* Just retransmit */
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "-- Got reject requesting packet %d... Retransmitting.\n", h->s.n_r);
- if (h->s.p_f) {
- /* If it has the poll bit set, send an appropriate supervisory response */
- q921_rr(pri, 1, 0);
- }
- sendnow = 0;
- /* Resend the proper I-frame */
- for(f=pri->txqueue;f;f=f->next) {
- if ((sendnow || (f->h.n_s == h->s.n_r)) && f->transmitted) {
- /* Matches the request, or follows in our window, and has
- already been transmitted. */
- sendnow = 1;
- pri_error(pri, "!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n", h->s.n_r, f->h.n_s);
- f->h.n_r = pri->v_r;
- q921_transmit(pri, (q921_h *)(&f->h), f->len);
- }
- }
- if (!sendnow) {
- if (pri->txqueue) {
- /* This should never happen */
- if (!h->s.p_f || h->s.n_r) {
- pri_error(pri, "!! Got reject for frame %d, but we only have others!\n", h->s.n_r);
- }
- } else {
- /* Hrm, we have nothing to send, but have been REJ'd. Reset v_a, v_s, etc */
- pri_error(pri, "!! Got reject for frame %d, but we have nothing -- resetting!\n", h->s.n_r);
- pri->v_a = h->s.n_r;
- pri->v_s = h->s.n_r;
- /* Reset t200 timer if it was somehow going */
- if (pri->t200_timer) {
- pri_schedule_del(pri, pri->t200_timer);
- pri->t200_timer = 0;
- }
- /* Reset and restart t203 timer */
- if (pri->t203_timer)
- pri_schedule_del(pri, pri->t203_timer);
- pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
- }
- }
- break;
+ case 1:
+ /* Receiver not ready */
+ if (pri->debug & PRI_DEBUG_Q921_STATE)
+ pri_message(pri, "-- Got receiver not ready\n");
+ if(h->s.p_f) {
+ /* Send RR if poll bit set */
+ q921_rr(pri, h->s.p_f, 0);
+ }
+ pri->busy = 1;
+ break;
+ case 2:
+ /* Just retransmit */
+ if (pri->debug & PRI_DEBUG_Q921_STATE)
+ pri_message(pri, "-- Got reject requesting packet %d... Retransmitting.\n", h->s.n_r);
+ if (h->s.p_f) {
+ /* If it has the poll bit set, send an appropriate supervisory response */
+ q921_rr(pri, 1, 0);
+ }
+ sendnow = 0;
+ /* Resend the proper I-frame */
+ for(f=pri->txqueue;f;f=f->next) {
+ if ((sendnow || (f->h.n_s == h->s.n_r)) && f->transmitted) {
+ /* Matches the request, or follows in our window, and has
+ already been transmitted. */
+ sendnow = 1;
+ pri_error(pri, "!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n", h->s.n_r, f->h.n_s);
+ f->h.n_r = pri->v_r;
+ q921_transmit(pri, (q921_h *)(&f->h), f->len);
+ }
+ }
+ if (!sendnow) {
+ if (pri->txqueue) {
+ /* This should never happen */
+ if (!h->s.p_f || h->s.n_r) {
+ pri_error(pri, "!! Got reject for frame %d, but we only have others!\n", h->s.n_r);
+ }
+ } else {
+ /* Hrm, we have nothing to send, but have been REJ'd. Reset v_a, v_s, etc */
+ pri_error(pri, "!! Got reject for frame %d, but we have nothing -- resetting!\n", h->s.n_r);
+ pri->v_a = h->s.n_r;
+ pri->v_s = h->s.n_r;
+ /* Reset t200 timer if it was somehow going */
+ if (pri->t200_timer) {
+ pri_schedule_del(pri, pri->t200_timer);
+ pri->t200_timer = 0;
+ }
+ /* Reset and restart t203 timer */
+ if (pri->t203_timer)
+ pri_schedule_del(pri, pri->t203_timer);
+ pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
+ }
+ }
+ break;
default:
pri_error(pri, "!! XXX Unknown Supervisory frame ss=0x%02x,pf=%02xnr=%02x vs=%02x, va=%02x XXX\n", h->s.ss, h->s.p_f, h->s.n_r,
pri->v_s, pri->v_a);
@@ -840,7 +953,7 @@
pri_message(pri, "-- Got DM Mode from peer.\n");
/* Disconnected mode, try again after T200 */
ev = q921_dchannel_down(pri);
- q921_start(pri, 0);
+ q921_restart(pri, 0);
return ev;
} else {
@@ -848,12 +961,15 @@
pri_message(pri, "-- Ignoring unsolicited DM with p/f set to 0\n");
#if 0
/* Requesting that we start */
- q921_start(pri, 0);
+ q921_restart(pri, 0);
#endif
}
break;
} else if (!h->u.m2) {
- pri_message(pri, "XXX Unnumbered Information not implemented XXX\n");
+ if ((pri->sapi == Q921_SAPI_LAYER2_MANAGEMENT) && (pri->tei == Q921_TEI_GROUP))
+ q921_receive_MDL(pri, (q921_u *)h, len);
+ else
+ pri_message(pri, "XXX Unnumbered Information not implemented XXX\n");
}
break;
case 2:
@@ -862,7 +978,7 @@
/* Acknowledge */
q921_send_ua(pri, h->u.p_f);
ev = q921_dchannel_down(pri);
- q921_start(pri, 0);
+ q921_restart(pri, 0);
return ev;
case 3:
if (h->u.m2 == 3) {
@@ -926,21 +1042,27 @@
if (h->h.ea1 || !(h->h.ea2))
return NULL;
+#if 0 /* Will be rejected by subchannel analyzis */
/* Check for broadcasts - not yet handled */
if (h->h.tei == Q921_TEI_GROUP)
return NULL;
+#endif
/* Check for SAPIs we don't yet handle */
if ((h->h.sapi != pri->sapi) || (h->h.tei != pri->tei)) {
-#ifdef PROCESS_SUBCHANNELS
+//#ifdef PROCESS_SUBCHANNELS
/* If it's not us, try any subchannels we have */
if (pri->subchannel)
return q921_receive(pri->subchannel, h, len + 2);
else
-#endif
+//#endif
+ {
+ pri_error(pri, "Message for SAPI/TEI=%d/%d IS NOT HANDLED\n", h->h.sapi, h->h.tei);
return NULL;
-
- }
+ }
+
+ }
+ pri_message(pri, "Handling message for SAPI/TEI=%d/%d\n", h->h.sapi, h->h.tei);
ev = __q921_receive_qualified(pri, h, len);
reschedule_t203(pri);
return ev;
@@ -956,7 +1078,7 @@
return e;
}
-void q921_start(struct pri *pri, int now)
+static void q921_restart(struct pri *pri, int now)
{
if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED) {
pri_error(pri, "!! q921_start: Not in 'Link Connection Released' state\n");
@@ -967,3 +1089,17 @@
/* Do the SABME XXX Maybe we should implement T_WAIT? XXX */
q921_send_sabme(pri, now);
}
+
+void q921_start(struct pri *pri, int isCPE)
+{
+ q921_reset(pri);
+ if ((pri->sapi == Q921_SAPI_LAYER2_MANAGEMENT) && (pri->tei == Q921_TEI_GROUP)) {
+ pri_message(pri, "Starting in BRI mode\n");
+ pri->q921_state = Q921_DOWN;
+ if (isCPE)
+ q921_tei_request(pri);
+ } else {
+ pri_message(pri, "Starting in PRI mode, isCPE=%d, SAPI/TEI=%d/%d\n", isCPE, pri->sapi, pri->tei);
+ q921_send_sabme(pri, isCPE);
+ }
+}
Modified: trunk/q931.c
URL: http://svn.digium.com/view/libpri/trunk/q931.c?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/q931.c (original)
+++ trunk/q931.c Tue Jun 19 15:31:54 2007
@@ -2625,6 +2625,7 @@
return send_message(pri, c, Q931_SETUP_ACKNOWLEDGE, connect_ies);
}
+/* T313 expiry, first time */
static void pri_connect_timeout(void *data)
{
struct q931_call *c = data;
@@ -2635,6 +2636,7 @@
}
+/* T308 expiry, first time */
static void pri_release_timeout(void *data)
{
struct q931_call *c = data;
@@ -2643,9 +2645,12 @@
pri_message(pri, "Timed out looking for release complete\n");
c->t308_timedout++;
c->alive = 1;
- q931_release(pri, c, PRI_CAUSE_NORMAL_CLEARING);
-}
-
+
+ /* The call to q931_release will re-schedule T308 */
+ q931_release(pri, c, c->cause);
+}
+
+/* T308 expiry, second time */
static void pri_release_finaltimeout(void *data)
{
struct q931_call *c = data;
@@ -2667,6 +2672,7 @@
q931_hangup(pri, c, c->cause);
}
+/* T305 expiry, first time */
static void pri_disconnect_timeout(void *data)
{
struct q931_call *c = data;
Modified: trunk/testprilib.c
URL: http://svn.digium.com/view/libpri/trunk/testprilib.c?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/testprilib.c (original)
+++ trunk/testprilib.c Tue Jun 19 15:31:54 2007
@@ -64,7 +64,7 @@
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
-#define TEST_CALLS 32
+#define TEST_CALLS 1
static void event1(struct pri *pri, pri_event *e)
{
@@ -232,9 +232,9 @@
}
if (e) {
if (first == pri) {
- event1(pri, e);
+ event1(e->gen.pri, e);
} else {
- event2(pri, e);
+ event2(e->gen.pri, e);
}
}
pthread_mutex_unlock(&lock);
@@ -254,7 +254,7 @@
perror("socketpair");
exit(1);
}
- if (!(pri = pri_new(pair[0], PRI_NETWORK, PRI_DEF_SWITCHTYPE))) {
+ if (!(pri = pri_new_bri(pair[0], PRI_NETWORK, PRI_DEF_SWITCHTYPE))) {
perror("pri(0)");
exit(1);
}
@@ -265,7 +265,7 @@
perror("thread(0)");
exit(1);
}
- if (!(pri = pri_new(pair[1], PRI_CPE, PRI_DEF_SWITCHTYPE))) {
+ if (!(pri = pri_new_bri(pair[1], PRI_CPE, PRI_DEF_SWITCHTYPE))) {
perror("pri(1)");
exit(1);
}
More information about the libpri-commits
mailing list