📄 tp.trans
字号:
if ($P.tp_state == TP_OPEN) tp_indicate(T_DISCONNECT, $P, 0); else { int so_error = ECONNREFUSED; if ($$.e_reason != (E_TP_NO_SESSION ^ TP_ERROR_MASK) && $$.e_reason != (E_TP_NO_CR_ON_NC ^ TP_ERROR_MASK) && $$.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_sref != 0 ) (void) tp_emit(DC_TPDU_type, $P, 0, 0, MNULL); } };SAME <== TP_CLOSED DR_TPDU DEFAULT { if( $$.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); };/* NBS(34) */TP_REFWAIT <== TP_CRSENT ER_TPDU DEFAULT { tp_cuntimeout($P, TM_retrans); tp_indicate(ER_TPDU, $P, $$.e_reason); tp_soisdisconnected($P); };/* NBS(27) */TP_REFWAIT <== TP_CLOSING DR_TPDU DEFAULT { tp_cuntimeout($P, TM_retrans); tp_soisdisconnected($P); };/* these two transitions are the same but can't be combined because xebec * can't handle the use of $$.e_reason if they're combined *//* NBS(27) */TP_REFWAIT <== TP_CLOSING ER_TPDU DEFAULT { tp_indicate(ER_TPDU, $P, $$.e_reason); tp_cuntimeout($P, TM_retrans); tp_soisdisconnected($P); };/* NBS(27) */TP_REFWAIT <== TP_CLOSING DC_TPDU DEFAULT { tp_cuntimeout($P, TM_retrans); tp_soisdisconnected($P); };/* NBS(21) */SAME <== TP_CLOSED [ CC_TPDU, CR_TPDU ] DEFAULT { /* 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 */ };/* NBS(34) */TP_REFWAIT <== TP_OPEN ER_TPDU ($P.tp_class == TP_CLASS_0) { tp_soisdisconnecting($P.tp_sock); tp_indicate(ER_TPDU, $P, $$.e_reason); tp_soisdisconnected($P); tp_netcmd( $P, CONN_CLOSE ); };TP_CLOSING <== [ TP_AKWAIT, TP_OPEN ] ER_TPDU DEFAULT { 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_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); };/* NBS(6) */TP_OPEN <== TP_CRSENT CC_TPDU ($P.tp_class == TP_CLASS_0) { tp_cuntimeout($P, TM_retrans); IncStat(ts_tp0_conn); $P.tp_fcredit = 1; soisconnected($P.tp_sock); };TP_OPEN <== TP_CRSENT CC_TPDU DEFAULT { 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_sref; $P.tp_fcredit = $$.e_cdt; if (($P.tp_rx_strat & TPRX_FASTSTART) && ($$.e_cdt > 0)) $P.tp_cong_win = $$.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_datalen > 0) { ASSERT($P.tp_Xrcv.sb_cc == 0); /* should be empty */ sbappendrecord(&$P.tp_Xrcv, $$.e_data); $$.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); };/* TP4 only */SAME <== TP_CRSENT TM_retrans ( $P.tp_retrans > 0 ) { 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); };/* TP4 only */TP_REFWAIT <== TP_CRSENT TM_retrans DEFAULT /* no more CR retransmissions */ { IncStat(ts_conn_gaveup); $P.tp_sock->so_error = ETIMEDOUT; tp_indicate(T_DISCONNECT, $P, ETIMEDOUT); tp_soisdisconnected($P); };/* TP4 only */SAME <== TP_AKWAIT CR_TPDU DEFAULT /* duplicate CR (which doesn't really exist in the context of * a connectionless network layer) * Doesn't occur in class 0. */ { 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); };/* TP4 only */TP_OPEN <== TP_AKWAIT DT_TPDU ( IN_RWINDOW( $P, $$.e_seq, $P.tp_rcvnxt, SEQ($P, $P.tp_rcvnxt + $P.tp_lcredit)) ) { 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 };SAME <== TP_OPEN DT_TPDU ( $P.tp_class == TP_CLASS_0 ) { tp0_stash($P, $E); sbwakeup( &$P.tp_sock->so_rcv ); IFDEBUG(D_DATA) printf("after stash calling sbwakeup\n"); ENDDEBUG };/* TP4 only */SAME <== TP_OPEN DT_TPDU ( IN_RWINDOW( $P, $$.e_seq, $P.tp_rcvnxt, SEQ($P, $P.tp_rcvnxt + $P.tp_lcredit)) ) { 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 };/* Not in window - we must ack under certain circumstances, namely * a) if the seq number is below lwe but > lwe - (max credit ever given) * (to handle lost acks) Can use max-possible-credit for this ^^^. * and * b) seq number is > uwe but < uwe + previously sent & withdrawn credit * * (see 12.2.3.8.1 of ISO spec, p. 73) * We just always ack. *//* TP4 only */SAME <== [ TP_OPEN, TP_AKWAIT ] DT_TPDU DEFAULT /* Not in window */ { IFTRACE(D_DATA) tptrace(TPPTmisc, "NIW seq rcvnxt lcredit ", $$.e_seq, $P.tp_rcvnxt, $P.tp_lcredit, 0); ENDTRACE IncStat(ts_dt_niw); m_freem($$.e_data); tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks); (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, MNULL ); };/* TP4 only */TP_OPEN <== TP_AKWAIT AK_TPDU DEFAULT { if ($P.tp_ucddata) { m_freem($P.tp_ucddata); $P.tp_ucddata = 0; } (void) tp_goodack($P, $$.e_cdt, $$.e_seq, $$.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); };/* TP4 only */TP_OPEN <== [ TP_OPEN, TP_AKWAIT ] XPD_TPDU ($P.tp_Xrcvnxt == $$.e_seq) { 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_seq, $$.e_datalen, $$.e_data->m_len); ENDTRACE $P.tp_sock->so_state |= SS_RCVATMARK; $$.e_data->m_flags |= M_EOR; sbinsertoob(&$P.tp_Xrcv, $$.e_data); IFDEBUG(D_XPD) dump_mbuf($$.e_data, "XPD TPDU: tp_Xrcv"); ENDDEBUG tp_indicate(T_XDATA, $P, 0); sbwakeup( &$P.tp_Xrcv ); (void) tp_emit(XAK_TPDU_type, $P, $P.tp_Xrcvnxt, 0, MNULL); SEQ_INC($P, $P.tp_Xrcvnxt); };/* TP4 only */SAME <== TP_OPEN T_USR_Xrcvd DEFAULT { if( $P.tp_Xrcv.sb_cc == 0 ) { /* kludge for select(): */ /* $P.tp_sock->so_state &= ~SS_OOBAVAIL; */ } } /* OLD WAY: * Ack only after the user receives the XPD. This is better for * users that use one XPD right after another. * Acking right away (the NEW WAY, see the prev. transition) is * better for occasional * XPD, when the receiving user doesn't * want to read the XPD immediately (which is session's behavior). * int error = tp_emit(XAK_TPDU_type, $P, $P.tp_Xrcvnxt, 0, MNULL); SEQ_INC($P, $P.tp_Xrcvnxt); return error; */;/* NOTE: presently if the user doesn't read the connection data * before and expedited data PDU comes in, the connection data will * be dropped. This is a bug. To avoid it, we need somewhere else * to put the connection data. * On the other hand, we need not to have it sitting around forever. * This is a problem with the idea of trying to accommodate * data on connect w/ a passive-open user interface. *//* TP4 only */SAME <== [ TP_AKWAIT, TP_OPEN ] XPD_TPDU DEFAULT /* not in window or cdt==0 */ { IFTRACE(D_XPD) tptrace(TPPTmisc, "XPD tpdu niw (Xrcvnxt, e_seq) or not cdt (cc)\n", $P.tp_Xrcvnxt, $$.e_seq, $P.tp_Xrcv.sb_cc , 0); ENDTRACE if( $P.tp_Xrcvnxt != $$.e_seq ) IncStat(ts_xpd_niw); if( $P.tp_Xrcv.sb_cc ) { /* might as well kick 'em again */ tp_indicate(T_XDATA, $P, 0); IncStat(ts_xpd_dup); } m_freem($$.e_data); tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks); /* don't send an xack because the xak gives "last one received", not * "next one i expect" (dumb) */ };/* Occurs (AKWAIT, OPEN) when parent (listening) socket gets aborted, and tries * to detach all its "children" * Also (CRSENT) when user kills a job that's doing a connect() */TP_REFWAIT <== TP_CRSENT T_DETACH ($P.tp_class == TP_CLASS_0) { struct socket *so = $P.tp_sock; /* detach from parent socket so it can finish closing */ if (so->so_head) { if (!soqremque(so, 0) && !soqremque(so, 1)) panic("tp: T_DETACH"); so->so_head = 0; } tp_soisdisconnecting($P.tp_sock); tp_netcmd( $P, CONN_CLOSE); tp_soisdisconnected($P); };
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -