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