home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 1 / HamRadio.cdr / misc / src0131 / nr4timer.c < prev    next >
C/C++ Source or Header  |  1989-09-26  |  4KB  |  171 lines

  1. /* net/rom level 4 (transport) protocol timer management.
  2.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  3.  * non-commercial distribution only.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include "global.h"
  8. #include "mbuf.h"
  9. #include "timer.h"
  10. #include "ax25.h"
  11. #include "lapb.h"
  12. #include "netrom.h"
  13. #include "nr4.h"
  14. #include <ctype.h>
  15.  
  16. #undef NR4DEBUG
  17.  
  18. /* The ACK timer has expired without any data becoming available.
  19.  * Go ahead and send an ACK.
  20.  */
  21.  
  22. void
  23. nr4ackit(p)
  24. void *p ;
  25. {
  26.     struct nr4cb *cb  = (struct nr4cb *)p ;
  27.     struct nr4hdr rhdr ;
  28.  
  29. #ifdef NR4DEBUG
  30.     printf("ACKIT called.\n") ;
  31. #endif
  32.     if (cb->qfull)                /* Are we choked? */
  33.         rhdr.opcode = NR4OPACK | NR4CHOKE ;
  34.     else
  35.         rhdr.opcode = NR4OPACK ;
  36.     rhdr.yourindex = cb->yournum ;
  37.     rhdr.yourid = cb->yourid ;
  38.     rhdr.u.ack.rxseq = cb->rxpected ;
  39.  
  40.     nr4sframe(cb->remote.node, &rhdr, NULLBUF) ;
  41. }
  42.  
  43. /* Called when one of the transmit timers has expired */
  44.  
  45. void
  46. nr4txtimeout(p)
  47. void *p ;
  48. {
  49.     struct nr4cb *cb = (struct nr4cb *)p ;
  50.     unsigned seq ;
  51.     struct nr4txbuf *t ;
  52.  
  53.     /* Sanity check */
  54.  
  55.     if (cb->state != NR4STCON)
  56.         return ;
  57.  
  58.     /* Scan through the send window looking for expired timers */
  59.     
  60.     for (seq = cb->ackxpected ;
  61.          nr4between(cb->ackxpected, seq, cb->nextosend) ;
  62.          seq = (seq + 1) & NR4SEQMASK) {
  63.         
  64.         t = &cb->txbufs[seq % cb->window] ;
  65.  
  66.         if (t->tretry.state == TIMER_EXPIRE) {
  67.             t->tretry.state = TIMER_STOP ;    /* So we don't do it again */
  68.  
  69.             if (t->retries == Nr4retries) {
  70.                 cb->dreason = NR4RTIMEOUT ;
  71.                 nr4state(cb, NR4STDISC) ;
  72.             }
  73.  
  74.             t->retries++ ;
  75.             
  76.             /* We keep track of the highest retry count in the window. */
  77.             /* If packet times out and its new retry count exceeds the *
  78.             /* max, we update the max and bump the backoff level.  This */
  79.             /* expedient is to avoid bumping the backoff level for every */
  80.             /* expiration, since with more than one timer we would back */
  81.             /* off way too fast (and at a rate dependent on the window */
  82.             /* size! */
  83.  
  84.             if (t->retries > cb->txmax) {
  85.                 cb->blevel++ ;
  86.                 cb->txmax = t->retries ;    /* update the max */
  87.             }
  88.             
  89.             nr4sbuf(cb,seq) ;    /* Resend buffer */
  90.         }
  91.      }
  92.     
  93. }
  94.  
  95. /* Connect/disconnect acknowledgement timeout */
  96.  
  97. void
  98. nr4cdtimeout(p)
  99. void *p ;
  100. {
  101.     struct nr4cb *cb = (struct nr4cb *)p ;
  102.     struct nr4hdr hdr ;
  103.  
  104.     switch(cb->state) {
  105.       case NR4STCPEND:
  106.           if (cb->cdtries == Nr4retries) {    /* Have we tried long enough? */
  107.             cb->dreason = NR4RTIMEOUT ;
  108.             nr4state(cb, NR4STDISC) ;        /* Give it up */
  109.         } else {
  110.             /* Set up header */
  111.             
  112.             hdr.opcode = NR4OPCONRQ ;
  113.             hdr.u.conreq.myindex = cb->mynum ;
  114.             hdr.u.conreq.myid = cb->myid ;
  115.             hdr.u.conreq.window = Nr4window ;
  116.             memcpy(hdr.u.conreq.user,cb->local.user,AXALEN) ;
  117.             memcpy(hdr.u.conreq.node,cb->local.node,AXALEN) ;
  118.  
  119.             /* Bump tries counter and backoff level, and restart timer */
  120.             /* We use a binary exponential backoff. */
  121.             
  122.             cb->cdtries++ ;
  123.             cb->blevel++ ;
  124.             cb->tcd.start *= 2 ;
  125.             start_timer(&cb->tcd) ;
  126.  
  127.             /* Send connect request packet */
  128.  
  129.             nr4sframe(cb->remote.node,&hdr, NULLBUF) ;
  130.         }
  131.         break ;
  132.         
  133.       case NR4STDPEND:
  134.           if (cb->cdtries == Nr4retries) {    /* Have we tried long enough? */
  135.             cb->dreason = NR4RTIMEOUT ;
  136.             nr4state(cb, NR4STDISC) ;        /* Give it up */
  137.         } else {
  138.             /* Format header */
  139.             
  140.             hdr.opcode = NR4OPDISRQ ;
  141.             hdr.yourindex = cb->yournum ;
  142.             hdr.yourid = cb->yourid ;
  143.  
  144.             /* Bump retry count and start timer */
  145.             /* We don't really need to be fancy here, since we */
  146.             /* should have a good idea of the round trip time by now. */
  147.             
  148.             cb->cdtries++ ;
  149.             start_timer(&cb->tcd) ;
  150.  
  151.             /* Send disconnect request packet */
  152.  
  153.             nr4sframe(cb->remote.node,&hdr, NULLBUF) ;
  154.         }
  155.         break ;
  156.     }
  157. }
  158.  
  159. /* The choke timer has expired.  Unchoke and kick. */
  160.  
  161. void
  162. nr4unchoke(p)
  163. void *p ;
  164. {
  165.     struct nr4cb *cb = (struct nr4cb *)p ;
  166.  
  167.     cb->choked = 0 ;
  168.     nr4output(cb) ;
  169. }
  170.  
  171.