⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 q921.c

📁 Q.931/Q.921 source code compiles
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* Discard anything waiting to go out */	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 pri_event *q921_receive_MDL(struct pri *pri, q921_u *h, int len){	int ri;	struct pri *sub;	int tei;	if (pri->debug & PRI_DEBUG_Q921_STATE)		pri_message(pri, "Received MDL message\n");	if (h->data[0] != 0x0f) {		pri_error(pri, "Received MDL with unsupported management entity %02x\n", h->data[0]);		return NULL;	}	if (!(h->data[4] & 0x01)) {		pri_error(pri, "Received MDL with multibyte TEI identifier\n");		return NULL;	}	ri = (h->data[1] << 8) | h->data[2];	tei = (h->data[4] >> 1);	switch(h->data[3]) {	case Q921_TEI_IDENTITY_REQUEST:		if (tei != 127) {			pri_error(pri, "Received TEI identity request with invalid TEI %d\n", tei);			q921_send_tei(pri, Q921_TEI_IDENTITY_DENIED, ri, tei, 1);		}		/* Go to master */		for (sub = pri; sub->master; sub = sub->master);		tei = 64;		while(sub->subchannel) {			if(sub->subchannel->tei == tei)				++tei;		}		sub->subchannel = __pri_new_tei(-1, pri->localtype, pri->switchtype, pri, NULL, NULL, NULL, tei, 1);		if (!sub->subchannel) {			pri_error(pri, "Unable to allocate D-channel for new TEI %d\n", tei);			return NULL;		}		q921_send_tei(pri, Q921_TEI_IDENTITY_ASSIGNED, ri, tei, 1);		break;	case Q921_TEI_IDENTITY_ASSIGNED:		if (ri != pri->ri) {			pri_message(pri, "TEI assignment received for invalid Ri %02x (our is %02x)\n", ri, pri->ri);			return NULL;		}		if (pri->t202_timer) {			pri_schedule_del(pri, pri->t202_timer);			pri->t202_timer = 0;		}		if (pri->subchannel && (pri->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);			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:		/* We're assuming one TEI per PRI in TE PTMP mode */		/* If no subchannel (TEI) ignore */		if (!pri->subchannel)			return NULL;		/* If it's addressed to the group TEI or to our TEI specifically, we respond */		if ((tei == Q921_TEI_GROUP) || (tei == pri->subchannel->tei))			q921_send_tei(pri, Q921_TEI_IDENTITY_CHECK_RESPONSE, random() % 65535, pri->subchannel->tei, 1);		break;	case Q921_TEI_IDENTITY_REMOVE:		/* 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);		}	}	return NULL;	/* Do we need to return something??? */}static int is_command(struct pri *pri, q921_h *h){	int	command =0;	int c_r = h->s.h.c_r;	if ((pri->localtype == PRI_NETWORK && c_r == 0) ||		(pri->localtype == PRI_CPE && c_r == 1))		command = 1;	return( command );}static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len){	q921_frame *f;	pri_event *ev;	int sendnow;	switch(h->h.data[0] & Q921_FRAMETYPE_MASK) {	case 0:	case 2:		if (pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED) {			pri_error(pri, "!! Got I-frame while link state %d\n", pri->q921_state);			return NULL;		}		/* Informational frame */		if (len < 4) {			pri_error(pri, "!! Received short I-frame (expected 4, got %d)\n", len);			break;		}		return q921_handle_iframe(pri, &h->i, len);			break;	case 1:		if (pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED) {			pri_error(pri, "!! Got S-frame while link down\n");			return NULL;		}		if (len < 4) {			pri_error(pri, "!! Received short S-frame (expected 4, got %d)\n", len);			break;		}		switch(h->s.ss) {		case 0:			/* Receiver Ready */			pri->busy = 0;			/* Acknowledge frames as necessary */			ev = q921_ack_rx(pri, h->s.n_r, 1);			if (ev)				return ev;			if (is_command(pri, h))				pri->solicitfbit = 0;			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 (!is_command(pri, h)) {					if (pri->debug & PRI_DEBUG_Q921_DUMP)						pri_message(pri, "-- Got RR response to our frame\n");					pri->retrans = 0;				} else {					if (pri->debug & PRI_DEBUG_Q921_DUMP)						pri_message(pri, "-- Unsolicited RR with P/F bit, responding\n");						q921_rr(pri, 1, 0);				}			}			break; 		case 1: 			/* Receiver not ready */ 			if (pri->debug & PRI_DEBUG_Q921_STATE) 				pri_message(pri, "-- Got receiver not ready\n"); 			pri->busy = 1;			ev = q921_ack_rx(pri, h->s.n_r, 0);			if (ev)				return ev;			if (h->s.p_f && is_command(pri, h))				q921_rr(pri, 1, 0);			pri->solicitfbit = 1;			pri->retrans = 0;			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;			}			if (pri->debug & PRI_DEBUG_Q921_DUMP)				pri_message(pri, "Restarting T_200 timer\n");			reschedule_t200(pri);			 			break;    		case 2: 			/* Just retransmit */ 			if (pri->debug & PRI_DEBUG_Q921_STATE) 				pri_message(pri, "-- Got reject requesting packet %d...  Retransmitting.\n", h->s.n_r);			if (pri->busy && !is_command(pri, h))				pri->solicitfbit = 0;			pri->busy = 0;			if (is_command(pri, h) && h->s.p_f)					q921_rr(pri, 1, 0);			q921_ack_rx(pri, h->s.n_r, 0);			/*Resend only if we are in the Multiple Frame Established state or when			  we are in the Time Recovery state and received responce with bit F=1*/			if ((pri->solicitfbit == 0) || (pri->solicitfbit && !is_command(pri, h) && h->s.p_f)) {				pri->solicitfbit = 0;				pri->retrans = 0;				sendnow = 0;				/* Resend I-frames starting from frame where f->h.n_s == h->s.n_r */				for (f = pri->txqueue; f && (f->h.n_s != h->s.n_r); f = f->next);				while (f) {					sendnow = 1;					if (f->transmitted || (!f->transmitted && (pri->windowlen < pri->window))) {			 			if (pri->debug & PRI_DEBUG_Q921_STATE)							pri_error(pri, "!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n", h->s.n_r, f->h.n_s);						f->h.n_r = pri->v_r;						f->h.p_f = 0;						if (!f->transmitted && (pri->windowlen < pri->window))							pri->windowlen++;						q921_transmit(pri, (q921_h *)(&f->h), f->len);					}					f = f->next; 				} 				if (!sendnow) {					if (pri->txqueue) {						/* This should never happen */						if (!h->s.p_f || h->s.n_r) {							pri_error(pri, "!! Got reject for frame %d, but we only have others!\n", h->s.n_r);						}					} else {						/* Hrm, we have nothing to send, but have been REJ'd.  Reset v_a, v_s, etc */						pri_error(pri, "!! Got reject for frame %d, but we have nothing -- resetting!\n", h->s.n_r);						pri->v_a = h->s.n_r;						pri->v_s = h->s.n_r;					}				}				/* Reset t200 timer if it was somehow going */				if (pri->t200_timer) {					pri_schedule_del(pri, pri->t200_timer);					pri->t200_timer = 0;				}				/* Reset and restart t203 timer */				reschedule_t203(pri);			} 			break;		default:			pri_error(pri, "!! XXX Unknown Supervisory frame ss=0x%02x,pf=%02xnr=%02x vs=%02x, va=%02x XXX\n", h->s.ss, h->s.p_f, h->s.n_r,					pri->v_s, pri->v_a);		}		break;	case 3:		if (len < 3) {			pri_error(pri, "!! Received short unnumbered frame\n");			break;		}		switch(h->u.m3) {		case 0:			if (h->u.m2 == 3) {				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 */					if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP))						pri_message(pri, "-- Got DM Mode from peer.\n");					/* Disconnected mode, try again after T200 */					ev = q921_dchannel_down(pri);					q921_restart(pri, 0);					return ev;										} else {					if (pri->debug & PRI_DEBUG_Q921_DUMP)						pri_message(pri, "-- Ignoring unsolicited DM with p/f set to 0\n");#if 0					/* Requesting that we start */					q921_restart(pri, 0);#endif									}				break;			} else if (!h->u.m2) {				if ((pri->sapi == Q921_SAPI_LAYER2_MANAGEMENT) && (pri->tei == Q921_TEI_GROUP))					q921_receive_MDL(pri, (q921_u *)h, len);				else {					int res;					res = q931_receive(pri, (q931_h *) h->u.data, len - 3);					if (res == -1) {						return NULL;					}					if (res & Q931_RES_HAVEEVENT)						return &pri->ev;				}			}			break;		case 2:			if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP))				pri_message(pri, "-- Got Disconnect from peer.\n");			/* Acknowledge */			q921_send_ua(pri, h->u.p_f);			ev = q921_dchannel_down(pri);			q921_restart(pri, 0);			return ev;		case 3:			if (h->u.m2 == 3) {				/* SABME */				if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP)) {					pri_message(pri, "-- Got SABME from %s peer.\n", h->h.c_r ? "network" : "cpe");				}				if (h->h.c_r) {					pri->remotetype = PRI_NETWORK;					if (pri->localtype == PRI_NETWORK) {						/* We can't both be networks */						return pri_mkerror(pri, "We think we're the network, but they think they're the network, too.");					}				} else {					pri->remotetype = PRI_CPE;					if (pri->localtype == PRI_CPE) {						/* We can't both be CPE */						return pri_mkerror(pri, "We think we're the CPE, but they think they're the CPE too.\n");					}				}				/* Send Unnumbered Acknowledgement */				q921_send_ua(pri, h->u.p_f);				return q921_dchannel_up(pri);			} else if (h->u.m2 == 0) {					/* It's a UA */				if (pri->q921_state == Q921_AWAITING_ESTABLISH) {					if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP)) {						pri_message(pri, "-- Got UA from %s peer  Link up.\n", h->h.c_r ? "cpe" : "network");					}					return q921_dchannel_up(pri);				} else if ((pri->q921_state >= Q921_TEI_ASSIGNED) && pri->bri) {					/* Possible duplicate TEI assignment */					if (pri->master)						q921_tei_release_and_reacquire(pri->master);					else						pri_error(pri, "Huh!? no master found\n");				} else {					/* Since we're not in the AWAITING_ESTABLISH STATE, it's unsolicited */					pri_error(pri, "!! Got a UA, but i'm in state %d\n", pri->q921_state);				}			} else 				pri_error(pri, "!! Weird frame received (m3=3, m2 = %d)\n", h->u.m2);			break;		case 4:			pri_error(pri, "!! Frame got rejected!\n");			break;		case 5:			pri_error(pri, "!! XID frames not supported\n");			break;		default:			pri_error(pri, "!! Don't know what to do with M3=%d u-frames\n", h->u.m3);		}		break;					}	return NULL;}static pri_event *__q921_receive(struct pri *pri, q921_h *h, int len){	pri_event *ev;	/* Discard FCS */	len -= 2;		if (!pri->master && pri->debug & (PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW))		q921_dump(pri, h, len, pri->debug & PRI_DEBUG_Q921_RAW, 0);	/* Check some reject conditions -- Start by rejecting improper ea's */	if (h->h.ea1 || !(h->h.ea2))		return NULL;#if 0 /* Will be rejected by subchannel analyzis */	/* Check for broadcasts - not yet handled */	if (h->h.tei == Q921_TEI_GROUP)		return NULL;#endif	if (!((h->h.sapi == pri->sapi) && ((h->h.tei == pri->tei) || (h->h.tei == Q921_TEI_GROUP)))) {		/* Check for SAPIs we don't yet handle */		/* If it's not us, try any subchannels we have */		if (pri->subchannel)			return q921_receive(pri->subchannel, h, len + 2);		else {			return NULL;		}	}	if (pri->debug & PRI_DEBUG_Q921_DUMP)		pri_message(pri, "Handling message for SAPI/TEI=%d/%d\n", h->h.sapi, h->h.tei);	ev = __q921_receive_qualified(pri, h, len);	reschedule_t203(pri);	return ev;}pri_event *q921_receive(struct pri *pri, q921_h *h, int len){	pri_event *e;	e = __q921_receive(pri, h, len);#ifdef LIBPRI_COUNTERS	pri->q921_rxcount++;#endif	return e;}static void q921_restart(struct pri *pri, int now){	if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED) {		pri_error(pri, "!! q921_start: Not in 'Link Connection Released' state\n");		return;	}	/* Reset our interface */	q921_reset(pri);	/* Do the SABME XXX Maybe we should implement T_WAIT? XXX */	q921_send_sabme(pri, now);}void q921_start(struct pri *pri, int isCPE){	q921_reset(pri);	if ((pri->sapi == Q921_SAPI_LAYER2_MANAGEMENT) && (pri->tei == Q921_TEI_GROUP)) {		pri->q921_state = Q921_DOWN;		if (isCPE)			q921_tei_request(pri);	} else {		q921_send_sabme(pri, isCPE);	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -