Patch to add PTMP mode (BRI support)

git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@429 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
Matthew Fredrickson
2007-06-19 20:31:54 +00:00
parent 453e006faa
commit cbda0d7376
10 changed files with 305 additions and 107 deletions

View File

@@ -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

View File

@@ -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

25
pri.c
View File

@@ -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)

View File

@@ -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

View File

@@ -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,

View File

@@ -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 */

View File

@@ -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;x<MAX_SCHED;x++)
if (!pri->pri_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;

266
q921.c
View File

@@ -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);
}
}

8
q931.c
View File

@@ -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;

View File

@@ -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);
}