Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6a9ed870b | ||
|
|
0777515137 | ||
|
|
8f9296ef00 | ||
|
|
e1394704ad | ||
|
|
0961ecb4b0 | ||
|
|
a36186ce49 | ||
|
|
5f6e12c3e5 | ||
|
|
d80324dbdd | ||
|
|
e172ca2a03 | ||
|
|
e4f9ea7583 | ||
|
|
b5fa5986b2 | ||
|
|
f63cc76a94 | ||
|
|
cb01262a54 | ||
|
|
79e10c30a1 | ||
|
|
06d9c2aeb3 | ||
|
|
4e6c9e0410 | ||
|
|
88656d9497 | ||
|
|
fe0eba8175 | ||
|
|
24b85a379b | ||
|
|
ec99ad86dd | ||
|
|
ee9ef9ef3c | ||
|
|
f6966bc35b | ||
|
|
45efb97ebd | ||
|
|
110062aef6 | ||
|
|
de24dd76a6 | ||
|
|
e09654f0ed | ||
|
|
86fe59eacc | ||
|
|
2809056303 | ||
|
|
f8d3569b56 | ||
|
|
5f1aba027a | ||
|
|
a85d2c508b | ||
|
|
34f700b584 | ||
|
|
5137d733f9 | ||
|
|
5478d68b2a | ||
|
|
6e8e051464 | ||
|
|
80355d96c5 | ||
|
|
e4d3ca388b |
6
Makefile
Executable file → Normal file
6
Makefile
Executable file → Normal file
@@ -20,12 +20,16 @@
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
#
|
||||
# Uncomment if you want libpri not send PROGRESS_INDICATOR w/ALERTING
|
||||
#ALERTING=-DALERTING_NO_PROGRESS
|
||||
|
||||
TOBJS=testpri.o
|
||||
STATIC_LIBRARY=libpri.a
|
||||
DYNAMIC_LIBRARY=libpri.so.1.0
|
||||
STATIC_OBJS=pri.o q921.o prisched.o q931.o
|
||||
DYNAMIC_OBJS=pri.lo q921.lo prisched.lo q931.lo
|
||||
CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g
|
||||
CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g $(ALERTING)
|
||||
INSTALL_PREFIX=
|
||||
|
||||
all: $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
|
||||
|
||||
43
libpri.h
Executable file → Normal file
43
libpri.h
Executable file → Normal file
@@ -48,6 +48,7 @@
|
||||
#define PRI_SWITCH_ATT4ESS 4 /* AT&T 4ESS */
|
||||
#define PRI_SWITCH_EUROISDN_E1 5 /* Standard EuroISDN (CTR4, ETSI 300-102) */
|
||||
#define PRI_SWITCH_EUROISDN_T1 6 /* T1 EuroISDN variant (ETSI 300-102) */
|
||||
#define PRI_SWITCH_NI1 7 /* National ISDN 1 */
|
||||
|
||||
/* PRI D-Channel Events */
|
||||
#define PRI_EVENT_DCHAN_UP 1 /* D-channel is up */
|
||||
@@ -62,6 +63,9 @@
|
||||
#define PRI_EVENT_RESTART_ACK 10 /* Restart complete on a given channel */
|
||||
#define PRI_EVENT_FACNAME 11 /* Caller*ID Name received on Facility */
|
||||
#define PRI_EVENT_INFO_RECEIVED 12 /* Additional info (keypad) received */
|
||||
#define PRI_EVENT_PROCEEDING 13 /* When we get CALL_PROCEEDING or PROGRESS */
|
||||
#define PRI_EVENT_SETUP_ACK 14 /* When we get SETUP_ACKNOWLEDGE */
|
||||
#define PRI_EVENT_HANGUP_REQ 15 /* Requesting the higher layer to hangup */
|
||||
|
||||
/* Simple states */
|
||||
#define PRI_STATE_DOWN 0
|
||||
@@ -176,6 +180,8 @@
|
||||
#define PRI_LAYER_1_V120_RATE_ADAPT 0x28
|
||||
#define PRI_LAYER_1_X31_RATE_ADAPT 0x29
|
||||
|
||||
#define PRI_COPY_DIGITS_CALLED_NUMBER
|
||||
|
||||
typedef struct q931_call q931_call;
|
||||
|
||||
typedef struct pri_event_generic {
|
||||
@@ -231,6 +237,7 @@ typedef struct pri_event_ring {
|
||||
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? */
|
||||
q931_call *call; /* Opaque call pointer */
|
||||
} pri_event_ring;
|
||||
|
||||
@@ -247,6 +254,16 @@ typedef struct pri_event_restart_ack {
|
||||
int channel;
|
||||
} pri_event_restart_ack;
|
||||
|
||||
typedef struct pri_event_proceeding {
|
||||
int e;
|
||||
int channel;
|
||||
} pri_event_proceeding;
|
||||
|
||||
typedef struct pri_event_setup_ack {
|
||||
int e;
|
||||
int channel;
|
||||
} pri_event_setup_ack;
|
||||
|
||||
typedef union {
|
||||
int e;
|
||||
pri_event_generic gen; /* Generic view */
|
||||
@@ -258,6 +275,8 @@ typedef union {
|
||||
pri_event_ringing ringing; /* Ringing */
|
||||
pri_event_ringing answer; /* Answer */
|
||||
pri_event_restart_ack restartack; /* Restart Acknowledge */
|
||||
pri_event_proceeding proceeding; /* Call proceeding & Progress */
|
||||
pri_event_setup_ack setup_ack; /* SETUP_ACKNOWLEDGE structure */
|
||||
} pri_event;
|
||||
|
||||
struct pri;
|
||||
@@ -319,11 +338,31 @@ extern int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int
|
||||
Set non-isdn to non-zero if you are not connecting to ISDN equipment */
|
||||
extern int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
|
||||
|
||||
#if 0
|
||||
/* deprecated routines, use pri_hangup */
|
||||
/* Release/Reject a call */
|
||||
extern int pri_release(struct pri *pri, q931_call *call, int cause);
|
||||
|
||||
/* Hangup / Disconnect a call */
|
||||
extern int pri_disconnect(struct pri *pri, q931_call *call, int cause);
|
||||
#endif
|
||||
|
||||
#undef pri_release
|
||||
#undef pri_disconnect
|
||||
|
||||
/* backwards compatibility for those who don't use asterisk with libpri */
|
||||
#define pri_release(a,b,c) \
|
||||
pri_hangup(a,b,c)
|
||||
|
||||
#define pri_disconnect(a,b,c) \
|
||||
pri_hangup(a,b,c)
|
||||
|
||||
/* Hangup a call */
|
||||
#define PRI_HANGUP
|
||||
extern int pri_hangup(struct pri *pri, q931_call *call, int cause);
|
||||
|
||||
#define PRI_DESTROYCALL
|
||||
extern void pri_destroycall(struct pri *pri, q931_call *call);
|
||||
|
||||
extern int pri_reset(struct pri *pri, int channel);
|
||||
|
||||
@@ -343,4 +382,8 @@ extern int pri_call(struct pri *pri, q931_call *c, int transmode, int channel,
|
||||
/* Override message and error stuff */
|
||||
extern void pri_set_message(void (*__pri_error)(char *));
|
||||
extern void pri_set_error(void (*__pri_error)(char *));
|
||||
|
||||
/* Set overlap mode */
|
||||
#define PRI_SET_OVERLAPDIAL
|
||||
extern void pri_set_overlapdial(struct pri *pri,int state);
|
||||
#endif
|
||||
|
||||
30
pri.c
Executable file → Normal file
30
pri.c
Executable file → Normal file
@@ -49,6 +49,8 @@ char *pri_switch2str(int sw)
|
||||
return "Lucent 5E";
|
||||
case PRI_SWITCH_ATT4ESS:
|
||||
return "AT&T 4ESS";
|
||||
case PRI_SWITCH_NI1:
|
||||
return "National ISDN 1";
|
||||
default:
|
||||
return "Unknown switchtype";
|
||||
}
|
||||
@@ -188,6 +190,13 @@ int pri_information(struct pri *pri, q931_call *call, char digit)
|
||||
return q931_information(pri, call, digit);
|
||||
}
|
||||
|
||||
void pri_destroycall(struct pri *pri, q931_call *call)
|
||||
{
|
||||
if (pri && call)
|
||||
__q931_destroycall(pri, call);
|
||||
return;
|
||||
}
|
||||
|
||||
int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn)
|
||||
{
|
||||
if (!pri || !call)
|
||||
@@ -202,6 +211,8 @@ int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn)
|
||||
return q931_connect(pri, call, channel, nonisdn);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* deprecated routines, use pri_hangup */
|
||||
int pri_release(struct pri *pri, q931_call *call, int cause)
|
||||
{
|
||||
if (!pri || !call)
|
||||
@@ -215,6 +226,17 @@ int pri_disconnect(struct pri *pri, q931_call *call, int cause)
|
||||
return -1;
|
||||
return q931_disconnect(pri, call, cause);
|
||||
}
|
||||
#endif
|
||||
|
||||
int pri_hangup(struct pri *pri, q931_call *call, int cause)
|
||||
{
|
||||
if (!pri || !call)
|
||||
return -1;
|
||||
if (cause == -1)
|
||||
/* normal clear cause */
|
||||
cause = 16;
|
||||
return q931_hangup(pri, call, cause);
|
||||
}
|
||||
|
||||
int pri_reset(struct pri *pri, int channel)
|
||||
{
|
||||
@@ -263,7 +285,7 @@ int pri_call(struct pri *pri, q931_call *c, int transmode, int channel, int excl
|
||||
{
|
||||
if (!pri || !c)
|
||||
return -1;
|
||||
return q931_setup(pri, c, transmode, channel, exclusive, nonisdn, caller, callerplan, callername, callerpres, called, calledplan, ulayer1);
|
||||
return q931_setup(pri, c, transmode, channel, exclusive, nonisdn, caller, callerplan, callername, callerpres, called, calledplan, ulayer1);
|
||||
}
|
||||
|
||||
static void (*__pri_error)(char *stuff);
|
||||
@@ -304,3 +326,9 @@ void pri_error(char *fmt, ...)
|
||||
else
|
||||
fprintf(stderr, tmp);
|
||||
}
|
||||
/* Set overlap mode */
|
||||
void pri_set_overlapdial(struct pri *pri,int state)
|
||||
{
|
||||
pri->overlapdial = state;
|
||||
}
|
||||
|
||||
|
||||
4
pri_internal.h
Executable file → Normal file
4
pri_internal.h
Executable file → Normal file
@@ -58,6 +58,7 @@ struct pri {
|
||||
int v_na; /* What we've told our peer we've acknowledged */
|
||||
int solicitfbit; /* Have we sent an I or S frame with the F-bit set? */
|
||||
int retrans; /* Retransmissions */
|
||||
int sentrej; /* Are we in reject state */
|
||||
|
||||
int cref; /* Next call reference value */
|
||||
|
||||
@@ -78,6 +79,9 @@ struct pri {
|
||||
|
||||
/* Q.931 calls */
|
||||
q931_call *calls;
|
||||
|
||||
/* do we do overlap dialing */
|
||||
int overlapdial;
|
||||
};
|
||||
|
||||
extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);
|
||||
|
||||
0
pri_q921.h
Executable file → Normal file
0
pri_q921.h
Executable file → Normal file
5
pri_q931.h
Executable file → Normal file
5
pri_q931.h
Executable file → Normal file
@@ -255,6 +255,8 @@ extern int q931_release(struct pri *pri, q931_call *call, int cause);
|
||||
|
||||
extern int q931_disconnect(struct pri *pri, q931_call *call, int cause);
|
||||
|
||||
extern int q931_hangup(struct pri *pri, q931_call *call, int cause);
|
||||
|
||||
extern int q931_restart(struct pri *pri, int channel);
|
||||
|
||||
extern q931_call *q931_new_call(struct pri *pri);
|
||||
@@ -263,4 +265,7 @@ extern int q931_setup(struct pri *pri, q931_call *c, int transmode, int channel,
|
||||
int nonisdn, char *caller, int callerplan, char *callername, int callerpres, char *called,
|
||||
int calledplan, int ulay1);
|
||||
extern void q931_dump(q931_h *h, int len, int txrx);
|
||||
|
||||
extern void __q931_destroycall(struct pri *pri, q931_call *c);
|
||||
|
||||
#endif
|
||||
|
||||
0
prisched.c
Executable file → Normal file
0
prisched.c
Executable file → Normal file
139
q921.c
Executable file → Normal file
139
q921.c
Executable file → Normal file
@@ -49,6 +49,8 @@
|
||||
(hf).h.tei = 0; \
|
||||
} while(0)
|
||||
|
||||
static void reschedule_t203(struct pri *pri);
|
||||
|
||||
static void q921_discard_retransmissions(struct pri *pri)
|
||||
{
|
||||
struct q921_frame *f, *p;
|
||||
@@ -62,7 +64,8 @@ static void q921_discard_retransmissions(struct pri *pri)
|
||||
pri->txqueue = NULL;
|
||||
}
|
||||
|
||||
static int q921_transmit(struct pri *pri, q921_h *h, int len) {
|
||||
static int q921_transmit(struct pri *pri, q921_h *h, int len)
|
||||
{
|
||||
int res;
|
||||
#ifdef RANDOM_DROPS
|
||||
if (!(random() % 3)) {
|
||||
@@ -80,6 +83,7 @@ static int q921_transmit(struct pri *pri, q921_h *h, int len) {
|
||||
pri_error("Short write: %d/%d (%s)\n", res, len + 2, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
reschedule_t203(pri);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -174,17 +178,33 @@ static int q921_ack_packet(struct pri *pri, int num)
|
||||
|
||||
static void t203_expire(void *);
|
||||
static void t200_expire(void *);
|
||||
static pri_event *q921_dchannel_down(struct pri *pri);
|
||||
|
||||
static void q921_ack_rx(struct pri *pri, int ack)
|
||||
static void reschedule_t203(struct pri *pri)
|
||||
{
|
||||
if (pri->t203_timer) {
|
||||
pri_schedule_del(pri, pri->t203_timer);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static pri_event *q921_ack_rx(struct pri *pri, int ack)
|
||||
{
|
||||
int x;
|
||||
int cnt=0;
|
||||
pri_event *ev;
|
||||
/* Make sure the ACK was within our window */
|
||||
for (x=pri->v_a; (x != pri->v_s) && (x != ack); Q921_INC(x));
|
||||
if (x != ack) {
|
||||
/* ACK was outside of our window --- ignore */
|
||||
pri_error("ACK received outside of window, ignoring\n");
|
||||
return;
|
||||
pri_error("ACK received outside of window, restarting\n");
|
||||
ev = q921_dchannel_down(pri);
|
||||
q921_start(pri, 1);
|
||||
pri->schedev = 1;
|
||||
return ev;
|
||||
}
|
||||
/* Cancel each packet as necessary */
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
@@ -216,9 +236,10 @@ static void q921_ack_rx(struct pri *pri, int ack)
|
||||
/* Nothing to transmit, start the T203 counter instead */
|
||||
pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void q921_reject(struct pri *pri)
|
||||
static void q921_reject(struct pri *pri, int pf)
|
||||
{
|
||||
q921_h h;
|
||||
Q921_INIT(h);
|
||||
@@ -226,7 +247,7 @@ static void q921_reject(struct pri *pri)
|
||||
h.s.ss = 2; /* Reject */
|
||||
h.s.ft = 1; /* Frametype (01) */
|
||||
h.s.n_r = pri->v_r; /* Where to start retransmission */
|
||||
h.s.p_f = 1; /* XXX Should it always be set to 1? XXX */
|
||||
h.s.p_f = pf;
|
||||
switch(pri->localtype) {
|
||||
case PRI_NETWORK:
|
||||
h.h.c_r = 0;
|
||||
@@ -240,10 +261,11 @@ static void q921_reject(struct pri *pri)
|
||||
}
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
pri_message("Sending Reject (%d)\n", pri->v_r);
|
||||
pri->sentrej = 1;
|
||||
q921_transmit(pri, &h, 4);
|
||||
}
|
||||
|
||||
static void q921_rr(struct pri *pri, int pbit) {
|
||||
static void q921_rr(struct pri *pri, int pbit, int cmd) {
|
||||
q921_h h;
|
||||
Q921_INIT(h);
|
||||
h.s.x0 = 0; /* Always 0 */
|
||||
@@ -253,10 +275,16 @@ static void q921_rr(struct pri *pri, int pbit) {
|
||||
h.s.p_f = pbit; /* Poll/Final set appropriately */
|
||||
switch(pri->localtype) {
|
||||
case PRI_NETWORK:
|
||||
h.h.c_r = 0;
|
||||
if (cmd)
|
||||
h.h.c_r = 1;
|
||||
else
|
||||
h.h.c_r = 0;
|
||||
break;
|
||||
case PRI_CPE:
|
||||
h.h.c_r = 1;
|
||||
if (cmd)
|
||||
h.h.c_r = 0;
|
||||
else
|
||||
h.h.c_r = 1;
|
||||
break;
|
||||
default:
|
||||
pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
|
||||
@@ -268,8 +296,6 @@ static void q921_rr(struct pri *pri, int pbit) {
|
||||
q921_transmit(pri, &h, 4);
|
||||
}
|
||||
|
||||
static pri_event *q921_dchannel_down(struct pri *pri);
|
||||
|
||||
static void t200_expire(void *vpri)
|
||||
{
|
||||
struct pri *pri = vpri;
|
||||
@@ -289,14 +315,17 @@ static void t200_expire(void *vpri)
|
||||
/* Reschedule t200_timer */
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
pri_message("-- Retransmitting %d bytes\n", pri->txqueue->len);
|
||||
q921_transmit(pri, (q921_h *)&pri->txqueue->h, pri->txqueue->len);
|
||||
if (pri->busy)
|
||||
q921_rr(pri, 1, 0);
|
||||
else
|
||||
q921_transmit(pri, (q921_h *)&pri->txqueue->h, pri->txqueue->len);
|
||||
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);
|
||||
} else {
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
pri_message("-- Timeout occured, restarting PRI\n");
|
||||
pri->state = Q921_LINK_CONNECTION_RELEASED;
|
||||
pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
|
||||
pri->t200_timer = 0;
|
||||
q921_dchannel_down(pri);
|
||||
q921_start(pri, 1);
|
||||
@@ -344,8 +373,9 @@ int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr)
|
||||
else
|
||||
pri->txqueue = f;
|
||||
/* Immediately transmit unless we're in a recovery state */
|
||||
if (!pri->retrans)
|
||||
if (!pri->retrans && !pri->busy) {
|
||||
q921_transmit(pri, (q921_h *)(&f->h), f->len);
|
||||
}
|
||||
if (pri->t203_timer) {
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
pri_message("Stopping T_203 timer\n");
|
||||
@@ -370,47 +400,57 @@ int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr)
|
||||
static void t203_expire(void *vpri)
|
||||
{
|
||||
struct pri *pri = vpri;
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
pri_message("T203 counter expired, sending RR and scheduling T203 again\n");
|
||||
/* Solicit an F-bit in the other's RR */
|
||||
pri->solicitfbit = 1;
|
||||
q921_rr(pri, 1);
|
||||
/* Restart ourselves */
|
||||
pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri);
|
||||
if (pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) {
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
pri_message("T203 counter expired, sending RR and scheduling T203 again\n");
|
||||
/* Solicit an F-bit in the other's RR */
|
||||
pri->solicitfbit = 1;
|
||||
q921_rr(pri, 1, 1);
|
||||
/* Restart ourselves */
|
||||
pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri);
|
||||
} else {
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
pri_message("T203 counter expired in weird statd %d\n", pri->q921_state);
|
||||
pri->t203_timer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static pri_event *q921_handle_iframe(struct pri *pri, q921_i *i, int len)
|
||||
{
|
||||
int res;
|
||||
pri_event *ev;
|
||||
/* Make sure this is a valid packet */
|
||||
if (i->n_s == pri->v_r) {
|
||||
/* Increment next expected I-frame */
|
||||
Q921_INC(pri->v_r);
|
||||
/* Handle their ACK */
|
||||
q921_ack_rx(pri, i->n_r);
|
||||
pri->sentrej = 0;
|
||||
ev = q921_ack_rx(pri, i->n_r);
|
||||
if (ev)
|
||||
return ev;
|
||||
if (i->p_f) {
|
||||
/* If the Poll/Final bit is set, immediate send the RR */
|
||||
q921_rr(pri, 1);
|
||||
q921_rr(pri, 1, 0);
|
||||
} else if (pri->busy) {
|
||||
q921_rr(pri, 0, 0);
|
||||
}
|
||||
/* Receive Q.931 data */
|
||||
res = q931_receive(pri, (q931_h *)i->data, len - 4);
|
||||
/* Send an RR if one wasn't sent already */
|
||||
if (pri->v_na != pri->v_r)
|
||||
q921_rr(pri, 0);
|
||||
q921_rr(pri, 0, 0);
|
||||
if (res == -1) {
|
||||
return NULL;
|
||||
}
|
||||
if (res & Q931_RES_HAVEEVENT)
|
||||
return &pri->ev;
|
||||
} else {
|
||||
if (((pri->v_r - i->n_s) & 127) < pri->window) {
|
||||
/* It's within our window -- send back an RR */
|
||||
q921_rr(pri, 0);
|
||||
} else
|
||||
q921_reject(pri);
|
||||
#if 0
|
||||
q931_reject(pri);
|
||||
#endif
|
||||
/* If we haven't already sent a reject, send it now, otherwise
|
||||
we are obliged to RR */
|
||||
if (!pri->sentrej)
|
||||
q921_reject(pri, i->p_f);
|
||||
else if (i->p_f)
|
||||
q921_rr(pri, 1, 0);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -553,6 +593,9 @@ static pri_event *q921_dchannel_up(struct pri *pri)
|
||||
pri_schedule_del(pri, pri->sabme_timer);
|
||||
pri->sabme_timer = 0;
|
||||
|
||||
/* Reset any rejects */
|
||||
pri->sentrej = 0;
|
||||
|
||||
/* Go into connection established state */
|
||||
pri->q921_state = Q921_LINK_CONNECTION_ESTABLISHED;
|
||||
|
||||
@@ -592,13 +635,16 @@ void q921_reset(struct pri *pri)
|
||||
pri->solicitfbit = 0;
|
||||
pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
|
||||
pri->retrans = 0;
|
||||
pri->sentrej = 0;
|
||||
|
||||
/* Discard anything waiting to go out */
|
||||
q921_discard_retransmissions(pri);
|
||||
}
|
||||
|
||||
pri_event *q921_receive(struct pri *pri, q921_h *h, int len)
|
||||
static pri_event *__q921_receive(struct pri *pri, q921_h *h, int len)
|
||||
{
|
||||
q921_frame *f;
|
||||
pri_event *ev;
|
||||
int sendnow;
|
||||
/* Discard FCS */
|
||||
len -= 2;
|
||||
@@ -646,7 +692,9 @@ pri_event *q921_receive(struct pri *pri, q921_h *h, int len)
|
||||
/* Receiver Ready */
|
||||
pri->busy = 0;
|
||||
/* Acknowledge frames as necessary */
|
||||
q921_ack_rx(pri, h->s.n_r);
|
||||
ev = q921_ack_rx(pri, h->s.n_r);
|
||||
if (ev)
|
||||
return ev;
|
||||
if (h->s.p_f) {
|
||||
/* If it's a p/f one then send back a RR in return with the p/f bit set */
|
||||
if (pri->solicitfbit) {
|
||||
@@ -655,26 +703,28 @@ pri_event *q921_receive(struct pri *pri, q921_h *h, int len)
|
||||
} else {
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
pri_message("-- Unsolicited RR with P/F bit, responding\n");
|
||||
q921_rr(pri, 1);
|
||||
q921_rr(pri, 1, 0);
|
||||
}
|
||||
pri->solicitfbit = 0;
|
||||
}
|
||||
break;
|
||||
#if 0
|
||||
case 1:
|
||||
/* Receiver not ready */
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
pri_message("-- 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;
|
||||
#endif
|
||||
case 2:
|
||||
/* Just retransmit */
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
pri_message("-- 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);
|
||||
q921_rr(pri, 1, 0);
|
||||
}
|
||||
sendnow = 0;
|
||||
/* Resend the proper I-frame */
|
||||
@@ -726,7 +776,6 @@ pri_event *q921_receive(struct pri *pri, q921_h *h, int len)
|
||||
if (h->u.p_f) {
|
||||
/* Section 5.7.1 says we should restart on receiving a DM response with the f-bit set to
|
||||
one, but we wait T200 first */
|
||||
pri_event *ev = NULL;
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
pri_message("-- Got DM Mode from peer.\n");
|
||||
/* Disconnected mode, try again after T200 */
|
||||
@@ -752,7 +801,9 @@ pri_event *q921_receive(struct pri *pri, q921_h *h, int len)
|
||||
pri_message("-- Got Disconnect from peer.\n");
|
||||
/* Acknowledge */
|
||||
q921_send_ua(pri, h->u.p_f);
|
||||
return q921_dchannel_down(pri);
|
||||
ev = q921_dchannel_down(pri);
|
||||
q921_start(pri, 0);
|
||||
return ev;
|
||||
case 3:
|
||||
if (h->u.m2 == 3) {
|
||||
/* SABME */
|
||||
@@ -802,6 +853,14 @@ pri_event *q921_receive(struct pri *pri, q921_h *h, int len)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pri_event *q921_receive(struct pri *pri, q921_h *h, int len)
|
||||
{
|
||||
pri_event *e;
|
||||
e = __q921_receive(pri, h, len);
|
||||
reschedule_t203(pri);
|
||||
return e;
|
||||
}
|
||||
|
||||
void q921_start(struct pri *pri, int now)
|
||||
{
|
||||
if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED) {
|
||||
|
||||
Reference in New Issue
Block a user