Annotation of lucent/sys/src/9/port/stil.c, revision 1.1.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.