diff --git a/libpri.h b/libpri.h index 3bcf0d1..e060ff9 100755 --- a/libpri.h +++ b/libpri.h @@ -481,7 +481,47 @@ extern void pri_enslave(struct pri *master, struct pri *slave); #define PRI_ENSLAVE_SUPPORT #define PRI_SETUP_CALL #define PRI_RECEIVE_SUBADDR -#endif /* Send notification */ extern int pri_notify(struct pri *pri, q931_call *c, int channel, int info); + +/* Get/Set PRI Timers */ +#define PRI_GETSET_TIMERS +extern int pri_set_timer(struct pri *pri, int timer, int value); +extern int pri_get_timer(struct pri *pri, int timer); +extern int pri_timer2idx(char *timer); + +#define PRI_MAX_TIMERS 32 + +#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_T200 4 /* time between SABME's */ +#define PRI_TIMER_T201 5 /* minimum time between retransmissions of the TEI Identity check messages */ +#define PRI_TIMER_T202 6 /* minimum time between transmission of TEI Identity request messages */ +#define PRI_TIMER_T203 7 /* maxiumum time without exchanging packets */ + +#define PRI_TIMER_T300 8 +#define PRI_TIMER_T301 9 /* maximum time to respond to an ALERT */ +#define PRI_TIMER_T302 10 +#define PRI_TIMER_T303 11 /* maximum time to wait after sending a SETUP without a response */ +#define PRI_TIMER_T304 12 +#define PRI_TIMER_T305 13 +#define PRI_TIMER_T306 14 +#define PRI_TIMER_T307 15 +#define PRI_TIMER_T308 16 +#define PRI_TIMER_T309 17 +#define PRI_TIMER_T310 18 /* maximum time between receiving a CALLPROCEEDING and receiving a ALERT/CONNECT/DISCONNECT/PROGRESS */ +#define PRI_TIMER_T313 19 +#define PRI_TIMER_T314 20 +#define PRI_TIMER_T316 21 /* maximum time between transmitting a RESTART and receiving a RESTART ACK */ +#define PRI_TIMER_T317 22 +#define PRI_TIMER_T318 23 +#define PRI_TIMER_T319 24 +#define PRI_TIMER_T320 25 +#define PRI_TIMER_T321 26 +#define PRI_TIMER_T322 27 + +#endif diff --git a/pri.c b/pri.c index 95cb650..c77d206 100755 --- a/pri.c +++ b/pri.c @@ -23,6 +23,7 @@ #include "pri_internal.h" #include "pri_q921.h" #include "pri_q931.h" +#include "pri_timers.h" char *pri_node2str(int node) { @@ -62,6 +63,92 @@ char *pri_switch2str(int sw) } } +static void pri_default_timers(struct pri *pri, int switchtype) +{ + int defaulttimers[20][PRI_MAX_TIMERS] = PRI_TIMERS_ALL; + int x; + + for (x = 0; xtimers[x] = defaulttimers[switchtype][x]; + } +} + +int pri_set_timer(struct pri *pri, int timer, int value) +{ + if (timer < 0 || timer > PRI_MAX_TIMERS || value < 0) + return -1; + + pri->timers[timer] = value; + return 0; +} + +int pri_get_timer(struct pri *pri, int timer) +{ + if (timer < 0 || timer > PRI_MAX_TIMERS) + return -1; + return pri->timers[timer]; +} + +int pri_timer2idx(char *timer) +{ + if (!strcasecmp(timer, "N200")) + return PRI_TIMER_N200; + else if (!strcasecmp(timer, "N201")) + return PRI_TIMER_N201; + else if (!strcasecmp(timer, "N202")) + return PRI_TIMER_N202; + else if (!strcasecmp(timer, "K")) + return PRI_TIMER_K; + else if (!strcasecmp(timer, "T200")) + return PRI_TIMER_T200; + else if (!strcasecmp(timer, "T202")) + return PRI_TIMER_T202; + else if (!strcasecmp(timer, "T203")) + return PRI_TIMER_T203; + else if (!strcasecmp(timer, "T300")) + return PRI_TIMER_T300; + else if (!strcasecmp(timer, "T301")) + return PRI_TIMER_T301; + else if (!strcasecmp(timer, "T302")) + return PRI_TIMER_T302; + else if (!strcasecmp(timer, "T303")) + return PRI_TIMER_T303; + else if (!strcasecmp(timer, "T304")) + return PRI_TIMER_T304; + else if (!strcasecmp(timer, "T305")) + return PRI_TIMER_T305; + else if (!strcasecmp(timer, "T306")) + return PRI_TIMER_T306; + else if (!strcasecmp(timer, "T307")) + return PRI_TIMER_T307; + else if (!strcasecmp(timer, "T308")) + return PRI_TIMER_T308; + else if (!strcasecmp(timer, "T309")) + return PRI_TIMER_T309; + else if (!strcasecmp(timer, "T310")) + return PRI_TIMER_T310; + else if (!strcasecmp(timer, "T313")) + return PRI_TIMER_T313; + else if (!strcasecmp(timer, "T314")) + return PRI_TIMER_T314; + else if (!strcasecmp(timer, "T316")) + return PRI_TIMER_T316; + else if (!strcasecmp(timer, "T317")) + return PRI_TIMER_T317; + else if (!strcasecmp(timer, "T318")) + return PRI_TIMER_T318; + else if (!strcasecmp(timer, "T319")) + return PRI_TIMER_T319; + else if (!strcasecmp(timer, "T320")) + return PRI_TIMER_T320; + else if (!strcasecmp(timer, "T321")) + return PRI_TIMER_T321; + else if (!strcasecmp(timer, "T322")) + return PRI_TIMER_T322; + else + return -1; +} + static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *master) { struct pri *p; @@ -78,6 +165,7 @@ static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *maste p->protodisc = Q931_PROTOCOL_DISCRIMINATOR; p->master = master; p->callpool = &p->localpool; + pri_default_timers(p, switchtype); #ifdef LIBPRI_COUNTERS p->q921_rxcount = 0; p->q921_txcount = 0; @@ -474,6 +562,12 @@ void pri_dump_info(struct pri *pri) pri_message("Retrans: %d\n", pri->retrans); pri_message("Busy: %d\n", pri->busy); pri_message("Overlap Dial: %d\n", pri->overlapdial); + pri_message("T200 Timer: %d\n", pri->timers[PRI_TIMER_T200]); + pri_message("T203 Timer: %d\n", pri->timers[PRI_TIMER_T203]); + pri_message("T305 Timer: %d\n", pri->timers[PRI_TIMER_T305]); + pri_message("T308 Timer: %d\n", pri->timers[PRI_TIMER_T308]); + pri_message("T313 Timer: %d\n", pri->timers[PRI_TIMER_T313]); + pri_message("N200 Counter: %d\n", pri->timers[PRI_TIMER_N200]); } int pri_get_crv(struct pri *pri, q931_call *call, int *callmode) @@ -537,3 +631,4 @@ int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int cal sr->callerpres = callerpres; return 0; } + diff --git a/pri_internal.h b/pri_internal.h index b7882b2..6f8c184 100755 --- a/pri_internal.h +++ b/pri_internal.h @@ -40,6 +40,8 @@ enum q931_mode; /* No more than 128 scheduled events */ #define MAX_SCHED 128 +#define MAX_TIMERS 32 + struct pri { int fd; /* File descriptor for D-Channel */ struct pri *subchannel; /* Sub-channel if appropriate */ @@ -76,7 +78,9 @@ struct pri { int sabme_timer; /* SABME retransmit */ int t203_timer; /* Max idle time */ int t200_timer; /* T-200 retransmission timer */ - + /* All ISDN Timer values */ + int timers[MAX_TIMERS]; + /* Used by scheduler */ struct timeval tv; int schedev; diff --git a/pri_q921.h b/pri_q921.h index 6a7eb4a..d0f63ca 100755 --- a/pri_q921.h +++ b/pri_q921.h @@ -36,9 +36,6 @@ #define T_WAIT_MIN 2000 #define T_WAIT_MAX 10000 -#define T_200 1000 /* 1 second between SABME's */ -#define T_203 10000 /* 10 seconds with no packets max */ -#define N_200 3 /* 3 retries */ #define Q921_FRAMETYPE_MASK 0x3 diff --git a/pri_timers.h b/pri_timers.h new file mode 100755 index 0000000..0eef282 --- /dev/null +++ b/pri_timers.h @@ -0,0 +1,83 @@ +/* + * libpri: An implementation of Primary Rate ISDN + * + * Written by Mark Spencer + * + * Copyright (C) 2001, Linux Support Services, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _PRI_TIMERS_H +#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 */ \ + 1000, /* T200 */ \ + -1, /* T201 */ \ + -1, /* T202 */ \ + 10000, /* T203 */ \ + -1, /* T300 */ \ + -1, /* T301 */ \ + -1, /* T302 */ \ + -1, /* T303 */ \ + -1, /* T304 */ \ + 30000, /* T305 */ \ + -1, /* T306 */ \ + -1, /* T307 */ \ + 4000, /* T308 */ \ + -1, /* T309 */ \ + -1, /* T310 */ \ + 4000, /* T313 */ \ + -1, /* T314 */ \ + -1, /* T316 */ \ + -1, /* T317 */ \ + -1, /* T318 */ \ + -1, /* T319 */ \ + -1, /* T320 */ \ + -1, /* T321 */ \ + -1 /* T322 */ \ + } + +/* XXX Only our default timers are setup now XXX */ +#define PRI_TIMERS_UNKNOWN PRI_TIMERS_DEFAULT +#define PRI_TIMERS_NI2 PRI_TIMERS_DEFAULT +#define PRI_TIMERS_DMS100 PRI_TIMERS_DEFAULT +#define PRI_TIMERS_LUCENT5E PRI_TIMERS_DEFAULT +#define PRI_TIMERS_ATT4ESS PRI_TIMERS_DEFAULT +#define PRI_TIMERS_EUROISDN_E1 PRI_TIMERS_DEFAULT +#define PRI_TIMERS_EUROISDN_T1 PRI_TIMERS_DEFAULT +#define PRI_TIMERS_NI1 PRI_TIMERS_DEFAULT +#define PRI_TIMERS_GR303_EOC PRI_TIMERS_DEFAULT +#define PRI_TIMERS_GR303_TMC PRI_TIMERS_DEFAULT + +#define PRI_TIMERS_ALL { PRI_TIMERS_UNKNOWN, \ + PRI_TIMERS_NI2, \ + PRI_TIMERS_DMS100, \ + PRI_TIMERS_LUCENT5E, \ + PRI_TIMERS_ATT4ESS, \ + PRI_TIMERS_EUROISDN_E1, \ + PRI_TIMERS_EUROISDN_T1, \ + PRI_TIMERS_NI1, \ + PRI_TIMERS_GR303_EOC, \ + PRI_TIMERS_GR303_TMC \ + } + +#endif diff --git a/q921.c b/q921.c index 1a64b3d..c29e215 100755 --- a/q921.c +++ b/q921.c @@ -123,7 +123,7 @@ static void q921_send_sabme(void *vpri, int now) q921_h h; pri_schedule_del(pri, pri->sabme_timer); pri->sabme_timer = 0; - pri->sabme_timer = pri_schedule_event(pri, T_200, q921_send_sabme_now, pri); + pri->sabme_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], q921_send_sabme_now, pri); if (!now) return; Q921_INIT(pri, h); @@ -208,7 +208,7 @@ static void reschedule_t203(struct pri *pri) if (pri->debug & PRI_DEBUG_Q921_STATE) pri_message("-- Restarting T203 counter\n"); /* Nothing to transmit, start the T203 counter instead */ - pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri); + pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri); } } @@ -250,12 +250,12 @@ static pri_event *q921_ack_rx(struct pri *pri, int ack) if (pri->debug & PRI_DEBUG_Q921_STATE) pri_message("-- Something left to transmit (%d), restarting T200 counter\n", pri->txqueue->h.n_s); if (!pri->t200_timer) - pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri); + pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri); } else { if (pri->debug & PRI_DEBUG_Q921_STATE) pri_message("-- Nothing left, starting T203 counter\n"); /* Nothing to transmit, start the T203 counter instead */ - pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri); + pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri); } return NULL; } @@ -332,7 +332,7 @@ static void t200_expire(void *vpri) pri->solicitfbit = 1; pri->retrans++; /* Up to three retransmissions */ - if (pri->retrans < N_200) { + if (pri->retrans < pri->timers[PRI_TIMER_N200]) { /* Reschedule t200_timer */ if (pri->debug & PRI_DEBUG_Q921_STATE) pri_message("-- Retransmitting %d bytes\n", pri->txqueue->len); @@ -345,7 +345,7 @@ static void t200_expire(void *vpri) } if (pri->debug & PRI_DEBUG_Q921_STATE) pri_message("-- Rescheduling retransmission (%d)\n", pri->retrans); - pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri); + pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri); } else { if (pri->debug & PRI_DEBUG_Q921_STATE) pri_message("-- Timeout occured, restarting PRI\n"); @@ -359,10 +359,10 @@ static void t200_expire(void *vpri) if (pri->debug & PRI_DEBUG_Q921_STATE) pri_message("-- Retrying poll with f-bit\n"); pri->retrans++; - if (pri->retrans < N_200) { + if (pri->retrans < pri->timers[PRI_TIMER_N200]) { pri->solicitfbit = 1; q921_rr(pri, 1, 1); - pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri); + pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri); } else { if (pri->debug & PRI_DEBUG_Q921_STATE) pri_message("-- Timeout occured, restarting PRI\n"); @@ -436,7 +436,7 @@ int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr) if (!pri->t200_timer) { if (pri->debug & PRI_DEBUG_Q921_STATE) pri_message("Starting T_200 timer\n"); - pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri); + pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri); } else if (pri->debug & PRI_DEBUG_Q921_STATE) pri_message("T_200 timer already going (%d)\n", pri->t200_timer); @@ -459,7 +459,7 @@ static void t203_expire(void *vpri) pri->retrans = 0; q921_rr(pri, 1, 1); /* Start timer T200 to resend our RR if we don't get it */ - pri->t203_timer = pri_schedule_event(pri, T_200, t200_expire, pri); + pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri); } else { if (pri->debug & PRI_DEBUG_Q921_STATE) pri_message("T203 counter expired in weird state %d\n", pri->q921_state); @@ -656,7 +656,7 @@ static pri_event *q921_dchannel_up(struct pri *pri) pri->q921_state = Q921_LINK_CONNECTION_ESTABLISHED; /* Start the T203 timer */ - pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri); + pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri); /* Report event that D-Channel is now up */ pri->ev.gen.e = PRI_EVENT_DCHAN_UP; @@ -680,7 +680,7 @@ void q921_reset(struct pri *pri) pri->v_a = 0; pri->v_r = 0; pri->v_na = 0; - pri->window = 7; + pri->window = pri->timers[PRI_TIMER_K]; pri->windowlen = 0; pri_schedule_del(pri, pri->sabme_timer); pri_schedule_del(pri, pri->t203_timer); @@ -797,7 +797,7 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len) /* Reset and restart t203 timer */ if (pri->t203_timer) pri_schedule_del(pri, pri->t203_timer); - pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri); + pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri); } } break; diff --git a/q931.c b/q931.c index ceeb86a..d0e7cc8 100755 --- a/q931.c +++ b/q931.c @@ -201,10 +201,6 @@ struct msgtype facilities[] = { #define LOC_INTERNATIONAL_NETWORK 0x7 #define LOC_NETWORK_BEYOND_INTERWORKING 0xa -#define T_308 4000 -#define T_305 30000 -#define T_313 4000 - struct q931_call { struct pri *pri; /* PRI */ int cr; /* Call Reference */ @@ -2114,7 +2110,7 @@ int q931_connect(struct pri *pri, q931_call *c, int channel, int nonisdn) pri_schedule_del(pri, c->retranstimer); c->retranstimer = 0; if ((pri->localtype == PRI_CPE) && (!pri->subchannel)) - c->retranstimer = pri_schedule_event(pri, T_313, pri_connect_timeout, c); + c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T313], pri_connect_timeout, c); return send_message(pri, c, Q931_CONNECT, connect_ies); } @@ -2133,9 +2129,9 @@ int q931_release(struct pri *pri, q931_call *c, int cause) if (c->retranstimer) pri_schedule_del(pri, c->retranstimer); if (!c->t308_timedout) { - c->retranstimer = pri_schedule_event(pri, T_308, pri_release_timeout, c); + c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T308], pri_release_timeout, c); } else { - c->retranstimer = pri_schedule_event(pri, T_308, pri_release_finaltimeout, c); + c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T308], pri_release_finaltimeout, c); } return send_message(pri, c, Q931_RELEASE, release_ies); } else @@ -2179,7 +2175,7 @@ int q931_disconnect(struct pri *pri, q931_call *c, int cause) c->sendhangupack = 1; if (c->retranstimer) pri_schedule_del(pri, c->retranstimer); - c->retranstimer = pri_schedule_event(pri, T_305, pri_disconnect_timeout, c); + c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T305], pri_disconnect_timeout, c); return send_message(pri, c, Q931_DISCONNECT, disconnect_ies); } else return 0;