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

📄 tp_driver.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Header$ *//* $Source$ */#ifndef lintstatic char *rcsid = "$Header/**/$";#endif lint#define _XEBEC_PG static#include "tp_states.h"static struct act_ent {	int a_newstate;	int a_action;} statetable[] = { {0,0},#include "tp_states.init"};/* @(#)tp.trans	8.1 (Berkeley) 6/10/93 */#include <sys/param.h>#include <sys/systm.h>#include <sys/socket.h>#include <sys/socketvar.h>#include <sys/protosw.h>#include <sys/mbuf.h>#include <sys/time.h>#include <sys/errno.h>#include <netiso/tp_param.h>#include <netiso/tp_stat.h>#include <netiso/tp_pcb.h>#include <netiso/tp_tpdu.h>#include <netiso/argo_debug.h>#include <netiso/tp_trace.h>#include <netiso/iso_errno.h>#include <netiso/tp_seq.h>#include <netiso/cons.h>#define DRIVERTRACE TPPTdriver#define sbwakeup(sb)	sowakeup(p->tp_sock, sb);#define MCPY(d, w) (d ? m_copym(d, 0, (int)M_COPYALL, w): 0)static 	trick_hc = 1;int 	tp_emit(),		tp_goodack(),				tp_goodXack(),		tp_stash();void	tp_indicate(),				tp_getoptions(),			tp_soisdisconnecting(), 	tp_soisdisconnected(),		tp_recycle_tsuffix(),		#ifdef TP_DEBUG_TIMERS		tp_etimeout(),				tp_euntimeout(),		tp_ctimeout(),				tp_cuntimeout(),		tp_ctimeout_MIN(),#endif		tp_freeref(),				tp_detach(),		tp0_stash(), 				tp0_send(),		tp_netcmd(),				tp_send();typedef  struct tp_pcb tpcb_struct;typedef tpcb_struct tp_PCB_;#include "tp_events.h"_XEBEC_PG int _Xebec_action(a,e,p)int a;struct tp_event *e;tp_PCB_ *p;{switch(a) {case -1:  return tp_protocol_error(e,p);case 0x1: 		{		(void) tp_emit(DC_TPDU_type, p, 0, 0, MNULL);	}		 break;case 0x2: 		{#		ifdef TP_DEBUG		if( e->ev_number != AK_TPDU )			printf("TPDU 0x%x in REFWAIT!!!!\n", e->ev_number);#		endif TP_DEBUG	}		 break;case 0x3: 		{		/* oh, man is this grotesque or what? */		(void) tp_goodack(p, e->ev_union.EV_AK_TPDU.e_cdt, e->ev_union.EV_AK_TPDU.e_seq,  e->ev_union.EV_AK_TPDU.e_subseq);		/* but it's necessary because this pseudo-ack may happen		 * before the CC arrives, but we HAVE to adjust the		 * snduna as a result of the ack, WHENEVER it arrives		 */	}		 break;case 0x4: 		{		tp_detach(p);	}		 break;case 0x5: 		{		p->tp_refstate = REF_OPEN; /* has timers ??? */	}		 break;case 0x6: 		{		IFTRACE(D_CONN)			tptrace(TPPTmisc, "CR datalen data", e->ev_union.EV_CR_TPDU.e_datalen, e->ev_union.EV_CR_TPDU.e_data,0,0);		ENDTRACE		IFDEBUG(D_CONN)			printf("CR datalen 0x%x data 0x%x", e->ev_union.EV_CR_TPDU.e_datalen, e->ev_union.EV_CR_TPDU.e_data);		ENDDEBUG		p->tp_refstate = REF_OPEN; /* has timers */		p->tp_fcredit = e->ev_union.EV_CR_TPDU.e_cdt;		if (e->ev_union.EV_CR_TPDU.e_datalen > 0) {			/* n/a for class 0 */			ASSERT(p->tp_Xrcv.sb_cc == 0); 			sbappendrecord(&p->tp_Xrcv, e->ev_union.EV_CR_TPDU.e_data);			e->ev_union.EV_CR_TPDU.e_data = MNULL; 		} 	}		 break;case 0x7: 		{		IncStat(ts_tp0_conn);		IFTRACE(D_CONN)			tptrace(TPPTmisc, "Confiming", p, 0,0,0);		ENDTRACE		IFDEBUG(D_CONN)			printf("Confirming connection: p" );		ENDDEBUG		soisconnected(p->tp_sock);		(void) tp_emit(CC_TPDU_type, p, 0,0, MNULL) ;		p->tp_fcredit = 1;	}		 break;case 0x8: 		{		IncStat(ts_tp4_conn); /* even though not quite open */		IFTRACE(D_CONN)			tptrace(TPPTmisc, "Confiming", p, 0,0,0);		ENDTRACE		IFDEBUG(D_CONN)			printf("Confirming connection: p" );		ENDDEBUG		tp_getoptions(p);		soisconnecting(p->tp_sock);		if ((p->tp_rx_strat & TPRX_FASTSTART) && (p->tp_fcredit > 0))			p->tp_cong_win = p->tp_fcredit * p->tp_l_tpdusize;		p->tp_retrans = p->tp_Nretrans;		tp_ctimeout(p, TM_retrans, (int)p->tp_cc_ticks);	}		 break;case 0x9: 		{		IFDEBUG(D_CONN)			printf("event: CR_TPDU emit CC failed done " );		ENDDEBUG		soisdisconnected(p->tp_sock);		tp_recycle_tsuffix(p);		tp_freeref(p->tp_lref);		tp_detach(p);	}		 break;case 0xa: 		{		int error;		struct mbuf *data = MNULL;		IFTRACE(D_CONN)			tptrace(TPPTmisc, "T_CONN_req flags ucddata", (int)p->tp_flags,			p->tp_ucddata, 0, 0);		ENDTRACE		data =  MCPY(p->tp_ucddata, M_WAIT);		if (data) {			IFDEBUG(D_CONN)				printf("T_CONN_req.trans m_copy cc 0x%x\n", 					p->tp_ucddata);				dump_mbuf(data, "sosnd @ T_CONN_req");			ENDDEBUG		}		if (error = tp_emit(CR_TPDU_type, p, 0, 0, data) )			return error; /* driver WON'T change state; will return error */				p->tp_refstate = REF_OPEN; /* has timers */		if(p->tp_class != TP_CLASS_0) {			p->tp_retrans = p->tp_Nretrans;			tp_ctimeout(p, TM_retrans, (int)p->tp_cr_ticks);		}	}		 break;case 0xb: 		{		sbflush(&p->tp_Xrcv); /* purge non-delivered data data */		if (e->ev_union.EV_DR_TPDU.e_datalen > 0) {			sbappendrecord(&p->tp_Xrcv, e->ev_union.EV_DR_TPDU.e_data);			e->ev_union.EV_DR_TPDU.e_data = MNULL;		} 		if (p->tp_state == TP_OPEN)			tp_indicate(T_DISCONNECT, p, 0);		else {			int so_error = ECONNREFUSED;			if (e->ev_union.EV_DR_TPDU.e_reason != (E_TP_NO_SESSION ^ TP_ERROR_MASK) &&			    e->ev_union.EV_DR_TPDU.e_reason != (E_TP_NO_CR_ON_NC ^ TP_ERROR_MASK) &&			    e->ev_union.EV_DR_TPDU.e_reason != (E_TP_REF_OVERFLOW ^ TP_ERROR_MASK))				so_error = ECONNABORTED;			tp_indicate(T_DISCONNECT, p, so_error);		}		tp_soisdisconnected(p);		if (p->tp_class != TP_CLASS_0) {			if (p->tp_state == TP_OPEN ) {				tp_euntimeout(p, TM_data_retrans); /* all */				tp_cuntimeout(p, TM_retrans);				tp_cuntimeout(p, TM_inact);				tp_cuntimeout(p, TM_sendack);				p->tp_flags &= ~TPF_DELACK;			}			tp_cuntimeout(p, TM_retrans);			if( e->ev_union.EV_DR_TPDU.e_sref !=  0 ) 				(void) tp_emit(DC_TPDU_type, p, 0, 0, MNULL);		}	}		 break;case 0xc: 		{		if( e->ev_union.EV_DR_TPDU.e_sref != 0 )			(void) tp_emit(DC_TPDU_type, p, 0, 0, MNULL); 		/* reference timer already set - reset it to be safe (???) */		tp_euntimeout(p, TM_reference); /* all */		tp_etimeout(p, TM_reference, (int)p->tp_refer_ticks);	}		 break;case 0xd: 		{			tp_cuntimeout(p, TM_retrans);		tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason);		tp_soisdisconnected(p);	}		 break;case 0xe: 		{	 		tp_cuntimeout(p, TM_retrans);		tp_soisdisconnected(p);	}		 break;case 0xf: 		{	 		tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason);		tp_cuntimeout(p, TM_retrans);		tp_soisdisconnected(p);	}		 break;case 0x10: 		{	 		tp_cuntimeout(p, TM_retrans);		tp_soisdisconnected(p);	}		 break;case 0x11: 		{	/* don't ask me why we have to do this - spec says so */		(void) tp_emit(DR_TPDU_type, p, 0, E_TP_NO_SESSION, MNULL);		/* don't bother with retransmissions of the DR */	}		 break;case 0x12: 		{		tp_soisdisconnecting(p->tp_sock);		tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason);		tp_soisdisconnected(p);		tp_netcmd( p, CONN_CLOSE );	}		 break;case 0x13: 		{		if (p->tp_state == TP_OPEN) {			tp_euntimeout(p, TM_data_retrans); /* all */			tp_cuntimeout(p, TM_inact);			tp_cuntimeout(p, TM_sendack);		}		tp_soisdisconnecting(p->tp_sock);		tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason);		p->tp_retrans = p->tp_Nretrans;		tp_ctimeout(p, TM_retrans, (int)p->tp_dr_ticks);		(void) tp_emit(DR_TPDU_type, p, 0, E_TP_PROTO_ERR, MNULL);	}		 break;case 0x14: 		{			tp_cuntimeout(p, TM_retrans);		IncStat(ts_tp0_conn);		p->tp_fcredit = 1;		soisconnected(p->tp_sock);	}		 break;case 0x15: 		{			IFDEBUG(D_CONN)			printf("trans: CC_TPDU in CRSENT state flags 0x%x\n", 				(int)p->tp_flags);		ENDDEBUG		IncStat(ts_tp4_conn);		p->tp_fref = e->ev_union.EV_CC_TPDU.e_sref;		p->tp_fcredit = e->ev_union.EV_CC_TPDU.e_cdt;		if ((p->tp_rx_strat & TPRX_FASTSTART) && (e->ev_union.EV_CC_TPDU.e_cdt > 0))			p->tp_cong_win = e->ev_union.EV_CC_TPDU.e_cdt * p->tp_l_tpdusize;		tp_getoptions(p);		tp_cuntimeout(p, TM_retrans);		if (p->tp_ucddata) {			IFDEBUG(D_CONN)				printf("dropping user connect data cc 0x%x\n",					p->tp_ucddata->m_len);			ENDDEBUG			m_freem(p->tp_ucddata);			p->tp_ucddata = 0;		}		soisconnected(p->tp_sock);		if (e->ev_union.EV_CC_TPDU.e_datalen > 0) {			ASSERT(p->tp_Xrcv.sb_cc == 0); /* should be empty */			sbappendrecord(&p->tp_Xrcv, e->ev_union.EV_CC_TPDU.e_data);			e->ev_union.EV_CC_TPDU.e_data = MNULL;		}		(void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL);		tp_ctimeout(p, TM_inact, (int)p->tp_inact_ticks);	}		 break;case 0x16: 		{		struct mbuf *data = MNULL;		int error;		IncStat(ts_retrans_cr);		p->tp_cong_win = 1 * p->tp_l_tpdusize;		data = MCPY(p->tp_ucddata, M_NOWAIT);		if(p->tp_ucddata) {			IFDEBUG(D_CONN)				printf("TM_retrans.trans m_copy cc 0x%x\n", data);				dump_mbuf(p->tp_ucddata, "sosnd @ TM_retrans");			ENDDEBUG			if( data == MNULL )				return ENOBUFS;		}		p->tp_retrans --;		if( error = tp_emit(CR_TPDU_type, p, 0, 0, data) ) {			p->tp_sock->so_error = error;		}		tp_ctimeout(p, TM_retrans, (int)p->tp_cr_ticks);	}		 break;case 0x17: 		{ 			IncStat(ts_conn_gaveup);		p->tp_sock->so_error = ETIMEDOUT;		tp_indicate(T_DISCONNECT, p, ETIMEDOUT);		tp_soisdisconnected(p);	}		 break;case 0x18: 		{			int error;		struct mbuf *data = MCPY(p->tp_ucddata, M_WAIT);		if( error = tp_emit(CC_TPDU_type, p, 0, 0, data) ) {			p->tp_sock->so_error = error;		}		p->tp_retrans = p->tp_Nretrans;		tp_ctimeout(p, TM_retrans, (int)p->tp_cc_ticks);	}		 break;case 0x19: 		{		int doack;		/*		 * Get rid of any confirm or connect data, so that if we		 * crash or close, it isn't thought of as disconnect data.		 */		if (p->tp_ucddata) {			m_freem(p->tp_ucddata);			p->tp_ucddata = 0;		}		tp_ctimeout(p, TM_inact, (int)p->tp_inact_ticks);		tp_cuntimeout(p, TM_retrans);		soisconnected(p->tp_sock);		tp_ctimeout(p, TM_inact, (int)p->tp_inact_ticks);		/* see also next 2 transitions, if you make any changes */		doack = tp_stash(p, e);		IFDEBUG(D_DATA)			printf("tp_stash returns %d\n",doack);		ENDDEBUG		if (doack) {			(void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL ); 			tp_ctimeout(p, TM_sendack, (int)p->tp_keepalive_ticks);		} else			tp_ctimeout( p, TM_sendack, (int)p->tp_sendack_ticks);				IFDEBUG(D_DATA)			printf("after stash calling sbwakeup\n");		ENDDEBUG	}		 break;case 0x1a: 		{		tp0_stash(p, e);		sbwakeup( &p->tp_sock->so_rcv );		IFDEBUG(D_DATA)			printf("after stash calling sbwakeup\n");		ENDDEBUG	}		 break;case 0x1b: 		{		int doack; /* tells if we must ack immediately */		tp_ctimeout(p, TM_inact, (int)p->tp_inact_ticks);		sbwakeup( &p->tp_sock->so_rcv );		doack = tp_stash(p, e);		IFDEBUG(D_DATA)			printf("tp_stash returns %d\n",doack);		ENDDEBUG		if(doack)			(void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL ); 		else			tp_ctimeout_MIN( p, TM_sendack, (int)p->tp_sendack_ticks);				IFDEBUG(D_DATA)			printf("after stash calling sbwakeup\n");		ENDDEBUG	}		 break;case 0x1c: 		{ 			IFTRACE(D_DATA)			tptrace(TPPTmisc, "NIW seq rcvnxt lcredit ",				e->ev_union.EV_DT_TPDU.e_seq, p->tp_rcvnxt, p->tp_lcredit, 0);		ENDTRACE		IncStat(ts_dt_niw);		m_freem(e->ev_union.EV_DT_TPDU.e_data);		tp_ctimeout(p, TM_inact, (int)p->tp_inact_ticks);		(void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL ); 	}		 break;case 0x1d: 		{		if (p->tp_ucddata) {			m_freem(p->tp_ucddata);			p->tp_ucddata = 0;		}		(void) tp_goodack(p, e->ev_union.EV_AK_TPDU.e_cdt, e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.e_subseq);		tp_cuntimeout(p, TM_retrans);		soisconnected(p->tp_sock);		IFTRACE(D_CONN)			struct socket *so = p->tp_sock;			tptrace(TPPTmisc, 			"called sosiconn: so so_state rcv.sb_sel rcv.sb_flags",				so, so->so_state, so->so_rcv.sb_sel, so->so_rcv.sb_flags);			tptrace(TPPTmisc, 			"called sosiconn 2: so_qlen so_error so_rcv.sb_cc so_head",				so->so_qlen, so->so_error, so->so_rcv.sb_cc, so->so_head);		ENDTRACE		tp_ctimeout(p, TM_sendack, (int)p->tp_keepalive_ticks);		tp_ctimeout(p, TM_inact, (int)p->tp_inact_ticks);	}		 break;case 0x1e: 		{		if( p->tp_state == TP_AKWAIT ) {			if (p->tp_ucddata) {				m_freem(p->tp_ucddata);				p->tp_ucddata = 0;			}			tp_cuntimeout(p, TM_retrans);			soisconnected(p->tp_sock);			tp_ctimeout(p, TM_sendack, (int)p->tp_keepalive_ticks);			tp_ctimeout(p, TM_inact, (int)p->tp_inact_ticks);		} 		IFTRACE(D_XPD)		tptrace(TPPTmisc, "XPD tpdu accepted Xrcvnxt, e_seq datalen m_len\n",				p->tp_Xrcvnxt,e->ev_union.EV_XPD_TPDU.e_seq,  e->ev_union.EV_XPD_TPDU.e_datalen, e->ev_union.EV_XPD_TPDU.e_data->m_len);		ENDTRACE		p->tp_sock->so_state |= SS_RCVATMARK;		e->ev_union.EV_XPD_TPDU.e_data->m_flags |= M_EOR;		sbinsertoob(&p->tp_Xrcv, e->ev_union.EV_XPD_TPDU.e_data);		IFDEBUG(D_XPD)			dump_mbuf(e->ev_union.EV_XPD_TPDU.e_data, "XPD TPDU: tp_Xrcv");

⌨️ 快捷键说明

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