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

TCP/IP协议栈

开发平台:

Visual C++

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