nr4user.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:5k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  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. #include <stdio.h>
  6. #include "global.h"
  7. #include "mbuf.h"
  8. #include "timer.h"
  9. #include "ax25.h"
  10. #include "lapb.h"
  11. #include "netrom.h"
  12. #include "nr4.h"
  13. #include <ctype.h>
  14. #undef NR4DEBUG
  15. /* Open a NET/ROM transport connection */
  16. struct nr4cb *
  17. open_nr4(local,remote,mode,r_upcall,t_upcall,s_upcall,user)
  18. struct nr4_addr *local ; /* local node address */
  19. struct nr4_addr *remote ; /* destination node address */
  20. int mode ; /* active/passive/server */
  21. void (*r_upcall)(struct nr4cb *,uint16) ; /* received data upcall */
  22. void (*t_upcall)(struct nr4cb *,uint16) ; /* transmit upcall */
  23. void (*s_upcall)(struct nr4cb *,int,int) ; /* state change upcall */
  24. int user ; /* user linkage area */
  25. {
  26. struct nr4cb *cb ;
  27. struct nr4hdr hdr ;
  28. struct nr4_addr nr4tmp;
  29. if ((cb = new_n4circ()) == NULL)
  30. return NULL ; /* No circuits available */
  31. if(remote == NULL){
  32. remote = &nr4tmp;
  33. setcall(remote->user," ");
  34. setcall(remote->node," ");
  35. }
  36. /* Stuff what info we can into control block */
  37. ASSIGN(cb->remote,*remote) ;
  38. /* Save local address for connect retries */
  39. ASSIGN(cb->local,*local) ;
  40. cb->r_upcall = r_upcall ;
  41. cb->t_upcall = t_upcall ;
  42. cb->s_upcall = s_upcall ;
  43. cb->user = user ;
  44. cb->clone = 0 ;
  45. switch(mode){
  46. case AX_SERVER:
  47. cb->clone = 1;
  48. case AX_PASSIVE: /* Note fall-thru */
  49. cb->state = NR4STLISTEN;
  50. return cb;
  51. case AX_ACTIVE:
  52. break;
  53. }    
  54. /* Format connect request header */
  55. hdr.opcode = NR4OPCONRQ ;
  56. hdr.u.conreq.myindex = cb->mynum ;
  57. hdr.u.conreq.myid = cb->myid ;
  58. hdr.u.conreq.window = Nr4window ;
  59. memcpy(hdr.u.conreq.user,local->user,AXALEN);
  60. /* If I have a unique callsign per interface, then a layer violation */
  61. /* will be required to determine the "real" callsign for my */
  62. /* (virtual) node.  This suggests that callsign-per-interface is not */
  63. /* desirable, which answers *that* particular open question. */
  64. memcpy(hdr.u.conreq.node,local->node,AXALEN);
  65. /* Set and start connection retry timer */
  66. cb->cdtries = 1 ;
  67. cb->srtt = Nr4irtt ;
  68. set_timer(&cb->tcd,2 * cb->srtt);
  69. cb->tcd.func = nr4cdtimeout ;
  70. cb->tcd.arg = cb ;
  71. start_timer(&cb->tcd) ;
  72. /* Send connect request packet */
  73. nr4sframe(remote->node,&hdr,NULL) ;
  74. /* Set up initial state and signal state change */
  75. cb->state = NR4STDISC ;
  76. nr4state(cb, NR4STCPEND) ;
  77. /* Return control block address */
  78. return cb ;
  79. }
  80. /* Send a net/rom transport data packet */
  81. int
  82. send_nr4(
  83. struct nr4cb *cb,
  84. struct mbuf **bpp
  85. ){
  86. if(cb == NULL){
  87. free_p(bpp);
  88. return -1 ;
  89. }
  90. enqueue(&cb->txq,bpp) ;
  91. return nr4output(cb) ;
  92. }
  93. /* Receive incoming net/rom transport data */
  94. struct mbuf *
  95. recv_nr4(cb,cnt)
  96. struct nr4cb *cb ;
  97. uint16 cnt ;
  98. {
  99. struct mbuf *bp ;
  100. if (cb->rxq == NULL)
  101. return NULL ;
  102. if (cnt == 0) {
  103. bp = cb->rxq ; /* Just give `em everything */
  104. cb->rxq = NULL ;
  105. }
  106. else {
  107. bp = ambufw(cnt);
  108. bp->cnt = pullup(&cb->rxq,bp->data,cnt);
  109. }
  110. /* If this has un-choked us, reopen the window */
  111. if (cb->qfull && len_p(cb->rxq) < Nr4qlimit) {
  112. cb->qfull = 0 ; /* Choke flag off */
  113. nr4ackit(cb) ; /* Get things rolling again */
  114. }
  115. return bp ;
  116. }
  117. /* Close a NET/ROM connection */
  118. void
  119. disc_nr4(cb)
  120. struct nr4cb *cb ;
  121. {
  122. struct nr4hdr hdr ;
  123. if (cb->state == NR4STLISTEN) {
  124. free_n4circ(cb);
  125. return;
  126. }
  127. /* Format disconnect request packet */
  128. hdr.opcode = NR4OPDISRQ ;
  129. hdr.yourindex = cb->yournum ;
  130. hdr.yourid = cb->yourid ;
  131. /* Set and start timer */
  132. cb->cdtries = 1 ;
  133. set_timer(&cb->tcd,2 * cb->srtt);
  134. cb->tcd.func = nr4cdtimeout ;
  135. cb->tcd.arg = cb ;
  136. start_timer(&cb->tcd) ;
  137. /* Send packet */
  138. nr4sframe(cb->remote.node, &hdr, NULL) ;
  139. if(cb->state != NR4STCON){
  140. /* Connection not established; just blow it away */
  141. reset_nr4(cb);
  142. return;
  143. }
  144. /* Connection established, try to close it gracefully */
  145. /* Signal state change.  nr4state will take care of stopping */
  146. /* the appropriate timers and resetting window pointers. */
  147. nr4state(cb, NR4STDPEND) ;
  148. }
  149. /* Abruptly terminate a NET/ROM transport connection */
  150. void
  151. reset_nr4(cb)
  152. struct nr4cb *cb ;
  153. {
  154. cb->dreason = NR4RRESET ;
  155. nr4state(cb,NR4STDISC) ;
  156. }
  157. /* Force retransmission on a NET/ROM transport connection */
  158. int
  159. kick_nr4(cb)
  160. struct nr4cb *cb ;
  161. {
  162. unsigned seq ;
  163. struct timer *t ;
  164. if(!nr4valcb(cb))
  165. return -1 ;
  166. switch (cb->state) {
  167.   case NR4STCPEND:
  168.   case NR4STDPEND:
  169.    stop_timer(&cb->tcd) ;
  170. nr4cdtimeout(cb) ;
  171. break ;
  172.   case NR4STCON:
  173.     if (cb->nextosend != cb->ackxpected) { /* if send window is open: */
  174. for (seq = cb->ackxpected ;
  175.  nr4between(cb->ackxpected, seq, cb->nextosend) ;
  176.  seq = (seq + 1) & NR4SEQMASK) {
  177. t = &cb->txbufs[seq % cb->window].tretry ;
  178. stop_timer(t) ;
  179. t->state = TIMER_EXPIRE ; /* fool retry routine */
  180. }
  181. nr4txtimeout(cb) ;
  182. }
  183. break ;
  184. }
  185. return 0 ;
  186. }