|
|
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.