diff --git a/Makefile b/Makefile index cafd668..d48931e 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ DYNAMIC_OBJS=copy_string.lo pri.lo q921.lo prisched.lo q931.lo pri_facility.lo 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 diff --git a/libpri.h b/libpri.h index 0ff1a48..5b0ee90 100644 --- a/libpri.h +++ b/libpri.h @@ -257,20 +257,24 @@ typedef struct q931_call q931_call; 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_ringing { typedef struct pri_event_answer { int e; + struct pri *pri; int channel; int cref; int progress; @@ -291,6 +296,7 @@ typedef struct pri_event_answer { 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 @@ typedef struct pri_event_facname { #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 @@ typedef struct pri_event_ring { 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_ring { typedef struct pri_event_hangup { int e; + struct pri *pri; int channel; /* Channel requested */ - int cause; int cref; + int cause; 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_hangup { 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_proceeding { 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 @@ typedef int (*pri_io_cb)(struct pri *pri, void *buf, int buflen); 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 @@ extern int pri_timer2idx(char *timer); #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 @@ extern int pri_timer2idx(char *timer); #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 diff --git a/pri.c b/pri.c index 98a7dbd..dda65bf 100644 --- a/pri.c +++ b/pri.c @@ -187,7 +187,7 @@ static int __pri_write(struct pri *pri, void *buf, int buflen) 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 @@ static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *maste 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 @@ static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *maste 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 @@ static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *maste 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 @@ int pri_restart(struct pri *pri) 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 @@ struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, 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) diff --git a/pri_internal.h b/pri_internal.h index f514ec4..649285b 100644 --- a/pri_internal.h +++ b/pri_internal.h @@ -83,6 +83,9 @@ struct pri { /* 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 @@ extern void pri_error(struct pri *pri, char *fmt, ...); 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 diff --git a/pri_q921.h b/pri_q921.h index 1c4d6ad..3bd8104 100644 --- a/pri_q921.h +++ b/pri_q921.h @@ -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 @@ -63,6 +64,14 @@ #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 u_int8_t sapi:6; /* Service Access Point Indentifier (always 0 for PRI) (0) */ @@ -154,6 +163,12 @@ typedef struct q921_frame { #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, diff --git a/pri_timers.h b/pri_timers.h index fd2e4eb..1666093 100644 --- a/pri_timers.h +++ b/pri_timers.h @@ -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 */ diff --git a/prisched.c b/prisched.c index eee5f1c..1e3558d 100644 --- a/prisched.c +++ b/prisched.c @@ -35,6 +35,9 @@ int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), vo { int x; struct timeval tv; + /* Scheduling runs on master channels only */ + while (pri->master) + pri = pri->master; for (x=1;xpri_sched[x].callback) break; @@ -113,6 +116,8 @@ pri_event *pri_schedule_run(struct pri *pri) 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; diff --git a/q921.c b/q921.c index 0ede219..6a05410 100644 --- a/q921.c +++ b/q921.c @@ -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) { @@ -94,6 +95,53 @@ static int q921_transmit(struct pri *pri, q921_h *h, int len) 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) { q921_h h; @@ -655,8 +703,10 @@ static pri_event *q921_dchannel_up(struct pri *pri) 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 @@ void q921_reset(struct pri *pri) 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; @@ -717,6 +770,66 @@ void q921_reset(struct pri *pri) 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) { q921_frame *f; @@ -767,59 +880,59 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len) 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 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len) 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 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len) 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 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len) /* 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 @@ static pri_event *__q921_receive(struct pri *pri, q921_h *h, int len) 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 @@ pri_event *q921_receive(struct pri *pri, q921_h *h, int len) 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 @@ void q921_start(struct pri *pri, int now) /* 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); + } +} diff --git a/q931.c b/q931.c index 97e3376..e974da7 100644 --- a/q931.c +++ b/q931.c @@ -2625,6 +2625,7 @@ int q931_setup_ack(struct pri *pri, q931_call *c, int channel, int nonisdn) 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 @@ static void pri_connect_timeout(void *data) } +/* T308 expiry, first time */ static void pri_release_timeout(void *data) { struct q931_call *c = data; @@ -2643,9 +2645,12 @@ static void pri_release_timeout(void *data) 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 @@ static void pri_release_finaltimeout(void *data) q931_hangup(pri, c, c->cause); } +/* T305 expiry, first time */ static void pri_disconnect_timeout(void *data) { struct q931_call *c = data; diff --git a/testprilib.c b/testprilib.c index e7560de..40e1a0c 100644 --- a/testprilib.c +++ b/testprilib.c @@ -64,7 +64,7 @@ static struct pri *first, *cur; 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 @@ static void *dchan(void *data) } 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 @@ int main(int argc, char *argv[]) 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 @@ int main(int argc, char *argv[]) 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); }