Annotation of 3BSD/cmd/net/prot.c, revision 1.1.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.