home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 3 / PDCD_3.iso / internet / tcpipsrc / h / if / Radio / c / NR4 < prev    next >
Text File  |  1993-12-22  |  27KB  |  707 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.  */
  5.  
  6. #include <stdio.h>
  7. #include <time.h>
  8. #include <ctype.h>
  9. #include "global.h"
  10. #include "mbuf.h"
  11. #include "timer.h"
  12. #include "ax25.h"
  13. #include "lapb.h"
  14. #include "netrom.h"
  15. #include "nr4.h"
  16. #include "misc.h"
  17.  
  18. #undef NR4DEBUG
  19.  
  20. /* Globals: */
  21.  
  22. /* The circuit table */
  23.  
  24. struct nr4circp Nr4circuits[NR4MAXCIRC] ;
  25.  
  26. /* Various limits */
  27.  
  28. unsigned Nr4window = 4 ;                /* Max window to negotiate */
  29. unsigned Nr4retries = 10 ;              /* Max retries */
  30. unsigned Nr4qlimit = 2048 ;             /* Max bytes on receive queue */
  31.  
  32. /* Timers */
  33.  
  34. long Nr4irtt = 15000 ;                  /* Initial round trip time */
  35. long Nr4acktime = 3000 ;                /* ACK delay timer */
  36. long Nr4choketime = 180000 ;    /* CHOKEd state timeout */
  37.  
  38.  
  39. /* This function is called when a net/rom layer four frame */
  40. /* is discovered inside a datagram addressed to us */
  41.  
  42. void nr4input(struct nr4hdr *hdr, struct mbuf *bp)
  43. {
  44.         struct nr4hdr rhdr ;
  45.         struct nr4cb *cb ;
  46.         struct ax25_addr dest ;
  47.         int op ;
  48.         unsigned window ;
  49.         int acceptc ;           /* indicates that connection should be accepted */
  50.         int newconn ;           /* indicates that this is a new incoming */
  51.                                                 /* connection.  You'll see. */
  52.         int gotchoke ;          /* The choke flag was set in this packet */             
  53.         
  54.         op = hdr->opcode & NR4OPCODE ;  /* Mask off flags */
  55.         
  56.         if (op == NR4OPCONRQ) {                 /* process connect request first */
  57.                 acceptc = 1 ;
  58.                 newconn = 0 ;
  59.  
  60.                 /* These fields are sent regardless of success */
  61.                 
  62.                 rhdr.yourindex = hdr->u.conreq.myindex ;
  63.                 rhdr.yourid = hdr->u.conreq.myid ;
  64.                 dest = hdr->u.conreq.node ;
  65.  
  66.                 /* Check to see if we have already received a connect */
  67.                 /* request for this circuit. */
  68.  
  69.                 if ((cb = match_n4circ(hdr->u.conreq.myindex, hdr->u.conreq.myid,
  70.                                                                   &hdr->u.conreq.user, &hdr->u.conreq.node))
  71.                          == NULLNR4CB) {        /* No existing circuit if NULL */
  72.  
  73.                         /* Try to get a new circuit */
  74.  
  75.                         if ((cb = new_n4circ()) == NULLNR4CB) {
  76.                                 acceptc = 0 ;
  77.                         } else {
  78.                         
  79.                                 /* Window is set to min of the offered and local windows */
  80.                                 
  81.                                 window = hdr->u.conreq.window > Nr4window ?
  82.                                                  Nr4window : hdr->u.conreq.window ;
  83.  
  84.                                 if (init_nr4window(cb, window) == -1) {
  85.                                         free_n4circ(cb) ;
  86.                                         acceptc = 0 ;
  87.                                 } else {
  88.                                         /* Set up control block */
  89.                                         cb->yournum = hdr->u.conreq.myindex ;
  90.                                         cb->yourid = hdr->u.conreq.myid ;
  91.                                         cb->user = hdr->u.conreq.user ;
  92.                                         cb->node = hdr->u.conreq.node ;
  93.                                         cb->luser = mycall ;/* we are local user on incomings */
  94.                                         cb->srtt = Nr4irtt ;/* Default round trip time */
  95.                                         nr4defaults(cb) ;       /* set up timers, window pointers */
  96.                                         cb->s_upcall = nr4_incom ;
  97.                                         cb->state = NR4STDISC ;
  98.                                         newconn = 1 ;
  99.                                 } /* End if window successfully allocated */
  100.                                 
  101.                         }       /* End if new circuit available */
  102.                         
  103.                  } /* End if no existing circuit matching parameters */
  104.                  
  105.                 /* Now set up response */
  106.  
  107.                 if (!acceptc) {
  108.                         rhdr.opcode = NR4OPCONAK | NR4CHOKE ;/* choke means reject */
  109.                         rhdr.u.conack.myindex = 0 ;
  110.                         rhdr.u.conack.myid = 0 ;
  111.                         rhdr.u.conack.window = 0 ;
  112.                 } else {
  113.                         rhdr.opcode = NR4OPCONAK ;
  114.                         rhdr.u.conack.myindex = cb->mynum ;
  115.                         rhdr.u.conack.myid = cb->myid ;
  116.                         rhdr.u.conack.window = cb->window ;
  117.                 }
  118.                 nr4sframe(&dest, &rhdr, NULLBUF) ;
  119.  
  120.                 /* Why, you ask, do we wait until now for the state change */
  121.                 /* upcall?  Well, it's like this:  if the state change triggers */
  122.                 /* something like the mailbox to send its banner, the banner */
  123.                 /* would have gone out *before* the conn ack if we'd done this */
  124.                 /* in the code above.  This is what happens when you don't plan */
  125.                 /* too well.  Learn from my mistakes :-) */
  126.                 
  127.                 if (newconn)
  128.                         nr4state(cb, NR4STCON) ;/* connected (no 3-way handshake) */
  129.                         
  130.                 free_p(bp) ;
  131.                 return ;
  132.         } /* end connect request code */
  133.  
  134.         /* validate circuit number */
  135.  
  136.         if ((cb = get_n4circ(hdr->yourindex, hdr->yourid)) == NULLNR4CB) {
  137.                 free_p(bp) ;
  138.                 return ;
  139.         }
  140.  
  141.         /* Check for choke flag */
  142.  
  143.         if (hdr->opcode & NR4CHOKE)
  144.                 gotchoke = 1 ;
  145.         else
  146.                 gotchoke = 0 ;
  147.         
  148.         /* Here's where the interesting stuff gets done */
  149.  
  150.         switch (cb->state) {
  151.           case NR4STCPEND:
  152.             switch (op) {
  153.                   case NR4OPCONAK:
  154.                         stop_timer(&cb->tcd) ;
  155.                     if (gotchoke) {                                     /* connect rejected */
  156.                                 cb->dreason = NR4RREFUSED ;
  157.                                 nr4state(cb, NR4STDISC) ;
  158.                                 break ;
  159.                         }
  160.                         cb->yournum = hdr->u.conack.myindex ;
  161.                         cb->yourid = hdr->u.conack.myid ;
  162.                         window = hdr->u.conack.window > Nr4window ?
  163.                                          Nr4window : hdr->u.conack.window ;
  164.  
  165.                         if (init_nr4window(cb, window) == -1) {
  166.                                 cb->dreason = NR4RRESET ;
  167.                                 nr4state(cb, NR4STDISC) ;
  168.                         } else {
  169.                                 nr4defaults(cb) ;       /* set up timers, window pointers */
  170.                                 
  171.                                 if (cb->cdtries == 1)                   /* No retries */
  172.                                         cb->srtt = cb->tcd.count * MSPTICK ;/* Use measured rtt */
  173.                                 else
  174.                                         cb->srtt = Nr4irtt ;            /* else use default */
  175.                                         
  176.                                 nr4state(cb, NR4STCON) ;
  177.                                 nr4output(cb) ;         /* start sending anything on the txq */
  178.                         }
  179.                         break ;
  180.  
  181.                   default:              /* We can't respond to anything else without */
  182.                                                 /* Their ID and index */
  183.                         free_p(bp) ;
  184.                         return ;
  185.                 }
  186.                 break ;
  187.                 
  188.           case NR4STCON:
  189.             switch (op) {
  190.                   case NR4OPDISRQ:
  191.                         /* format reply packet */
  192.                         rhdr.opcode = NR4OPDISAK ;
  193.                         rhdr.yourindex = cb->yournum ;
  194.                         rhdr.yourid = cb->y