home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR3 / KA9Q212.ZIP / NR4.C < prev    next >
C/C++ Source or Header  |  1993-07-16  |  22KB  |  756 lines

  1. /* net/rom level 4 (transport) protocol implementation
  2.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  3.  * non-commercial distribution only.
  4.  * Ported to NOS by SM0RGV, 890525.
  5.  */
  6.  
  7. /****************************************************************************
  8. *    $Id: nr4.c 1.2 93/07/16 11:47:26 ROOT_DOS Exp $
  9. *    14 Jul 93    1.2        GT    Fix warnings.                                    *
  10. ****************************************************************************/
  11.  
  12. #include <stdio.h>
  13. #include "global.h"
  14. #include "mbuf.h"
  15. #include "timer.h"
  16. #include "ax25.h"
  17. #include "lapb.h"
  18. #include "netrom.h"
  19. #include "nr4.h"
  20. #include <ctype.h>
  21. #include "ip.h"
  22.  
  23. #undef NR4DEBUG
  24.  
  25. #if    NETROM
  26.  
  27. /* Globals: */
  28.  
  29. /* The circuit table */
  30.  
  31. struct nr4circp Nr4circuits[NR4MAXCIRC];
  32.  
  33. /* Various limits */
  34.  
  35. unsigned short Nr4window = 4;        /* Max window to negotiate */
  36. unsigned short Nr4retries = 10;    /* Max retries */
  37. unsigned short Nr4qlimit = 2048;    /* Max bytes on receive queue */
  38.  
  39. /* Timers */
  40.  
  41. int32 Nr4irtt = 15000;            /* Initial round trip time */
  42. int32 Nr4acktime = 3000;        /* ACK delay timer */
  43. int32 Nr4choketime = 180000L;        /* CHOKEd state timeout */
  44.  
  45. static void nr4ackours __ARGS((struct nr4cb *, unsigned, int));
  46. static void nr4choke __ARGS((struct nr4cb *));
  47. static void nr4gotnak __ARGS((struct nr4cb *, unsigned));
  48. static void nr4rframe __ARGS((struct nr4cb *, unsigned, struct mbuf *));
  49.  
  50. /* This function is called when a net/rom layer four frame */
  51. /* is discovered inside a datagram addressed to us */
  52.  
  53. void
  54. nr4input(hdr,bp)
  55. struct nr4hdr *hdr;
  56. struct mbuf *bp;
  57. {
  58.     struct nr4hdr rhdr;
  59.     struct nr4cb *cb, *cb2;
  60.     int op;
  61.     unsigned window;
  62.     int acceptc;        /* indicates that connection should be accepted */
  63.     int newconn;        /* indicates that this is a new incoming */
  64.                         /* connection.  You'll see. */
  65.     int gotchoke;        /* The choke flag was set in this packet */        
  66.     int i;
  67.     
  68.     op = hdr->opcode & NR4OPCODE;    /* Mask off flags */
  69.     
  70.     if(op == NR4OPCONRQ){            /* process connect request first */
  71.         acceptc = 1;
  72.         newconn = 0;
  73.  
  74.         /* These fields are sent regardless of success */
  75.         rhdr.yourindex = hdr->u.conreq.myindex;
  76.         rhdr.yourid = hdr->u.conreq.myid;
  77.  
  78.         /* Check to see if we have already received a connect */
  79.         /* request for this circuit. */
  80.         if((cb = match_n4circ(hdr->u.conreq.myindex,
  81.          hdr->u.conreq.myid,hdr->u.conreq.user,hdr->u.conreq.node))
  82.          == NULLNR4CB){    /* No existing circuit if NULL */
  83.  
  84.             /* Try to get a new circuit */
  85.             if((cb = new_n4circ()) == NULLNR4CB)
  86.                 acceptc = 0;
  87.             /* See if we have any listening sockets */
  88.             for(i = 0; i < NR4MAXCIRC; i++){
  89.                 if((cb2 = Nr4circuits[i].ccb) == NULLNR4CB)
  90.                 continue;/* not an open circuit */
  91.                 if(cb2->state == NR4STLISTEN)
  92.                     /* A listener was found */
  93.                     break;
  94.             }
  95.             if(i == NR4MAXCIRC){ /* We are refusing connects */
  96.                 acceptc = 0;
  97.                 free_n4circ(cb);
  98.             }
  99.             if(acceptc){
  100.                 /* Load the listeners settings */
  101.                 cb->clone = cb2->clone;
  102.                 cb->user = cb2->user;
  103.                 cb->t_upcall = cb2->t_upcall;
  104.                 cb->s_upcall = cb2->s_upcall;
  105.                 cb->r_upcall = cb2->r_upcall;
  106.                 ASSIGN(cb->local,cb2->local);
  107.  
  108.                 /* Window is set to min of the offered
  109.                  * and local windows
  110.                  */
  111.                 window = hdr->u.conreq.window > Nr4window ?
  112.                          Nr4window : hdr->u.conreq.window;
  113.  
  114.                 if(init_nr4window(cb, window) == -1){
  115.                     free_n4circ(cb);
  116.                     acceptc = 0;
  117.                 } else {
  118.                     /* Set up control block */
  119.                     cb->yournum = hdr->u.conreq.myindex;
  120.                     cb->yourid = hdr->u.conreq.myid;
  121.                     memcpy(cb->remote.user,
  122.                            hdr->u.conreq.user,AXALEN);
  123.                     memcpy(cb->remote.node,
  124.                            hdr->u.conreq.node,AXALEN);
  125.                     /* Default round trip time */
  126.                     cb->srtt = Nr4irtt;
  127.                     /* set up timers, window pointers */
  128.                     nr4defaults(cb);
  129.                     cb->state = NR4STDISC;
  130.                     newconn = 1;
  131.                 } /* End if window successfully allocated */
  132.             }    /* End if new circuit available */
  133.          } /* End if no existing circuit matching parameters */
  134.  
  135.         /* Now set up response */
  136.         if(!acceptc){
  137.             rhdr.opcode = NR4OPCONAK | NR4CHOKE;/* choke means reject */
  138.             rhdr.u.conack.myindex = 0;
  139.             rhdr.u.conack.myid = 0;
  140.             rhdr.u.conack.window = 0;
  141.         } else {
  142.             rhdr.opcode = NR4OPCONAK;
  143.             rhdr.u.conack.myindex = cb->mynum;
  144.             rhdr.u.conack.myid = cb->myid;
  145.             rhdr.u.conack.window = cb->window;
  146.         }
  147.         nr4sframe(hdr->u.conreq.node, &rhdr, NULLBUF);
  148.  
  149.         /* Why, you ask, do we wait until now for the state change
  150.          * upcall?  Well, it's like this:  if the state change triggers
  151.          * something like the mailbox to send its banner, the banner
  152.          * would have gone out *before* the conn ack if we'd done this
  153.          * in the code above.  This is what happens when you don't plan
  154.          * too well.  Learn from my mistakes :-)
  155.          */
  156.         if(newconn)
  157.             nr4state(cb, NR4STCON);/* connected (no 3-way handshake) */
  158.             
  159.         free_p(bp);
  160.         return;
  161.     } /* end connect request code */
  162.  
  163.     /* validate circuit number */
  164.     if((cb = get_n4circ(hdr->yourindex, hdr->yourid)) == NULLNR4CB){
  165.         free_p(bp);
  166.         return;
  167.     }
  168.  
  169.     /* Check for choke flag */
  170.     if(hdr->opcode & NR4CHOKE)
  171.         gotchoke = 1;
  172.     else
  173.         gotchoke = 0;
  174.     
  175.     /* Here's where the interesting stuff gets done */
  176.     switch(cb->state){
  177.     case NR4STCPEND:
  178.         switch(op){
  179.         case NR4OPCONAK:
  180.             /* Save the round trip time for later use */
  181.             i = (int) (dur_timer(&cb->tcd) - read_timer(&cb->tcd));
  182.             stop_timer(&cb->tcd);
  183.             if(gotchoke){        /* connect rejected */
  184.                 cb->dreason = NR4RREFUSED;
  185.                 nr4state(cb, NR4STDISC);
  186.                 break;
  187.             }
  188.             cb->yournum = hdr->u.conack.myindex;
  189.             cb->yourid = hdr->u.conack.myid;
  190.             window = hdr->u.conack.window > Nr4window ?
  191.                      Nr4window : hdr->u.conack.window;
  192.  
  193.             if(init_nr4window(cb, window) == -1){
  194.                 cb->dreason = NR4RRESET;
  195.                 nr4state(cb, NR4STDISC);
  196.             } else {
  197.                 nr4defaults(cb);    /* set up timers, window pointers */
  198.                 
  199.                 if(cb->cdtries == 1)    /* No retries */
  200.                     /* Use measured rtt */
  201.                     cb->srtt = i;
  202.                 else
  203.                     /* else use default */
  204.                     cb->srtt = Nr4irtt;
  205.                     
  206.                 nr4state(cb, NR4STCON);
  207.                 nr4output(cb);        /* start sending anything on the txq */
  208.             }
  209.             break;
  210.         default:
  211.             /* We can't respond to anything else without
  212.              * Their ID and index
  213.              */
  214.               free_p(bp);
  215.             return;
  216.         }
  217.         break;
  218.     case NR4STCON:
  219.         switch(op){
  220.         case NR4OPDISRQ:
  221.             /* format reply packet */
  222.             rhdr.opcode = NR4OPDISAK;
  223.             rhdr.yourindex = cb->yournum;
  224.             rhdr.yourid = cb->yourid;
  225.             nr4sframe(cb->remote.node,&rhdr,NULLBUF);
  226.             cb->dreason = NR4RREMOTE;
  227.             nr4state(cb, NR4STDISC);
  228.             break;
  229.           case NR4OPINFO:
  230.             /* Do receive frame processing */
  231.               nr4rframe(cb, hdr->u.info.txseq, bp);
  232.  
  233.             /* Reset the choke flag if no longer choked.  Processing
  234.              * the ACK will kick things off again.
  235.              */
  236.             if(cb->choked && !gotchoke){
  237.                 stop_timer(&cb->tchoke);
  238.                 cb->choked = 0;
  239.             }
  240.                 
  241.             /* We delay processing the receive sequence number until
  242.              * now, because the ACK might pull more off the txq and send
  243.              * it, and we want the implied ACK in those frames to be right
  244.              *
  245.              * Only process NAKs if the choke flag is off.  It appears
  246.              * that NAKs should never be sent with choke on, by the way,
  247.              * but you never know, considering that there is no official
  248.              * standard for this protocol
  249.              */
  250.             if(hdr->opcode & NR4NAK && !gotchoke)
  251.                 nr4gotnak(cb, hdr->u.info.rxseq);
  252.  
  253.             /* We always do ACK processing, too, since the NAK of one
  254.              * packet may be the implied ACK of another.  The gotchoke
  255.              * flag is used to prevent sending any new frames, since
  256.              * we are just going to purge them next anyway if this is
  257.              * the first time we've seen the choke flag.  If we are
  258.              * already choked, this call will return immediately.
  259.              */
  260.             nr4ackours(cb, hdr->u.info.rxseq, gotchoke);
  261.  
  262.             /* If we haven't seen the choke flag before, purge the
  263.              * send window and set the timer and the flag.
  264.              */
  265.             if(!cb->choked && gotchoke)
  266.                 nr4choke(cb);
  267.             break;
  268.           case NR4OPACK:
  269.             if(cb->choked && !gotchoke){
  270.                 /* clear choke if appropriate */
  271.                 stop_timer(&cb->tchoke);
  272.                 cb->choked = 0;
  273.             }    
  274.               if(hdr->opcode & NR4NAK && !gotchoke)
  275.                 nr4gotnak(cb, hdr->u.ack.rxseq);    /* process NAKs */
  276.                 
  277.               nr4ackours(cb, hdr->u.ack.rxseq, gotchoke); /* and ACKs */
  278.  
  279.             if(!cb->choked && gotchoke)    /* First choke seen */
  280.                 nr4choke(cb);        /* Set choke status */
  281.  
  282.             break;
  283.         }
  284.         break;
  285.     case NR4STDPEND:
  286.         switch(op){
  287.         case NR4OPDISAK:
  288.               cb->dreason = NR4RNORMAL;
  289.             nr4state(cb, NR4STDISC);
  290.             break;
  291.         case NR4OPINFO:
  292.             /* We can still do receive frame processing until
  293.              * the disconnect acknowledge arrives, but we won't
  294.              * bother to process ACKs, since we've flushed our
  295.              * transmit buffers and queue already.
  296.              */
  297.               nr4rframe(cb, hdr->u.info.txseq, bp);
  298.             break;
  299.         }
  300.     }    /* End switch(state) */
  301. }
  302.  
  303.  
  304. /* Send a net/rom layer 4 frame.  bp should be NULLBUF unless the frame
  305.  * type is info.
  306.  */
  307. void
  308. nr4sframe(dest, hdr, bp)
  309. char *dest;
  310. struct nr4hdr *hdr;
  311. struct mbuf *bp;
  312. {
  313.     struct mbuf *n4b;
  314.  
  315.     if((n4b = htonnr4(hdr)) == NULLBUF){
  316.         free_p(bp);
  317.         return;
  318.     } else {
  319.         append(&n4b, bp);
  320.         nr3output(dest, n4b);
  321.     }
  322. }
  323.  
  324. /* Receive frame processing */
  325. static void
  326. nr4rframe(cb, rxseq, bp)
  327. struct nr4cb *cb;
  328. unsigned rxseq;
  329. struct mbuf *bp;
  330. {
  331.     struct nr4hdr rhdr;
  332.     unsigned window = cb->window;
  333.     unsigned rxbuf = rxseq % window;
  334.     unsigned newdata = 0;        /* whether to upcall */
  335.  
  336. #ifdef NR4DEBUG
  337.     printf("Processing received info\n");
  338. #endif
  339.  
  340.     /* If we're choked, just reset the ACK timer to blast out
  341.      * another CHOKE indication after the ackdelay
  342.      */
  343.     if(cb->qfull){
  344.         start_timer(&cb->tack);
  345.         return;
  346.     }
  347.     
  348.     /* If frame is out of sequence, it is either due to a lost frame
  349.      * or a retransmission of one seen earlier.  We do not want to NAK
  350.      * the latter, as the far end would see this as a requirement to
  351.      * retransmit the expected frame, which is probably already in the
  352.      * pipeline.  This in turn would cause another out-of-sequence
  353.      * condition, another NAK, and the process would repeat indefinitely.
  354.      * Therefore, if the frame is out-of-sequence, but within the last
  355.      * 'n' frames by sequence number ('n' being the window size), just
  356.      * accept it and discard it.  Else, NAK it if we haven't already.
  357.      *    (Modified by Rob Stampfli, kd8wk, 9 Jan 1990)
  358.      */
  359.     if(rxseq != cb->rxpected && !cb->naksent){
  360. #ifdef NR4DEBUG
  361.         printf("Frame out of sequence -- expected %u, got %u.\n",
  362.                cb->rxpected, rxseq);
  363. #endif                
  364.         if(nr4between(cb->rxpected,
  365.            (rxseq + window) & NR4SEQMASK, cb->rxpastwin))
  366.             /* just a repeat of old frame -- queue ack for
  367.              * expected frame
  368.              */
  369.             start_timer(&cb->tack);
  370.         else {            /* really bogus -- a NAKable frame */
  371.             rhdr.opcode = NR4OPACK | NR4NAK;
  372.             rhdr.yourindex = cb->yournum;
  373.             rhdr.yourid = cb->yourid;
  374.             rhdr.u.ack.rxseq = cb->rxpected;
  375.             nr4sframe(cb->remote.node,&rhdr,NULLBUF);
  376.         
  377.             /* Now make sure we don't send any more of these until
  378.              * we see some good data.  Otherwise full window
  379.              * retransmissions would result in a flurry of NAKs
  380.              */
  381.         
  382.             cb->naksent = 1;
  383.         }
  384.     }
  385.             
  386.     /* If this is a new frame, within the window, buffer it,
  387.      * then see what we can deliver
  388.      */
  389.     if(nr4between(cb->rxpected,rxseq,cb->rxpastwin)
  390.         && !cb->rxbufs[rxbuf].occupied){
  391. #ifdef NR4DEBUG
  392.         printf("Frame within window\n");
  393. #endif
  394.         cb->rxbufs[rxbuf].occupied = 1;
  395.         cb->rxbufs[rxbuf].data = bp;
  396.                 
  397.         for(rxbuf = cb->rxpected % window; cb->rxbufs[rxbuf].occupied;
  398.              rxbuf = cb->rxpected % window){
  399. #ifdef NR4DEBUG
  400.             printf("Removing frame from buffer %d\n", rxbuf);
  401. #endif
  402.             newdata = 1;
  403.             cb->rxbufs[rxbuf].occupied = 0;
  404.             append(&cb->rxq,cb->rxbufs[rxbuf].data);
  405.             cb->rxbufs[rxbuf].data = NULLBUF;
  406.             cb->rxpected = (cb->rxpected + 1) & NR4SEQMASK;
  407.             cb->rxpastwin = (cb->rxpastwin + 1) & NR4SEQMASK;
  408.         }
  409.         if(newdata){
  410.             cb->naksent = 0;    /* OK to send NAKs again */
  411.             if(cb->r_upcall != NULLVFP)
  412.                 (*cb->r_upcall)(cb,len_p(cb->rxq));
  413.  
  414.             /* Now that our upcall has had a shot at the queue, */
  415.             /* see if it's past the queue length limit.  If so, */
  416.             /* go into choked mode (i.e. flow controlled). */
  417.  
  418.             if(len_p(cb->rxq) > Nr4qlimit){
  419.                 cb->qfull = 1;
  420.                 nr4ackit((void *)cb);    /* Tell `em right away */
  421.             } else
  422.                 start_timer(&cb->tack);
  423.         }
  424.     } else     /* It's out of the window or we've seen it already */
  425.         free_p(bp);
  426. }
  427.  
  428.  
  429. /* Send the transmit buffer whose sequence number is seq */
  430. void
  431. nr4sbuf(cb, seq)
  432. struct nr4cb *cb;
  433. unsigned seq;
  434. {
  435.     struct nr4hdr hdr;
  436.     struct mbuf *bufbp, *bp;
  437.     unsigned bufnum = seq % cb->window;
  438.     struct timer *t;
  439.     
  440.     /* sanity check */
  441.     if(bufnum >= cb->window){
  442. #ifdef NRDEBUG
  443.         printf("sbuf: buffer number %u beyond window\n",bufnum);
  444. #endif
  445.         return;
  446.     }
  447.  
  448.     /* Stop the ACK timer, since our sending of the frame is
  449.      * an implied ACK.
  450.      */
  451.     stop_timer(&cb->tack);
  452.     
  453.     /* Duplicate the mbuf, since we have to keep it around
  454.      * until it is acknowledged
  455.      */
  456.     bufbp = cb->txbufs[bufnum].data;
  457.  
  458.     /* Notice that we use copy_p instead of dup_p.  This is because
  459.      * a frame can still be sitting on the AX.25 send queue when it
  460.      * get acknowledged, and we don't want to deallocate its data
  461.      * before it gets sent!
  462.      */
  463.     if((bp = copy_p(bufbp, len_p(bufbp))) == NULLBUF){
  464.         free_mbuf(bp);
  465.         return;
  466.     }
  467.  
  468.     /* Prepare the header */
  469.     if(cb->qfull)                /* are we choked? */
  470.         hdr.opcode = NR4OPINFO | NR4CHOKE;
  471.     else
  472.         hdr.opcode = NR4OPINFO;
  473.     hdr.yourindex = cb->yournum;
  474.     hdr.yourid = cb->yourid;
  475.     hdr.u.info.txseq = (unsigned char)(seq & NR4SEQMASK);
  476.     hdr.u.info.rxseq = cb->rxpected;
  477.     
  478.     /* Send the frame, then set and start the timer */
  479.     nr4sframe(cb->remote.node, &hdr, bp);
  480.  
  481.     t = &cb->txbufs[bufnum].tretry;
  482.     set_timer(t, (1 << cb->blevel) * (4 * cb->mdev + cb->srtt));
  483.     start_timer(t);
  484. }
  485.  
  486. /* Check to see if any of our frames have been ACKed */
  487.  
  488. static void
  489. nr4ackours(cb, seq, gotchoke)
  490. struct nr4cb *cb;
  491. unsigned seq;
  492. int gotchoke;    /* The choke flag is set in the received frame */
  493. {
  494.     unsigned txbuf;
  495.     struct timer *t;
  496.     
  497.     /* If we are choked, there is nothing in the send window
  498.      * by definition, so we can just return.
  499.      */
  500.     if(cb->choked)
  501.         return;
  502.         
  503.     /* Adjust seq to point to the frame being ACK'd, not the one
  504.      * beyond it, which is how it arrives.
  505.      */
  506.     seq = (seq - 1) & NR4SEQMASK;
  507.  
  508.     /* Free up all the ack'd frames, and adjust the round trip
  509.      * timing stuff
  510.      */
  511.     while (nr4between(cb->ackxpected, seq, cb->nextosend)){
  512. #ifdef NR4DEBUG
  513.         printf("Sequence # %u acknowledged\n", seq);
  514. #endif
  515.         cb->nbuffered--;
  516.         txbuf = cb->ackxpected % cb->window;
  517.         free_mbuf(cb->txbufs[txbuf].data);
  518.         cb->txbufs[txbuf].data = NULLBUF;
  519.         cb->ackxpected = (cb->ackxpected + 1) & NR4SEQMASK;
  520.  
  521.         /* Round trip time estimation, cribbed from TCP */
  522.         if(cb->txbufs[txbuf].retries == 0){
  523.             /* We only sent this one once */
  524.             int32 rtt;
  525.             int32 abserr;
  526.  
  527.             t = &cb->txbufs[txbuf].tretry;
  528.             /* get our rtt in msec */
  529.             rtt = dur_timer(t) - read_timer(t);
  530.             abserr = (rtt > cb->srtt) ? rtt - cb->srtt : cb->srtt - rtt;
  531.             cb->srtt = (cb->srtt * 7 + rtt) >> 3;
  532.             cb->mdev = (cb->mdev * 3 + abserr) >> 2;
  533.  
  534.             /* Reset the backoff level */
  535.             cb->blevel = 0;
  536.         }
  537.         stop_timer(&cb->txbufs[txbuf].tretry);
  538.     }    
  539.     /* Now we recalculate tmax, the maximum number of retries for
  540.      * any frame in the window.  tmax is used as a baseline to
  541.      * determine when the window has reached a new high in retries.
  542.      * We don't want to increment blevel for every frame that times
  543.      * out, since that would lead to us backing off too fast when
  544.      * all the frame timers expired at around the same time.
  545.      */
  546.     cb->txmax = 0;
  547.     
  548.     for(seq = cb->ackxpected;
  549.          nr4between(cb->ackxpected, seq, cb->nextosend);
  550.          seq = (seq + 1) & NR4SEQMASK)
  551.         if(cb->txbufs[seq % cb->window].retries > cb->txmax)
  552.             cb->txmax = cb->txbufs[seq % cb->window].retries;
  553.  
  554.     /* This is kind of a hack.  This function is called under
  555.      * three different conditions:  either we are choked, in
  556.      * which case we return immediately, or we are not choked,
  557.      * in which case we proceed normally to keep the send
  558.      * window full, or we have seen the choke flag for the first
  559.      * time.  In the last case, gotchoke is true while cb->choked
  560.      * is false.  We want to process any acknowledgments of existing
  561.      * frames in the send window before we purge it, while at the
  562.      * same time we don't want to take anything else off the txq
  563.      * or send it out.  So, in the third case we listed, we return
  564.      * now since we've processed the ACK.
  565.      */
  566.     
  567.     if(gotchoke)
  568.         return;
  569.         
  570.     nr4output(cb);            /* yank stuff off txq and send it */
  571.  
  572.     /* At this point, either the send window is full, or
  573.      * nr4output() didn't find enough on the txq to fill it.
  574.      * If the window is not full, then the txq must be empty,
  575.      * and we'll make a tx upcall
  576.      */
  577.     if(cb->nbuffered < cb->window && cb->t_upcall != NULLVFP)
  578.         (*cb->t_upcall)(cb, (int16)((cb->window - cb->nbuffered) * NR4MAXINFO));
  579.  
  580. }
  581.  
  582.  
  583. /* If the send window is open and there are frames on the txq,
  584.  * move as many as possible to the transmit buffers and send them.
  585.  * Return the number of frames sent.
  586.  */
  587. int
  588. nr4output(cb)
  589. struct nr4cb *cb;
  590. {
  591.     int numq, i;
  592.     struct mbuf *bp;
  593.     struct nr4txbuf *tp;
  594.  
  595.     /* Are we in the proper state? */
  596.     if(cb->state != NR4STCON || cb->choked)
  597.         return 0;        /* No sending if not connected */
  598.                     /* or if choked */
  599.         
  600.     /* See if the window is open */
  601.     if(cb->nbuffered >= cb->window)
  602.         return 0;
  603.  
  604.     numq = len_q(cb->txq);
  605.     
  606. #ifdef NR4DEBUG
  607.     printf("nr4output: %d packets on txq\n", numq);
  608. #endif
  609.     
  610.     for(i = 0; i < numq; i++){
  611.         bp = dequeue(&cb->txq);
  612. #ifdef NR4DEBUG
  613.         if(len_p(bp) > NR4MAXINFO){    /* should be checked higher up */
  614.             printf("Upper layers queued too big a buffer\n");
  615.             continue;
  616.         }
  617. #endif
  618.         /* Set up and send buffer */
  619.         tp = &cb->txbufs[cb->nextosend % cb->window];
  620.         tp->retries = 0;
  621.         tp->data = bp;
  622.         nr4sbuf(cb, cb->nextosend);
  623.  
  624.         /* Update window and buffered count */
  625.         cb->nextosend = (cb->nextosend + 1) & NR4SEQMASK;
  626.         if(++cb->nbuffered >= cb->window)
  627.             break;
  628.     }
  629.     return i;        
  630. }
  631.  
  632. void
  633. nr4state(cb, newstate)
  634. struct nr4cb *cb;
  635. int newstate;
  636. {
  637.     int i;
  638.     int oldstate = cb->state;
  639.     
  640.     cb->state = newstate;
  641.  
  642.     switch(cb->state){
  643.     case NR4STDPEND:
  644.         stop_timer(&cb->tchoke);
  645.  
  646.         /* When we request a disconnect, we lose the contents of
  647.          * our transmit queue and buffers, but we retain our ability
  648.          * to receive any packets in transit until a disconnect
  649.          * acknowledge arrives
  650.          */
  651.         free_q(&cb->txq);
  652.         
  653.         for(i = 0; i < cb->window; i++){
  654.             free_mbuf(cb->txbufs[i].data);
  655.             cb->txbufs[i].data = NULLBUF;
  656.             stop_timer(&cb->txbufs[i].tretry);
  657.         }
  658.         
  659.         /* Tidy up stats: roll the top window pointer back
  660.          * and reset nbuffered to reflect this.  Not really
  661.          * necessary, but leads to a bit more truth telling
  662.          * in the status displays.
  663.          */
  664.         cb->nextosend = cb->ackxpected;
  665.         cb->nbuffered = 0;
  666.         break;
  667.       case NR4STDISC:
  668.         stop_timer(&cb->tchoke);
  669.         stop_timer(&cb->tack);
  670.         stop_timer(&cb->tcd);
  671.  
  672.         /* We don't clear the rxq, since the state change upcall
  673.          * may pull something off of it at the last minute.
  674.          */
  675.         free_q(&cb->txq);
  676.  
  677.         /* The following loop will only be executed if the
  678.          * window was set, since when the control block is
  679.          * calloc'd the window field gets a 0 in it.  This
  680.          * protects us from dereferencing an unallocated
  681.          * window buffer pointer
  682.          */
  683.         for(i = 0; i < cb->window; i++){
  684.             free_mbuf(cb->rxbufs[i].data);
  685.             cb->rxbufs[i].data = NULLBUF;
  686.             free_mbuf(cb->txbufs[i].data);
  687.             cb->txbufs[i].data = NULLBUF;
  688.             stop_timer(&cb->txbufs[i].tretry);
  689.         }
  690.         break;
  691.     }
  692.  
  693.     if(oldstate != newstate && cb->s_upcall != NULLVFP)
  694.         (*cb->s_upcall)(cb, oldstate, newstate);
  695.  
  696.     /* We take responsibility for deleting the circuit
  697.      * descriptor.  Don't do this anywhere else!
  698.      */
  699.     if(newstate == NR4STDISC)
  700.         free_n4circ(cb);
  701. }
  702.  
  703. /* Process NAKs.  seq indicates the next frame expected by the
  704.  * NAK'ing station.
  705.  */
  706.  
  707. static void
  708. nr4gotnak(cb, seq)
  709. struct nr4cb *cb;
  710. unsigned seq;
  711. {
  712.     if(nr4between(cb->ackxpected, seq, cb->nextosend))
  713.         nr4sbuf(cb, seq);
  714. }
  715.  
  716.  
  717. /* This is called when we first get a CHOKE indication from the
  718.  * remote.  It purges the send window and sets the choke timer.
  719.  */
  720.  
  721. static void
  722. nr4choke(cb)
  723. struct nr4cb *cb;
  724. {
  725.     unsigned seq;
  726.     struct mbuf *q, *bp;
  727.     struct nr4txbuf *t;
  728.  
  729.     q = cb->txq;
  730.  
  731.     /* We purge the send window, returning the buffers to the
  732.      * txq in the proper order.
  733.      */
  734.     for(seq = (cb->nextosend - 1) & NR4SEQMASK;
  735.          nr4between(cb->ackxpected, seq, cb->nextosend);
  736.          seq = (seq - 1) & NR4SEQMASK){
  737.  
  738.         t = &cb->txbufs[seq % cb->window];
  739.         stop_timer(&t->tretry);
  740.         bp = t->data;
  741.         t->data = NULLBUF;
  742.         enqueue(&bp, q);    /* prepend this packet to the queue */
  743.         q = bp;
  744.      }
  745.  
  746.     cb->nextosend = cb->ackxpected;    /* close the window */
  747.     cb->nbuffered = 0;        /* nothing in the window */
  748.     cb->txq = q;            /* Replace the txq with the one that has */
  749.                     /* the purged packets prepended */
  750.     cb->choked = 1;        /* Set the choked flag */
  751.  
  752.     start_timer(&cb->tchoke);
  753. }
  754.  
  755. #endif    /* NETROM */
  756.