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