|
|
1.1.1.2 ! root 1: /* $Header: /cvsroot/src/sys/netiso/tp_driver.c,v 1.1 1993/04/09 12:01:30 cgd Exp $ */ ! 2: /* $Source: /cvsroot/src/sys/netiso/tp_driver.c,v $ */ 1.1 root 3: #ifndef lint 4: static char *rcsid = "$Header/**/$"; 5: #endif lint 6: #define _XEBEC_PG static 7: 8: #include "tp_states.h" 9: 10: static struct act_ent { 11: int a_newstate; 12: int a_action; 13: } statetable[] = { {0,0}, 14: #include "tp_states.init" 15: }; 16: 17: /* %W% (Berkeley) %G% */ 18: #include "param.h" 19: #include "socket.h" 20: #include "socketvar.h" 21: #include "protosw.h" 22: #include "mbuf.h" 23: #include "time.h" 24: #include "errno.h" 25: #include "../netiso/tp_param.h" 26: #include "../netiso/tp_stat.h" 27: #include "../netiso/tp_pcb.h" 28: #include "../netiso/tp_tpdu.h" 29: #include "../netiso/argo_debug.h" 30: #include "../netiso/tp_trace.h" 31: #include "../netiso/iso_errno.h" 32: #include "../netiso/tp_seq.h" 33: #include "../netiso/cons.h" 34: 35: #define DRIVERTRACE TPPTdriver 36: #define sbwakeup(sb) sowakeup(p->tp_sock, sb); 37: #define MCPY(d, w) (d ? m_copym(d, 0, (int)M_COPYALL, w): 0) 38: 39: static trick_hc = 1; 40: 41: int tp_emit(), 42: tp_goodack(), tp_goodXack(), 43: tp_stash() 44: ; 45: void tp_indicate(), tp_getoptions(), 46: tp_soisdisconnecting(), tp_soisdisconnected(), 47: tp_recycle_tsuffix(), 48: tp_etimeout(), tp_euntimeout(), 49: tp_euntimeout_lss(), tp_ctimeout(), 50: tp_cuntimeout(), tp_ctimeout_MIN(), 51: tp_freeref(), tp_detach(), 52: tp0_stash(), tp0_send(), 53: tp_netcmd(), tp_send() 54: ; 55: 56: typedef struct tp_pcb tpcb_struct; 57: 58: 59: 60: typedef tpcb_struct tp_PCB_; 61: 62: #include "tp_events.h" 63: 64: _XEBEC_PG int _Xebec_action(a,e,p) 65: int a; 66: struct tp_event *e; 67: tp_PCB_ *p; 68: { 69: switch(a) { 70: case -1: return tp_protocol_error(e,p); 71: case 0x1: 72: { 73: (void) tp_emit(DC_TPDU_type, p, 0, 0, MNULL); 74: } 75: break; 76: case 0x2: 77: { 78: # ifdef TP_DEBUG 79: if( e->ev_number != AK_TPDU ) 80: printf("TPDU 0x%x in REFWAIT!!!!\n", e->ev_number); 81: # endif TP_DEBUG 82: } 83: break; 84: case 0x3: 85: { 86: /* oh, man is this grotesque or what? */ 87: (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); 88: /* but it's necessary because this pseudo-ack may happen 89: * before the CC arrives, but we HAVE to adjust the 90: * snduna as a result of the ack, WHENEVER it arrives 91: */ 92: } 93: break; 94: case 0x4: 95: { 96: tp_detach(p); 97: } 98: break; 99: case 0x5: 100: { 101: p->tp_refp->tpr_state = REF_OPEN; /* has timers ??? */ 102: } 103: break; 104: case 0x6: 105: { 106: IFTRACE(D_CONN) 107: tptrace(TPPTmisc, "CR datalen data", e->ev_union.EV_CR_TPDU.e_datalen, e->ev_union.EV_CR_TPDU.e_data,0,0); 108: ENDTRACE 109: IFDEBUG(D_CONN) 110: printf("CR datalen 0x%x data 0x%x", e->ev_union.EV_CR_TPDU.e_datalen, e->ev_union.EV_CR_TPDU.e_data); 111: ENDDEBUG 112: p->tp_refp->tpr_state = REF_OPEN; /* has timers */ 113: p->tp_fcredit = e->ev_union.EV_CR_TPDU.e_cdt; 114: 115: if (e->ev_union.EV_CR_TPDU.e_datalen > 0) { 116: /* n/a for class 0 */ 117: ASSERT(p->tp_Xrcv.sb_cc == 0); 118: sbappendrecord(&p->tp_Xrcv, e->ev_union.EV_CR_TPDU.e_data); 119: e->ev_union.EV_CR_TPDU.e_data = MNULL; 120: } 121: } 122: break; 123: case 0x7: 124: { 125: IncStat(ts_tp0_conn); 126: IFTRACE(D_CONN) 127: tptrace(TPPTmisc, "Confiming", p, 0,0,0); 128: ENDTRACE 129: IFDEBUG(D_CONN) 130: printf("Confirming connection: p" ); 131: ENDDEBUG 132: soisconnected(p->tp_sock); 133: (void) tp_emit(CC_TPDU_type, p, 0,0, MNULL) ; 134: p->tp_fcredit = 1; 135: } 136: break; 137: case 0x8: 138: { 139: IncStat(ts_tp4_conn); /* even though not quite open */ 140: IFTRACE(D_CONN) 141: tptrace(TPPTmisc, "Confiming", p, 0,0,0); 142: ENDTRACE 143: IFDEBUG(D_CONN) 144: printf("Confirming connection: p" ); 145: ENDDEBUG 146: soisconnecting(p->tp_sock); 147: if ((p->tp_rx_strat & TPRX_FASTSTART) && (p->tp_fcredit > 0)) 148: p->tp_cong_win = p->tp_fcredit; 149: p->tp_retrans = p->tp_Nretrans; 150: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_cc_ticks); 151: } 152: break; 153: case 0x9: 154: { 155: register struct tp_ref *r = p->tp_refp; 156: 157: IFDEBUG(D_CONN) 158: printf("event: CR_TPDU emit CC failed done " ); 159: ENDDEBUG 160: soisdisconnected(p->tp_sock); 161: tp_recycle_tsuffix( p ); 162: tp_freeref(r); 163: tp_detach(p); 164: } 165: break; 166: case 0xa: 167: { 168: int error; 169: struct mbuf *data = MNULL; 170: 171: IFTRACE(D_CONN) 172: tptrace(TPPTmisc, "T_CONN_req flags ucddata", (int)p->tp_flags, 173: p->tp_ucddata, 0, 0); 174: ENDTRACE 175: data = MCPY(p->tp_ucddata, M_WAIT); 176: if (data) { 177: IFDEBUG(D_CONN) 178: printf("T_CONN_req.trans m_copy cc 0x%x\n", 179: p->tp_ucddata); 180: dump_mbuf(data, "sosnd @ T_CONN_req"); 181: ENDDEBUG 182: } 183: 184: if (error = tp_emit(CR_TPDU_type, p, 0, 0, data) ) 185: return error; /* driver WON'T change state; will return error */ 186: 187: p->tp_refp->tpr_state = REF_OPEN; /* has timers */ 188: if(p->tp_class != TP_CLASS_0) { 189: p->tp_retrans = p->tp_Nretrans; 190: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_cr_ticks); 191: } 192: } 193: break; 194: case 0xb: 195: { 196: sbflush(&p->tp_Xrcv); /* purge non-delivered data data */ 197: if (e->ev_union.EV_DR_TPDU.e_datalen > 0) { 198: sbappendrecord(&p->tp_Xrcv, e->ev_union.EV_DR_TPDU.e_data); 199: e->ev_union.EV_DR_TPDU.e_data = MNULL; 200: } 201: /* must return no error, or disc data and reason can't be read */ 202: tp_indicate(T_DISCONNECT, p, 0); 203: tp_soisdisconnected(p); 204: if (p->tp_class != TP_CLASS_0) { 205: if (p->tp_state == TP_OPEN ) { 206: tp_euntimeout(p->tp_refp, TM_data_retrans); /* all */ 207: tp_cuntimeout(p->tp_refp, TM_retrans); 208: tp_cuntimeout(p->tp_refp, TM_inact); 209: tp_cuntimeout(p->tp_refp, TM_sendack); 210: } 211: tp_cuntimeout(p->tp_refp, TM_retrans); 212: if( e->ev_union.EV_DR_TPDU.e_sref != 0 ) 213: (void) tp_emit(DC_TPDU_type, p, 0, 0, MNULL); 214: } 215: } 216: break; 217: case 0xc: 218: { 219: if( e->ev_union.EV_DR_TPDU.e_sref != 0 ) 220: (void) tp_emit(DC_TPDU_type, p, 0, 0, MNULL); 221: /* reference timer already set - reset it to be safe (???) */ 222: tp_euntimeout(p->tp_refp, TM_reference); /* all */ 223: tp_etimeout(p->tp_refp, TM_reference, 0, 0, 0, (int)p->tp_refer_ticks); 224: } 225: break; 226: case 0xd: 227: { 228: tp_cuntimeout(p->tp_refp, TM_retrans); 229: tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason); 230: tp_soisdisconnected(p); 231: } 232: break; 233: case 0xe: 234: { 235: tp_cuntimeout(p->tp_refp, TM_retrans); 236: tp_soisdisconnected(p); 237: } 238: break; 239: case 0xf: 240: { 241: tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason); 242: tp_cuntimeout(p->tp_refp, TM_retrans); 243: tp_soisdisconnected(p); 244: } 245: break; 246: case 0x10: 247: { 248: tp_cuntimeout(p->tp_refp, TM_retrans); 249: tp_soisdisconnected(p); 250: } 251: break; 252: case 0x11: 253: { /* don't ask me why we have to do this - spec says so */ 254: (void) tp_emit(DR_TPDU_type, p, 0, E_TP_NO_SESSION, MNULL); 255: /* don't bother with retransmissions of the DR */ 256: } 257: break; 258: case 0x12: 259: { 260: tp_soisdisconnecting(p->tp_sock); 261: tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason); 262: tp_soisdisconnected(p); 263: tp_netcmd( p, CONN_CLOSE ); 264: } 265: break; 266: case 0x13: 267: { 268: if (p->tp_state == TP_OPEN) { 269: tp_euntimeout(p->tp_refp, TM_data_retrans); /* all */ 270: tp_cuntimeout(p->tp_refp, TM_inact); 271: tp_cuntimeout(p->tp_refp, TM_sendack); 272: } 273: tp_soisdisconnecting(p->tp_sock); 274: tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason); 275: p->tp_retrans = p->tp_Nretrans; 276: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); 277: (void) tp_emit(DR_TPDU_type, p, 0, E_TP_PROTO_ERR, MNULL); 278: } 279: break; 280: case 0x14: 281: { 282: tp_cuntimeout(p->tp_refp, TM_retrans); 283: IncStat(ts_tp0_conn); 284: p->tp_fcredit = 1; 285: soisconnected(p->tp_sock); 286: } 287: break; 288: case 0x15: 289: { 290: IFDEBUG(D_CONN) 291: printf("trans: CC_TPDU in CRSENT state flags 0x%x\n", 292: (int)p->tp_flags); 293: ENDDEBUG 294: IncStat(ts_tp4_conn); 295: p->tp_fref = e->ev_union.EV_CC_TPDU.e_sref; 296: p->tp_fcredit = e->ev_union.EV_CC_TPDU.e_cdt; 297: p->tp_ackrcvd = 0; 298: if ((p->tp_rx_strat & TPRX_FASTSTART) && (e->ev_union.EV_CC_TPDU.e_cdt > 0)) 299: p->tp_cong_win = e->ev_union.EV_CC_TPDU.e_cdt; 300: tp_getoptions(p); 301: tp_cuntimeout(p->tp_refp, TM_retrans); 302: if (p->tp_ucddata) { 303: IFDEBUG(D_CONN) 304: printf("dropping user connect data cc 0x%x\n", 305: p->tp_ucddata->m_len); 306: ENDDEBUG 307: m_freem(p->tp_ucddata); 308: p->tp_ucddata = 0; 309: } 310: soisconnected(p->tp_sock); 311: if (e->ev_union.EV_CC_TPDU.e_datalen > 0) { 312: ASSERT(p->tp_Xrcv.sb_cc == 0); /* should be empty */ 313: sbappendrecord(&p->tp_Xrcv, e->ev_union.EV_CC_TPDU.e_data); 314: e->ev_union.EV_CC_TPDU.e_data = MNULL; 315: } 316: 317: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL); 318: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 319: } 320: break; 321: case 0x16: 322: { 323: struct mbuf *data = MNULL; 324: int error; 325: 326: IncStat(ts_retrans_cr); 327: p->tp_cong_win = 1; 328: p->tp_ackrcvd = 0; 329: data = MCPY(p->tp_ucddata, M_NOWAIT); 330: if(p->tp_ucddata) { 331: IFDEBUG(D_CONN) 332: printf("TM_retrans.trans m_copy cc 0x%x\n", data); 333: dump_mbuf(p->tp_ucddata, "sosnd @ TM_retrans"); 334: ENDDEBUG 335: if( data == MNULL ) 336: return ENOBUFS; 337: } 338: 339: p->tp_retrans --; 340: if( error = tp_emit(CR_TPDU_type, p, 0, 0, data) ) { 341: p->tp_sock->so_error = error; 342: } 343: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_cr_ticks); 344: } 345: break; 346: case 0x17: 347: { 348: IncStat(ts_conn_gaveup); 349: p->tp_sock->so_error = ETIMEDOUT; 350: tp_indicate(T_DISCONNECT, p, ETIMEDOUT); 351: tp_soisdisconnected(p); 352: } 353: break; 354: case 0x18: 355: { 356: int error; 357: struct mbuf *data = MCPY(p->tp_ucddata, M_WAIT); 358: 359: if( error = tp_emit(CC_TPDU_type, p, 0, 0, data) ) { 360: p->tp_sock->so_error = error; 361: } 362: p->tp_retrans = p->tp_Nretrans; 363: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_cc_ticks); 364: } 365: break; 366: case 0x19: 367: { 368: int doack; 369: 370: /* 371: * Get rid of any confirm or connect data, so that if we 372: * crash or close, it isn't thought of as disconnect data. 373: */ 374: if (p->tp_ucddata) { 375: m_freem(p->tp_ucddata); 376: p->tp_ucddata = 0; 377: } 378: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 379: tp_cuntimeout(p->tp_refp, TM_retrans); 380: soisconnected(p->tp_sock); 381: tp_getoptions(p); 382: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 383: 384: /* see also next 2 transitions, if you make any changes */ 385: 386: doack = tp_stash(p, e); 387: IFDEBUG(D_DATA) 388: printf("tp_stash returns %d\n",doack); 389: ENDDEBUG 390: 391: if(doack) { 392: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL ); 393: tp_ctimeout(p->tp_refp, TM_sendack, (int)p->tp_keepalive_ticks); 394: } else 395: tp_ctimeout( p->tp_refp, TM_sendack, (int)p->tp_sendack_ticks); 396: 397: IFDEBUG(D_DATA) 398: printf("after stash calling sbwakeup\n"); 399: ENDDEBUG 400: } 401: break; 402: case 0x1a: 403: { 404: tp0_stash(p, e); 405: sbwakeup( &p->tp_sock->so_rcv ); 406: 407: IFDEBUG(D_DATA) 408: printf("after stash calling sbwakeup\n"); 409: ENDDEBUG 410: } 411: break; 412: case 0x1b: 413: { 414: int doack; /* tells if we must ack immediately */ 415: 416: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 417: sbwakeup( &p->tp_sock->so_rcv ); 418: 419: doack = tp_stash(p, e); 420: IFDEBUG(D_DATA) 421: printf("tp_stash returns %d\n",doack); 422: ENDDEBUG 423: 424: if(doack) 425: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL ); 426: else 427: tp_ctimeout_MIN( p->tp_refp, TM_sendack, (int)p->tp_sendack_ticks); 428: 429: IFDEBUG(D_DATA) 430: printf("after stash calling sbwakeup\n"); 431: ENDDEBUG 432: } 433: break; 434: case 0x1c: 435: { 436: IFTRACE(D_DATA) 437: tptrace(TPPTmisc, "NIW seq rcvnxt lcredit ", 438: e->ev_union.EV_DT_TPDU.e_seq, p->tp_rcvnxt, p->tp_lcredit, 0); 439: ENDTRACE 440: IncStat(ts_dt_niw); 441: m_freem(e->ev_union.EV_DT_TPDU.e_data); 442: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 443: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL ); 444: } 445: break; 446: case 0x1d: 447: { 448: if (p->tp_ucddata) { 449: m_freem(p->tp_ucddata); 450: p->tp_ucddata = 0; 451: } 452: (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); 453: tp_cuntimeout(p->tp_refp, TM_retrans); 454: 455: tp_getoptions(p); 456: soisconnected(p->tp_sock); 457: IFTRACE(D_CONN) 458: struct socket *so = p->tp_sock; 459: tptrace(TPPTmisc, 460: "called sosiconn: so so_state rcv.sb_sel rcv.sb_flags", 461: so, so->so_state, so->so_rcv.sb_sel, so->so_rcv.sb_flags); 462: tptrace(TPPTmisc, 463: "called sosiconn 2: so_qlen so_error so_rcv.sb_cc so_head", 464: so->so_qlen, so->so_error, so->so_rcv.sb_cc, so->so_head); 465: ENDTRACE 466: 467: tp_ctimeout(p->tp_refp, TM_sendack, (int)p->tp_keepalive_ticks); 468: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 469: } 470: break; 471: case 0x1e: 472: { 473: if( p->tp_state == TP_AKWAIT ) { 474: if (p->tp_ucddata) { 475: m_freem(p->tp_ucddata); 476: p->tp_ucddata = 0; 477: } 478: tp_cuntimeout(p->tp_refp, TM_retrans); 479: tp_getoptions(p); 480: soisconnected(p->tp_sock); 481: tp_ctimeout(p->tp_refp, TM_sendack, (int)p->tp_keepalive_ticks); 482: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 483: } 484: IFTRACE(D_XPD) 485: tptrace(TPPTmisc, "XPD tpdu accepted Xrcvnxt, e_seq datalen m_len\n", 486: 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); 487: ENDTRACE 488: 489: p->tp_sock->so_state |= SS_RCVATMARK; 490: e->ev_union.EV_XPD_TPDU.e_data->m_flags |= M_EOR; 491: sbinsertoob(&p->tp_Xrcv, e->ev_union.EV_XPD_TPDU.e_data); 492: IFDEBUG(D_XPD) 493: dump_mbuf(e->ev_union.EV_XPD_TPDU.e_data, "XPD TPDU: tp_Xrcv"); 494: ENDDEBUG 495: tp_indicate(T_XDATA, p, 0); 496: sbwakeup( &p->tp_Xrcv ); 497: 498: (void) tp_emit(XAK_TPDU_type, p, p->tp_Xrcvnxt, 0, MNULL); 499: SEQ_INC(p, p->tp_Xrcvnxt); 500: } 501: break; 502: case 0x1f: 503: { 504: if( p->tp_Xrcv.sb_cc == 0 ) { 505: /* kludge for select(): */ 506: /* p->tp_sock->so_state &= ~SS_OOBAVAIL; */ 507: } 508: } 509: break; 510: case 0x20: 511: { 512: IFTRACE(D_XPD) 513: tptrace(TPPTmisc, "XPD tpdu niw (Xrcvnxt, e_seq) or not cdt (cc)\n", 514: p->tp_Xrcvnxt, e->ev_union.EV_XPD_TPDU.e_seq, p->tp_Xrcv.sb_cc , 0); 515: ENDTRACE 516: if( p->tp_Xrcvnxt != e->ev_union.EV_XPD_TPDU.e_seq ) 517: IncStat(ts_xpd_niw); 518: if( p->tp_Xrcv.sb_cc ) { 519: /* might as well kick 'em again */ 520: tp_indicate(T_XDATA, p, 0); 521: IncStat(ts_xpd_dup); 522: } 523: m_freem(e->ev_union.EV_XPD_TPDU.e_data); 524: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 525: /* don't send an xack because the xak gives "last one received", not 526: * "next one i expect" (dumb) 527: */ 528: } 529: break; 530: case 0x21: 531: { 532: struct socket *so = p->tp_sock; 533: 534: /* detach from parent socket so it can finish closing */ 535: if (so->so_head) { 536: if (!soqremque(so, 0) && !soqremque(so, 1)) 537: panic("tp: T_DETACH"); 538: so->so_head = 0; 539: } 540: tp_soisdisconnecting(p->tp_sock); 541: tp_netcmd( p, CONN_CLOSE); 542: tp_soisdisconnected(p); 543: } 544: break; 545: case 0x22: 546: { 547: struct socket *so = p->tp_sock; 548: struct mbuf *data = MNULL; 549: 550: /* detach from parent socket so it can finish closing */ 551: if (so->so_head) { 552: if (!soqremque(so, 0) && !soqremque(so, 1)) 553: panic("tp: T_DETACH"); 554: so->so_head = 0; 555: } 556: if (p->tp_state != TP_CLOSING) { 557: tp_soisdisconnecting(p->tp_sock); 558: data = MCPY(p->tp_ucddata, M_NOWAIT); 559: (void) tp_emit(DR_TPDU_type, p, 0, E_TP_NORMAL_DISC, data); 560: p->tp_retrans = p->tp_Nretrans; 561: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); 562: } 563: } 564: break; 565: case 0x23: 566: { 567: tp_soisdisconnecting(p->tp_sock); 568: tp_netcmd( p, CONN_CLOSE); 569: tp_soisdisconnected(p); 570: } 571: break; 572: case 0x24: 573: { 574: struct mbuf *data = MCPY(p->tp_ucddata, M_WAIT); 575: 576: if(p->tp_state == TP_OPEN) { 577: tp_euntimeout(p->tp_refp, TM_data_retrans); /* all */ 578: tp_cuntimeout(p->tp_refp, TM_inact); 579: tp_cuntimeout(p->tp_refp, TM_sendack); 580: } 581: if (data) { 582: IFDEBUG(D_CONN) 583: printf("T_DISC_req.trans tp_ucddata 0x%x\n", 584: p->tp_ucddata); 585: dump_mbuf(data, "ucddata @ T_DISC_req"); 586: ENDDEBUG 587: } 588: tp_soisdisconnecting(p->tp_sock); 589: p->tp_retrans = p->tp_Nretrans; 590: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); 591: 592: if( trick_hc ) 593: return tp_emit(DR_TPDU_type, p, 0, e->ev_union.EV_T_DISC_req.e_reason, data); 594: } 595: break; 596: case 0x25: 597: { 598: int error; 599: struct mbuf *data = MCPY(p->tp_ucddata, M_WAIT); 600: 601: IncStat(ts_retrans_cc); 602: p->tp_retrans --; 603: p->tp_cong_win = 1; 604: p->tp_ackrcvd = 0; 605: 606: if( error = tp_emit(CC_TPDU_type, p, 0, 0, data) ) 607: p->tp_sock->so_error = error; 608: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_cc_ticks); 609: } 610: break; 611: case 0x26: 612: { 613: IncStat(ts_conn_gaveup); 614: tp_soisdisconnecting(p->tp_sock); 615: p->tp_sock->so_error = ETIMEDOUT; 616: tp_indicate(T_DISCONNECT, p, ETIMEDOUT); 617: (void) tp_emit(DR_TPDU_type, p, 0, E_TP_CONGEST, MNULL); 618: p->tp_retrans = p->tp_Nretrans; 619: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); 620: } 621: break; 622: case 0x27: 623: { 624: tp_euntimeout(p->tp_refp, TM_data_retrans); /* all */ 625: tp_cuntimeout(p->tp_refp, TM_inact); 626: tp_cuntimeout(p->tp_refp, TM_sendack); 627: 628: IncStat(ts_conn_gaveup); 629: tp_soisdisconnecting(p->tp_sock); 630: p->tp_sock->so_error = ETIMEDOUT; 631: tp_indicate(T_DISCONNECT, p, ETIMEDOUT); 632: (void) tp_emit(DR_TPDU_type, p, 0, E_TP_CONGEST_2, MNULL); 633: p->tp_retrans = p->tp_Nretrans; 634: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); 635: } 636: break; 637: case 0x28: 638: { 639: p->tp_cong_win = 1; 640: p->tp_ackrcvd = 0; 641: /* resume XPD */ 642: if ( p->tp_Xsnd.sb_mb ) { 643: struct mbuf *m = m_copy(p->tp_Xsnd.sb_mb, 0, (int)p->tp_Xsnd.sb_cc); 644: /* m_copy doesn't preserve the m_xlink field, but at this pt. 645: * that doesn't matter 646: */ 647: 648: IFTRACE(D_XPD) 649: tptrace(TPPTmisc, "XPD retrans: Xuna Xsndnxt sndhiwat snduna", 650: p->tp_Xuna, p->tp_Xsndnxt, p->tp_sndhiwat, 651: p->tp_snduna); 652: ENDTRACE 653: IFDEBUG(D_XPD) 654: dump_mbuf(m, "XPD retrans emitting M"); 655: ENDDEBUG 656: IncStat(ts_retrans_xpd); 657: p->tp_retrans --; 658: (void) tp_emit(XPD_TPDU_type, p, p->tp_Xuna, 1, m); 659: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_xpd_ticks); 660: } 661: } 662: break; 663: case 0x29: 664: { 665: register SeqNum low, lowsave = 0; 666: register struct tp_rtc *r = p->tp_snduna_rtc; 667: register struct mbuf *m; 668: register SeqNum high = e->ev_union.EV_TM_data_retrans.e_high; 669: 670: low = p->tp_snduna; 671: lowsave = high = low; 672: 673: tp_euntimeout_lss(p->tp_refp, TM_data_retrans, 674: SEQ_ADD(p, p->tp_sndhiwat, 1)); 675: p->tp_retrans_hiwat = p->tp_sndhiwat; 676: 677: if ((p->tp_rx_strat & TPRX_EACH) == 0) 678: high = (high>low)?low:high; 679: 680: if( p->tp_rx_strat & TPRX_USE_CW ) { 681: register int i; 682: 683: p->tp_cong_win = 1; 684: p->tp_ackrcvd = 0; 685: i = SEQ_ADD(p, low, p->tp_cong_win); 686: 687: high = SEQ_MIN(p, high, p->tp_sndhiwat); 688: 689: } 690: 691: while( SEQ_LEQ(p, low, high) ){ 692: if ( r == (struct tp_rtc *)0 ){ 693: IFDEBUG(D_RTC) 694: printf( "tp: retrans rtc list is GONE!\n"); 695: ENDDEBUG 696: break; 697: } 698: if ( r->tprt_seq == low ){ 699: if(( m = m_copy(r->tprt_data, 0, r->tprt_octets ))== MNULL) 700: break; 701: (void) tp_emit(DT_TPDU_type, p, low, r->tprt_eot, m); 702: IncStat(ts_retrans_dt); 703: SEQ_INC(p, low ); 704: } 705: r = r->tprt_next; 706: } 707: /* CE_BIT 708: if ( SEQ_LEQ(p, lowsave, high) ){ 709: */ 710: e->ev_union.EV_TM_data_retrans.e_retrans --; 711: tp_etimeout(p->tp_refp, TM_data_retrans, (caddr_t)lowsave, 712: (caddr_t)high, e->ev_union.EV_TM_data_retrans.e_retrans, 713: (p->tp_Nretrans - e->ev_union.EV_TM_data_retrans.e_retrans) * (int)p->tp_dt_ticks); 714: /* CE_BIT 715: } 716: */ 717: } 718: break; 719: case 0x2a: 720: { 721: p->tp_retrans --; 722: (void) tp_emit(DR_TPDU_type, p, 0, E_TP_DR_NO_REAS, MNULL); 723: IncStat(ts_retrans_dr); 724: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); 725: } 726: break; 727: case 0x2b: 728: { 729: p->tp_sock->so_error = ETIMEDOUT; 730: p->tp_refp->tpr_state = REF_FROZEN; 731: tp_recycle_tsuffix( p ); 732: tp_etimeout(p->tp_refp, TM_reference, 0,0,0, (int)p->tp_refer_ticks); 733: } 734: break; 735: case 0x2c: 736: { 737: tp_freeref(p->tp_refp); 738: tp_detach(p); 739: } 740: break; 741: case 0x2d: 742: { 743: if( p->tp_class != TP_CLASS_0) { 744: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 745: if ( e->ev_number == CC_TPDU ) 746: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL); 747: } 748: /* ignore it if class 0 - state tables are blank for this */ 749: } 750: break; 751: case 0x2e: 752: { 753: IFTRACE(D_DATA) 754: tptrace(TPPTmisc, "T_DATA_req sndhiwat snduna fcredit, tpcb", 755: p->tp_sndhiwat, p->tp_snduna, p->tp_fcredit, p); 756: ENDTRACE 757: 758: tp_send(p); 759: } 760: break; 761: case 0x2f: 762: { 763: int error = 0; 764: 765: /* resume XPD */ 766: if ( p->tp_Xsnd.sb_mb ) { 767: struct mbuf *m = m_copy(p->tp_Xsnd.sb_mb, 0, (int)p->tp_Xsnd.sb_cc); 768: /* m_copy doesn't preserve the m_xlink field, but at this pt. 769: * that doesn't matter 770: */ 771: 772: IFTRACE(D_XPD) 773: tptrace(TPPTmisc, "XPD req: Xuna Xsndnxt sndhiwat snduna", 774: p->tp_Xuna, p->tp_Xsndnxt, p->tp_sndhiwat, 775: p->tp_snduna); 776: ENDTRACE 777: IFDEBUG(D_XPD) 778: printf("T_XPD_req: sb_cc 0x%x\n", p->tp_Xsnd.sb_cc); 779: dump_mbuf(m, "XPD req emitting M"); 780: ENDDEBUG 781: error = 782: tp_emit(XPD_TPDU_type, p, p->tp_Xuna, 1, m); 783: p->tp_retrans = p->tp_Nretrans; 784: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_xpd_ticks); 785: SEQ_INC(p, p->tp_Xsndnxt); 786: } 787: if(trick_hc) 788: return error; 789: } 790: break; 791: case 0x30: 792: { 793: IFDEBUG(D_ACKRECV) 794: printf("GOOD ACK seq 0x%x cdt 0x%x\n", e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.e_cdt); 795: ENDDEBUG 796: if( p->tp_class != TP_CLASS_0) { 797: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 798: tp_euntimeout_lss(p->tp_refp, TM_data_retrans, e->ev_union.EV_AK_TPDU.e_seq); 799: } 800: sbwakeup( &p->tp_sock->so_snd ); 801: 802: if (p->tp_sndhiwat <= p->tp_retrans_hiwat && 803: p->tp_snduna <= p->tp_retrans_hiwat) { 804: 805: register struct mbuf *m; 806: /* extern struct mbuf *m_copy(); */ 807: register struct tp_rtc *r; 808: SeqNum high, retrans, low_save; 809: 810: high = SEQ_MIN(p, SEQ_ADD(p, p->tp_snduna, 811: MIN(p->tp_cong_win, p->tp_fcredit)) - 1, 812: p->tp_sndhiwat); 813: low_save = retrans = SEQ_MAX(p, SEQ_ADD(p, p->tp_last_retrans, 1), 814: p->tp_snduna); 815: for (; SEQ_LEQ(p, retrans, high); SEQ_INC(p, retrans)) { 816: 817: for (r = p->tp_snduna_rtc; r; r = r->tprt_next){ 818: if ( r->tprt_seq == retrans ){ 819: if(( m = m_copy(r->tprt_data, 0, r->tprt_octets )) 820: == MNULL) 821: break; 822: (void) tp_emit(DT_TPDU_type, p, retrans, 823: r->tprt_eot, m); 824: p->tp_last_retrans = retrans; 825: IncStat(ts_retrans_dt); 826: break; 827: } 828: } 829: if ( r == (struct tp_rtc *)0 ){ 830: IFDEBUG(D_RTC) 831: printf( "tp: retrans rtc list is GONE!\n"); 832: ENDDEBUG 833: break; 834: } 835: } 836: tp_etimeout(p->tp_refp, TM_data_retrans, (caddr_t)low_save, 837: (caddr_t)high, p->tp_retrans, (int)p->tp_dt_ticks); 838: if (SEQ_DEC(p, retrans) == p->tp_retrans_hiwat) 839: tp_send(p); 840: } 841: else { 842: tp_send(p); 843: } 844: IFDEBUG(D_ACKRECV) 845: printf("GOOD ACK new sndhiwat 0x%x\n", p->tp_sndhiwat); 846: ENDDEBUG 847: } 848: break; 849: case 0x31: 850: { 851: IFTRACE(D_ACKRECV) 852: tptrace(TPPTmisc, "BOGUS ACK fcc_present, tp_r_subseq e_subseq", 853: e->ev_union.EV_AK_TPDU.e_fcc_present, p->tp_r_subseq, e->ev_union.EV_AK_TPDU.e_subseq, 0); 854: ENDTRACE 855: if( p->tp_class != TP_CLASS_0 ) { 856: 857: if ( !e->ev_union.EV_AK_TPDU.e_fcc_present ) { 858: /* send ACK with FCC */ 859: IncStat( ts_ackreason[_ACK_FCC_] ); 860: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 1, MNULL); 861: } 862: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 863: } 864: } 865: break; 866: case 0x32: 867: { 868: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 869: tp_cuntimeout(p->tp_refp, TM_retrans); 870: 871: sbwakeup( &p->tp_sock->so_snd ); 872: 873: /* resume normal data */ 874: tp_send(p); 875: } 876: break; 877: case 0x33: 878: { 879: IFTRACE(D_ACKRECV) 880: tptrace(TPPTmisc, "BOGUS XACK eventtype ", e->ev_number, 0, 0,0); 881: ENDTRACE 882: if( p->tp_class != TP_CLASS_0 ) { 883: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 884: } 885: } 886: break; 887: case 0x34: 888: { 889: IFTRACE(D_TIMER) 890: tptrace(TPPTsendack, -1, p->tp_lcredit, p->tp_sent_uwe, 891: p->tp_sent_lcdt, 0); 892: ENDTRACE 893: IncPStat(p, tps_n_TMsendack); 894: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL); 895: } 896: break; 897: case 0x35: 898: { 899: if (sbspace(&p->tp_sock->so_rcv) > 0) 900: tp0_openflow(p); 901: } 902: break; 903: case 0x36: 904: { 905: if( trick_hc ) { 906: IncStat(ts_ackreason[_ACK_USRRCV_]); 907: 908: /* send an ACK only if there's new information */ 909: LOCAL_CREDIT( p ); 910: if ((p->tp_rcvnxt != p->tp_sent_rcvnxt) || 911: (p->tp_lcredit != p->tp_sent_lcdt)) 912: 913: return tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL); 914: } 915: } 916: break; 917: case 0x37: 918: { 919: if(trick_hc) 920: return ECONNABORTED; 921: } 922: break; 923: case 0x38: 924: { 925: ASSERT( p->tp_state != TP_LISTENING ); 926: tp_indicate(T_DISCONNECT, p, ECONNRESET); 927: tp_soisdisconnected(p); 928: } 929: break; 930: } 931: return 0; 932: } 933: 934: _XEBEC_PG int 935: _Xebec_index( e,p ) 936: struct tp_event *e; 937: tp_PCB_ *p; 938: { 939: switch( (e->ev_number<<4)+(p->tp_state) ) { 940: case 0x12: 941: if ( p->tp_retrans > 0 ) return 0x1e; 942: else return 0x1f; 943: case 0x13: 944: if ( p->tp_retrans > 0 ) return 0x2f; 945: else return 0x30; 946: case 0x14: 947: if ( p->tp_retrans > 0 ) return 0x32; 948: else return 0x31; 949: case 0x15: 950: if ( p->tp_retrans > 0 ) return 0x34; 951: else return 0x35; 952: case 0x54: 953: if ( e->ev_union.EV_TM_data_retrans.e_retrans > 0 ) return 0x33; 954: else return 0x31; 955: case 0x64: 956: if (p->tp_class == TP_CLASS_0) return 0x1a; 957: else return 0x1b; 958: case 0x77: 959: if ( p->tp_class == TP_CLASS_0) return 0xd; 960: else return 0xe; 961: case 0x86: 962: if ( e->ev_union.EV_DR_TPDU.e_sref != 0 ) return 0x2; 963: else return 0x3; 964: case 0xa2: 965: if (p->tp_class == TP_CLASS_0) return 0x1c; 966: else return 0x1d; 967: case 0xb2: 968: if (p->tp_class == TP_CLASS_0) return 0x5; 969: else return 0x0; 970: case 0xb4: 971: if ( 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) ) return 0x3a; 972: else return 0x3b; 973: case 0xc3: 974: if ( IN_RWINDOW( p, e->ev_union.EV_DT_TPDU.e_seq, 975: p->tp_rcvnxt, SEQ(p, p->tp_rcvnxt + p->tp_lcredit)) ) return 0x21; 976: else return 0x24; 977: case 0xc4: 978: if ( p->tp_class == TP_CLASS_0 ) return 0x22; 979: else if ( IN_RWINDOW( p, e->ev_union.EV_DT_TPDU.e_seq, 980: p->tp_rcvnxt, SEQ(p, p->tp_rcvnxt + p->tp_lcredit)) ) return 0x23; 981: else return 0x25; 982: case 0xd3: 983: if (p->tp_Xrcvnxt == e->ev_union.EV_XPD_TPDU.e_seq) return 0x27; 984: else return 0x2a; 985: case 0xd4: 986: if (p->tp_Xrcvnxt == e->ev_union.EV_XPD_TPDU.e_seq) return 0x27; 987: else return 0x29; 988: case 0xe4: 989: if ( tp_goodXack(p, e->ev_union.EV_XAK_TPDU.e_seq) ) return 0x3c; 990: else return 0x3d; 991: case 0x102: 992: if ( p->tp_class == TP_CLASS_0 ) return 0x2d; 993: else return 0x2e; 994: case 0x104: 995: if ( p->tp_class == TP_CLASS_0 ) return 0x2d; 996: else return 0x2e; 997: case 0x144: 998: if (p->tp_class == TP_CLASS_0) return 0x3f; 999: else return 0x40; 1000: case 0x162: 1001: if (p->tp_class == TP_CLASS_0) return 0x2b; 1002: else return 0x2c; 1003: case 0x172: 1004: if ( p->tp_class != TP_CLASS_4 ) return 0x42; 1005: else return 0x46; 1006: case 0x174: 1007: if ( p->tp_class != TP_CLASS_4 ) return 0x42; 1008: else return 0x47; 1009: case 0x177: 1010: if ( p->tp_class != TP_CLASS_4 ) return 0x42; 1011: else return 0x43; 1012: case 0x188: 1013: if ( p->tp_class == TP_CLASS_0 ) return 0xf; 1014: else if (tp_emit(CC_TPDU_type, p, 0,0, MCPY(p->tp_ucddata, M_NOWAIT)) == 0) return 0x10; 1015: else return 0x11; 1016: default: return 0; 1017: } /* end switch */ 1018: } /* _Xebec_index() */ 1019: static int inx[26][9] = { {0,0,0,0,0,0,0,0,0,}, 1020: {0x0,0x0,0x0,0x0,0x31,0x0,0x0,0x0,0x0, }, 1021: {0x0,0x0,-1,-1,-1,-1,0x0,0x0,0x0, }, 1022: {0x0,0x0,0x0,0x0,0x3e,0x0,0x0,0x0,0x0, }, 1023: {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, }, 1024: {0x0,0x0,0x0,0x0,0x0,0x0,0x36,0x0,0x0, }, 1025: {0x0,0x0,0x0,0x0,-1,0x0,0x0,0x0,0x0, }, 1026: {0x0,0x7,0x15,0x1b,-1,0x17,0x3,0xa,0x0, }, 1027: {0x0,0x19,0x6,0x20,0x37,0x8,0x3,-1,0x0, }, 1028: {0x0,0x14,0x13,0x13,0x13,0x16,-1,0xa,0x0, }, 1029: {0x0,0x7,0x6,0x1,0x9,0x18,0x3,0xa,0x0, }, 1030: {0x0,0x19,-1,0x1,0x37,0x8,0x3,0xa,0x0, }, 1031: {0x0,0x7,-1,0x26,-1,0x8,0x3,0xa,0x0, }, 1032: {0x0,0x7,0x6,-1,-1,0x8,0x3,0xa,0x0, }, 1033: {0x0,0x7,0x6,-1,-1,0x8,0x3,0xa,0x0, }, 1034: {0x0,0x7,0x6,0x1,-1,0x8,0x3,0xa,0x0, }, 1035: {0x0,0x12,0x0,0x0,0x0,0x0,0x0,0x0,0x0, }, 1036: {0x0,0x0,-1,0x2e,-1,0x0,0x4,0x0,0x2e, }, 1037: {0x0,0xb,0x0,0x0,0x0,0x0,0x0,0x0,0x0, }, 1038: {0x0,0x0,0x0,0x0,0x38,0x0,0x0,0x0,0x0, }, 1039: {0x0,0x0,0x0,0x0,0x39,0x0,0x0,0x0,0x0, }, 1040: {0x0,0x0,0x0,0x0,-1,0x0,0x41,0x0,0x0, }, 1041: {0x0,0x0,0x0,0x0,0x28,0x0,0x41,0x0,0x0, }, 1042: {0x0,0xc,-1,0x2c,0x0,0x2c,0x4,0xc,0x2c, }, 1043: {0x0,0x49,-1,0x45,-1,0x44,0x48,-1,0x0, }, 1044: {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,-1, }, 1045: }; 1046: tp_driver(p, e) 1047: register tp_PCB_ *p; 1048: register struct tp_event *e; 1049: { 1050: register int index, error=0; 1051: struct act_ent *a; 1052: static struct act_ent erroraction = {0,-1}; 1053: 1054: index = inx[1 + e->ev_number][p->tp_state]; 1055: if(index<0) index=_Xebec_index(e, p); 1056: if (index==0) { 1057: a = &erroraction; 1058: } else 1059: a = &statetable[index]; 1060: 1061: if(a->a_action) 1062: error = _Xebec_action( a->a_action, e, p ); 1063: IFTRACE(D_DRIVER) 1064: tptrace(DRIVERTRACE, a->a_newstate, p->tp_state, e->ev_number, a->a_action, 0); 1065: 1066: ENDTRACE 1067: if(error==0) 1068: p->tp_state = a->a_newstate; 1069: return error; 1070: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.