Annotation of lucent/sys/src/9/port/stil.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.