[libpri-commits] mattf: branch 1.4 r1406 - /branches/1.4/
SVN commits to the libpri project
libpri-commits at lists.digium.com
Wed Jan 13 13:38:01 CST 2010
Author: mattf
Date: Wed Jan 13 13:37:59 2010
New Revision: 1406
URL: http://svnview.digium.com/svn/libpri?view=rev&rev=1406
Log:
Merge of Q.921 rewrite branch for wider testing.
Modified:
branches/1.4/Makefile
branches/1.4/pri.c
branches/1.4/pri_internal.h
branches/1.4/pri_q921.h
branches/1.4/pri_q931.h
branches/1.4/q921.c
branches/1.4/q931.c
Modified: branches/1.4/Makefile
URL: http://svnview.digium.com/svn/libpri/branches/1.4/Makefile?view=diff&rev=1406&r1=1405&r2=1406
==============================================================================
--- branches/1.4/Makefile (original)
+++ branches/1.4/Makefile Wed Jan 13 13:37:59 2010
@@ -144,7 +144,7 @@
ifneq (${OSARCH},SunOS)
install -m 644 libpri.h $(INSTALL_PREFIX)$(INSTALL_BASE)/include
install -m 755 $(DYNAMIC_LIBRARY) $(INSTALL_PREFIX)$(libdir)
- if [ -x /usr/sbin/sestatus ] && ( /usr/sbin/sestatus | grep "SELinux status:" | grep -q "enabled"); then /sbin/restorecon -v $(INSTALL_PREFIX)$(libdir)/$(DYNAMIC_LIBRARY); fi
+ #if [ -x /usr/sbin/sestatus ] && ( /usr/sbin/sestatus | grep "SELinux status:" | grep -q "enabled"); then /sbin/restorecon -v $(INSTALL_PREFIX)$(libdir)/$(DYNAMIC_LIBRARY); fi
( cd $(INSTALL_PREFIX)$(libdir) ; ln -sf libpri.so.$(SONAME) libpri.so)
install -m 644 $(STATIC_LIBRARY) $(INSTALL_PREFIX)$(libdir)
if test $$(id -u) = 0; then $(LDCONFIG) $(LDCONFIG_FLAGS) $(INSTALL_PREFIX)$(libdir); fi
Modified: branches/1.4/pri.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri.c?view=diff&rev=1406&r1=1405&r2=1406
==============================================================================
--- branches/1.4/pri.c (original)
+++ branches/1.4/pri.c Wed Jan 13 13:37:59 2010
@@ -144,7 +144,12 @@
/* Set timer values to standard defaults. Time is in ms. */
ctrl->timers[PRI_TIMER_N200] = 3; /* Max numer of Q.921 retransmissions */
ctrl->timers[PRI_TIMER_N202] = 3; /* Max numer of transmissions of the TEI identity request message */
- ctrl->timers[PRI_TIMER_K] = 7; /* Max number of outstanding I-frames */
+
+ if (ctrl->bri == 1)
+ ctrl->timers[PRI_TIMER_K] = 1; /* Max number of outstanding I-frames */
+ else
+ ctrl->timers[PRI_TIMER_K] = 7; /* Max number of outstanding I-frames */
+
ctrl->timers[PRI_TIMER_T200] = 1000; /* Time between SABME's */
ctrl->timers[PRI_TIMER_T202] = 10 * 1000; /* Min time between transmission of TEI Identity request messages */
ctrl->timers[PRI_TIMER_T203] = 10 * 1000; /* Max time without exchanging packets */
@@ -154,6 +159,7 @@
ctrl->timers[PRI_TIMER_TM20] = 2500; /* Max time awaiting XID response - Q.921 Appendix IV */
ctrl->timers[PRI_TIMER_NM20] = 3; /* Number of XID retransmits - Q.921 Appendix IV */
ctrl->timers[PRI_TIMER_T303] = 4 * 1000; /* Length between SETUP retransmissions and timeout */
+ ctrl->timers[PRI_TIMER_T309] = 6000; /* Time to wait before clearing calls in case of D-channel transient event. Q.931 specifies 6-90 seconds */
ctrl->timers[PRI_TIMER_T_HOLD] = 4 * 1000; /* Wait for HOLD request response. */
ctrl->timers[PRI_TIMER_T_RETRIEVE] = 4 * 1000;/* Wait for RETRIEVE request response. */
@@ -343,9 +349,16 @@
default:
break;
}
- /* Start Q.921 layer, Wait if we're the network */
- if (p)
- q921_start(p, p->localtype == PRI_CPE);
+ p->k = p->timers[PRI_TIMER_K];
+
+ if (p->tei == Q921_TEI_GROUP && p->sapi == Q921_SAPI_LAYER2_MANAGEMENT && p->localtype == PRI_CPE) {
+ p->subchannel = __pri_new_tei(-1, p->localtype, p->switchtype, p, NULL, NULL, NULL, Q921_TEI_PRI, 1);
+ if (!p->subchannel) {
+ free(p);
+ return NULL;
+ }
+ } else
+ q921_start(p);
return p;
}
@@ -363,11 +376,15 @@
int pri_restart(struct pri *pri)
{
+#if 0
/* Restart Q.921 layer */
if (pri) {
q921_reset(pri, 1);
q921_start(pri, pri->localtype == PRI_CPE);
}
+#else
+ pri_error(pri, "pri_restart should never be called !!!!\n");
+#endif
return 0;
}
@@ -1303,12 +1320,14 @@
}
used = pri_snprintf(buf, used, buf_size, "Q921 Outstanding: %u\n", q921outstanding);
#endif
- used = pri_snprintf(buf, used, buf_size, "Window Length: %d/%d\n", ctrl->windowlen,
+#if 0
+ used = pri_snprintf(buf, used, buf_size, "Window Length: %d/%d\n", ctrl->k,
ctrl->window);
used = pri_snprintf(buf, used, buf_size, "Sentrej: %d\n", ctrl->sentrej);
used = pri_snprintf(buf, used, buf_size, "SolicitFbit: %d\n", ctrl->solicitfbit);
used = pri_snprintf(buf, used, buf_size, "Retrans: %d\n", ctrl->retrans);
used = pri_snprintf(buf, used, buf_size, "Busy: %d\n", ctrl->busy);
+#endif
used = pri_snprintf(buf, used, buf_size, "Overlap Dial: %d\n", ctrl->overlapdial);
used = pri_snprintf(buf, used, buf_size, "Logical Channel Mapping: %d\n",
ctrl->chan_mapping_logical);
Modified: branches/1.4/pri_internal.h
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri_internal.h?view=diff&rev=1406&r1=1405&r2=1406
==============================================================================
--- branches/1.4/pri_internal.h (original)
+++ branches/1.4/pri_internal.h Wed Jan 13 13:37:59 2010
@@ -89,25 +89,30 @@
unsigned int hold_support:1;/* TRUE if upper layer supports call hold. */
unsigned int deflection_support:1;/* TRUE if upper layer supports call deflection/rerouting. */
+ /* MDL variables */
+ int mdl_error;
+ int mdl_error_state;
+ int mdl_timer;
+ int mdl_free_me;
+
/* Q.921 State */
int q921_state;
- int window; /* Max window size */
- int windowlen; /* Fullness of window */
+ int k;
+ int RC;
+ int peer_rx_busy:1;
+ int own_rx_busy:1;
+ int acknowledge_pending:1;
+ int reject_exception:1;
+
int v_s; /* Next N(S) for transmission */
int v_a; /* Last acknowledged frame */
int v_r; /* Next frame expected to be received */
- 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 */
- int busy; /* Peer is busy */
+ int l3initiated;
/* Various timers */
- int sabme_timer; /* SABME retransmit */
- int sabme_count; /* SABME retransmit counter for BRI */
int t203_timer; /* Max idle time */
int t202_timer;
int n202_counter;
@@ -515,6 +520,8 @@
-1 - No reverse charging
1 - Reverse charging
0,2-7 - Reserved for future use */
+ /*! \brief TEI associated with call */
+ int tei;
int t303_timer;
int t303_expirycnt;
@@ -627,13 +634,40 @@
return pri->bri && (((pri)->localtype == PRI_CPE) && ((pri)->tei == Q921_TEI_GROUP));
}
-static inline int PRI_PTP(struct pri *mypri)
+static inline int NT_MODE(struct pri *mypri)
{
struct pri *pri;
pri = PRI_MASTER(mypri);
- return !pri->bri;
+ return pri->localtype == PRI_NETWORK;
+}
+
+static inline int TE_MODE(struct pri *mypri)
+{
+ struct pri *pri;
+
+ pri = PRI_MASTER(mypri);
+
+ return pri->localtype == PRI_CPE;
+}
+
+static inline int PTP_MODE(struct pri *mypri)
+{
+ struct pri *pri;
+
+ pri = PRI_MASTER(mypri);
+
+ return pri->tei == Q921_TEI_PRI;
+}
+
+static inline int PTMP_MODE(struct pri *mypri)
+{
+ struct pri *pri;
+
+ pri = PRI_MASTER(mypri);
+
+ return pri->tei == Q921_TEI_GROUP;
}
#define Q931_DUMMY_CALL_REFERENCE -1
Modified: branches/1.4/pri_q921.h
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri_q921.h?view=diff&rev=1406&r1=1405&r2=1406
==============================================================================
--- branches/1.4/pri_q921.h (original)
+++ branches/1.4/pri_q921.h Wed Jan 13 13:37:59 2010
@@ -166,36 +166,41 @@
} q921_frame;
#define Q921_INC(j) (j) = (((j) + 1) % 128)
+#define Q921_DEC(j) (j) = (((j) - 1) % 128)
typedef enum q921_state {
- Q921_DOWN = 0,
- 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,
- Q921_AWAITING_RELEASE
+ /* All states except Q921_DOWN are defined in Q.921 SDL diagrams */
+ Q921_TEI_UNASSIGNED = 1,
+ Q921_ASSIGN_AWAITING_TEI = 2,
+ Q921_ESTABLISH_AWAITING_TEI = 3,
+ Q921_TEI_ASSIGNED = 4,
+ Q921_AWAITING_ESTABLISHMENT = 5,
+ Q921_AWAITING_RELEASE = 6,
+ Q921_MULTI_FRAME_ESTABLISHED = 7,
+ Q921_TIMER_RECOVERY = 8,
} q921_state;
+
+static inline int Q921_ADD(int a, int b)
+{
+ return (a + b) % 128;
+}
/* Dumps a *known good* Q.921 packet */
extern void q921_dump(struct pri *pri, q921_h *h, int len, int showraw, int txrx);
/* Bring up the D-channel */
-extern void q921_start(struct pri *pri, int now);
-
-extern void q921_reset(struct pri *pri, int reset_iqueue);
+extern void q921_start(struct pri *pri);
+
+//extern void q921_reset(struct pri *pri, int reset_iqueue);
extern pri_event *q921_receive(struct pri *pri, q921_h *h, int len);
-extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr);
+extern int q921_transmit_iframe(struct pri *pri, int tei, void *buf, int len, int cr);
extern int q921_transmit_uiframe(struct pri *pri, void *buf, int len);
extern pri_event *q921_dchannel_up(struct pri *pri);
-extern pri_event *q921_dchannel_down(struct pri *pri);
-
-#endif
+//extern pri_event *q921_dchannel_down(struct pri *pri);
+
+#endif
Modified: branches/1.4/pri_q931.h
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri_q931.h?view=diff&rev=1406&r1=1405&r2=1406
==============================================================================
--- branches/1.4/pri_q931.h (original)
+++ branches/1.4/pri_q931.h Wed Jan 13 13:37:59 2010
@@ -452,7 +452,7 @@
/* Q.SIG specific */
#define QSIG_IE_TRANSIT_COUNT 0x31
-extern int q931_receive(struct pri *pri, q931_h *h, int len);
+extern int q931_receive(struct pri *pri, int tei, q931_h *h, int len);
extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info);
Modified: branches/1.4/q921.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/q921.c?view=diff&rev=1406&r1=1405&r2=1406
==============================================================================
--- branches/1.4/q921.c (original)
+++ branches/1.4/q921.c Wed Jan 13 13:37:59 2010
@@ -56,10 +56,21 @@
(hf).h.tei = (pri)->tei; \
} while(0)
-static void reschedule_t203(struct pri *pri);
+//static void reschedule_t203(struct pri *pri);
static void reschedule_t200(struct pri *pri);
-static void q921_restart(struct pri *pri, int now);
-static void q921_tei_release_and_reacquire(struct pri *master);
+//static void q921_restart(struct pri *pri, int now);
+//static void q921_tei_release_and_reacquire(struct pri *master);
+static void q921_dump_pri(struct pri *pri);
+static void q921_establish_data_link(struct pri *pri);
+static void q921_mdl_error(struct pri *pri, char error);
+static void q921_mdl_remove(struct pri *pri);
+
+static void q921_setstate(struct pri *pri, int newstate)
+{
+ if ((pri->q921_state != newstate) && (newstate != 7) && (newstate != 8))
+ pri_error(pri, "Changing from state %d to %d\n", pri->q921_state, newstate);
+ pri->q921_state = newstate;
+}
static void q921_discard_retransmissions(struct pri *pri)
{
@@ -72,6 +83,11 @@
free(p);
}
pri->txqueue = NULL;
+}
+
+static void q921_discard_iqueue(struct pri *pri)
+{
+ q921_discard_retransmissions(pri);
}
static int q921_transmit(struct pri *pri, q921_h *h, int len)
@@ -126,20 +142,14 @@
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");
+ pri->n202_counter++;
+ if (pri->n202_counter > pri->timers[PRI_TIMER_N202]) {
+ pri_error(pri, "Unable to receive TEI from network!\n");
+ pri->n202_counter = 0;
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);
+ q921_send_tei(PRI_MASTER(pri), Q921_TEI_IDENTITY_REQUEST, pri->ri, Q921_TEI_GROUP, 1);
pri_schedule_del(pri, pri->t202_timer);
pri->t202_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T202], q921_tei_request, pri);
}
@@ -168,17 +178,10 @@
q921_transmit(pri, &h, 3);
}
-static void q921_send_sabme_now(void *vpri);
-
-static void q921_send_sabme(void *vpri, int now)
-{
- struct pri *pri = vpri;
+static void q921_send_sabme(struct pri *pri)
+{
q921_h h;
- pri_schedule_del(pri, pri->sabme_timer);
- pri->sabme_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], q921_send_sabme_now, pri);
- if (!now)
- return;
Q921_INIT(pri, h);
h.u.m3 = 3; /* M3 = 3 */
h.u.m2 = 3; /* M2 = 3 */
@@ -195,33 +198,21 @@
pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype);
return;
}
- if (pri->bri && (pri->state == Q921_AWAITING_ESTABLISH)) {
- if (pri->sabme_count >= pri->timers[PRI_TIMER_N200]) {
- pri_schedule_del(pri, pri->sabme_timer);
- pri->sabme_timer = 0;
- q921_tei_release_and_reacquire(pri->master);
- } else {
- pri->sabme_count++;
- }
- }
- if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP))
- pri_message(pri, "Sending Set Asynchronous Balanced Mode Extended\n");
q921_transmit(pri, &h, 3);
- if (pri->debug & PRI_DEBUG_Q921_STATE && pri->q921_state != Q921_AWAITING_ESTABLISH)
- pri_message(pri, DBGHEAD "q921_state now is Q921_AWAITING_ESTABLISH\n", DBGINFO);
- pri->q921_state = Q921_AWAITING_ESTABLISH;
-}
-
+}
+
+#if 0
static void q921_send_sabme_now(void *vpri)
{
q921_send_sabme(vpri, 1);
}
+#endif
static int q921_ack_packet(struct pri *pri, int num)
{
struct q921_frame *f, *prev = NULL;
f = pri->txqueue;
- while(f) {
+ while (f) {
if (f->h.n_s == num) {
/* Cancel each packet as necessary */
/* That's our packet */
@@ -232,12 +223,7 @@
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "-- ACKing packet %d, new txqueue is %d (-1 means empty)\n", f->h.n_s, pri->txqueue ? pri->txqueue->h.n_s : -1);
/* Update v_a */
- pri->v_a = num;
free(f);
- /* Reset retransmission counter if we actually acked something */
- pri->retrans = 0;
- /* Decrement window size */
- pri->windowlen--;
return 1;
}
prev = f;
@@ -257,6 +243,9 @@
pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
}
+#define restart_t200(pri) reschedule_t200((pri))
+
+#if 0
static void reschedule_t203(struct pri *pri)
{
if (pri->debug & PRI_DEBUG_Q921_DUMP)
@@ -264,77 +253,113 @@
pri_schedule_del(pri, pri->t203_timer);
pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
}
-
-static void q921_send_queued_iframes(struct pri *pri)
+#endif
+
+#if 0
+static int q921_unacked_iframes(struct pri *pri)
+{
+ struct q921_frame *f = pri->txqueue;
+ int cnt = 0;
+
+ while(f) {
+ if (f->transmitted)
+ cnt++;
+ f = f->next;
+ }
+
+ return cnt;
+}
+#endif
+
+static void start_t203(struct pri *pri)
+{
+ if (pri->t203_timer) {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "T203 requested to start without stopping first\n");
+ pri_schedule_del(pri, pri->t203_timer);
+ }
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "-- Starting T203 timer\n");
+ pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
+}
+
+static void stop_t203(struct pri *pri)
+{
+ if (pri->t203_timer) {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "-- Stopping T203 timer\n");
+ pri_schedule_del(pri, pri->t203_timer);
+ pri->t203_timer = 0;
+ } else {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "-- T203 requested to stop when not started\n");
+ }
+}
+
+static void start_t200(struct pri *pri)
+{
+ if (pri->t200_timer) {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "T200 requested to start without stopping first\n");
+ pri_schedule_del(pri, pri->t200_timer);
+ }
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "-- Starting T200 timer\n");
+ pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
+}
+
+static void stop_t200(struct pri *pri)
+{
+ if (pri->t200_timer) {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "-- Stopping T200 timer\n");
+ pri_schedule_del(pri, pri->t200_timer);
+ pri->t200_timer = 0;
+ } else {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "-- T200 requested to stop when not started\n");
+ }
+}
+
+/* This is the equivalent of the I-Frame queued up path in Figure B.7 in MULTI_FRAME_ESTABLISHED */
+static int q921_send_queued_iframes(struct pri *pri)
{
struct q921_frame *f;
+ int frames_txd = 0;
+
+ if (pri->peer_rx_busy || (pri->v_s == Q921_ADD(pri->v_a, pri->k))) {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "Couldn't transmit I frame at this time due to peer busy condition or window shut\n");
+ return 0;
+ }
f = pri->txqueue;
- while(f && (pri->windowlen < pri->window)) {
+ while (f && (pri->v_s != Q921_ADD(pri->v_a, pri->k))) {
if (!f->transmitted) {
/* Send it now... */
if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "-- Finally transmitting %d, since window opened up (%d)\n", f->h.n_s, pri->windowlen);
+ pri_message(pri, "-- Finally transmitting %d, since window opened up (%d)\n", f->h.n_s, pri->k);
f->transmitted++;
- pri->windowlen++;
+ f->h.n_s = pri->v_s;
f->h.n_r = pri->v_r;
+ f->h.ft = 0;
f->h.p_f = 0;
q921_transmit(pri, (q921_h *)(&f->h), f->len);
+ Q921_INC(pri->v_s);
+ frames_txd++;
+ pri->acknowledge_pending = 0;
}
f = f->next;
}
-}
-
-static pri_event *q921_ack_rx(struct pri *pri, int ack, int send_untransmitted_frames)
-{
- 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(pri, "ACK received for '%d' outside of window of '%d' to '%d', restarting\n", ack, pri->v_a, pri->v_s);
- 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_DUMP)
- pri_message(pri, "-- ACKing all packets from %d to (but not including) %d\n", pri->v_a, ack);
- for (x=pri->v_a; x != ack; Q921_INC(x))
- cnt += q921_ack_packet(pri, x);
- if (!pri->txqueue) {
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "-- Since there was nothing left, stopping T200 counter\n");
- /* Something was ACK'd. Stop T200 counter */
- pri_schedule_del(pri, pri->t200_timer);
- pri->t200_timer = 0;
- }
- if (pri->t203_timer) {
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "-- Stopping T203 counter since we got an ACK\n");
- pri_schedule_del(pri, pri->t203_timer);
- pri->t203_timer = 0;
- }
- if (pri->txqueue) {
- /* Something left to transmit, Start the T200 counter again if we stopped it */
- if (!pri->busy && send_untransmitted_frames) {
- pri->retrans = 0;
- /* Search for something to send */
- q921_send_queued_iframes(pri);
- }
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "-- Waiting for acknowledge, restarting T200 counter\n");
- reschedule_t200(pri);
- } else {
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "-- Nothing left, starting T203 counter\n");
- /* Nothing to transmit, start the T203 counter instead */
- pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
- }
- return NULL;
+
+ if (frames_txd) {
+ if (!pri->t200_timer) {
+ stop_t203(pri);
+ start_t200(pri);
+ }
+ }
+
+ return frames_txd;
}
static void q921_reject(struct pri *pri, int pf)
@@ -359,7 +384,6 @@
}
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "Sending Reject (%d)\n", pri->v_r);
- pri->sentrej = 1;
q921_transmit(pri, &h, 4);
}
@@ -388,96 +412,82 @@
pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype);
return;
}
- pri->v_na = pri->v_r; /* Make a note that we've already acked this */
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "Sending Receiver Ready (%d)\n", pri->v_r);
q921_transmit(pri, &h, 4);
}
+static void transmit_enquiry(struct pri *pri)
+{
+ if (!pri->own_rx_busy) {
+ q921_rr(pri, 1, 1);
+ pri->acknowledge_pending = 0;
+ start_t200(pri);
+ } else {
+ /* XXX: Implement me... */
+ }
+}
+
static void t200_expire(void *vpri)
{
struct pri *pri = vpri;
- q921_frame *f, *lastframe=NULL;
-
- if (pri->txqueue) {
- /* Retransmit first packet in the queue, setting the poll bit */
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "-- T200 counter expired, What to do...\n");
- pri->solicitfbit = 1;
- /* Up to three retransmissions */
- if (pri->retrans < pri->timers[PRI_TIMER_N200]) {
- pri->retrans++;
- /* Reschedule t200_timer */
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "-- Retransmitting %d bytes\n", pri->txqueue->len);
- if (pri->busy)
- q921_rr(pri, 1, 1);
- else {
- if (!pri->txqueue->transmitted)
- pri_error(pri, "!! Not good - head of queue has not been transmitted yet\n");
- /*Actually we need to retransmit the last transmitted packet, setting the poll bit */
- for (f=pri->txqueue; f; f = f->next) {
- if (f->transmitted)
- lastframe = f;
- }
- if (lastframe) {
- /* Force Poll bit */
- lastframe->h.p_f = 1;
- /* Update nr */
- lastframe->h.n_r = pri->v_r;
- pri->v_na = pri->v_r;
- q921_transmit(pri, (q921_h *)&lastframe->h, lastframe->len);
- }
- }
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "-- Rescheduling retransmission (%d)\n", pri->retrans);
- pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
+
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "%s\n", __FUNCTION__);
+
+ q921_dump_pri(pri);
+
+ pri->t200_timer = 0;
+
+ switch (pri->q921_state) {
+ case Q921_MULTI_FRAME_ESTABLISHED:
+ pri->RC = 0;
+ transmit_enquiry(pri);
+ pri->RC++;
+ q921_setstate(pri, Q921_TIMER_RECOVERY);
+ break;
+ case Q921_TIMER_RECOVERY:
+ /* SDL Flow Figure B.8/Q.921 Page 81 */
+ if (pri->RC != pri->timers[PRI_TIMER_N200]) {
+#if 0
+ if (pri->v_s == pri->v_a) {
+ transmit_enquiry(pri);
+ }
+#else
+ /* We are chosing to enquiry by default (to reduce risk of T200 timer errors at the other
+ * side, instead of retransmission of the last I frame we sent */
+ transmit_enquiry(pri);
+#endif
+ pri->RC++;
} else {
- if (pri->debug & PRI_DEBUG_Q921_STATE)
- pri_message(pri, "-- Timeout occured, restarting PRI\n");
- if (pri->debug & PRI_DEBUG_Q921_STATE && pri->q921_state != Q921_LINK_CONNECTION_RELEASED)
- pri_message(pri, DBGHEAD "q921_state now is Q921_LINK_CONNECTION_RELEASED\n",DBGINFO);
- pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
- pri->t200_timer = 0;
- if (pri->bri && pri->master) {
- q921_tei_release_and_reacquire(pri->master);
- return;
- } else {
- q921_dchannel_down(pri);
- q921_start(pri, 1);
- pri->schedev = 1;
- }
- }
- } else if (pri->solicitfbit) {
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "-- Retrying poll with f-bit\n");
- if (pri->retrans < pri->timers[PRI_TIMER_N200]) {
- pri->retrans++;
- pri->solicitfbit = 1;
- q921_rr(pri, 1, 1);
- pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
+ //pri_error(pri, "MDL-ERROR (I): T200 = N200 in timer recovery state\n");
+ q921_mdl_error(pri, 'I');
+ q921_establish_data_link(pri);
+ pri->l3initiated = 0;
+ q921_setstate(pri, Q921_AWAITING_ESTABLISHMENT);
+ }
+ break;
+ case Q921_AWAITING_ESTABLISHMENT:
+ if (pri->RC != pri->timers[PRI_TIMER_N200]) {
+ pri->RC++;
+ q921_send_sabme(pri);
+ start_t200(pri);
} else {
- if (pri->debug & PRI_DEBUG_Q921_STATE)
- pri_message(pri, "-- Timeout occured, restarting PRI\n");
- if (pri->debug & PRI_DEBUG_Q921_STATE && pri->q921_state != Q921_LINK_CONNECTION_RELEASED)
- pri_message(pri, DBGHEAD "q921_state now is Q921_LINK_CONNECTION_RELEASED\n", DBGINFO);
- pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
- pri->t200_timer = 0;
- if (pri->bri && pri->master) {
- q921_tei_release_and_reacquire(pri->master);
- return;
- } else {
- q921_dchannel_down(pri);
- q921_start(pri, 1);
- pri->schedev = 1;
- }
- }
- } else {
- pri_error(pri, "T200 counter expired, nothing to send...\n");
- pri->t200_timer = 0;
- }
-}
-
+ q921_discard_iqueue(pri);
+ //pri_error(pri, "MDL-ERROR (G) : T200 expired N200 times in state %d\n", pri->q921_state);
+ q921_mdl_error(pri, 'G');
+ q921_setstate(pri, Q921_TEI_ASSIGNED);
+ /* DL-RELEASE indication */
+ q931_dl_indication(pri, PRI_EVENT_DCHAN_DOWN);
+ }
+ break;
+ default:
+ pri_error(pri, "Cannot handle T200 expire in state %d\n", pri->q921_state);
+ }
+
+}
+
+/* This is sending a DL-UNIT-DATA request */
int q921_transmit_uiframe(struct pri *pri, void *buf, int len)
{
uint8_t ubuf[512];
@@ -517,74 +527,108 @@
return 0;
}
-int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr)
+static struct pri * pri_find_tei(struct pri *vpri, int sapi, int tei)
+{
+ struct pri *pri;
+ for (pri = PRI_MASTER(vpri); pri; pri = pri->subchannel) {
+ if (pri->tei == tei && pri->sapi == sapi)
+ return pri;
+ }
+
+ return NULL;
+}
+
+/* This is the equivalent of a DL-DATA request, as well as the I frame queued up outcome */
+int q921_transmit_iframe(struct pri *vpri, int tei, void *buf, int len, int cr)
{
q921_frame *f, *prev=NULL;
-
- for (f=pri->txqueue; f; f = f->next) prev = f;
- f = calloc(1, sizeof(q921_frame) + len + 2);
- if (f) {
- Q921_INIT(pri, f->h);
- switch(pri->localtype) {
- case PRI_NETWORK:
- if (cr)
- f->h.h.c_r = 1;
+ struct pri *pri;
+
+ if (BRI_NT_PTMP(vpri)) {
+ if (tei == Q921_TEI_GROUP) {
+ pri_error(vpri, "Huh?! For NT-PTMP, we shouldn't be sending I-frames out the group TEI\n");
+ return 0;
+ }
+
+ pri = pri_find_tei(vpri, Q921_SAPI_CALL_CTRL, tei);
+ if (!pri) {
+ pri_error(vpri, "Huh?! Unable to locate PRI associated with TEI %d. Did we have to ditch it due to error conditions?\n", tei);
+ return 0;
+ }
+ } else if (BRI_TE_PTMP(vpri)) {
+ /* We don't care what the tei is, since we only support one sub and one TEI */
+ pri = PRI_MASTER(vpri)->subchannel;
+
+ if (pri->q921_state == Q921_TEI_UNASSIGNED) {
+ q921_tei_request(pri);
+ /* We don't setstate here because the pri with the TEI we need hasn't been created */
+ q921_setstate(pri, Q921_ESTABLISH_AWAITING_TEI);
+ }
+ } else {
+ /* Should just be PTP modes, which shouldn't have subs */
+ pri = vpri;
+ }
+
+ /* Figure B.7/Q.921 Page 70 */
+ switch (pri->q921_state) {
+ case Q921_TEI_ASSIGNED:
+ /* If we aren't in a state compatiable with DL-DATA requests, start getting us there here */
+ q921_establish_data_link(pri);
+ pri->l3initiated = 1;
+ q921_setstate(pri, Q921_AWAITING_ESTABLISHMENT);
+ /* For all rest, we've done the work to get us up prior to this and fall through */
+ case Q921_TEI_UNASSIGNED:
+ case Q921_ESTABLISH_AWAITING_TEI:
+ case Q921_ASSIGN_AWAITING_TEI:
+ case Q921_TIMER_RECOVERY:
+ case Q921_AWAITING_ESTABLISHMENT:
+ case Q921_MULTI_FRAME_ESTABLISHED:
+ for (f=pri->txqueue; f; f = f->next) prev = f;
+ f = calloc(1, sizeof(q921_frame) + len + 2);
+ if (f) {
+ Q921_INIT(pri, f->h);
+ switch(pri->localtype) {
+ case PRI_NETWORK:
+ if (cr)
+ f->h.h.c_r = 1;
+ else
+ f->h.h.c_r = 0;
+ break;
+ case PRI_CPE:
+ if (cr)
+ f->h.h.c_r = 0;
+ else
+ f->h.h.c_r = 1;
+ break;
+ }
+ f->next = NULL;
+ f->transmitted = 0;
+ f->len = len + 4;
+ memcpy(f->h.data, buf, len);
+ if (prev)
+ prev->next = f;
else
- f->h.h.c_r = 0;
- break;
- case PRI_CPE:
- if (cr)
- f->h.h.c_r = 0;
- else
- f->h.h.c_r = 1;
- break;
- }
- f->next = NULL;
- f->transmitted = 0;
- f->len = len + 4;
- memcpy(f->h.data, buf, len);
- f->h.n_s = pri->v_s;
- f->h.n_r = pri->v_r;
- pri->v_s++;
- pri->v_na = pri->v_r;
- f->h.p_f = 0;
- f->h.ft = 0;
- if (prev)
- prev->next = f;
- else
- pri->txqueue = f;
- /* Immediately transmit unless we're in a recovery state, or the window
- size is too big */
- if (pri->debug & PRI_DEBUG_Q921_DUMP) {
- pri_message(pri, "TEI/SAPI: %d/%d state %d retran %d busy %d\n",
- pri->tei, pri->sapi, pri->q921_state, pri->retrans, pri->busy);
- }
- if ((pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) && (!pri->retrans && !pri->busy)) {
- if (pri->windowlen < pri->window) {
- q921_send_queued_iframes(pri);
- } else {
+ pri->txqueue = f;
+
+ if (pri->q921_state != Q921_MULTI_FRAME_ESTABLISHED) {
+ return 0;
+ }
+
+ if (pri->peer_rx_busy || (pri->v_s == Q921_ADD(pri->v_a, pri->k))) {
if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "Delaying transmission of %d, window is %d/%d long\n",
- f->h.n_s, pri->windowlen, pri->window);
- }
- }
- if (pri->t203_timer) {
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "Stopping T_203 timer\n");
- pri_schedule_del(pri, pri->t203_timer);
- pri->t203_timer = 0;
- }
-
- /* Check this so that we don't try to send frames while multi frame mode is down */
- if (pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) {
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "Starting T_200 timer\n");
-
- reschedule_t200(pri);
- }
- } else {
- pri_error(pri, "!! Out of memory for Q.921 transmit\n");
- return -1;
+ pri_message(pri, "Couldn't transmit I frame at this time due to peer busy condition or window shut\n");
+ return 0;
+ }
+
+ q921_send_queued_iframes(pri);
+
+ return 0;
+ } else {
+ pri_error(pri, "!! Out of memory for Q.921 transmit\n");
+ return -1;
+ }
+ default:
+ pri_error(pri, "Cannot transmit frames in state %d\n", pri->q921_state);
}
return 0;
}
@@ -592,66 +636,44 @@
static void t203_expire(void *vpri)
{
struct pri *pri = vpri;
- if (pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "%s\n", __FUNCTION__);
+ pri->t203_timer = 0;
+ switch (pri->q921_state) {
+ case Q921_MULTI_FRAME_ESTABLISHED:
+ transmit_enquiry(pri);
+ pri->RC = 0;
+ q921_setstate(pri, Q921_TIMER_RECOVERY);
+ break;
+ default:
if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "T203 counter expired, sending RR and scheduling T203 again\n");
- /* Solicit an F-bit in the other's RR */
- pri->solicitfbit = 1;
- 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, pri->timers[PRI_TIMER_T200], t200_expire, pri);
- } else {
- if (pri->debug & PRI_DEBUG_Q921_DUMP) {
- pri_message(pri,
- "T203 counter expired in weird state %d on pri with SAPI/TEI of %d/%d\n",
- pri->q921_state, pri->sapi, pri->tei);
- }
+ pri_message(pri, "T203 counter expired in weird state %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;
-
- pri->solicitfbit = 0;
- /* 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 */
- pri->sentrej = 0;
- ev = q921_ack_rx(pri, i->n_r, 1);
- if (ev)
- return ev;
- if (i->p_f) {
- /* If the Poll/Final bit is set, immediate send the RR */
- q921_rr(pri, 1, 0);
- } else if (pri->busy || pri->retrans) {
- 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, 0);
- if (res == -1) {
- return NULL;
- }
- if (res & Q931_RES_HAVEEVENT)
- return &pri->ev;
- } else {
- /* 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;
-}
+static void q921_dump_iqueue_info(struct pri *pri, int force)
+{
+ struct q921_frame *f;
+ int pending = 0, unacked = 0;
+
+ unacked = pending = 0;
+
+ for (f = pri->txqueue; f && f->next; f = f->next) {
+ if (f->transmitted) {
+ unacked++;
+ } else {
+ pending++;
+ }
+ }
+
+ if (force)
+ pri_error(pri, "Number of pending packets %d, sent but unacked %d\n", pending, unacked);
+
+ return;
+}
+
+static void q921_dump_pri_by_h(struct pri *pri, q921_h *h);
void q921_dump(struct pri *pri, q921_h *h, int len, int showraw, int txrx)
{
@@ -659,6 +681,8 @@
char *type;
char direction_tag;
+ q921_dump_pri_by_h(pri, h);
+
direction_tag = txrx ? '>' : '<';
if (showraw) {
char *buf = malloc(len * 3 + 1);
@@ -831,103 +855,36 @@
}
}
-pri_event *q921_dchannel_up(struct pri *pri)
-{
- if (pri->tei == Q921_TEI_PRI) {
- q921_reset(pri, 1);
- } else {
- q921_reset(pri, 0);
- }
-
- /* Stop any SABME retransmissions */
- pri_schedule_del(pri, pri->sabme_timer);
- pri->sabme_timer = 0;
-
- /* Reset any rejects */
- pri->sentrej = 0;
-
- /* Go into connection established state */
- if (pri->debug & PRI_DEBUG_Q921_STATE && pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED)
- pri_message(pri, DBGHEAD "q921_state now is Q921_LINK_CONNECTION_ESTABLISHED\n", DBGINFO);
- pri->q921_state = Q921_LINK_CONNECTION_ESTABLISHED;
-
- /* Ensure that we do not have T200 or T203 running when the link comes up */
- pri_schedule_del(pri, pri->t200_timer);
- pri->t200_timer = 0;
-
- /* Start the T203 timer */
- pri_schedule_del(pri, pri->t203_timer);
- pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
-
- /* Notify Layer 3 */
- q931_dl_indication(pri, PRI_EVENT_DCHAN_UP);
-
- q921_send_queued_iframes(pri);
-
- /* Report event that D-Channel is now up */
- pri->ev.gen.e = PRI_EVENT_DCHAN_UP;
- return &pri->ev;
-}
-
-pri_event *q921_dchannel_down(struct pri *pri)
-{
- /* Reset counters, reset sabme timer etc */
- q921_reset(pri, 1);
-
- /* Notify Layer 3 */
- q931_dl_indication(pri, PRI_EVENT_DCHAN_DOWN);
-
- /* Report event that D-Channel is now down */
- pri->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
- return &pri->ev;
-}
-
-void q921_reset(struct pri *pri, int reset_iqueue)
-{
- /* Having gotten a SABME we MUST reset our entire state */
- if (reset_iqueue)
- pri->v_s = 0;
-
- pri->v_a = 0;
- pri->v_r = 0;
- 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);
- pri->sabme_timer = 0;
- pri->sabme_count = 0;
- pri->t203_timer = 0;
- pri->t200_timer = 0;
- pri->busy = 0;
- pri->solicitfbit = 0;
- if (pri->debug & PRI_DEBUG_Q921_STATE && pri->q921_state != Q921_LINK_CONNECTION_RELEASED)
- pri_message(pri, DBGHEAD "q921_state now is Q921_LINK_CONNECTION_RELEASED\n", DBGINFO);
- pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
- pri->retrans = 0;
- pri->sentrej = 0;
-
- /* Discard anything waiting to go out */
- if (reset_iqueue)
- q921_discard_retransmissions(pri);
-}
-
-static void q921_tei_release_and_reacquire(struct pri *master)
-{
- /* Make sure the master is passed into this function */
- q921_dchannel_down(master->subchannel);
- __pri_free_tei(master->subchannel);
- master->subchannel = NULL;
- master->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
- master->schedev = 1;
- q921_start(master, master->localtype == PRI_CPE);
+static void q921_dump_pri(struct pri *pri)
+{
+ pri_message(pri, "TEI: %d State %d\n", pri->tei, pri->q921_state);
+ pri_message(pri, "V(S) %d V(A) %d V(R) %d\n", pri->v_s, pri->v_a, pri->v_r);
+ pri_message(pri, "K %d, RC %d, l3initiated %d, reject_except %d ack_pend %d\n", pri->k, pri->RC, pri->l3initiated, pri->reject_exception, pri->acknowledge_pending);
+ pri_message(pri, "T200 %d, N200 %d, T203 %d\n", pri->t200_timer, 3, pri->t203_timer);
+}
+
+static void q921_dump_pri_by_h(struct pri *vpri, q921_h *h)
+{
+ struct pri *pri = NULL;
+
+ if (BRI_NT_PTMP(vpri)) {
+ pri = pri_find_tei(vpri, h->h.sapi, h->h.tei);
+ } else if (BRI_TE_PTMP(vpri)) {
+ pri = PRI_MASTER(vpri)->subchannel;
+ } else
+ pri = vpri;
+ if (pri) {
+ q921_dump_pri(pri);
+ } else if (!PTMP_MODE(vpri)) {
+ pri_error(vpri, "Huh.... no pri found to dump\n");
+ }
}
static pri_event *q921_receive_MDL(struct pri *pri, q921_u *h, int len)
{
int ri;
struct pri *sub = pri;
+ pri_event *res = NULL;
int tei;
if (!BRI_NT_PTMP(pri) && !BRI_TE_PTMP(pri)) {
@@ -947,6 +904,7 @@
}
ri = (h->data[1] << 8) | h->data[2];
tei = (h->data[4] >> 1);
+
switch(h->data[3]) {
case Q921_TEI_IDENTITY_REQUEST:
if (!BRI_NT_PTMP(pri)) {
@@ -963,44 +921,68 @@
++tei;
sub = sub->subchannel;
}
+
+ if (tei >= Q921_TEI_GROUP) {
+ pri_error(pri, "Reached maximum TEI quota, cannot assign new TEI\n");
+ return NULL;
+ }
sub->subchannel = __pri_new_tei(-1, pri->localtype, pri->switchtype, pri, NULL, NULL, NULL, tei, 1);
+
if (!sub->subchannel) {
pri_error(pri, "Unable to allocate D-channel for new TEI %d\n", tei);
return NULL;
}
+ q921_setstate(sub->subchannel, Q921_TEI_ASSIGNED);
+ pri_error(pri, "Allocating new TEI %d\n", tei);
q921_send_tei(pri, Q921_TEI_IDENTITY_ASSIGNED, ri, tei, 1);
break;
case Q921_TEI_IDENTITY_ASSIGNED:
if (!BRI_TE_PTMP(pri))
return NULL;
+ /* Assuming we're operating on the sub here */
+ pri = pri->subchannel;
+
+ switch (pri->q921_state) {
+ case Q921_ASSIGN_AWAITING_TEI:
+ case Q921_ESTABLISH_AWAITING_TEI:
+ break;
+ default:
+ pri_message(pri, "Ignoring unrequested TEI assign message\n");
+ return NULL;
+ }
+
if (ri != pri->ri) {
pri_message(pri, "TEI assignment received for invalid Ri %02x (our is %02x)\n", ri, pri->ri);
return NULL;
}
+
pri_schedule_del(pri, pri->t202_timer);
pri->t202_timer = 0;
- if (pri->subchannel && (pri->subchannel->tei == tei)) {
- pri_error(pri, "TEI already assigned (new is %d, current is %d)\n", tei, pri->subchannel->tei);
- q921_tei_release_and_reacquire(pri);
+ pri->tei = tei;
+
+ switch (pri->q921_state) {
+ case Q921_ASSIGN_AWAITING_TEI:
+ q921_setstate(pri, Q921_TEI_ASSIGNED);
+ pri->ev.gen.e = PRI_EVENT_DCHAN_UP;
+ res = &pri->ev;
+ break;
+ case Q921_ESTABLISH_AWAITING_TEI:
+ q921_establish_data_link(pri);
+ pri->l3initiated = 1;
+ q921_setstate(pri, Q921_AWAITING_ESTABLISHMENT);
+ break;
+ default:
+ pri_error(pri, "Error 3\n");
return NULL;
}
- pri_message(pri, "TEI assiged to %d\n", tei);
- pri->subchannel = __pri_new_tei(-1, pri->localtype, pri->switchtype, pri, NULL, NULL, NULL, tei, 1);
- 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;
case Q921_TEI_IDENTITY_CHECK_REQUEST:
if (!BRI_TE_PTMP(pri))
return NULL;
- /* We're assuming one TEI per PRI in TE PTMP mode */
-
- /* If no subchannel (TEI) ignore */
- if (!pri->subchannel)
+
+ if (pri->subchannel->q921_state < Q921_TEI_ASSIGNED)
return NULL;
/* If it's addressed to the group TEI or to our TEI specifically, we respond */
@@ -1011,162 +993,885 @@
case Q921_TEI_IDENTITY_REMOVE:
if (!BRI_TE_PTMP(pri))
return NULL;
- /* XXX: Assuming multiframe mode has been disconnected already */
- if (!pri->subchannel)
- return NULL;
if ((tei == Q921_TEI_GROUP) || (tei == pri->subchannel->tei)) {
- q921_tei_release_and_reacquire(pri);
- }
- }
[... 1368 lines stripped ...]
More information about the libpri-commits
mailing list