home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 024 / psi110g.zip / NR4USER.C < prev    next >
C/C++ Source or Header  |  1994-04-17  |  7KB  |  257 lines

  1. /* net/rom level 4 (transport) protocol user level calls
  2.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  3.  * non-commercial distribution only.
  4.  */
  5.   
  6. #include "global.h"
  7. #ifdef NETROM
  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. /* Open a NET/ROM transport connection */
  19. struct nr4cb *
  20. open_nr4(local,remote,mode,r_upcall,t_upcall,s_upcall,user)
  21. struct nr4_addr *local ;    /* local node address */
  22. struct nr4_addr *remote ;   /* destination node address */
  23. int mode ;          /* active/passive/server */
  24. void (*r_upcall)__ARGS((struct nr4cb *,int)) ;      /* received data upcall */
  25. void (*t_upcall)__ARGS((struct nr4cb *,int)) ;      /* transmit upcall */
  26. void (*s_upcall)__ARGS((struct nr4cb *,int,int)) ;  /* state change upcall */
  27. int user ;          /* user linkage area */
  28. {
  29.     struct nr4cb *cb ;
  30.     struct nr4hdr hdr ;
  31.     struct nr4_addr nr4tmp;
  32.   
  33.     if ((cb = new_n4circ()) == NULLNR4CB)
  34.         return NULLNR4CB ;      /* No circuits available */
  35.   
  36.     if(remote == NULLNRADDR){
  37.         remote = &nr4tmp;
  38.         setcall(remote->user," ");
  39.         setcall(remote->node," ");
  40.     }
  41.   
  42.     /* Stuff what info we can into control block */
  43.   
  44.     ASSIGN(cb->remote,*remote) ;
  45.     /* Save local address for connect retries */
  46.     ASSIGN(cb->local,*local) ;
  47.   
  48.     cb->r_upcall = (void (*)(struct nr4cb *,int16)) r_upcall ;
  49.     cb->t_upcall = (void (*)(struct nr4cb *,int16)) t_upcall ;
  50.     cb->s_upcall = s_upcall ;
  51.     cb->user = user ;
  52.     cb->clone = 0 ;
  53.   
  54.     switch(mode){
  55.         case AX_SERVER:
  56.             cb->clone = 1;
  57.         case AX_PASSIVE:    /* Note fall-thru */
  58.             cb->state = NR4STLISTEN;
  59.             return cb;
  60.         case AX_ACTIVE:
  61.             break;
  62.     }
  63.     /* Format connect request header */
  64.   
  65.     hdr.opcode = NR4OPCONRQ ;
  66.     hdr.u.conreq.myindex = cb->mynum ;
  67.     hdr.u.conreq.myid = cb->myid ;
  68.     hdr.u.conreq.window = Nr4window ;
  69.     memcpy(hdr.u.conreq.user,local->user,AXALEN);
  70.   
  71.     /* If I have a unique callsign per interface, then a layer violation */
  72.     /* will be required to determine the "real" callsign for my */
  73.     /* (virtual) node.  This suggests that callsign-per-interface is not */
  74.     /* desirable, which answers *that* particular open question. */
  75.   
  76.     memcpy(hdr.u.conreq.node,local->node,AXALEN);
  77.   
  78.     /* Set and start connection retry timer */
  79.   
  80.     cb->cdtries = 1 ;
  81.     cb->srtt = Nr4irtt ;
  82.     set_timer(&cb->tcd,2 * cb->srtt);
  83.     cb->tcd.func = nr4cdtimeout ;
  84.     cb->tcd.arg = cb ;
  85.     start_timer(&cb->tcd) ;
  86.   
  87.     /* Send connect request packet */
  88.   
  89.     nr4sframe(remote->node,&hdr,NULLBUF) ;
  90.   
  91.     /* Set up initial state and signal state change */
  92.   
  93.     cb->state = NR4STDISC ;
  94.     nr4state(cb, NR4STCPEND) ;
  95.   
  96.     /* Return control block address */
  97.   
  98.     return cb ;
  99. }
  100.   
  101. /* Send a net/rom transport data packet */
  102. /* Modified to fragment packets larger then Nr_iface->mtu
  103.  * into smaller ones. This allows NETROM to work over ax.25 connections
  104.  * with paclen < 256, WITHOUT fragmenting in the ax.25 layer (ie. v2.1)
  105.  * Thus staying compatible with Thenet, BPQ etc... - WG7J
  106.  */
  107. int
  108. send_nr4(cb,bp)
  109. struct nr4cb *cb ;
  110. struct mbuf *bp ;
  111. {
  112.     struct mbuf *bp1;
  113.     int16 offset,len,size;
  114.   
  115.     if (cb == NULLNR4CB || bp == NULLBUF) {
  116.         free_p(bp);
  117.         return -1 ;
  118.     }
  119.   
  120.     if((len = len_p(bp)) > Nr_iface->mtu) {
  121.         offset = 0;
  122.         /* It is important that all the pushdowns be done before
  123.          * any part of the original packet is freed.
  124.          * Otherwise the pushdown might erroneously overwrite
  125.          * a part of the packet that had been duped and freed.
  126.          */
  127.         while(len != 0){
  128.             size = min(len,Nr_iface->mtu);
  129.             dup_p(&bp1,bp,offset,size);
  130.             len -= size;
  131.             offset += size;
  132.             enqueue(&cb->txq,bp1);
  133.         }
  134.         free_p(bp);
  135.     } else
  136.         enqueue(&cb->txq,bp);
  137.   
  138.     return nr4output(cb) ;
  139. }
  140.   
  141. /* Receive incoming net/rom transport data */
  142. struct mbuf *
  143. recv_nr4(cb,cnt)
  144. struct nr4cb *cb ;
  145. int16 cnt ;
  146. {
  147.     struct mbuf *bp ;
  148.   
  149.     if (cb->rxq == NULLBUF)
  150.         return NULLBUF ;
  151.   
  152.     if (cnt == 0) {
  153.         bp = cb->rxq ;          /* Just give `em everything */
  154.         cb->rxq = NULLBUF ;
  155.     }
  156.     else {
  157.         bp = ambufw(cnt);
  158.         bp->cnt = pullup(&cb->rxq,bp->data,cnt);
  159.     }
  160.     /* If this has un-choked us, reopen the window */
  161.     if (cb->qfull && len_p(cb->rxq) < Nr4qlimit) {
  162.         cb->qfull = 0 ;             /* Choke flag off */
  163.         nr4ackit(cb) ;      /* Get things rolling again */
  164.     }
  165.   
  166.     return bp ;
  167. }
  168.   
  169. /* Close a NET/ROM connection */
  170. void
  171. disc_nr4(cb)
  172. struct nr4cb *cb ;
  173. {
  174.     struct nr4hdr hdr ;
  175.   
  176.     if (cb->state == NR4STLISTEN) {
  177.         free_n4circ(cb);
  178.         return;
  179.     }
  180.     if (cb->state != NR4STCON)
  181.         return ;
  182.   
  183.     /* Format disconnect request packet */
  184.   
  185.     hdr.opcode = NR4OPDISRQ ;
  186.     hdr.yourindex = cb->yournum ;
  187.     hdr.yourid = cb->yourid ;
  188.   
  189.     /* Set and start timer */
  190.   
  191.     cb->cdtries = 1 ;
  192.     set_timer(&cb->tcd,2 * cb->srtt);
  193.     cb->tcd.func = nr4cdtimeout ;
  194.     cb->tcd.arg = cb ;
  195.     start_timer(&cb->tcd) ;
  196.   
  197.     /* Send packet */
  198.   
  199.     nr4sframe(cb->remote.node, &hdr, NULLBUF) ;
  200.   
  201.     /* Signal state change.  nr4state will take care of stopping */
  202.     /* the appropriate timers and resetting window pointers. */
  203.   
  204.     nr4state(cb, NR4STDPEND) ;
  205.   
  206. }
  207.   
  208. /* Abruptly terminate a NET/ROM transport connection */
  209. void
  210. reset_nr4(cb)
  211. struct nr4cb *cb ;
  212. {
  213.     /* Be nice and send a disconnect frame */
  214.     disc_nr4(cb);
  215.     cb->dreason = NR4RRESET ;
  216.     nr4state(cb,NR4STDISC) ;
  217. }
  218.   
  219.   
  220. /* Force retransmission on a NET/ROM transport connection */
  221. int
  222. kick_nr4(cb)
  223. struct nr4cb *cb ;
  224. {
  225.     unsigned seq ;
  226.     struct timer *t ;
  227.   
  228.     if(!nr4valcb(cb))
  229.         return -1 ;
  230.   
  231.     switch (cb->state) {
  232.         case NR4STCPEND:
  233.         case NR4STDPEND:
  234.             stop_timer(&cb->tcd) ;
  235.             nr4cdtimeout(cb) ;
  236.             break ;
  237.   
  238.         case NR4STCON:
  239.             if (cb->nextosend != cb->ackxpected) {  /* if send window is open: */
  240.                 for (seq = cb->ackxpected ;
  241.                     nr4between(cb->ackxpected, seq, cb->nextosend) ;
  242.                 seq = (seq + 1) & NR4SEQMASK) {
  243.                     t = &cb->txbufs[seq % cb->window].tretry ;
  244.                     stop_timer(t) ;
  245.                     t->state = TIMER_EXPIRE ;   /* fool retry routine */
  246.                 }
  247.                 nr4txtimeout(cb) ;
  248.             }
  249.             break ;
  250.     }
  251.   
  252.     return 0 ;
  253. }
  254.   
  255. #endif /* NETROM */
  256.   
  257.