|
|
1.1 root 1: /*
2: * stil - Internet link protocol
3: */
4: #include "u.h"
5: #include "../port/lib.h"
6: #include "mem.h"
7: #include "dat.h"
8: #include "fns.h"
9: #include "io.h"
10: #include "../port/error.h"
11: #include "arp.h"
12: #include "../port/ipdat.h"
13:
14: #define DBG if(0)print
15: int ilcksum = 1;
16: static int initseq = 25001;
17: static Rendez ilackr;
18:
19: char *ilstate[] =
20: {
21: "Closed",
22: "Syncer",
23: "Syncee",
24: "Established",
25: "Listening",
26: "Closing"
27: };
28:
29: char *iltype[] =
30: {
31: "sync",
32: "data",
33: "dataquerey",
34: "ack",
35: "querey",
36: "state",
37: "close"
38: };
39: static char *etime = "connection timed out";
40:
41: /* Always Acktime < Fasttime < Slowtime << Ackkeepalive */
42: enum
43: {
44: Iltickms = 100,
45: Slowtime = 350*Iltickms,
46: Fasttime = 4*Iltickms,
47: Acktime = 2*Iltickms,
48: Ackkeepalive = 6000*Iltickms,
49: Querytime = 60*Iltickms, /* time between queries */
50: Keepalivetime = 10*Querytime, /* keep alive time */
51: Defaultwin = 20,
52: ILgain = 8,
53: };
54:
55: #define Starttimer(s) {(s)->timeout = 0; \
56: (s)->fasttime = (Fasttime*(s)->rtt)/Iltickms; \
57: (s)->slowtime = (Slowtime*(s)->rtt)/Iltickms; }
58:
59: void ilrcvmsg(Ipifc*, Block*);
60: void ilackproc(void*);
61: void ilsendctl(Ipconv*, Ilhdr*, int, ulong, ulong);
62: void ilackq(Ilcb*, Block*);
63: void ilprocess(Ipconv*, Ilhdr*, Block*);
64: void ilpullup(Ipconv*);
65: void ilhangup(Ipconv*, char *);
66: void ilfreeq(Ilcb*);
67: void ilrexmit(Ilcb*);
68: void ilbackoff(Ilcb*);
69:
70: void
71: ilopen(Queue *q, Stream *s)
72: {
73: Ipconv *ipc;
74: static int ilkproc;
75:
76: if(ilkproc == 0) {
77: ilkproc = 1;
78: kproc("ilack", ilackproc, ipifc[s->dev]);
79: }
80:
81: ipc = ipcreateconv(ipifc[s->dev], s->id);
82: initipifc(ipc->ifc, IP_ILPROTO, ilrcvmsg);
83:
84: ipc->readq = RD(q);
85: RD(q)->ptr = (void *)ipc;
86: WR(q)->next->ptr = (void *)ipc->ifc;
87: WR(q)->ptr = (void *)ipc;
88: }
89:
90: void
91: ilclose(Queue *q)
92: {
93: Ipconv *s;
94: Ilcb *ic;
95:
96: s = (Ipconv *)(q->ptr);
97: ic = &s->ilctl;
98: qlock(s);
99: s->readq = 0;
100: qunlock(s);
101:
102: switch(ic->state) {
103: case Ilclosing:
104: case Ilclosed:
105: break;
106: case Ilsyncer:
107: case Ilsyncee:
108: case Ilestablished:
109: ilfreeq(ic);
110: ic->state = Ilclosing;
111: ilsendctl(s, 0, Ilclose, ic->next, ic->recvd);
112: break;
113: case Illistening:
114: ic->state = Ilclosed;
115: s->psrc = 0;
116: s->pdst = 0;
117: s->dst = 0;
118: break;
119: }
120: }
121:
122: void
123: iloput(Queue *q, Block *bp)
124: {
125: Ipconv *ipc;
126: Ilhdr *ih;
127: Ilcb *ic;
128: int dlen;
129: Block *f;
130: ulong id;
131:
132: ipc = (Ipconv *)(q->ptr);
133: if(ipc->psrc == 0)
134: error(Enoport);
135:
136: ic = &ipc->ilctl;
137: switch(ic->state) {
138: case Ilclosed:
139: case Illistening:
140: case Ilclosing:
141: error(Ehungup);
142: }
143:
144: if(bp->type != M_DATA) {
145: freeb(bp);
146: error(Ebadctl);
147: }
148:
149: /* Only allow atomic Il writes to form datagrams */
150: for(f = bp; f->next; f = f->next)
151: ;
152: if((f->flags & S_DELIM) == 0) {
153: freeb(bp);
154: error(Emsgsize);
155: }
156:
157: dlen = blen(bp);
158: if(dlen > IL_DATMAX) {
159: freeb(bp);
160: error(Emsgsize);
161: }
162:
163: /* Make space to fit il & ip & ethernet header */
164: bp = padb(bp, IL_EHSIZE+IL_HDRSIZE);
165: ih = (Ilhdr *)(bp->rptr);
166:
167: /* Ip fields */
168: ih->frag[0] = 0;
169: ih->frag[1] = 0;
170: hnputl(ih->dst, ipc->dst);
171: if(ipc->src == 0)
172: ipc->src = ipgetsrc(ih->dst);
173: hnputl(ih->src, ipc->src);
174: ih->proto = IP_ILPROTO;
175: /* Il fields */
176: hnputs(ih->illen, dlen+IL_HDRSIZE);
177: hnputs(ih->ilsrc, ipc->psrc);
178: hnputs(ih->ildst, ipc->pdst);
179:
180: qlock(&ic->ackq);
181: id = ic->next++;
182: hnputl(ih->ilid, id);
183:
184: hnputl(ih->ilack, ic->recvd);
185: ih->iltype = Ildata;
186: ih->ilspec = 0;
187: ih->ilsum[0] = 0;
188: ih->ilsum[1] = 0;
189:
190: /* Checksum of ilheader plus data (not ip & no pseudo header) */
191: if(ilcksum)
192: hnputs(ih->ilsum, ptcl_csum(bp, IL_EHSIZE, dlen+IL_HDRSIZE));
193: ilackq(ic, bp);
194: qunlock(&ic->ackq);
195:
196: /* Start the round trip timer for this packet if the timer is free */
197: if(ic->rttack == 0) {
198: ic->rttack = id;
199: ic->ackms = MACHP(0)->ticks;
200: }
201: ic->acktime = Ackkeepalive;
202:
203: ipmuxoput(0, bp);
204: }
205:
206: void
207: ilackq(Ilcb *ic, Block *bp)
208: {
209: Block *np;
210:
211: /* Enqueue a copy on the unacked queue in case this one gets lost */
212: np = copyb(bp, blen(bp));
213: if(ic->unacked)
214: ic->unackedtail->list = np;
215: else {
216: /* Start timer since we may have been idle for some time */
217: Starttimer(ic);
218: ic->unacked = np;
219: }
220: ic->unackedtail = np;
221: np->list = 0;
222: }
223:
224: void
225: ilackto(Ilcb *ic, ulong ackto)
226: {
227: Ilhdr *h;
228: Block *bp;
229: ulong id, t;
230:
231: if(ic->rttack == ackto) {
232: t = TK2MS(MACHP(0)->ticks - ic->ackms);
233: /* Guard against the ulong zero wrap if MACP->ticks */
234: if(t < 1000*ic->rtt)
235: ic->rtt = (ic->rtt*(ILgain-1)+t)/ILgain;
236: if(ic->rtt < Iltickms)
237: ic->rtt = Iltickms;
238: }
239:
240: /* Cancel if we lost the packet we were interested in */
241: if(ic->rttack <= ackto)
242: ic->rttack = 0;
243:
244: qlock(&ic->ackq);
245: while(ic->unacked) {
246: h = (Ilhdr *)ic->unacked->rptr;
247: id = nhgetl(h->ilid);
248: if(ackto < id)
249: break;
250:
251: bp = ic->unacked;
252: ic->unacked = bp->list;
253: bp->list = 0;
254: freeb(bp);
255: }
256: qunlock(&ic->ackq);
257: }
258:
259: void
260: iliput(Queue *q, Block *bp)
261: {
262: PUTNEXT(q, bp);
263: }
264:
265: void
266: ilrcvmsg(Ipifc *ifc, Block *bp)
267: {
268: Ilhdr *ih;
269: Ilcb *ic;
270: int plen, illen;
271: Ipconv *s, **p, **etab, *new, *spec, *gen;
272: short sp, dp;
273: Ipaddr dst;
274: char *st;
275:
276: ih = (Ilhdr *)bp->rptr;
277: plen = blen(bp);
278: if(plen < IL_EHSIZE+IL_HDRSIZE)
279: goto drop;
280:
281: illen = nhgets(ih->illen);
282: if(illen+IL_EHSIZE > plen)
283: goto drop;
284:
285: sp = nhgets(ih->ildst);
286: dp = nhgets(ih->ilsrc);
287: dst = nhgetl(ih->src);
288:
289:
290: if(ilcksum && ptcl_csum(bp, IL_EHSIZE, illen) != 0) {
291: ifc->chkerrs++;
292: st = (ih->iltype < 0 || ih->iltype > Ilclose) ? "?" : iltype[ih->iltype];
293: print("il: cksum error, pkt(%s id %lud ack %lud %d.%d.%d.%d/%d->%d)\n",
294: st, nhgetl(ih->ilid), nhgetl(ih->ilack), fmtaddr(dst), sp, dp); /**/
295: goto drop;
296: }
297:
298: etab = &ifc->conv[Nipconv];
299: for(p = ifc->conv; p < etab; p++) {
300: s = *p;
301: if(s == 0)
302: break;
303: if(s->psrc == sp)
304: if(s->pdst == dp)
305: if(s->dst == dst) {
306: ilprocess(s, ih, bp);
307: return;
308: }
309: }
310: if(ih->iltype != Ilsync)
311: goto drop;
312:
313: gen = 0;
314: spec = 0;
315: etab = &ifc->conv[Nipconv];
316: for(p = ifc->conv; p < etab && *p; p++) {
317: s = *p;
318: if(s->ilctl.state == Illistening)
319: if(s->pdst == 0)
320: if(s->dst == 0) {
321: if(s->psrc == sp){
322: spec = s;
323: break;
324: }
325: if(s->psrc == 0)
326: gen = s;
327: }
328: }
329:
330: if(spec)
331: s = spec;
332: else if(gen)
333: s = gen;
334: else
335: goto drop;
336:
337: if(s->curlog > s->backlog)
338: goto reset;
339:
340: new = ipincoming(ifc, s);
341: if(new == 0)
342: goto reset;
343:
344: new->newcon = s;
345: new->ifc = s->ifc;
346: new->psrc = sp;
347: new->pdst = dp;
348: new->dst = nhgetl(ih->src);
349: new->src = nhgetl(ih->dst);
350:
351: ic = &new->ilctl;
352: ic->state = Ilsyncee;
353: initseq += TK2MS(MACHP(0)->ticks);
354: ic->start = initseq & 0xffffff;
355: ic->next = ic->start+1;
356: ic->recvd = 0;
357: ic->rstart = nhgetl(ih->ilid);
358: ic->slowtime = Slowtime;
359: ic->rtt = Iltickms;
360: ic->querytime = Keepalivetime;
361: ic->deathtime = Keepalivetime;
362: ic->window = Defaultwin;
363: ilprocess(new, ih, bp);
364:
365: s->curlog++;
366: wakeup(&s->listenr);
367: return;
368:
369: drop:
370: freeb(bp);
371: return;
372: reset:
373: ilsendctl(0, ih, Ilclose, 0, 0);
374: freeb(bp);
375: }
376:
377: void
378: _ilprocess(Ipconv *s, Ilhdr *h, Block *bp)
379: {
380: Ilcb *ic;
381: ulong id, ack;
382:
383: id = nhgetl(h->ilid);
384: ack = nhgetl(h->ilack);
385: ic = &s->ilctl;
386:
387: ic->querytime = Keepalivetime;
388: ic->deathtime = Keepalivetime;
389: switch(ic->state) {
390: default:
391: panic("il unknown state");
392: case Ilclosed:
393: freeb(bp);
394: break;
395: case Ilsyncer:
396: switch(h->iltype) {
397: default:
398: break;
399: case Ilsync:
400: if(ack != ic->start)
401: ilhangup(s, "connection rejected");
402: else {
403: ic->recvd = id;
404: ic->rstart = id;
405: ilsendctl(s, 0, Ilack, ic->next, ic->recvd);
406: ic->state = Ilestablished;
407: wakeup(&ic->syncer);
408: ilpullup(s);
409: Starttimer(ic);
410: }
411: break;
412: case Ilclose:
413: if(ack == ic->start)
414: ilhangup(s, "remote close");
415: break;
416: }
417: freeb(bp);
418: break;
419: case Ilsyncee:
420: switch(h->iltype) {
421: default:
422: break;
423: case Ilsync:
424: if(id != ic->rstart || ack != 0)
425: ic->state = Ilclosed;
426: else {
427: ic->recvd = id;
428: ilsendctl(s, 0, Ilsync, ic->start, ic->recvd);
429: Starttimer(ic);
430: }
431: break;
432: case Ilack:
433: if(ack == ic->start) {
434: ic->state = Ilestablished;
435: ilpullup(s);
436: Starttimer(ic);
437: }
438: break;
439: case Ilclose:
440: if(id == ic->next)
441: ilhangup(s, "remote close");
442: break;
443: }
444: freeb(bp);
445: break;
446: case Ilestablished:
447: switch(h->iltype) {
448: case Ilsync:
449: if(id != ic->rstart)
450: ilhangup(s, "remote close");
451: else {
452: ilsendctl(s, 0, Ilack, ic->next, ic->rstart);
453: Starttimer(ic);
454: }
455: freeb(bp);
456: break;
457: case Ildata:
458: Starttimer(ic);
459: ilackto(ic, ack);
460: ic->acktime = Acktime;
461: iloutoforder(s, h, bp);
462: ilpullup(s);
463: break;
464: case Ildataquery:
465: Starttimer(ic);
466: ilackto(ic, ack);
467: ic->acktime = Acktime;
468: iloutoforder(s, h, bp);
469: ilpullup(s);
470: ilsendctl(s, 0, Ilstate, ic->next, ic->recvd);
471: break;
472: case Ilack:
473: ilackto(ic, ack);
474: Starttimer(ic);
475: freeb(bp);
476: break;
477: case Ilquerey:
478: ilackto(ic, ack);
479: ilsendctl(s, 0, Ilstate, ic->next, ic->recvd);
480: Starttimer(ic);
481: freeb(bp);
482: break;
483: case Ilstate:
484: ilackto(ic, ack);
485: ilrexmit(ic);
486: Starttimer(ic);
487: freeb(bp);
488: break;
489: case Ilclose:
490: freeb(bp);
491: if(ack < ic->start || ack > ic->next)
492: break;
493: ilsendctl(s, 0, Ilclose, ic->next, ic->recvd);
494: ic->state = Ilclosing;
495: ilfreeq(ic);
496: Starttimer(ic);
497: break;
498: }
499: break;
500: case Illistening:
501: freeb(bp);
502: break;
503: case Ilclosing:
504: switch(h->iltype) {
505: case Ilclose:
506: ic->recvd = id;
507: ilsendctl(s, 0, Ilclose, ic->next, ic->recvd);
508: if(ack == ic->next)
509: ilhangup(s, 0);
510: Starttimer(ic);
511: break;
512: default:
513: break;
514: }
515: freeb(bp);
516: break;
517: }
518: }
519:
520: void
521: ilrexmit(Ilcb *ic)
522: {
523: Block *nb;
524: Ilhdr *h;
525:
526: nb = 0;
527: qlock(&ic->ackq);
528: if(ic->unacked)
529: nb = copyb(ic->unacked, blen(ic->unacked));
530: qunlock(&ic->ackq);
531:
532: if(nb == 0)
533: return;
534:
535: h = (Ilhdr*)nb->rptr;
536: DBG("rxmit %d.", nhgetl(h->ilid));
537:
538: h->iltype = Ildataquery;
539: hnputl(h->ilack, ic->recvd);
540: h->ilsum[0] = 0;
541: h->ilsum[1] = 0;
542: if(ilcksum)
543: hnputs(h->ilsum, ptcl_csum(nb, IL_EHSIZE, nhgets(h->illen)));
544:
545: ipmuxoput(0, nb);
546: }
547:
548: /* DEBUG */
549: void
550: ilprocess(Ipconv *s, Ilhdr *h, Block *bp)
551: {
552: Ilcb *ic = &s->ilctl;
553:
554: USED(ic);
555: DBG("%11s rcv %d/%d snt %d/%d pkt(%s id %d ack %d %d->%d) ",
556: ilstate[ic->state], ic->rstart, ic->recvd, ic->start, ic->next,
557: iltype[h->iltype], nhgetl(h->ilid), nhgetl(h->ilack),
558: nhgets(h->ilsrc), nhgets(h->ildst));
559:
560: _ilprocess(s, h, bp);
561:
562: DBG("%11s rcv %d snt %d\n", ilstate[ic->state], ic->recvd, ic->next);
563: }
564:
565: void
566: ilhangup(Ipconv *s, char *msg)
567: {
568: Block *nb;
569: int l;
570: Ilcb *ic;
571: int callout;
572:
573: DBG("hangup! %s %d/%d\n", msg ? msg : "??", s->psrc, s->pdst);
574:
575: ic = &s->ilctl;
576: callout = ic->state == Ilsyncer;
577: ic->state = Ilclosed;
578: qlock(s);
579: if(s->readq) {
580: if(msg) {
581: l = strlen(msg);
582: nb = allocb(l);
583: strcpy((char*)nb->wptr, msg);
584: nb->wptr += l;
585: }
586: else
587: nb = allocb(0);
588: nb->type = M_HANGUP;
589: nb->flags |= S_DELIM;
590: PUTNEXT(s->readq, nb);
591: }
592: qunlock(s);
593: if(callout)
594: wakeup(&ic->syncer);
595: s->psrc = 0;
596: s->pdst = 0;
597: s->dst = 0;
598: }
599:
600: void
601: ilpullup(Ipconv *s)
602: {
603: Ilcb *ic;
604: Ilhdr *oh;
605: Block *bp;
606: ulong oid, dlen;
607:
608: if(s->readq == 0)
609: return;
610:
611: ic = &s->ilctl;
612: if(ic->state != Ilestablished)
613: return;
614:
615: qlock(&ic->outo);
616: while(ic->outoforder) {
617: bp = ic->outoforder;
618: oh = (Ilhdr*)bp->rptr;
619: oid = nhgetl(oh->ilid);
620: if(oid <= ic->recvd) {
621: ic->outoforder = bp->list;
622: freeb(bp);
623: continue;
624: }
625: if(oid != ic->recvd+1)
626: break;
627:
628: ic->recvd = oid;
629: ic->outoforder = bp->list;
630:
631: qunlock(&ic->outo);
632: bp->list = 0;
633: dlen = nhgets(oh->illen)-IL_HDRSIZE;
634: bp = btrim(bp, IL_EHSIZE+IL_HDRSIZE, dlen);
635: PUTNEXT(s->readq, bp);
636: qlock(&ic->outo);
637: }
638: qunlock(&ic->outo);
639: }
640:
641: void
642: iloutoforder(Ipconv *s, Ilhdr *h, Block *bp)
643: {
644: Block *f, **l;
645: Ilcb *ic;
646: ulong id, newid;
647: uchar *lid;
648:
649: ic = &s->ilctl;
650: bp->list = 0;
651:
652:
653: id = nhgetl(h->ilid);
654: /* Window checks */
655: if(id <= ic->recvd || id > ic->recvd+ic->window) {
656: freeb(bp);
657: return;
658: }
659:
660: /* Packet is acceptable so sort onto receive queue for pullup */
661: qlock(&ic->outo);
662: if(ic->outoforder == 0)
663: ic->outoforder = bp;
664: else {
665: l = &ic->outoforder;
666: for(f = *l; f; f = f->list) {
667: lid = ((Ilhdr*)(f->rptr))->ilid;
668: newid = nhgetl(lid);
669: if(id <= newid) {
670: if(id == newid) {
671: qunlock(&ic->outo);
672: freeb(bp);
673: return;
674: }
675: bp->list = f;
676: *l = bp;
677: qunlock(&ic->outo);
678: return;
679: }
680: l = &f->list;
681: }
682: *l = bp;
683: }
684: qunlock(&ic->outo);
685: }
686:
687: void
688: ilsendctl(Ipconv *ipc, Ilhdr *inih, int type, ulong id, ulong ack)
689: {
690: Ilhdr *ih;
691: Ilcb *ic;
692: Block *bp;
693:
694: bp = allocb(IL_EHSIZE+IL_HDRSIZE);
695: bp->wptr += IL_EHSIZE+IL_HDRSIZE;
696: bp->flags |= S_DELIM;
697:
698: ih = (Ilhdr *)(bp->rptr);
699: ic = &ipc->ilctl;
700:
701: /* Ip fields */
702: ih->proto = IP_ILPROTO;
703: hnputs(ih->illen, IL_HDRSIZE);
704: ih->frag[0] = 0;
705: ih->frag[1] = 0;
706: if(inih) {
707: hnputl(ih->dst, nhgetl(inih->src));
708: hnputs(ih->ilsrc, nhgets(inih->ildst));
709: hnputs(ih->ildst, nhgets(inih->ilsrc));
710: hnputl(ih->ilid, nhgetl(inih->ilack));
711: hnputl(ih->ilack, nhgetl(inih->ilid));
712: }
713: else {
714: hnputl(ih->dst, ipc->dst);
715: hnputs(ih->ilsrc, ipc->psrc);
716: hnputs(ih->ildst, ipc->pdst);
717: hnputl(ih->ilid, id);
718: hnputl(ih->ilack, ack);
719: ic->acktime = Ackkeepalive;
720: }
721: if(ipc->src == 0)
722: ipc->src = ipgetsrc(ih->dst);
723: hnputl(ih->src, ipc->src);
724: ih->iltype = type;
725: ih->ilspec = 0;
726: ih->ilsum[0] = 0;
727: ih->ilsum[1] = 0;
728:
729: if(ilcksum)
730: hnputs(ih->ilsum, ptcl_csum(bp, IL_EHSIZE, IL_HDRSIZE));
731:
732: /* DBG("\nctl(%s id %d ack %d %d->%d)\n",
733: iltype[ih->iltype], nhgetl(ih->ilid), nhgetl(ih->ilack),
734: nhgets(ih->ilsrc), nhgets(ih->ildst));
735: */
736: ipmuxoput(0, bp);
737: }
738:
739: void
740: ilackproc(void *a)
741: {
742: Ipifc *ifc;
743: Ipconv **base, **p, **last, *s;
744: Ilcb *ic;
745:
746: ifc = (Ipifc*)a;
747: base = ifc->conv;
748: last = &base[Nipconv];
749:
750: for(;;) {
751: tsleep(&ilackr, return0, 0, Iltickms);
752: for(p = base; p < last && *p; p++) {
753: s = *p;
754: ic = &s->ilctl;
755: ic->timeout += Iltickms;
756: switch(ic->state) {
757: case Ilclosed:
758: case Illistening:
759: break;
760: case Ilclosing:
761: if(ic->timeout >= ic->fasttime) {
762: ilsendctl(s, 0, Ilclose, ic->next, ic->recvd);
763: ilbackoff(ic);
764: }
765: if(ic->timeout >= ic->slowtime)
766: ilhangup(s, 0);
767: break;
768: case Ilsyncee:
769: case Ilsyncer:
770: if(ic->timeout >= ic->fasttime) {
771: ilsendctl(s, 0, Ilsync, ic->start, ic->recvd);
772: ilbackoff(ic);
773: }
774: if(ic->timeout >= ic->slowtime)
775: ilhangup(s, etime);
776: break;
777: case Ilestablished:
778: ic->acktime -= Iltickms;
779: if(ic->acktime <= 0)
780: ilsendctl(s, 0, Ilack, ic->next, ic->recvd);
781:
782: ic->querytime -= Iltickms;
783: if(ic->querytime <= 0){
784: ic->deathtime -= Querytime;
785: if(ic->deathtime < 0){
786: ilhangup(s, etime);
787: break;
788: }
789: ilsendctl(s, 0, Ilquerey, ic->next, ic->recvd);
790: ic->querytime = Querytime;
791: }
792: if(ic->unacked == 0) {
793: ic->timeout = 0;
794: break;
795: }
796: if(ic->timeout >= ic->fasttime) {
797: ilrexmit(ic);
798: ilbackoff(ic);
799: }
800: if(ic->timeout >= ic->slowtime) {
801: ilhangup(s, etime);
802: break;
803: }
804: break;
805: }
806: }
807: }
808: }
809:
810: void
811: ilbackoff(Ilcb *ic)
812: {
813: if(ic->fasttime < Slowtime/2)
814: ic->fasttime += Fasttime;
815: else
816: ic->fasttime = (ic->fasttime)*3/2;
817: }
818:
819: static int
820: notsyncer(void *ic)
821: {
822: Ilcb *i;
823:
824: i = ic;
825: return i->state != Ilsyncer;
826: }
827:
828: void
829: ilstart(Ipconv *ipc, int type, int window)
830: {
831: Ilcb *ic = &ipc->ilctl;
832:
833: if(ic->state != Ilclosed)
834: return;
835:
836: ic->unacked = 0;
837: ic->outoforder = 0;
838: ic->slowtime = Slowtime;
839: ic->rtt = Iltickms;
840: Starttimer(ic);
841:
842: initseq += TK2MS(MACHP(0)->ticks);
843: ic->start = initseq & 0xffffff;
844: ic->next = ic->start+1;
845: ic->recvd = 0;
846: ic->window = window;
847:
848: switch(type) {
849: case IL_PASSIVE:
850: ic->state = Illistening;
851: break;
852: case IL_ACTIVE:
853: ic->state = Ilsyncer;
854: ilsendctl(ipc, 0, Ilsync, ic->start, ic->recvd);
855: sleep(&ic->syncer, notsyncer, ic);
856: if(ic->state == Ilclosed)
857: error(Etimedout);
858: break;
859: }
860: }
861:
862: void
863: ilfreeq(Ilcb *ic)
864: {
865: Block *bp, *next;
866:
867: qlock(&ic->ackq);
868: for(bp = ic->unacked; bp; bp = next) {
869: next = bp->list;
870: freeb(bp);
871: }
872: ic->unacked = 0;
873: qunlock(&ic->ackq);
874:
875: qlock(&ic->outo);
876: for(bp = ic->outoforder; bp; bp = next) {
877: next = bp->list;
878: freeb(bp);
879: }
880: ic->outoforder = 0;
881: qunlock(&ic->outo);
882: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.