Allow PRI timers to be congfigurable. (bug 2518)

git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@138 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
James Golovich 2004-10-02 14:55:20 +00:00
parent 2b7b7e2e68
commit ba5a5ca907
7 changed files with 241 additions and 26 deletions

View File

@ -481,7 +481,47 @@ extern void pri_enslave(struct pri *master, struct pri *slave);
#define PRI_ENSLAVE_SUPPORT #define PRI_ENSLAVE_SUPPORT
#define PRI_SETUP_CALL #define PRI_SETUP_CALL
#define PRI_RECEIVE_SUBADDR #define PRI_RECEIVE_SUBADDR
#endif
/* Send notification */ /* Send notification */
extern int pri_notify(struct pri *pri, q931_call *c, int channel, int info); 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

95
pri.c
View File

@ -23,6 +23,7 @@
#include "pri_internal.h" #include "pri_internal.h"
#include "pri_q921.h" #include "pri_q921.h"
#include "pri_q931.h" #include "pri_q931.h"
#include "pri_timers.h"
char *pri_node2str(int node) 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; x<PRI_MAX_TIMERS; x++) {
pri->timers[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) static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *master)
{ {
struct pri *p; 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->protodisc = Q931_PROTOCOL_DISCRIMINATOR;
p->master = master; p->master = master;
p->callpool = &p->localpool; p->callpool = &p->localpool;
pri_default_timers(p, switchtype);
#ifdef LIBPRI_COUNTERS #ifdef LIBPRI_COUNTERS
p->q921_rxcount = 0; p->q921_rxcount = 0;
p->q921_txcount = 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("Retrans: %d\n", pri->retrans);
pri_message("Busy: %d\n", pri->busy); pri_message("Busy: %d\n", pri->busy);
pri_message("Overlap Dial: %d\n", pri->overlapdial); 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) 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; sr->callerpres = callerpres;
return 0; return 0;
} }

View File

@ -40,6 +40,8 @@ enum q931_mode;
/* No more than 128 scheduled events */ /* No more than 128 scheduled events */
#define MAX_SCHED 128 #define MAX_SCHED 128
#define MAX_TIMERS 32
struct pri { struct pri {
int fd; /* File descriptor for D-Channel */ int fd; /* File descriptor for D-Channel */
struct pri *subchannel; /* Sub-channel if appropriate */ struct pri *subchannel; /* Sub-channel if appropriate */
@ -76,6 +78,8 @@ struct pri {
int sabme_timer; /* SABME retransmit */ int sabme_timer; /* SABME retransmit */
int t203_timer; /* Max idle time */ int t203_timer; /* Max idle time */
int t200_timer; /* T-200 retransmission timer */ int t200_timer; /* T-200 retransmission timer */
/* All ISDN Timer values */
int timers[MAX_TIMERS];
/* Used by scheduler */ /* Used by scheduler */
struct timeval tv; struct timeval tv;

View File

@ -36,9 +36,6 @@
#define T_WAIT_MIN 2000 #define T_WAIT_MIN 2000
#define T_WAIT_MAX 10000 #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 #define Q921_FRAMETYPE_MASK 0x3

83
pri_timers.h Executable file
View File

@ -0,0 +1,83 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Written by Mark Spencer <markster@linux-support.net>
*
* 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

26
q921.c
View File

@ -123,7 +123,7 @@ static void q921_send_sabme(void *vpri, int now)
q921_h h; q921_h h;
pri_schedule_del(pri, pri->sabme_timer); pri_schedule_del(pri, pri->sabme_timer);
pri->sabme_timer = 0; 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) if (!now)
return; return;
Q921_INIT(pri, h); Q921_INIT(pri, h);
@ -208,7 +208,7 @@ static void reschedule_t203(struct pri *pri)
if (pri->debug & PRI_DEBUG_Q921_STATE) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message("-- Restarting T203 counter\n"); pri_message("-- Restarting T203 counter\n");
/* Nothing to transmit, start the T203 counter instead */ /* 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) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message("-- Something left to transmit (%d), restarting T200 counter\n", pri->txqueue->h.n_s); pri_message("-- Something left to transmit (%d), restarting T200 counter\n", pri->txqueue->h.n_s);
if (!pri->t200_timer) 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 { } else {
if (pri->debug & PRI_DEBUG_Q921_STATE) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message("-- Nothing left, starting T203 counter\n"); pri_message("-- Nothing left, starting T203 counter\n");
/* Nothing to transmit, start the T203 counter instead */ /* 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; return NULL;
} }
@ -332,7 +332,7 @@ static void t200_expire(void *vpri)
pri->solicitfbit = 1; pri->solicitfbit = 1;
pri->retrans++; pri->retrans++;
/* Up to three retransmissions */ /* Up to three retransmissions */
if (pri->retrans < N_200) { if (pri->retrans < pri->timers[PRI_TIMER_N200]) {
/* Reschedule t200_timer */ /* Reschedule t200_timer */
if (pri->debug & PRI_DEBUG_Q921_STATE) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message("-- Retransmitting %d bytes\n", pri->txqueue->len); 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) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message("-- Rescheduling retransmission (%d)\n", pri->retrans); 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 { } else {
if (pri->debug & PRI_DEBUG_Q921_STATE) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message("-- Timeout occured, restarting PRI\n"); pri_message("-- Timeout occured, restarting PRI\n");
@ -359,10 +359,10 @@ static void t200_expire(void *vpri)
if (pri->debug & PRI_DEBUG_Q921_STATE) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message("-- Retrying poll with f-bit\n"); pri_message("-- Retrying poll with f-bit\n");
pri->retrans++; pri->retrans++;
if (pri->retrans < N_200) { if (pri->retrans < pri->timers[PRI_TIMER_N200]) {
pri->solicitfbit = 1; pri->solicitfbit = 1;
q921_rr(pri, 1, 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 { } else {
if (pri->debug & PRI_DEBUG_Q921_STATE) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message("-- Timeout occured, restarting PRI\n"); 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->t200_timer) {
if (pri->debug & PRI_DEBUG_Q921_STATE) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message("Starting T_200 timer\n"); 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 } else
if (pri->debug & PRI_DEBUG_Q921_STATE) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message("T_200 timer already going (%d)\n", pri->t200_timer); 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; pri->retrans = 0;
q921_rr(pri, 1, 1); q921_rr(pri, 1, 1);
/* Start timer T200 to resend our RR if we don't get it */ /* 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 { } else {
if (pri->debug & PRI_DEBUG_Q921_STATE) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message("T203 counter expired in weird state %d\n", pri->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; pri->q921_state = Q921_LINK_CONNECTION_ESTABLISHED;
/* Start the T203 timer */ /* 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 */ /* Report event that D-Channel is now up */
pri->ev.gen.e = PRI_EVENT_DCHAN_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_a = 0;
pri->v_r = 0; pri->v_r = 0;
pri->v_na = 0; pri->v_na = 0;
pri->window = 7; pri->window = pri->timers[PRI_TIMER_K];
pri->windowlen = 0; pri->windowlen = 0;
pri_schedule_del(pri, pri->sabme_timer); pri_schedule_del(pri, pri->sabme_timer);
pri_schedule_del(pri, pri->t203_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 */ /* Reset and restart t203 timer */
if (pri->t203_timer) if (pri->t203_timer)
pri_schedule_del(pri, 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; break;

12
q931.c
View File

@ -201,10 +201,6 @@ struct msgtype facilities[] = {
#define LOC_INTERNATIONAL_NETWORK 0x7 #define LOC_INTERNATIONAL_NETWORK 0x7
#define LOC_NETWORK_BEYOND_INTERWORKING 0xa #define LOC_NETWORK_BEYOND_INTERWORKING 0xa
#define T_308 4000
#define T_305 30000
#define T_313 4000
struct q931_call { struct q931_call {
struct pri *pri; /* PRI */ struct pri *pri; /* PRI */
int cr; /* Call Reference */ 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); pri_schedule_del(pri, c->retranstimer);
c->retranstimer = 0; c->retranstimer = 0;
if ((pri->localtype == PRI_CPE) && (!pri->subchannel)) 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); 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) if (c->retranstimer)
pri_schedule_del(pri, c->retranstimer); pri_schedule_del(pri, c->retranstimer);
if (!c->t308_timedout) { 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 { } 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); return send_message(pri, c, Q931_RELEASE, release_ies);
} else } else
@ -2179,7 +2175,7 @@ int q931_disconnect(struct pri *pri, q931_call *c, int cause)
c->sendhangupack = 1; c->sendhangupack = 1;
if (c->retranstimer) if (c->retranstimer)
pri_schedule_del(pri, 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); return send_message(pri, c, Q931_DISCONNECT, disconnect_ies);
} else } else
return 0; return 0;