Annotation of 3BSD/cmd/net/prot.c, revision 1.1

1.1     ! root        1: # include "defs.h"
        !             2: struct packet *xptr, *gptr;
        !             3: # define PACKETLENGTH (datasize + sizeof *xptr - 1)
        !             4: # define ACKLENGTH (sizeof *xptr - 1)
        !             5: static int bufleft;
        !             6: int atime = ATIME;
        !             7: int maxbread = MAXBREAD;
        !             8: int datasize;
        !             9: static char savebuf[BUFSIZ], retransmit;
        !            10: static jmp_buf env;
        !            11: short masterseqno, lastseqno;
        !            12: FILE *readtty,*writetty;
        !            13: struct dumpstruc dump;
        !            14: 
        !            15: /*
        !            16:    one problem has been character loss on
        !            17:    overloaded systems due to the daemon
        !            18:    taking too long to swap in
        !            19:    and losing characters.
        !            20:    A high priority process of small size
        !            21:    with a pipe would do the job.
        !            22: */
        !            23: alarmint(){
        !            24:        errno = 100;
        !            25:        signal(SIGCLK,SIG_IGN);         /* alarm off */
        !            26:        longjmp(env,0);                 /* ugh */
        !            27:        }
        !            28: /* returns number of bytes written, error returns WRITEFAIL (-3) */
        !            29: xwrite(inbuf,size,amt)
        !            30:   char *inbuf;
        !            31: {
        !            32:        struct packet *rpp;
        !            33:        int cnt, num, savetime;
        !            34:        register char *p, *b;
        !            35:        register int i;
        !            36:        if(xptr == NULL)xptr = (struct packet *)calloc((PACKETLENGTH+20)/4,4);
        !            37:        if(xptr == NULL){error("xptr NULL"); return(WRITEFAIL); }
        !            38:        amt = amt * size;
        !            39:        cnt = 0;
        !            40:        retransmit = 0;
        !            41:        savetime = atime;
        !            42:        while(amt > 0){
        !            43:                if(retransmit > maxbread){
        !            44:                        debug("xwrite fail");
        !            45:                        return(WRITEFAIL);
        !            46:                        }
        !            47:                b = inbuf+cnt;
        !            48:                num = min(datasize,amt);
        !            49:                xptr->pcode = REQUEST;
        !            50:                xptr->seqno = masterseqno;
        !            51:                xptr->len = num;
        !            52:                p = xptr->data;
        !            53:                i = num;
        !            54:                while(i--)*p++ = *b++;
        !            55:                sendpacket(xptr);
        !            56:                rpp = getpacket();
        !            57:                if(rpp == NULL){
        !            58:                        atime += 3;             /* wait three more secs */
        !            59:                        retransmit++;
        !            60:                        dump.nretrans++;
        !            61:                        continue;
        !            62:                        }
        !            63:                if(rpp->chksum != 0 || rpp->pcode != ACK
        !            64:                        || rpp->seqno != xptr->seqno ){
        !            65:                        if(rpp->pcode == RESET){
        !            66:                                error("reset");
        !            67:                                return(WRITEFAIL);
        !            68:                                }
        !            69:                        if(rpp->seqno == 1 && rpp->pcode == REQUEST){
        !            70:                                error("collision");
        !            71:                                return(WRITEFAIL);
        !            72:                                }
        !            73:                        if(rpp->chksum != 0)
        !            74:                                error("chksum %d",rpp->seqno);
        !            75:                        else if(rpp->pcode != ACK)
        !            76:                                error("not ack %d %d",rpp->pcode,rpp->seqno);
        !            77:                        else if(rpp->seqno != xptr ->seqno)
        !            78:                                error("WRSQNO got %d request %d",rpp->seqno,
        !            79:                                        xptr->seqno);
        !            80:                        atime += 3;
        !            81:                        retransmit++;
        !            82:                        dump.nretrans++;
        !            83:                        continue;
        !            84:                        }
        !            85:                masterseqno++;
        !            86:                amt -= num;
        !            87:                retransmit = 0;
        !            88:                cnt += num;
        !            89:                }
        !            90:        atime = savetime;
        !            91:        return(cnt/size);
        !            92:        }
        !            93: /* return the number of bytes read, or error = BROKENREAD (-2) */
        !            94: nread(b,size,num)
        !            95:   register char *b;
        !            96: {
        !            97:        register char *p;
        !            98:        int bcnt = 0;
        !            99:        char *q;
        !           100:        register struct packet *pp;
        !           101:        int n,j,cnt;
        !           102:        num = num * size;
        !           103:        cnt = 0;
        !           104:        if(bufleft > 0){
        !           105:                p = savebuf;
        !           106:                cnt = n = min(bufleft,num);
        !           107:                while(n--)*b++ = *p++;
        !           108:                num -= cnt;
        !           109:                bufleft -= cnt;
        !           110:                if(bufleft > 0){
        !           111:                        q = savebuf;
        !           112:                        n = bufleft;
        !           113:                        while(n--)*q++ = *p++;
        !           114:                        }
        !           115:                }
        !           116:        if(num <= 0)
        !           117:                return(cnt/size);
        !           118:        retransmit = 0;
        !           119:        for(;;){
        !           120:                pp = getpacket();
        !           121:                if(pp == NULL){
        !           122:                        if(++bcnt >= maxbread){
        !           123:                                debug("read timeout");
        !           124:                                return(BROKENREAD);
        !           125:                                }
        !           126:                        continue;
        !           127:                        }
        !           128:                if(pp->chksum != 0){
        !           129:                        error("chksum %d",pp->seqno);
        !           130:                        retransmit++;
        !           131:                        continue;
        !           132:                        }
        !           133:                if(pp->pcode & ~(REQUEST|RESET)){
        !           134:                        error("pcode %d %d",pp->pcode,pp->seqno);
        !           135:                        retransmit++;
        !           136:                        continue;
        !           137:                        }
        !           138:                else if(pp->pcode == RESET)break;
        !           139:                else {          /* else was a REQUEST packet, no chksum errs */
        !           140:                        pp->pcode = ACK;
        !           141:                        n = pp->len;
        !           142:                        pp->len = 0;
        !           143:                        sendpacket(pp);         /* send ACK */
        !           144:                        pp->len = n;
        !           145:                        break;
        !           146:                        }
        !           147:                }
        !           148:        retransmit = 0;
        !           149:        j = n = min(num,pp->len);
        !           150:        cnt += j;
        !           151:        p = pp->data;
        !           152:        while(n--)*b++ = *p++;
        !           153:        if(pp->len > num){
        !           154:                n = bufleft = pp->len - num;
        !           155:                q = savebuf;
        !           156:                while(n--)*q++ = *p++;
        !           157:                }
        !           158:        return(cnt/size);
        !           159:        }
        !           160: printpacket(pp,dest)
        !           161:   char *dest;
        !           162:   struct packet *pp; {
        !           163:        char *s;
        !           164:        int i;
        !           165:        char c;
        !           166:        dest[0] = 0;
        !           167:        if(pp == NULL)return;
        !           168:        if(pp->pcode == REQUEST)c='r';
        !           169:        else if(pp->pcode == ACK)c = 'a';
        !           170:        else if(pp->pcode == RESET)c = 'x';
        !           171:        else if(pp->pcode == PURGE)c = 'p';
        !           172:        else c = 'u';
        !           173:        sprintf(dest,"p:%d len:%d c:%c d:", pp->seqno, pp->len, c);
        !           174:        s = dest + strlen(dest);
        !           175:        for(i=0; i<pp->len && pp->data[i]; i++)*s++ = pp->data[i];
        !           176:        *s = 0;
        !           177:        }
        !           178: /*
        !           179:  * A purge can always be sent -
        !           180:  * the receiver totally ignores it.
        !           181:  * It is used to push the packet terminator
        !           182:  * down the wire in case of a crash
        !           183:  * leaving the receiver half reading.
        !           184:  */
        !           185: sendpurge()
        !           186:   {
        !           187:        if(xptr == NULL)xptr = (struct packet *)calloc((PACKETLENGTH+20)/4,4);
        !           188:        if(xptr == NULL){
        !           189:                error("bad xptr");
        !           190:                return;
        !           191:                }
        !           192:        xptr->pcode = PURGE;
        !           193:        xptr->seqno = 0;
        !           194:        xptr->len = 0;
        !           195:        debug("send purge");
        !           196:        sendpacket(xptr);
        !           197:        }
        !           198: /*
        !           199:  * A reset is sent by the sender whenever he begins to send.
        !           200:  * It is not acknowledged.
        !           201:  * The receiver must be prepared, when he receives a reset,
        !           202:  * to receive a new transmission.
        !           203:  */
        !           204: sendreset()
        !           205:   {
        !           206:        if(xptr == NULL)xptr = (struct packet *)calloc((PACKETLENGTH+20)/4,4);
        !           207:        if(xptr == NULL){
        !           208:                error("bad xptr");
        !           209:                return;
        !           210:                }
        !           211:        xptr->pcode = RESET;
        !           212:        xptr->seqno = 0;
        !           213:        xptr->len = 0;
        !           214:        debug("send reset");
        !           215:        sendpacket(xptr);
        !           216:        }
        !           217: /*
        !           218:  * Getreset returns in either of two cases:
        !           219:  * 1) the read times out (return BROKENREAD)
        !           220:  * 2) a reset packet is received (return 0)
        !           221:  * all other packets received are ignored.
        !           222:  */
        !           223: getreset() {
        !           224:        register struct packet *pp;
        !           225:        register int bcnt = 0;
        !           226:        bufleft = 0;            /* if any chars are left in buffer, flush them*/
        !           227:        atime = ATIME + ((rand()>>8)%15);
        !           228:        lastseqno = -1;         /* forces non-RESET pks to not be ACK-ed */
        !           229:        for(;;){
        !           230:                pp = getpacket();
        !           231:                if(pp == NULL){
        !           232:                        if(++bcnt >= maxbread){
        !           233:                                debug("reset timeout");
        !           234:                                return(BROKENREAD);
        !           235:                                }
        !           236:                        continue;
        !           237:                        }
        !           238:                if(pp->pcode == RESET){
        !           239:                        debug("got reset");
        !           240:                        addtolog(remote,"^R%c ",remote);
        !           241:                        lastseqno = 0;
        !           242:                        return(0);
        !           243:                        }
        !           244:                }
        !           245:        }
        !           246: /*
        !           247:  *     Just sends packet pp
        !           248:  *     Calculates the chksum
        !           249:  */
        !           250: sendpacket(pp)
        !           251:   struct packet *pp; {
        !           252:        char buf[BUFSIZ];
        !           253:        int len, n, i;
        !           254:        long nt,ot;
        !           255:        register char *q, *p;
        !           256:        register int j;
        !           257:        dump.nbytesent += pp->len;
        !           258:        dump.npacksent++;
        !           259:        pp->chksum = 0;
        !           260:        n = 0;
        !           261:        p = (char *)pp;
        !           262:        len = ACKLENGTH + pp->len;
        !           263:        for(j = 0; j < len; j++)n ^= *p++;
        !           264:        pp->chksum = n;
        !           265:        p = buf;
        !           266:        q = (char *)pp;
        !           267:        len = n = (len+2)/3;
        !           268:        while(n--){
        !           269:                *p++ = (*q & 077) + INCR;
        !           270:                j =    (*q++ >> 6) &03;
        !           271:                *p++ = (((*q << 2) | j) & 077) + INCR;
        !           272:                j =    (*q++ >> 4) & 017;
        !           273:                *p++ = (((*q << 4) | j) & 077) + INCR;
        !           274:                *p++ = ((*q++ >> 2) & 077) + INCR;
        !           275:                }
        !           276:        *p++ = '\n';
        !           277:        *p = 0;
        !           278: /*     because of bugs in processing around erase and kill in v6 */
        !           279:        for(p=buf; *p; p++)
        !           280:                if(*p == '\\')*p = '}';
        !           281:        /*
        !           282:        debug("send %d %s",len*4+1,buf);
        !           283:        */
        !           284:        ot = gettime();
        !           285:        i = fwrite(buf,1,len*4+1, writetty);
        !           286:        nt = gettime();
        !           287:        dump.waittime += (nt - ot);                     /* add time writing */
        !           288:        /*
        !           289:        debug("count %d",i);
        !           290:        */
        !           291:        fflush(writetty);
        !           292:        }
        !           293: /*
        !           294:  *     returns NULL if couldn't get a packet with correct seqno
        !           295:  *     chksum not checked here
        !           296:  *     because other programs may want to interrogate checksum
        !           297:  */
        !           298: struct packet *getpacket() {
        !           299:        char buf[BUFSIZ];
        !           300:        int i,n,j, len, plen;
        !           301:        int bcnt;
        !           302:        register char *q, *p;
        !           303:        long ot, nt;
        !           304:        if(gptr == NULL)gptr = (struct packet *)calloc((PACKETLENGTH+20)/4,4);
        !           305:        if(gptr == NULL){error("gptr NULL"); return(NULL); }
        !           306:        bcnt = 0;
        !           307:        errno = 0;
        !           308:        setjmp(env);
        !           309:        alarm(0);
        !           310:        signal(SIGCLK,alarmint);
        !           311:        for(;;){
        !           312:                if(bcnt++ > maxbread)errno = 100;       /* give up */
        !           313:                if(errno == 100){
        !           314:                        if(debugflg)putchar('^');
        !           315:                        return(NULL);
        !           316:                        }
        !           317:                alarm(atime);
        !           318:                ot = gettime();
        !           319:                p = fgets(buf,BUFSIZ,readtty);
        !           320:                alarm(0);
        !           321:                nt = gettime();
        !           322:                dump.waittime += (nt - ot);
        !           323:                if(p == NULL){error("getpacket fails"); return(NULL); }
        !           324:                plen = strlen(buf);
        !           325:                /*
        !           326:                debug("receive %d %s",plen,buf);
        !           327:                */
        !           328:                /* remove this loop later */
        !           329:                for(p=buf; *p; p++)
        !           330:                        if(*p == '}')*p = '\\';
        !           331:                p = buf;
        !           332:                q = (char *)gptr;
        !           333:                n = (strlen(buf)+3) /4;
        !           334:                while(n--){
        !           335:                        if(*p == '\n')break;
        !           336:                        if(*p < INCR || *p & 0200)error("bad char %o\n",*p);
        !           337:                        i =  *p++ - INCR;
        !           338:                        j =  *p++ - INCR;
        !           339:                        *q++ = ((j & 03) << 6) | (i & 077);
        !           340:                        i =  *p++ -INCR;
        !           341:                        *q++ = ((i & 017) << 4) | ((j >> 2) & 017);
        !           342:                        j =  *p++ - INCR;
        !           343:                        *q++ = ((j & 077) << 2) | ((i >> 4) & 03);
        !           344:                        }
        !           345:                *q = 0;
        !           346:                if(plen != ((ACKLENGTH + gptr->len + 2)/3)*4 + 1){
        !           347:                        error("too short %d",gptr->seqno);
        !           348:                        continue;
        !           349:                        }
        !           350:                if(gptr->pcode == PURGE){
        !           351:                        debug("got purge");
        !           352:                        continue;               /* never seen */
        !           353:                        }
        !           354:                if(gptr->pcode == RESET)
        !           355:                        break;
        !           356:                if(gptr->seqno == lastseqno){
        !           357:                        if(retransmit)break;
        !           358:                        /* send ACK - it was lost first time thru */
        !           359:                        len = gptr->len;
        !           360:                        n = gptr->pcode;
        !           361:                        gptr->len = 0;
        !           362:                        gptr->pcode = ACK;
        !           363:                        sendpacket(gptr);
        !           364:                        gptr->len = len;
        !           365:                        gptr->pcode = n;
        !           366:                        error("sendlostack %d",lastseqno);
        !           367:                        break;
        !           368:                        }
        !           369:                if(gptr->seqno == lastseqno + 1)break;
        !           370:                error("Wrong seq no g: %d last: %d",gptr->seqno,
        !           371:                        lastseqno);
        !           372:                }
        !           373:        lastseqno = gptr->seqno;
        !           374:        n = 0;
        !           375:        len = gptr->len + ACKLENGTH;
        !           376:        p = (char *)gptr;
        !           377:        for(i=0; i < len; i++)n ^= *p++;
        !           378:        gptr->chksum = n;
        !           379:        if(n != 0)dump.ncksum++;
        !           380:        dump.nbytercv += gptr->len;
        !           381:        dump.npackrcv++;
        !           382:        return(gptr);
        !           383: }

unix.superglobalmegacorp.com

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