Annotation of 43BSDReno/sys/netiso/tp.trans, revision 1.1.1.1

1.1       root        1: /***********************************************************
                      2:                Copyright IBM Corporation 1987
                      3: 
                      4:                       All Rights Reserved
                      5: 
                      6: Permission to use, copy, modify, and distribute this software and its 
                      7: documentation for any purpose and without fee is hereby granted, 
                      8: provided that the above copyright notice appear in all copies and that
                      9: both that copyright notice and this permission notice appear in 
                     10: supporting documentation, and that the name of IBM not be
                     11: used in advertising or publicity pertaining to distribution of the
                     12: software without specific, written prior permission.  
                     13: 
                     14: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
                     15: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
                     16: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
                     17: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
                     18: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
                     19: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
                     20: SOFTWARE.
                     21: 
                     22: ******************************************************************/
                     23: 
                     24: /*
                     25:  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
                     26:  */
                     27: /* $Header: tp.trans,v 5.1 88/10/12 12:22:07 root Exp $
                     28:  *
                     29:  * Transition file for TP.
                     30:  *
                     31:  * DO NOT:
                     32:  * - change the order of any of the events or states.  to do so will
                     33:  *   make tppt, netstat, etc. cease working.
                     34:  *
                     35:  * NOTE:
                     36:  * some hooks exist for data on (dis)connect, but it's ***NOT***SUPPORTED***
                     37:  * (read: may not work!)
                     38:  *
                     39:  * I tried to put everything that causes a change of state in here, hence 
                     40:  * there are some seemingly trivial events  like T_DETACH and T_LISTEN_req.
                     41:  *
                     42:  * Almost everything having to do w/ setting & cancelling timers is here
                     43:  * but once it was debugged, I moved the setting of the 
                     44:  * keepalive (sendack) timer to tp_emit(), where an AK_TPDU is sent.
                     45:  * This is so the code wouldn't be duplicated all over creation in here.
                     46:  *
                     47:  */
                     48: *PROTOCOL tp
                     49: 
                     50: *INCLUDE
                     51: 
                     52: {
                     53: /*     @(#)tp.trans    7.5 (Berkeley) 6/6/90 */
                     54: #include "param.h"
                     55: #include "socket.h"
                     56: #include "socketvar.h"
                     57: #include "protosw.h"
                     58: #include "mbuf.h"
                     59: #include "time.h"
                     60: #include "errno.h"
                     61: #include "../netiso/tp_param.h"
                     62: #include "../netiso/tp_stat.h"
                     63: #include "../netiso/tp_pcb.h"
                     64: #include "../netiso/tp_tpdu.h"
                     65: #include "../netiso/argo_debug.h"
                     66: #include "../netiso/tp_trace.h"
                     67: #include "../netiso/iso_errno.h"
                     68: #include "../netiso/tp_seq.h"
                     69: #include "../netiso/cons.h"
                     70: 
                     71: #define DRIVERTRACE TPPTdriver
                     72: #define sbwakeup(sb)   sowakeup(p->tp_sock, sb);
                     73: #define MCPY(d, w) (d ? m_copym(d, 0, (int)M_COPYALL, w): 0)
                     74: 
                     75: static         trick_hc = 1;
                     76: 
                     77: int    tp_emit(),
                     78:                tp_goodack(),                           tp_goodXack(),
                     79:                tp_stash()
                     80: ;
                     81: void   tp_indicate(),                          tp_getoptions(),        
                     82:                tp_soisdisconnecting(),         tp_soisdisconnected(),
                     83:                tp_recycle_tsuffix(),           
                     84:                tp_etimeout(),                          tp_euntimeout(),
                     85:                tp_euntimeout_lss(),            tp_ctimeout(),
                     86:                tp_cuntimeout(),                        tp_ctimeout_MIN(),
                     87:                tp_freeref(),                           tp_detach(),
                     88:                tp0_stash(),                            tp0_send(),
                     89:                tp_netcmd(),                            tp_send()
                     90: ;
                     91: 
                     92: typedef  struct tp_pcb tpcb_struct;
                     93: 
                     94: 
                     95: }
                     96: 
                     97: *PCB    tpcb_struct    SYNONYM  P
                     98: 
                     99: *STATES
                    100: 
                    101: TP_CLOSED      
                    102: TP_CRSENT
                    103: TP_AKWAIT
                    104: TP_OPEN
                    105: TP_CLOSING 
                    106: TP_REFWAIT
                    107: TP_LISTENING   /* Local to this implementation */
                    108: TP_CONFIRMING  /* Local to this implementation */
                    109: 
                    110: *EVENTS                { struct timeval e_time; }              SYNONYM  E
                    111: 
                    112:  /*
                    113:   * C (typically cancelled) timers  - 
                    114:   *
                    115:   * let these be the first ones so for the sake of convenience
                    116:   * their values are 0--> n-1
                    117:   * DO NOT CHANGE THE ORDER OF THESE TIMER EVENTS!! 
                    118:   */
                    119:  TM_inact              
                    120:  TM_retrans            
                    121:                                /* TM_retrans is used for all 
                    122:                                 * simple retransmissions - CR,CC,XPD,DR 
                    123:                                 */
                    124: 
                    125:  TM_sendack            
                    126:                                /* TM_sendack does dual duty - keepalive AND sendack.
                    127:                                 * It's set w/ keepalive-ticks every time an ack is sent.
                    128:                                 * (this is done in (void) tp_emit() ).
                    129:                                 * It's cancelled and reset whenever a DT
                    130:                                 * arrives and it doesn't require immediate acking.
                    131:                                 * Note that in this case it's set w/ the minimum of
                    132:                                 * its prev value and the sendack-ticks value so the 
                    133:                                 * purpose of the keepalive is preserved.
                    134:                                 */
                    135:  TM_notused    
                    136: 
                    137:  /* 
                    138:   * E (typically expired) timers - these may be in any order. 
                    139:   * These cause procedures to be executed directly; may not
                    140:   * cause an 'event' as we know them here.
                    141:   */
                    142:  TM_reference          { SeqNum e_low; SeqNum e_high; int e_retrans; }
                    143:  TM_data_retrans       { SeqNum e_low; SeqNum e_high; int e_retrans; }
                    144: 
                    145: /* NOTE: in tp_input is a minor optimization that assumes that
                    146:  * for all tpdu types that can take e_data and e_datalen, these
                    147:  * fields fall in the same place in the event structure, that is,
                    148:  * e_data is the first field and e_datalen is the 2nd field.
                    149:  */
                    150: 
                    151:  ER_TPDU               {
                    152:                                  u_char                e_reason;
                    153:                                }
                    154:  CR_TPDU               { struct mbuf   *e_data;        /* first field */
                    155:                                  int                   e_datalen; /* 2nd field */
                    156:                                  u_int                 e_cdt;
                    157:                                }
                    158:  DR_TPDU               { struct mbuf   *e_data;        /* first field */
                    159:                                  int                   e_datalen; /* 2nd field */
                    160:                                  u_short               e_sref;
                    161:                                  u_char                e_reason;
                    162:                                }
                    163:  DC_TPDU               
                    164:  CC_TPDU               { struct mbuf   *e_data;        /* first field */
                    165:                                  int                   e_datalen; /* 2nd field */
                    166:                                  u_short               e_sref;
                    167:                                  u_int                 e_cdt;
                    168:                                }
                    169:  AK_TPDU               { u_int                 e_cdt;  
                    170:                                  SeqNum                e_seq;          
                    171:                                  SeqNum                e_subseq;               
                    172:                                  u_char                e_fcc_present;          
                    173:                                }
                    174:  DT_TPDU               { struct mbuf   *e_data;        /* first field */
                    175:                                  int                   e_datalen; /* 2nd field */
                    176:                                  u_int                 e_eot;
                    177:                                  SeqNum                e_seq; 
                    178:                                }
                    179:  XPD_TPDU              { struct mbuf   *e_data;        /* first field */
                    180:                                  int                   e_datalen;      /* 2nd field */
                    181:                                  SeqNum                e_seq;  
                    182:                                }
                    183:  XAK_TPDU              { SeqNum                e_seq;          }
                    184: 
                    185:  T_CONN_req 
                    186:  T_DISC_req            { u_char                e_reason;       }
                    187:  T_LISTEN_req
                    188:  T_DATA_req
                    189:  T_XPD_req     
                    190:  T_USR_rcvd    
                    191:  T_USR_Xrcvd   
                    192:  T_DETACH
                    193:  T_NETRESET
                    194:  T_ACPT_req
                    195: 
                    196: 
                    197: *TRANSITIONS
                    198: 
                    199: 
                    200: /* TP_AKWAIT doesn't exist in TP 0 */
                    201: SAME                   <==                     TP_AKWAIT                       [ CC_TPDU, DC_TPDU, XAK_TPDU ]
                    202:        DEFAULT
                    203:        NULLACTION
                    204: ;
                    205: 
                    206: 
                    207: /* applicable in TP4, TP0 */
                    208: SAME                   <==                     TP_REFWAIT                                                              DR_TPDU
                    209:        ( $$.e_sref !=  0 ) 
                    210:        {
                    211:                (void) tp_emit(DC_TPDU_type, $P, 0, 0, MNULL);
                    212:        }
                    213: ;
                    214:        
                    215: /* applicable in TP4, TP0 */
                    216: SAME                   <==                     TP_REFWAIT                      [ CR_TPDU, CC_TPDU, DT_TPDU, 
                    217:                                        DR_TPDU, XPD_TPDU, AK_TPDU, XAK_TPDU, DC_TPDU, ER_TPDU ]
                    218:        DEFAULT
                    219:        {
                    220: #              ifdef TP_DEBUG
                    221:                if( $E.ev_number != AK_TPDU )
                    222:                        printf("TPDU 0x%x in REFWAIT!!!!\n", $E.ev_number);
                    223: #              endif TP_DEBUG
                    224:        }
                    225: ;
                    226: 
                    227: /* applicable in TP4, TP0 */
                    228: SAME                   <==                     TP_REFWAIT                              [ T_DETACH, T_DISC_req ]
                    229:        DEFAULT
                    230:        NULLACTION
                    231: ;
                    232: 
                    233: /* applicable in TP4, TP0 */
                    234: SAME                   <==                     TP_CRSENT                                                                AK_TPDU
                    235:        ($P.tp_class == TP_CLASS_0)
                    236:        {
                    237:                /* oh, man is this grotesque or what? */
                    238:                (void) tp_goodack($P, $$.e_cdt, $$.e_seq,  $$.e_subseq);
                    239:                /* but it's necessary because this pseudo-ack may happen
                    240:                 * before the CC arrives, but we HAVE to adjust the
                    241:                 * snduna as a result of the ack, WHENEVER it arrives
                    242:                 */
                    243:        }
                    244: ;
                    245: 
                    246: /* applicable in TP4, TP0 */
                    247: SAME                   <==                     TP_CRSENT       
                    248:                                        [ CR_TPDU, DC_TPDU, DT_TPDU, XPD_TPDU,  XAK_TPDU ]
                    249:        DEFAULT
                    250:        NULLACTION
                    251: ;
                    252: 
                    253: /* applicable in TP4, TP0 */
                    254: SAME                   <==                     TP_CLOSED                                       [ DT_TPDU, XPD_TPDU,
                    255:                                                                                ER_TPDU, DC_TPDU, AK_TPDU, XAK_TPDU ] 
                    256:        DEFAULT
                    257:        NULLACTION
                    258: ;
                    259: 
                    260: /* TP_CLOSING doesn't exist in TP 0 */
                    261: SAME                   <==             TP_CLOSING
                    262:                                        [ CC_TPDU, CR_TPDU, DT_TPDU, XPD_TPDU, AK_TPDU, XAK_TPDU ]
                    263:        DEFAULT
                    264:        NULLACTION
                    265: ;
                    266: 
                    267: 
                    268: /* DC_TPDU doesn't exist in TP 0 */
                    269: SAME                   <==                     TP_OPEN                                           DC_TPDU
                    270:        DEFAULT
                    271:        NULLACTION
                    272: ;
                    273: 
                    274: /* applicable in TP4, TP0 */
                    275: SAME                   <==                     TP_LISTENING  [DR_TPDU, CC_TPDU, DT_TPDU, XPD_TPDU,
                    276:                                                                                 ER_TPDU, DC_TPDU, AK_TPDU, XAK_TPDU ] 
                    277:        DEFAULT 
                    278:        NULLACTION
                    279: ;
                    280: 
                    281: /* applicable in TP4, TP0 */
                    282: TP_LISTENING   <==                     TP_CLOSED                                                       T_LISTEN_req 
                    283:        DEFAULT
                    284:        NULLACTION
                    285: ;
                    286: 
                    287: /* applicable in TP4, TP0 */
                    288: TP_CLOSED              <==             [ TP_LISTENING, TP_CLOSED ]                     T_DETACH
                    289:        DEFAULT
                    290:        {
                    291:                tp_detach($P);
                    292:        }
                    293: ;
                    294: 
                    295: TP_CONFIRMING  <==              TP_LISTENING                                                           CR_TPDU 
                    296:        ( $P.tp_class == TP_CLASS_0)
                    297:        {
                    298:                $P.tp_refp->tpr_state = REF_OPEN; /* has timers ??? */
                    299:        }
                    300: ;
                    301: 
                    302: TP_CONFIRMING          <==              TP_LISTENING                                                   CR_TPDU 
                    303:        DEFAULT
                    304:        {
                    305:                IFTRACE(D_CONN)
                    306:                        tptrace(TPPTmisc, "CR datalen data", $$.e_datalen, $$.e_data,0,0);
                    307:                ENDTRACE
                    308:                IFDEBUG(D_CONN)
                    309:                        printf("CR datalen 0x%x data 0x%x", $$.e_datalen, $$.e_data);
                    310:                ENDDEBUG
                    311:                $P.tp_refp->tpr_state = REF_OPEN; /* has timers */
                    312:                $P.tp_fcredit = $$.e_cdt;
                    313: 
                    314:                if ($$.e_datalen > 0) {
                    315:                        /* n/a for class 0 */
                    316:                        ASSERT($P.tp_Xrcv.sb_cc == 0); 
                    317:                        sbappendrecord(&$P.tp_Xrcv, $$.e_data);
                    318:                        /*$P.tp_flags |= TPF_CONN_DATA_IN;*/
                    319:                        $$.e_data = MNULL; 
                    320:                } 
                    321:        }
                    322: ;
                    323: 
                    324: TP_OPEN                <==              TP_CONFIRMING                                                                  T_ACPT_req 
                    325:        ( $P.tp_class == TP_CLASS_0 )
                    326:        {
                    327:                IncStat(ts_tp0_conn);
                    328:                IFTRACE(D_CONN)
                    329:                        tptrace(TPPTmisc, "Confiming", $P, 0,0,0);
                    330:                ENDTRACE
                    331:                IFDEBUG(D_CONN)
                    332:                        printf("Confirming connection: $P" );
                    333:                ENDDEBUG
                    334:                soisconnected($P.tp_sock);
                    335:                (void) tp_emit(CC_TPDU_type, $P, 0,0, MNULL) ;
                    336:                $P.tp_fcredit = 1;
                    337:        }
                    338: ;
                    339: 
                    340: TP_AKWAIT              <==              TP_CONFIRMING                                                          T_ACPT_req
                    341:        (tp_emit(CC_TPDU_type, $P, 0,0, MCPY($P.tp_ucddata, M_NOWAIT)) == 0)
                    342:        {
                    343:                IncStat(ts_tp4_conn); /* even though not quite open */
                    344:                IFTRACE(D_CONN)
                    345:                        tptrace(TPPTmisc, "Confiming", $P, 0,0,0);
                    346:                ENDTRACE
                    347:                IFDEBUG(D_CONN)
                    348:                        printf("Confirming connection: $P" );
                    349:                ENDDEBUG
                    350:                soisconnecting($P.tp_sock);
                    351:                if($P.tp_rx_strat & TPRX_FASTSTART)
                    352:                        $P.tp_cong_win = $P.tp_fcredit;
                    353:                $P.tp_retrans = $P.tp_Nretrans;
                    354:                tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_cc_ticks);
                    355:        }
                    356: ;
                    357: 
                    358: /* TP4 only */
                    359: TP_CLOSED              <==              TP_CONFIRMING                                                          T_ACPT_req
                    360:        DEFAULT /* emit failed */
                    361:        {
                    362:                register struct tp_ref *r = $P.tp_refp;
                    363: 
                    364:                IFDEBUG(D_CONN)
                    365:                        printf("event: CR_TPDU emit CC failed done " );
                    366:                ENDDEBUG
                    367:                soisdisconnected($P.tp_sock);
                    368:                tp_recycle_tsuffix( $P );
                    369:                tp_freeref(r);
                    370:                tp_detach($P);
                    371:        }
                    372: ;
                    373: 
                    374: /* applicable in TP4, TP0 */
                    375: TP_CRSENT              <==             TP_CLOSED                                                               T_CONN_req 
                    376:        DEFAULT
                    377:        {
                    378:                int error;
                    379:                struct mbuf *data = MNULL;
                    380: 
                    381:                IFTRACE(D_CONN)
                    382:                        tptrace(TPPTmisc, "T_CONN_req flags ucddata", (int)$P.tp_flags,
                    383:                        $P.tp_ucddata, 0, 0);
                    384:                ENDTRACE
                    385:                data =  MCPY($P.tp_ucddata, M_WAIT);
                    386:                if (data) {
                    387:                        IFDEBUG(D_CONN)
                    388:                                printf("T_CONN_req.trans m_copy cc 0x%x\n", 
                    389:                                        $P.tp_ucddata);
                    390:                                dump_mbuf(data, "sosnd @ T_CONN_req");
                    391:                        ENDDEBUG
                    392:                }
                    393: 
                    394:                if (error = tp_emit(CR_TPDU_type, $P, 0, 0, data) )
                    395:                        return error; /* driver WON'T change state; will return error */
                    396:                
                    397:                $P.tp_refp->tpr_state = REF_OPEN; /* has timers */
                    398:                if($P.tp_class != TP_CLASS_0) {
                    399:                        $P.tp_retrans = $P.tp_Nretrans;
                    400:                        tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_cr_ticks);
                    401:                }
                    402:        }
                    403: ;
                    404: 
                    405: /* applicable in TP4, TP0, but state TP_AKWAIT doesn't apply to TP0 */
                    406: TP_REFWAIT             <==             [ TP_CRSENT, TP_AKWAIT, TP_OPEN ]                       DR_TPDU 
                    407:        DEFAULT
                    408:        {
                    409:                if ($$.e_datalen > 0 && $P.tp_class != TP_CLASS_0) {
                    410:                        /*sbdrop(&$P.tp_Xrcv, $P.tp_Xrcv.sb_cc); /* purge expedited data */
                    411:                        sbflush(&$P.tp_Xrcv);
                    412:                        $P.tp_flags |= TPF_DISC_DATA_IN;
                    413:                        sbappendrecord(&$P.tp_Xrcv, $$.e_data);
                    414:                        $$.e_data = MNULL;
                    415:                } 
                    416:                tp_indicate(T_DISCONNECT, $P, TP_ERROR_MASK | (u_short)$$.e_reason);
                    417:                tp_soisdisconnected($P);
                    418:                if ($P.tp_class != TP_CLASS_0) {
                    419:                        if ($P.tp_state == TP_OPEN ) {
                    420:                                tp_euntimeout($P.tp_refp, TM_data_retrans); /* all */
                    421:                                tp_cuntimeout($P.tp_refp, TM_retrans);
                    422:                                tp_cuntimeout($P.tp_refp, TM_inact);
                    423:                                tp_cuntimeout($P.tp_refp, TM_sendack);
                    424:                        }
                    425:                        tp_cuntimeout($P.tp_refp, TM_retrans);
                    426:                        if( $$.e_sref !=  0 ) 
                    427:                                (void) tp_emit(DC_TPDU_type, $P, 0, 0, MNULL);
                    428:                }
                    429:        }
                    430: ;
                    431: 
                    432: SAME                   <==             TP_CLOSED                                                                       DR_TPDU 
                    433:        DEFAULT
                    434:        {
                    435:                if( $$.e_sref != 0 )
                    436:                        (void) tp_emit(DC_TPDU_type, $P, 0, 0, MNULL); 
                    437:                /* reference timer already set - reset it to be safe (???) */
                    438:                tp_euntimeout($P.tp_refp, TM_reference); /* all */
                    439:                tp_etimeout($P.tp_refp, TM_reference, 0, 0, 0, (int)$P.tp_refer_ticks);
                    440:        }
                    441: ;
                    442: 
                    443: /* NBS(34) */
                    444: TP_REFWAIT             <==     TP_CRSENT                                                                       ER_TPDU
                    445:        DEFAULT
                    446:        {       
                    447:                tp_cuntimeout($P.tp_refp, TM_retrans);
                    448:                tp_indicate(T_DISCONNECT, $P, 
                    449:                        TP_ERROR_MASK |(u_short)($$.e_reason | 0x40));
                    450:                tp_soisdisconnected($P);
                    451:        }
                    452: ;
                    453: 
                    454: /* NBS(27) */
                    455: TP_REFWAIT             <==             TP_CLOSING                                                                      DR_TPDU
                    456:        DEFAULT
                    457:        {        
                    458:                $P.tp_sock->so_error = (u_short)$$.e_reason;
                    459:                tp_cuntimeout($P.tp_refp, TM_retrans);
                    460:                tp_soisdisconnected($P);
                    461:        }
                    462: ;
                    463: /* these two transitions are the same but can't be combined because xebec
                    464:  * can't handle the use of $$.e_reason if they're combined
                    465:  */
                    466: /* NBS(27) */
                    467: TP_REFWAIT             <==             TP_CLOSING                                                                      ER_TPDU
                    468:        DEFAULT
                    469:        {        
                    470:                $P.tp_sock->so_error = (u_short)$$.e_reason;
                    471:                tp_cuntimeout($P.tp_refp, TM_retrans);
                    472:                tp_soisdisconnected($P);
                    473:        }
                    474: ;
                    475: /* NBS(27) */
                    476: TP_REFWAIT             <==             TP_CLOSING                                                                      DC_TPDU 
                    477:        DEFAULT
                    478:        {        
                    479:                tp_cuntimeout($P.tp_refp, TM_retrans);
                    480:                tp_soisdisconnected($P);
                    481:        }
                    482: ;
                    483: 
                    484: /* NBS(21) */
                    485: SAME                   <==     TP_CLOSED                                               [ CC_TPDU, CR_TPDU ]
                    486:        DEFAULT
                    487:        {       /* don't ask me why we have to do this - spec says so */
                    488:                (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_NO_SESSION, MNULL);
                    489:                /* don't bother with retransmissions of the DR */
                    490:        }
                    491: ;
                    492: 
                    493: /* NBS(34) */
                    494: TP_REFWAIT             <==     TP_OPEN                                                                         ER_TPDU
                    495:        ($P.tp_class == TP_CLASS_0)
                    496:        {
                    497:                tp_soisdisconnecting($P.tp_sock);
                    498:                tp_indicate(T_DISCONNECT, $P, 
                    499:                        TP_ERROR_MASK |(u_short)($$.e_reason | 0x40));
                    500: 
                    501:                tp_soisdisconnected($P);
                    502:                tp_netcmd( $P, CONN_CLOSE );
                    503:        }
                    504: ;
                    505: 
                    506: TP_CLOSING             <==     [ TP_AKWAIT, TP_OPEN ]                                          ER_TPDU
                    507:        DEFAULT
                    508:        {
                    509:                if ($P.tp_state == TP_OPEN) {
                    510:                        tp_euntimeout($P.tp_refp, TM_data_retrans); /* all */
                    511:                        tp_cuntimeout($P.tp_refp, TM_inact);
                    512:                        tp_cuntimeout($P.tp_refp, TM_sendack);
                    513:                }
                    514:                tp_soisdisconnecting($P.tp_sock);
                    515:                tp_indicate(T_DISCONNECT, $P, 
                    516:                        TP_ERROR_MASK |(u_short)($$.e_reason | 0x40));
                    517:                $P.tp_retrans = $P.tp_Nretrans;
                    518:                tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_dr_ticks);
                    519:                (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_PROTO_ERR, MNULL);
                    520:        }
                    521: ;
                    522: /* NBS(6) */
                    523: TP_OPEN                        <==             TP_CRSENT                                                                       CC_TPDU 
                    524:        ($P.tp_class == TP_CLASS_0) 
                    525:        {       
                    526:                tp_cuntimeout($P.tp_refp, TM_retrans);
                    527:                IncStat(ts_tp0_conn);
                    528:                $P.tp_fcredit = 1;
                    529:                soisconnected($P.tp_sock);
                    530:        }
                    531: ;
                    532: 
                    533: TP_OPEN                        <==             TP_CRSENT                                                                       CC_TPDU 
                    534:        DEFAULT
                    535:        {       
                    536:                IFDEBUG(D_CONN)
                    537:                        printf("trans: CC_TPDU in CRSENT state flags 0x%x\n", 
                    538:                                (int)$P.tp_flags);
                    539:                ENDDEBUG
                    540:                IncStat(ts_tp4_conn);
                    541:                $P.tp_fref = $$.e_sref;
                    542:                $P.tp_fcredit = $$.e_cdt;
                    543:                $P.tp_ackrcvd = 0;
                    544:                if($P.tp_rx_strat & TPRX_FASTSTART)
                    545:                        $P.tp_cong_win = $$.e_cdt;
                    546:                tp_getoptions($P);
                    547:                tp_cuntimeout($P.tp_refp, TM_retrans);
                    548:                if ($P.tp_ucddata) {
                    549:                        IFDEBUG(D_CONN)
                    550:                                printf("dropping user connect data cc 0x%x\n",
                    551:                                        $P.tp_ucddata->m_len);
                    552:                        ENDDEBUG
                    553:                        m_freem($P.tp_ucddata);
                    554:                        $P.tp_ucddata = 0;
                    555:                }
                    556:                soisconnected($P.tp_sock);
                    557:                if ($$.e_datalen > 0) {
                    558:                        ASSERT($P.tp_Xrcv.sb_cc == 0); /* should be empty */
                    559:                        sbappendrecord(&$P.tp_Xrcv, $$.e_data);
                    560:                        $P.tp_flags |= TPF_CONN_DATA_IN;
                    561:                        $$.e_data = MNULL;
                    562:                }
                    563: 
                    564:                (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, MNULL);
                    565:                tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
                    566:        }
                    567: ;
                    568: 
                    569: /* TP4 only */
                    570: SAME                   <==             TP_CRSENT                                                                       TM_retrans 
                    571:        (       $P.tp_retrans > 0 )
                    572:        {
                    573:                struct mbuf *data = MNULL;
                    574:                int error;
                    575: 
                    576:                IncStat(ts_retrans_cr);
                    577:                $P.tp_cong_win = 1;
                    578:                $P.tp_ackrcvd = 0;
                    579:                data = MCPY($P.tp_ucddata, M_NOWAIT);
                    580:                if($P.tp_ucddata) {
                    581:                        IFDEBUG(D_CONN)
                    582:                                printf("TM_retrans.trans m_copy cc 0x%x\n", data);
                    583:                                dump_mbuf($P.tp_ucddata, "sosnd @ TM_retrans");
                    584:                        ENDDEBUG
                    585:                        if( data == MNULL )
                    586:                                return ENOBUFS;
                    587:                }
                    588: 
                    589:                $P.tp_retrans --;
                    590:                if( error = tp_emit(CR_TPDU_type, $P, 0, 0, data) ) {
                    591:                        $P.tp_sock->so_error = error;
                    592:                }
                    593:                tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_cr_ticks);
                    594:        }
                    595: ;
                    596: 
                    597: /* TP4 only  */
                    598: TP_REFWAIT             <==             TP_CRSENT                                                                       TM_retrans 
                    599:        DEFAULT /* no more CR retransmissions */
                    600:        {       
                    601:                IncStat(ts_conn_gaveup);
                    602:                $P.tp_sock->so_error = ETIMEDOUT;
                    603:                tp_indicate(T_DISCONNECT, $P, ETIMEDOUT);
                    604:                tp_soisdisconnected($P);
                    605:        }
                    606: ;
                    607: 
                    608: /* TP4 only */
                    609: SAME                   <==      TP_AKWAIT                                                                                      CR_TPDU 
                    610:        DEFAULT
                    611:        /* duplicate CR (which doesn't really exist in the context of
                    612:         * a connectionless network layer) 
                    613:         * Doesn't occur in class 0.
                    614:         */
                    615:        {       
                    616:                int error;
                    617:                struct mbuf *data = MCPY($P.tp_ucddata, M_WAIT);
                    618: 
                    619:                if( error = tp_emit(CC_TPDU_type, $P, 0, 0, data) ) {
                    620:                        $P.tp_sock->so_error = error;
                    621:                }
                    622:                $P.tp_retrans = $P.tp_Nretrans;
                    623:                tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_cc_ticks);
                    624:        }
                    625: ;
                    626: 
                    627: /* TP4 only */
                    628: TP_OPEN                        <==             TP_AKWAIT                                                                               DT_TPDU 
                    629:        ( IN_RWINDOW( $P, $$.e_seq,
                    630:                                        $P.tp_rcvnxt, SEQ($P, $P.tp_rcvnxt + $P.tp_lcredit)) )
                    631:        {
                    632:                int doack;
                    633: 
                    634:                /*
                    635:                 * Get rid of any confirm or connect data, so that if we
                    636:                 * crash or close, it isn't thought of as disconnect data.
                    637:                 */
                    638:                if ($P.tp_ucddata) {
                    639:                        m_freem($P.tp_ucddata);
                    640:                        $P.tp_ucddata = 0;
                    641:                }
                    642:                tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
                    643:                tp_cuntimeout($P.tp_refp, TM_retrans);
                    644:                soisconnected($P.tp_sock);
                    645:                tp_getoptions($P);
                    646:                tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
                    647: 
                    648:                /* see also next 2 transitions, if you make any changes */
                    649: 
                    650:                doack = tp_stash($P, $E);
                    651:                IFDEBUG(D_DATA)
                    652:                        printf("tp_stash returns %d\n",doack);
                    653:                ENDDEBUG
                    654: 
                    655:                if(doack) {
                    656:                        (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, MNULL ); 
                    657:                        tp_ctimeout($P.tp_refp, TM_sendack, (int)$P.tp_keepalive_ticks);
                    658:                } else
                    659:                        tp_ctimeout( $P.tp_refp, TM_sendack, (int)$P.tp_sendack_ticks);
                    660:                
                    661:                IFDEBUG(D_DATA)
                    662:                        printf("after stash calling sbwakeup\n");
                    663:                ENDDEBUG
                    664:        }
                    665: ;
                    666: 
                    667: SAME                   <==             TP_OPEN                                                                         DT_TPDU 
                    668:        ( $P.tp_class == TP_CLASS_0 )
                    669:        {
                    670:                tp0_stash($P, $E);
                    671:                sbwakeup( &$P.tp_sock->so_rcv );
                    672: 
                    673:                IFDEBUG(D_DATA)
                    674:                        printf("after stash calling sbwakeup\n");
                    675:                ENDDEBUG
                    676:        }
                    677: ;
                    678: 
                    679: /* TP4 only */
                    680: SAME                   <==             TP_OPEN                                                                         DT_TPDU 
                    681:        ( IN_RWINDOW( $P, $$.e_seq,
                    682:                                        $P.tp_rcvnxt, SEQ($P, $P.tp_rcvnxt + $P.tp_lcredit)) )
                    683:        {
                    684:                int doack; /* tells if we must ack immediately */
                    685: 
                    686:                tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
                    687:                sbwakeup( &$P.tp_sock->so_rcv );
                    688: 
                    689:                doack = tp_stash($P, $E);
                    690:                IFDEBUG(D_DATA)
                    691:                        printf("tp_stash returns %d\n",doack);
                    692:                ENDDEBUG
                    693: 
                    694:                if(doack)
                    695:                        (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, MNULL ); 
                    696:                else
                    697:                        tp_ctimeout_MIN( $P.tp_refp, TM_sendack, (int)$P.tp_sendack_ticks);
                    698:                
                    699:                IFDEBUG(D_DATA)
                    700:                        printf("after stash calling sbwakeup\n");
                    701:                ENDDEBUG
                    702:        }
                    703: ;
                    704: 
                    705: /* Not in window  - we must ack under certain circumstances, namely
                    706:  * a) if the seq number is below lwe but > lwe - (max credit ever given)
                    707:  * (to handle lost acks) Can use max-possible-credit for this ^^^.
                    708:  * and 
                    709:  * b) seq number is > uwe but < uwe + previously sent & withdrawn credit
                    710:  *
                    711:  * (see 12.2.3.8.1 of ISO spec, p. 73)
                    712:  * We just always ack.
                    713:  */
                    714: /* TP4 only */
                    715: SAME                   <==     [ TP_OPEN, TP_AKWAIT ]                                                  DT_TPDU
                    716:        DEFAULT /* Not in window */
                    717:        {       
                    718:                IFTRACE(D_DATA)
                    719:                        tptrace(TPPTmisc, "NIW seq rcvnxt lcredit ",
                    720:                                $$.e_seq, $P.tp_rcvnxt, $P.tp_lcredit, 0);
                    721:                ENDTRACE
                    722:                IncStat(ts_dt_niw);
                    723:                m_freem($$.e_data);
                    724:                tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
                    725:                (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, MNULL ); 
                    726:        }
                    727: ;
                    728: 
                    729: /* TP4 only */
                    730: TP_OPEN                        <==             TP_AKWAIT                                                                               AK_TPDU
                    731:        DEFAULT
                    732:        {
                    733:                if ($P.tp_ucddata) {
                    734:                        m_freem($P.tp_ucddata);
                    735:                        $P.tp_ucddata = 0;
                    736:                }
                    737:                (void) tp_goodack($P, $$.e_cdt, $$.e_seq, $$.e_subseq);
                    738:                tp_cuntimeout($P.tp_refp, TM_retrans);
                    739: 
                    740:                tp_getoptions($P);
                    741:                soisconnected($P.tp_sock);
                    742:                IFTRACE(D_CONN)
                    743:                        struct socket *so = $P.tp_sock;
                    744:                        tptrace(TPPTmisc, 
                    745:                        "called sosiconn: so so_state rcv.sb_sel rcv.sb_flags",
                    746:                                so, so->so_state, so->so_rcv.sb_sel, so->so_rcv.sb_flags);
                    747:                        tptrace(TPPTmisc, 
                    748:                        "called sosiconn 2: so_qlen so_error so_rcv.sb_cc so_head",
                    749:                                so->so_qlen, so->so_error, so->so_rcv.sb_cc, so->so_head);
                    750:                ENDTRACE
                    751: 
                    752:                tp_ctimeout($P.tp_refp, TM_sendack, (int)$P.tp_keepalive_ticks);
                    753:                tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
                    754:        }
                    755: ;
                    756: 
                    757: /* TP4 only */
                    758: TP_OPEN                <==     [ TP_OPEN, TP_AKWAIT ]                                          XPD_TPDU
                    759:        ( $P.tp_Xrcvnxt == $$.e_seq  /* && $P.tp_Xrcv.sb_cc == 0*/)
                    760:        {
                    761:                if( $P.tp_state == TP_AKWAIT ) {
                    762:                        if ($P.tp_ucddata) {
                    763:                                m_freem($P.tp_ucddata);
                    764:                                $P.tp_ucddata = 0;
                    765:                        }
                    766:                        tp_cuntimeout($P.tp_refp, TM_retrans);
                    767:                        tp_getoptions($P);
                    768:                        soisconnected($P.tp_sock);
                    769:                        tp_ctimeout($P.tp_refp, TM_sendack, (int)$P.tp_keepalive_ticks);
                    770:                        tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
                    771:                } 
                    772:                IFTRACE(D_XPD)
                    773:                tptrace(TPPTmisc, "XPD tpdu accepted Xrcvnxt, e_seq datalen m_len\n",
                    774:                                $P.tp_Xrcvnxt,$$.e_seq,  $$.e_datalen, $$.e_data->m_len);
                    775:                ENDTRACE
                    776: 
                    777:                $P.tp_sock->so_state |= SS_RCVATMARK;
                    778:                sbinsertoob(&$P.tp_Xrcv, $$.e_data);
                    779:                IFDEBUG(D_XPD)
                    780:                        dump_mbuf($$.e_data, "XPD TPDU: tp_Xrcv");
                    781:                ENDDEBUG
                    782:                tp_indicate(T_XDATA, $P, 0);
                    783:                sbwakeup( &$P.tp_Xrcv );
                    784: 
                    785:                (void) tp_emit(XAK_TPDU_type, $P, $P.tp_Xrcvnxt, 0, MNULL);
                    786:                SEQ_INC($P, $P.tp_Xrcvnxt);
                    787:        }
                    788: ;
                    789: 
                    790: /* TP4 only */
                    791: SAME                   <==             TP_OPEN                                                                         T_USR_Xrcvd
                    792:        DEFAULT
                    793:        {
                    794:                if( $P.tp_Xrcv.sb_cc == 0 ) {
                    795:                        /*$P.tp_flags &= ~TPF_XPD_PRESENT;*/
                    796:                        /* kludge for select(): */ 
                    797:                        /* $P.tp_sock->so_state &= ~SS_OOBAVAIL; */
                    798:                }
                    799:        }
                    800:        /* OLD WAY:
                    801:         * Ack only after the user receives the XPD.  This is better for 
                    802:         * users that use one XPD right after another.
                    803:         * Acking right away (the NEW WAY, see the prev. transition) is 
                    804:         * better for occasional * XPD, when the receiving user doesn't 
                    805:         * want to read the XPD immediately (which is session's behavior).
                    806:         *
                    807:                int error = tp_emit(XAK_TPDU_type, $P, $P.tp_Xrcvnxt, 0, MNULL);
                    808:                SEQ_INC($P, $P.tp_Xrcvnxt);
                    809:                return error;
                    810:        */
                    811: ;
                    812: 
                    813: /* NOTE: presently if the user doesn't read the connection data
                    814:  * before and expedited data PDU comes in, the connection data will
                    815:  * be dropped. This is a bug.  To avoid it, we need somewhere else
                    816:  * to put the connection data.
                    817:  * On the other hand, we need not to have it sitting around forever.
                    818:  * This is a problem with the idea of trying to accommodate
                    819:  * data on connect w/ a passive-open user interface. 
                    820:  */
                    821: /* TP4 only */
                    822: 
                    823: SAME                   <==     [ TP_AKWAIT, TP_OPEN ]                                                  XPD_TPDU
                    824:        DEFAULT /* not in window or cdt==0 */
                    825:        {
                    826:                IFTRACE(D_XPD)
                    827:                        tptrace(TPPTmisc, "XPD tpdu niw (Xrcvnxt, e_seq) or not cdt (cc)\n",
                    828:                                $P.tp_Xrcvnxt, $$.e_seq,  $P.tp_Xrcv.sb_cc , 0);
                    829:                ENDTRACE
                    830:                if( $P.tp_Xrcvnxt != $$.e_seq )
                    831:                        IncStat(ts_xpd_niw);
                    832:                if( $P.tp_Xrcv.sb_cc ) {
                    833: #ifdef notdef
                    834:                        if( $P.tp_flags & TPF_CONN_DATA_IN ) {
                    835:                                /* user isn't reading the connection data; see note above */
                    836:                                sbdrop(&$P.tp_Xrcv, $P.tp_Xrcv.sb_cc);
                    837:                                $P.tp_flags &= ~TPF_CONN_DATA_IN;
                    838:                        }
                    839: #endif notdef
                    840:                        /* might as well kick 'em again */
                    841:                        tp_indicate(T_XDATA, $P, 0);
                    842:                        IncStat(ts_xpd_dup);
                    843:                }
                    844:                m_freem($$.e_data);
                    845:                tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
                    846:                /* don't send an xack because the xak gives "last one received", not
                    847:                 * "next one i expect" (dumb)
                    848:                 */
                    849:        }
                    850: ;
                    851: 
                    852: /* Occurs (AKWAIT, OPEN) when parent (listening) socket gets aborted, and tries
                    853:  * to detach all its "children"
                    854:  * Also (CRSENT) when user kills a job that's doing a connect()
                    855:  */
                    856: TP_REFWAIT             <==     TP_CRSENT                                                                               T_DETACH
                    857:        ($P.tp_class == TP_CLASS_0)
                    858:        {
                    859:                struct socket *so = $P.tp_sock;
                    860: 
                    861:                /* detach from parent socket so it can finish closing */
                    862:                if (so->so_head) {
                    863:                        if (!soqremque(so, 0) && !soqremque(so, 1))
                    864:                                panic("tp: T_DETACH");
                    865:                        so->so_head = 0;
                    866:                }
                    867:                tp_soisdisconnecting($P.tp_sock);
                    868:                tp_netcmd( $P, CONN_CLOSE);
                    869:                tp_soisdisconnected($P);
                    870:        }
                    871: ;
                    872: 
                    873: /* TP4 only */
                    874: TP_CLOSING             <== [ TP_CLOSING, TP_AKWAIT, TP_CRSENT, TP_CONFIRMING ] T_DETACH
                    875:        DEFAULT
                    876:        {
                    877:                struct socket *so = $P.tp_sock;
                    878:                struct mbuf *data = MNULL;
                    879: 
                    880:                /* detach from parent socket so it can finish closing */
                    881:                if (so->so_head) {
                    882:                        if (!soqremque(so, 0) && !soqremque(so, 1))
                    883:                                panic("tp: T_DETACH");
                    884:                        so->so_head = 0;
                    885:                }
                    886:                if ($P.tp_state != TP_CLOSING) {
                    887:                        tp_soisdisconnecting($P.tp_sock);
                    888:                        data = MCPY($P.tp_ucddata, M_NOWAIT);
                    889:                        (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_NORMAL_DISC, data);
                    890:                        $P.tp_retrans = $P.tp_Nretrans;
                    891:                        tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_dr_ticks);
                    892:                }
                    893:        }
                    894: ;
                    895: 
                    896: TP_REFWAIT             <==             [ TP_OPEN, TP_CRSENT ]                                          T_DISC_req
                    897:        ( $P.tp_class == TP_CLASS_0 )
                    898:        {
                    899:                tp_soisdisconnecting($P.tp_sock);
                    900:                tp_netcmd( $P, CONN_CLOSE);
                    901:                tp_soisdisconnected($P);
                    902:        }
                    903: ;
                    904: 
                    905: /* TP4 only */
                    906: TP_CLOSING             <==     [ TP_AKWAIT, TP_OPEN, TP_CRSENT, TP_CONFIRMING ]  T_DISC_req
                    907:        DEFAULT
                    908:        {
                    909:                struct mbuf *data = MCPY($P.tp_ucddata, M_WAIT);
                    910: 
                    911:                if($P.tp_state == TP_OPEN) {
                    912:                        tp_euntimeout($P.tp_refp, TM_data_retrans); /* all */
                    913:                        tp_cuntimeout($P.tp_refp, TM_inact);
                    914:                        tp_cuntimeout($P.tp_refp, TM_sendack);
                    915:                }
                    916:                if (data) {
                    917:                        IFDEBUG(D_CONN)
                    918:                                printf("T_DISC_req.trans tp_ucddata 0x%x\n", 
                    919:                                        $P.tp_ucddata);
                    920:                                dump_mbuf(data, "ucddata @ T_DISC_req");
                    921:                        ENDDEBUG
                    922:                }
                    923:                tp_soisdisconnecting($P.tp_sock);
                    924:                $P.tp_retrans = $P.tp_Nretrans;
                    925:                tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_dr_ticks);
                    926: 
                    927:                if( trick_hc )
                    928:                        return tp_emit(DR_TPDU_type, $P, 0, $$.e_reason, data);
                    929:        }
                    930: ;
                    931: 
                    932: /* TP4 only */
                    933: SAME                   <==             TP_AKWAIT                                                                       TM_retrans
                    934:        ( $P.tp_retrans > 0 )
                    935:        {
                    936:                int error;
                    937:                struct mbuf *data = MCPY($P.tp_ucddata, M_WAIT);
                    938: 
                    939:                IncStat(ts_retrans_cc);
                    940:                $P.tp_retrans --;
                    941:                $P.tp_cong_win = 1;
                    942:                $P.tp_ackrcvd = 0;
                    943: 
                    944:                if( error = tp_emit(CC_TPDU_type, $P, 0, 0, data) ) 
                    945:                        $P.tp_sock->so_error = error;
                    946:                tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_cc_ticks);
                    947:        }
                    948: ;
                    949: 
                    950: /* TP4 only */
                    951: TP_CLOSING             <==             TP_AKWAIT                                                                       TM_retrans
                    952:        DEFAULT  /* out of time */
                    953:        {
                    954:                IncStat(ts_conn_gaveup);
                    955:                tp_soisdisconnecting($P.tp_sock);
                    956:                $P.tp_sock->so_error = ETIMEDOUT;
                    957:                tp_indicate(T_DISCONNECT, $P, ETIMEDOUT);
                    958:                (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_CONGEST, MNULL);
                    959:                $P.tp_retrans = $P.tp_Nretrans;
                    960:                tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_dr_ticks);
                    961:        }
                    962: ;
                    963: 
                    964: /* the retrans timers had better go off BEFORE the inactivity timer does,
                    965:  * if transmissions are going on.
                    966:  * (i.e., TM_inact should be greater than timer for all retrans plus ack
                    967:  * turnaround)
                    968:  */
                    969: /* TP4 only */
                    970: TP_CLOSING             <==             TP_OPEN            [ TM_inact, TM_retrans, TM_data_retrans ]
                    971:        DEFAULT
                    972:        {
                    973:                tp_euntimeout($P.tp_refp, TM_data_retrans); /* all */
                    974:                tp_cuntimeout($P.tp_refp, TM_inact); 
                    975:                tp_cuntimeout($P.tp_refp, TM_sendack);
                    976: 
                    977:                IncStat(ts_conn_gaveup);
                    978:                tp_soisdisconnecting($P.tp_sock);
                    979:                $P.tp_sock->so_error = ETIMEDOUT;
                    980:                tp_indicate(T_DISCONNECT, $P, ETIMEDOUT);
                    981:                (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_CONGEST_2, MNULL);
                    982:                $P.tp_retrans = $P.tp_Nretrans;
                    983:                tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_dr_ticks);
                    984:        }
                    985: ;
                    986: 
                    987: /* TP4 only */
                    988: SAME                   <==             TP_OPEN                                                                         TM_retrans
                    989:        ( $P.tp_retrans > 0 )
                    990:        {
                    991:                $P.tp_cong_win = 1;
                    992:                $P.tp_ackrcvd = 0;
                    993:                /* resume XPD */
                    994:                if      ( $P.tp_Xsnd.sb_mb )  {
                    995:                        struct mbuf *m = m_copy($P.tp_Xsnd.sb_mb, 0, (int)$P.tp_Xsnd.sb_cc);
                    996:                        /* m_copy doesn't preserve the m_xlink field, but at this pt.
                    997:                         * that doesn't matter
                    998:                         */
                    999: 
                   1000:                        IFTRACE(D_XPD)
                   1001:                                tptrace(TPPTmisc, "XPD retrans: Xuna Xsndnxt sndhiwat snduna",
                   1002:                                        $P.tp_Xuna, $P.tp_Xsndnxt, $P.tp_sndhiwat, 
                   1003:                                        $P.tp_snduna); 
                   1004:                        ENDTRACE
                   1005:                        IFDEBUG(D_XPD)
                   1006:                                dump_mbuf(m, "XPD retrans emitting M");
                   1007:                        ENDDEBUG
                   1008:                        IncStat(ts_retrans_xpd);
                   1009:                        $P.tp_retrans --;
                   1010:                        (void) tp_emit(XPD_TPDU_type, $P, $P.tp_Xuna, 1, m);
                   1011:                        tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_xpd_ticks);
                   1012:                }
                   1013:        }
                   1014: ;
                   1015: 
                   1016: /* TP4 only */
                   1017: SAME                   <==             TP_OPEN                                                                 TM_data_retrans
                   1018:        ( $$.e_retrans > 0 )
                   1019:        {       
                   1020:                register        SeqNum                  low, lowsave = 0;
                   1021:                register        struct tp_rtc   *r = $P.tp_snduna_rtc;
                   1022:                register        struct mbuf     *m;
                   1023:                register        SeqNum                  high = $$.e_high;
                   1024: 
                   1025:                low = $P.tp_snduna;
                   1026:                lowsave = high = low;
                   1027: 
                   1028:                tp_euntimeout_lss($P.tp_refp, TM_data_retrans,
                   1029:                        SEQ_ADD($P, $P.tp_sndhiwat, 1));
                   1030:                $P.tp_retrans_hiwat = $P.tp_sndhiwat;
                   1031: 
                   1032:                if (($P.tp_rx_strat & TPRX_EACH) == 0)
                   1033:                        high = (high>low)?low:high;
                   1034: 
                   1035:                if( $P.tp_rx_strat & TPRX_USE_CW ) {
                   1036:                        register int i;
                   1037: 
                   1038:                        $P.tp_cong_win = 1;
                   1039:                        $P.tp_ackrcvd = 0;
                   1040:                        i = SEQ_ADD($P, low, $P.tp_cong_win);
                   1041: 
                   1042:                        high = SEQ_MIN($P, high, $P.tp_sndhiwat);
                   1043: 
                   1044:                }
                   1045: 
                   1046:                while( SEQ_LEQ($P, low, high) ){
                   1047:                        if ( r == (struct tp_rtc *)0 ){
                   1048:                                IFDEBUG(D_RTC)
                   1049:                                        printf( "tp: retrans rtc list is GONE!\n");
                   1050:                                ENDDEBUG
                   1051:                                break;
                   1052:                        }
                   1053:                        if ( r->tprt_seq == low ){
                   1054:                                if(( m = m_copy(r->tprt_data, 0, r->tprt_octets ))== MNULL)
                   1055:                                        break;
                   1056:                                (void) tp_emit(DT_TPDU_type, $P, low, r->tprt_eot, m);
                   1057:                                IncStat(ts_retrans_dt);
                   1058:                                SEQ_INC($P, low );
                   1059:                        }
                   1060:                        r = r->tprt_next;
                   1061:                }
                   1062: /* CE_BIT
                   1063:                if ( SEQ_LEQ($P, lowsave, high) ){
                   1064: */
                   1065:                        $$.e_retrans --;
                   1066:                        tp_etimeout($P.tp_refp, TM_data_retrans, (caddr_t)lowsave,
                   1067:                                        (caddr_t)high, $$.e_retrans,
                   1068:                                        ($P.tp_Nretrans - $$.e_retrans) * (int)$P.tp_dt_ticks);
                   1069: /* CE_BIT
                   1070:                }
                   1071: */
                   1072:        }
                   1073: ;
                   1074: 
                   1075: /* TP4 only */
                   1076: SAME                   <==             TP_CLOSING                                                                      TM_retrans
                   1077:        (       $P.tp_retrans > 0 )
                   1078:        {       
                   1079:                $P.tp_retrans --;
                   1080:                (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_DR_NO_REAS, MNULL);
                   1081:                IncStat(ts_retrans_dr);
                   1082:                tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_dr_ticks);
                   1083:        }
                   1084: ;
                   1085: 
                   1086: /* TP4 only */
                   1087: TP_REFWAIT             <==             TP_CLOSING                                                                      TM_retrans
                   1088:        DEFAULT /* no more retrans - gave up */
                   1089:        {       
                   1090:                $P.tp_sock->so_error = ETIMEDOUT;
                   1091:                $P.tp_refp->tpr_state = REF_FROZEN;
                   1092:                tp_recycle_tsuffix( $P );
                   1093:                tp_etimeout($P.tp_refp, TM_reference, 0,0,0, (int)$P.tp_refer_ticks);
                   1094:        }
                   1095: ;
                   1096: 
                   1097: /*
                   1098:  * The resources are kept around until the ref timer goes off.
                   1099:  * The suffices are wiped out sooner so they can be reused right away.
                   1100:  */
                   1101: /* applicable in TP4, TP0 */
                   1102: TP_CLOSED              <==             TP_REFWAIT                                                                      TM_reference
                   1103:        DEFAULT
                   1104:        {
                   1105:                tp_freeref($P.tp_refp);
                   1106:                tp_detach($P);
                   1107:        }
                   1108: ;
                   1109: 
                   1110: /* applicable in TP4, TP0 */
                   1111: /* A duplicate CR from connectionless network layer can't happen */
                   1112: SAME                   <==     TP_OPEN                                                         [ CR_TPDU, CC_TPDU ]
                   1113:        DEFAULT
                   1114:        {       
                   1115:                if( $P.tp_class != TP_CLASS_0) {
                   1116:                        tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
                   1117:                        if ( $E.ev_number == CC_TPDU )
                   1118:                                (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, MNULL); 
                   1119:                }
                   1120:                /* ignore it if class 0 - state tables are blank for this */
                   1121:        }
                   1122: ;
                   1123: 
                   1124: /* applicable in TP4, TP0 */
                   1125: SAME                   <==     TP_OPEN                                                                 T_DATA_req
                   1126:        DEFAULT
                   1127:        {
                   1128:                IFTRACE(D_DATA)
                   1129:                        tptrace(TPPTmisc, "T_DATA_req sndhiwat snduna fcredit, tpcb",
                   1130:                                $P.tp_sndhiwat, $P.tp_snduna, $P.tp_fcredit, $P);
                   1131:                ENDTRACE
                   1132: 
                   1133:                tp_send($P);
                   1134:        }
                   1135: ;
                   1136: 
                   1137: /* TP4 only */
                   1138: SAME                   <==             TP_OPEN                                                                         T_XPD_req
                   1139:        DEFAULT
                   1140:                /* T_XPD_req was issued by sosend iff xpd socket buf was empty
                   1141:                 * at time of sosend(), 
                   1142:                 * AND (which means) there were no unacknowledged XPD tpdus outstanding!
                   1143:                 */
                   1144:        {
                   1145:                int error = 0;
                   1146: 
                   1147:                /* resume XPD */
                   1148:                if      ( $P.tp_Xsnd.sb_mb )  {
                   1149:                        struct mbuf *m = m_copy($P.tp_Xsnd.sb_mb, 0, (int)$P.tp_Xsnd.sb_cc);
                   1150:                        /* m_copy doesn't preserve the m_xlink field, but at this pt.
                   1151:                         * that doesn't matter
                   1152:                         */
                   1153: 
                   1154:                        IFTRACE(D_XPD)
                   1155:                                tptrace(TPPTmisc, "XPD req: Xuna Xsndnxt sndhiwat snduna",
                   1156:                                        $P.tp_Xuna, $P.tp_Xsndnxt, $P.tp_sndhiwat, 
                   1157:                                        $P.tp_snduna); 
                   1158:                        ENDTRACE
                   1159:                        IFDEBUG(D_XPD)
                   1160:                                printf("T_XPD_req: sb_cc 0x%x\n", $P.tp_Xsnd.sb_cc);
                   1161:                                dump_mbuf(m, "XPD req emitting M");
                   1162:                        ENDDEBUG
                   1163:                        error = 
                   1164:                                tp_emit(XPD_TPDU_type, $P, $P.tp_Xuna, 1, m);
                   1165:                        $P.tp_retrans = $P.tp_Nretrans;
                   1166:                        tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_xpd_ticks);
                   1167:                        SEQ_INC($P, $P.tp_Xsndnxt);
                   1168:                } 
                   1169:                if(trick_hc)
                   1170:                        return error;
                   1171:        }
                   1172: ;
                   1173: 
                   1174: /* TP4, faked ack in TP0 when cons send completes */
                   1175: SAME                   <==             TP_OPEN                                                                         AK_TPDU
                   1176:        ( tp_goodack($P, $$.e_cdt, $$.e_seq, $$.e_subseq)  )
                   1177: 
                   1178:        /* tp_goodack == true means 
                   1179:         * EITHER it actually acked something heretofore unacknowledged
                   1180:         * OR no news but the credit should be processed.
                   1181:         */
                   1182:        {
                   1183:                IFDEBUG(D_ACKRECV)
                   1184:                        printf("GOOD ACK seq 0x%x cdt 0x%x\n", $$.e_seq, $$.e_cdt);
                   1185:                ENDDEBUG
                   1186:                if( $P.tp_class != TP_CLASS_0) {
                   1187:                        tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
                   1188:                        tp_euntimeout_lss($P.tp_refp, TM_data_retrans, $$.e_seq);
                   1189:                }
                   1190:                sbwakeup( &$P.tp_sock->so_snd );
                   1191: 
                   1192:                if ($P.tp_sndhiwat <= $P.tp_retrans_hiwat &&
                   1193:                        $P.tp_snduna <= $P.tp_retrans_hiwat) {
                   1194: 
                   1195:                        register    struct mbuf     *m;
                   1196:                        /* extern      struct mbuf     *m_copy(); */
                   1197:                        register    struct tp_rtc   *r;
                   1198:                        SeqNum      high, retrans, low_save;
                   1199: 
                   1200:                        high = SEQ_MIN($P, SEQ_ADD($P, $P.tp_snduna,
                   1201:                                        MIN($P.tp_cong_win, $P.tp_fcredit)) - 1,
                   1202:                                        $P.tp_sndhiwat);
                   1203:                        low_save = retrans = SEQ_MAX($P, SEQ_ADD($P, $P.tp_last_retrans, 1),
                   1204:                                        $P.tp_snduna);
                   1205:                        for (; SEQ_LEQ($P, retrans, high); SEQ_INC($P, retrans)) {
                   1206: 
                   1207:                                for (r = $P.tp_snduna_rtc; r; r = r->tprt_next){
                   1208:                                        if ( r->tprt_seq == retrans ){
                   1209:                                                if(( m = m_copy(r->tprt_data, 0, r->tprt_octets ))
                   1210:                                                                == MNULL)
                   1211:                                                        break;
                   1212:                                                (void) tp_emit(DT_TPDU_type, $P, retrans,
                   1213:                                                        r->tprt_eot, m);
                   1214:                                                $P.tp_last_retrans = retrans;
                   1215:                                                IncStat(ts_retrans_dt);
                   1216:                                                break;
                   1217:                                        }
                   1218:                                }
                   1219:                                if ( r == (struct tp_rtc *)0 ){
                   1220:                                        IFDEBUG(D_RTC)
                   1221:                                                printf( "tp: retrans rtc list is GONE!\n");
                   1222:                                        ENDDEBUG
                   1223:                                        break;
                   1224:                                }
                   1225:                        }
                   1226:                        tp_etimeout($P.tp_refp, TM_data_retrans, (caddr_t)low_save,
                   1227:                                        (caddr_t)high, $P.tp_retrans, (int)$P.tp_dt_ticks);
                   1228:                        if (SEQ_DEC($P, retrans) == $P.tp_retrans_hiwat)
                   1229:                                tp_send($P);
                   1230:                }
                   1231:                else {
                   1232:                        tp_send($P);
                   1233:                }
                   1234:                IFDEBUG(D_ACKRECV)
                   1235:                        printf("GOOD ACK new sndhiwat 0x%x\n", $P.tp_sndhiwat);
                   1236:                ENDDEBUG
                   1237:        }
                   1238: ;
                   1239: 
                   1240: /* TP4, and TP0 after sending a CC or possibly a CR */
                   1241: SAME                   <==             TP_OPEN                                                                          AK_TPDU
                   1242:        DEFAULT
                   1243:        {
                   1244:                IFTRACE(D_ACKRECV)
                   1245:                        tptrace(TPPTmisc, "BOGUS ACK fcc_present, tp_r_subseq e_subseq", 
                   1246:                                $$.e_fcc_present, $P.tp_r_subseq, $$.e_subseq, 0);
                   1247:                ENDTRACE
                   1248:                if( $P.tp_class != TP_CLASS_0 ) {
                   1249: 
                   1250:                        if ( !$$.e_fcc_present ) {
                   1251:                                /* send ACK with FCC */
                   1252:                                IncStat( ts_ackreason[_ACK_FCC_] );
                   1253:                                (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 1, MNULL);
                   1254:                        }
                   1255:                        tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
                   1256:                } 
                   1257:        }
                   1258: ;
                   1259: 
                   1260: /* NBS(47) */
                   1261:        /* goes in at *** */
                   1262:                /* just so happens that this is never true now, because we allow
                   1263:                 * only 1 packet in the queue at once (this could be changed)
                   1264:                if      ( $P.tp_Xsnd.sb_mb )  {
                   1265:                        struct mbuf *m = m_copy($P.tp_Xsnd.sb_mb, 0, ??);
                   1266: 
                   1267:                        (void) tp_emit(XPD_TPDU_type, $P, $P.tp_Xuna, 1, m);
                   1268:                        $P.tp_retrans = $P.tp_Nretrans;
                   1269:                        tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_xpd_ticks);
                   1270:                        SEQ_INC($P, $P.tp_Xsndnxt);
                   1271:                }
                   1272:                 */
                   1273:        /* end of the above hack */
                   1274: 
                   1275: /* TP4 only */
                   1276: SAME                   <==     TP_OPEN                                                                         XAK_TPDU
                   1277:        ( tp_goodXack($P, $$.e_seq) )
                   1278:        /* tp_goodXack checks for good ack, removes the correct 
                   1279:         * tpdu from the queue and  returns 1 if ack was legit, 0 if not.
                   1280:         * also updates tp_Xuna
                   1281:         */
                   1282:        {       
                   1283:                tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
                   1284:                tp_cuntimeout($P.tp_refp, TM_retrans);
                   1285: 
                   1286:                sbwakeup( &$P.tp_sock->so_snd );
                   1287: 
                   1288:                /* resume normal data */
                   1289:                tp_send($P);
                   1290:        }
                   1291: ;
                   1292: 
                   1293: /* TP4, and TP0 after sending a CC or possibly a CR */
                   1294: SAME                   <==             TP_OPEN                                                                         XAK_TPDU
                   1295:        DEFAULT
                   1296:        {
                   1297:                IFTRACE(D_ACKRECV)
                   1298:                        tptrace(TPPTmisc, "BOGUS XACK eventtype ", $E.ev_number, 0, 0,0);
                   1299:                ENDTRACE
                   1300:                if( $P.tp_class != TP_CLASS_0 ) {
                   1301:                        tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
                   1302:                } 
                   1303:        }
                   1304: ;
                   1305: 
                   1306: /* TP4 only */
                   1307: SAME                   <==             TP_OPEN                                                                 TM_sendack 
                   1308:        DEFAULT
                   1309:        {       
                   1310:                IFTRACE(D_TIMER)
                   1311:                        tptrace(TPPTsendack, -1, $P.tp_lcredit, $P.tp_sent_uwe, 
                   1312:                        $P.tp_sent_lcdt, 0);
                   1313:                ENDTRACE
                   1314:                IncPStat($P, tps_n_TMsendack);
                   1315:                (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, MNULL);
                   1316:        }
                   1317: ;
                   1318: 
                   1319: /* TP0 only */
                   1320: SAME                   <==             TP_OPEN                                                                         T_USR_rcvd
                   1321:        ($P.tp_class == TP_CLASS_0)
                   1322:        NULLACTION
                   1323: ;
                   1324: 
                   1325: /* TP4 only */
                   1326:                /* If old credit was zero, 
                   1327:                 * we'd better inform other side that we now have space
                   1328:                 * But this is not enough.  Sender might not yet have
                   1329:                 * seen an ack with cdt 0 but it might still think the
                   1330:                 * window is closed, so it's going to wait.
                   1331:                 * Best to send an ack each time.
                   1332:                 * Strictly speaking, this ought to be a function of the
                   1333:                 * general ack strategy.
                   1334:                 */
                   1335: SAME                   <==             TP_OPEN                                                                         T_USR_rcvd
                   1336:        DEFAULT
                   1337:        {       
                   1338:                if( trick_hc ) {
                   1339:                        IncStat(ts_ackreason[_ACK_USRRCV_]);
                   1340: 
                   1341:                        /* send an ACK only if there's new information */
                   1342:                        LOCAL_CREDIT( $P );
                   1343:                        if (($P.tp_rcvnxt != $P.tp_sent_rcvnxt) ||
                   1344:                                ($P.tp_lcredit != $P.tp_sent_lcdt))
                   1345: 
                   1346:                                return tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, MNULL);
                   1347:                }
                   1348:        }
                   1349: ;
                   1350: 
                   1351: /* applicable in TP4, TP0 */
                   1352: SAME                   <==             TP_REFWAIT                              [ T_USR_rcvd, T_USR_Xrcvd ]
                   1353:        DEFAULT
                   1354:        /* This happens if other end sent a DR when  the user was waiting 
                   1355:         * on a receive.  
                   1356:         * Processing the DR includes putting us in REFWAIT state.
                   1357:         */
                   1358:        {
                   1359:                if(trick_hc)
                   1360:                return ECONNABORTED;
                   1361:        }
                   1362: ;
                   1363: 
                   1364: /* TP0 only */
                   1365: TP_REFWAIT             <==             [ TP_OPEN, TP_CRSENT, TP_LISTENING ]    T_NETRESET
                   1366:        ( $P.tp_class != TP_CLASS_4 ) 
                   1367:                /* 0 or (4 and 0) */
                   1368:                /* in OPEN class will be 0 or 4 but not both */
                   1369:                /* in CRSENT or LISTENING it could be in negotiation, hence both */
                   1370:                /* Actually, this shouldn't ever happen in LISTENING */
                   1371:        {
                   1372:                ASSERT( $P.tp_state != TP_LISTENING );
                   1373:                tp_indicate(T_DISCONNECT, $P, ECONNRESET);
                   1374:                tp_soisdisconnected($P);
                   1375:        }
                   1376: ;
                   1377: 
                   1378: /* TP4: ignore resets */
                   1379: SAME           <==             [ TP_OPEN, TP_CRSENT, TP_AKWAIT,
                   1380:                                                TP_CLOSING, TP_LISTENING ]                              T_NETRESET
                   1381:        DEFAULT
                   1382:        NULLACTION
                   1383: ;
                   1384:  
                   1385: /* applicable in TP4, TP0 */
                   1386: SAME                   <==             [ TP_CLOSED, TP_REFWAIT ]                               T_NETRESET
                   1387:        DEFAULT
                   1388:        NULLACTION
                   1389: ;
                   1390: 
                   1391: /* C'EST TOUT */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.