Annotation of coherent/a/usr/bob/uusrc/dcp/gpkt.c, revision 1.1

1.1     ! root        1: /* 
        !             2:  * gpkt.c
        !             3:  *
        !             4:  * author: Peter S. Housel
        !             5:  *
        !             6:  * The |cksum()| routine is taken from UUPC, Copyright 1985, 1986, 1987 by
        !             7:  * Richard H. Lamb, with (possible) changes Copyright 1987 by Stuart Lynne
        !             8:  *
        !             9:  * All other code is Copyright 1989 by Peter S. Housel.
        !            10:  * Redistribution for any purpose is permitted provided this message
        !            11:  * is included intact. No warranty of any sort is provided.
        !            12:  *
        !            13:  * gpkt version 1.1 7/21/89
        !            14:  */
        !            15: 
        !            16: /* This program was written based on the original UUPC 'g' driver,
        !            17:  * John Gilmore's version of uuslave, and Greg Chesson's protocol
        !            18:  * description article. The last was especially helpful.
        !            19:  *
        !            20:  * This code was written around a severely hacked version of UUPC.
        !            21:  * The call interface is almost identical to the original, but
        !            22:  * the internal implementation is quite different. Also, many
        !            23:  * functions are called that were not available in the original
        !            24:  * UUPC support functions. It should serve as an adequate framework.
        !            25:  *
        !            26:  * The framing strategy requires that a |read()| be interruptable
        !            27:  * by a |SIGALRM|. No "busy wait" or nonblocking read is required.
        !            28:  */
        !            29: extern int     bad_count;
        !            30: extern int     total_errors;
        !            31: 
        !            32: #include "dcp.h"
        !            33: #include "alarm.h"
        !            34: 
        !            35: #define MAXPKT         64      /* incredibly conservative... actually 4096 */
        !            36: #define SWINDOW                3       /* initial send window size */
        !            37: #define RWINDOW                7       /* window size we want to recieve */
        !            38: #define SPKTSIZE       64      /* initial send packet size */
        !            39: #define RPKTSIZE       64      /* window size we want to receive */
        !            40: 
        !            41: #define MAXLOST                5       /* max lost packets (closes or such) */
        !            42: #define TIMEOUT                5       /* max seconds of before timeout */
        !            43: 
        !            44: #define LOSTPKT                -1      /* packet lost, got timeout */
        !            45: #define BADPKT         -2      /* bad checksum, or data read timed out */
        !            46: 
        !            47: #define ENV_DLE                0       /* framing char at start of envelope */
        !            48: #define ENV_K          1       /* packet length specifier */
        !            49: #define ENV_C0         2       /* low-order checksum */
        !            50: #define ENV_C1         3       /* high-order checksum */
        !            51: #define ENV_C          4       /* control byte */
        !            52: #define ENV_X          5       /* xor check byte */
        !            53: #define ENV_LEN                6       /* overall envelope length */
        !            54: 
        !            55: #define TT_CTRL                0       /* control packet */
        !            56: #define TT_DATA                2       /* data packet */
        !            57: #define TT_SDATA       3       /* short data packet */
        !            58: #define TT_ALTCHAN     1       /* 'alternate channel' - invalid */
        !            59: 
        !            60: #define X_CLOSE                1       /* close down protocol */
        !            61: #define X_RJ           2       /* reject recieved packet */
        !            62: #define X_SRJ          3       /* selectively reject packet - invalid */
        !            63: #define X_RR           4       /* reciever ready */
        !            64: #define X_INITC                5       /* third init packet */
        !            65: #define X_INITB                6       /* second init packet */
        !            66: #define X_INITA                7       /* first init packet */
        !            67: 
        !            68: #define OP_OPEN                1       /* request to open/init protocol */
        !            69: #define OP_CLOSE       2       /* request to close protocol */
        !            70: #define OP_WRITE       3       /* request to send packet */
        !            71: #define OP_READ                4       /* request to read packet */
        !            72: 
        !            73: #define MAGIC (unsigned) 0xAAAA        /* checksum magic value */
        !            74: 
        !            75: /* from original dcp - determinie if a <= b < c, for mod 8 seq numbers */
        !            76: #define between(a,b,c) (((a)<=(b) && (b)<(c)) \
        !            77: || ((c)<(a) && (a)<=(b)) \
        !            78:                        || ((b)<(c) && (c)<(a)))
        !            79: 
        !            80: unsigned cksum(/* unsigned char *data, int len */);
        !            81: 
        !            82: struct {
        !            83:        short sdata;            /* 'is this a short data packet' flag */
        !            84:        unsigned length;        /* length of this packet */
        !            85:        unsigned char *bufloc;  /* location of this data pkt's buffer */
        !            86: }
        !            87: inpbufs[8], outbufs[8]; /* input/output queues */
        !            88: 
        !            89: static int needack;            /* do we need to acknowledge a rcv'd pkt? */
        !            90: static int neednack;           /* do we need to reject a recieved pkt? */
        !            91: static int recv;               /* seq. number of last correctly rcv'd pkt */
        !            92: static int lastread;           /* seq. number of last pkt ret. to caller */
        !            93: static int send;               /* first packet in output window */
        !            94: static int next;               /* next pkt to send  send <= next < nstuff */
        !            95: static int nstuff;             /* next loc. to stuff a pkt in output queue */
        !            96: /* (last pkt in output window) + 1 */
        !            97: static int initpk;             /* current init sequence send packet */
        !            98: static int skipping;           /* skipping out-of-seq packets after RJ */
        !            99: static int spktsize;           /* send data size (requested by other end) */
        !           100: static int swindow;            /* send output window size (ditto) */
        !           101: static int nlost;              /* number of consecutive timeouts */
        !           102: static int chanopen = 0;       /* 'channel open' flag */
        !           103: 
        !           104: static unsigned char buf[ENV_LEN + RPKTSIZE+ BUFSIZ];  /* packet framing buffer */
        !           105: static unsigned char *low, *high;              /* framing buffer limits */
        !           106: 
        !           107: static unsigned char *ibufset, *obufset;       /* i/o packet buffer sets */
        !           108: 
        !           109: /* |gopenpk()| opens the 'g' packet protocol on the serial line. It
        !           110:  * initializes its state variables, allocates buffers, etc., then calls
        !           111:  * |gmachine()| to do the actual protocol negotiation/initialization.
        !           112:  */
        !           113: gopenpk()
        !           114: {
        !           115:        int i;                          /* index */
        !           116:        unsigned char *p, *q;           /* pointers into buffer set */
        !           117: 
        !           118:        high = low = buf;               /* empty input buffer */
        !           119:        needack = neednack = 0; /* don't need to accept or reject anything */
        !           120:        initpk = X_INITA;               /* send INITA during initialization */
        !           121:        recv = lastread = 0;            /* initial empty read queue, seq=0 */
        !           122:        send = next = nstuff = 1;       /* first in output queue, seq=1 */
        !           123:        skipping = nlost = 0;           /* nothing lost yet, not skipping */
        !           124: 
        !           125:        if (gmachine(OP_OPEN) < 0)      /* do the open */
        !           126:                return -1;
        !           127:        /* allocate send and recieve buffers */
        !           128:        if (NULL == (p = ibufset = (unsigned char *)malloc(8 * RPKTSIZE)))
        !           129:            return -1;
        !           130:        if (NULL == (q = obufset = (unsigned char *)malloc(8 * spktsize)))
        !           131:            return -1;
        !           132:        for(i = 0; i < 8; ++i) {
        !           133:                inpbufs[i].bufloc = p;
        !           134:                p += RPKTSIZE;
        !           135:                outbufs[i].bufloc = q;
        !           136:                q += spktsize;
        !           137:        }
        !           138: 
        !           139:        pktsize = spktsize;     /* for dcp compatibility */
        !           140:        return 0;
        !           141: }
        !           142: 
        !           143: /* |gclosepk()| closes down the packet protocol using the |OP_CLOSE| operation
        !           144:  * of |gmachine()|.
        !           145:  */
        !           146: gclosepk()
        !           147: {
        !           148:        return gmachine(OP_CLOSE);
        !           149: }
        !           150: 
        !           151: /* |ggetpkt()| reads one packet and returns it. The data is stored in
        !           152:  * the buffer pointed to by |cdata|, and the length is stored in |*lenp|.
        !           153:  * It calls |gmachine()| to get the data, and copies it from the proper input
        !           154:  * buffer to the user's buffer area. "Short data" packets are handled here,
        !           155:  * as opposed to within |gmachine()|.
        !           156:  */
        !           157: int
        !           158: ggetpkt(cdata, lenp)
        !           159: unsigned char *cdata; 
        !           160: int *lenp;
        !           161: {
        !           162:        int     i;
        !           163:        int nextread;
        !           164:        unsigned char *bufp;
        !           165: 
        !           166:        if (!chanopen)
        !           167:                return -1;
        !           168:        nextread = (lastread + 1) & 7;
        !           169:        printmsg(M_HIGHPROTO, "waiting for input pkt seq=%d", nextread);
        !           170:        if (gmachine(OP_READ) < 0)
        !           171:                return -1;
        !           172:        *lenp = inpbufs[nextread].length;
        !           173:        bufp = inpbufs[nextread].bufloc;
        !           174:        printmsg(M_HIGHPROTO, " lenp starts out at %d, and *bufp is %d",
        !           175:                *lenp, *bufp);
        !           176:        if (inpbufs[nextread].sdata) {
        !           177:                if (*bufp < 128) {
        !           178:                        /* less than 128 bytes shorter than packet length */
        !           179:                        printmsg(M_HIGHPROTO, "decrementing lenp once");
        !           180:                        *lenp -= *bufp++;
        !           181:                } else {                /* more than 128 bytes shorter */
        !           182:                        printmsg(M_HIGHPROTO, "decrementing lenp twice");
        !           183:                        *lenp -= (*bufp++ & 127) * 256;
        !           184:                        *lenp -= *bufp++;
        !           185:                }
        !           186:        }
        !           187:        printmsg(M_HIGHPROTO,
        !           188:        "about to call memcpy, cdata %04x, bufp %04x, lenp %04x, *lenp %d",
        !           189:        cdata, bufp, lenp, *lenp);
        !           190:        i = *lenp;
        !           191:        memcpy(cdata, bufp, i);
        !           192:        lastread = nextread;
        !           193:        return 0;
        !           194: }
        !           195: 
        !           196: /* |gsendpkt()| queues the packet pointed to by |cdata| of length |len|
        !           197:  * into the packet driver output buffer, and calls |gmachine()| to send
        !           198:  * it. (|gmachine()| will return when the packet has been transmitted but
        !           199:  * not necessarily acknowledged, with window size greater than 1.) If
        !           200:  * |flag| is nonzero, |cdata| is considered a null-terminated string
        !           201:  * which will be null-padded to the packet size and transmitted.
        !           202:  */
        !           203: int
        !           204: gsendpkt(cdata, len, flag)
        !           205: unsigned char *cdata; 
        !           206: int len, flag;
        !           207: {
        !           208:        unsigned char *destp;
        !           209:        unsigned diff;
        !           210: 
        !           211:        if (!chanopen)
        !           212:                return -1;
        !           213: 
        !           214:        outbufs[nstuff].sdata = 0;
        !           215:        destp = outbufs[nstuff].bufloc;
        !           216:        if (flag && len < spktsize) {
        !           217:                printmsg(M_HIGHPROTO, "Padded message packet |%s|", cdata);
        !           218:                strncpy(destp, cdata, spktsize);
        !           219:        } else {
        !           220:                if ((diff = spktsize - len) > 127) { /* really short packet? */
        !           221:                        *destp++ = (diff >> 8) | 128;
        !           222:                        *destp++ = diff & 255;
        !           223:                        outbufs[nstuff].sdata = 1;
        !           224:                } else if (diff > 0) {                  /* short packet */
        !           225:                        *destp++ = diff;
        !           226:                        outbufs[nstuff].sdata = 1;
        !           227:                } else
        !           228:                        outbufs[nstuff].sdata = 0;
        !           229:                memcpy(destp, cdata, len);              /* copy into buffer */
        !           230:        }
        !           231:        printmsg(M_HIGHPROTO, "queued data packet seq=%d len=%d", nstuff, len);
        !           232:        outbufs[nstuff].length = spktsize;
        !           233:        nstuff = (nstuff + 1) & 7;
        !           234: 
        !           235:        return gmachine(OP_WRITE);
        !           236: }
        !           237: 
        !           238: /* |gmachine()| is the heart of the 'g' packet driver. Its basic strategy
        !           239:  * is:
        !           240:  *     - transmit a packet if necessary
        !           241:  *     - return if possible,
        !           242:  *     - else read a packet and act on it
        !           243:  *     - repeat
        !           244:  *
        !           245:  * |OP_OPEN| requests that the channel be opened, and |OP_CLOSE| requests that
        !           246:  * it be closed. If |why| is |OP_WRITE|, |gmachine()| will return when the
        !           247:  * last packet in the output queue has been transmitted (but not necessarily
        !           248:  * acknowledged). |OP_READ| requests will return as soon as a new packet
        !           249:  * arrives.
        !           250:  */
        !           251: int gmachine(why)
        !           252: int why;
        !           253: {
        !           254:        int xxx, yyy, len;
        !           255:        unsigned char *bufp;
        !           256:        int shortdat;
        !           257:        int i;
        !           258:        while(1) {
        !           259:                if (OP_CLOSE == why) {
        !           260:                        gspack(TT_CTRL, X_CLOSE, 0, (unsigned char *)NULL, 0);
        !           261:                        chanopen = 0;
        !           262:                        printmsg(M_MEDPROTO, "Sending CLOSE request...");
        !           263:                } else if (neednack) {
        !           264:                        gspack(TT_CTRL, X_RJ, recv, (unsigned char *)NULL, 0);
        !           265:                        neednack = 0;
        !           266:                        printmsg(M_MEDPROTO, "Sending RJ... recv=%d", recv);
        !           267:                } else if (send != nstuff       /* nonzero output queue? */
        !           268:                && between(send, next, nstuff)  /* 'next' in queue? */
        !           269:                && between(send, next, (send + swindow) & 7)) {
        !           270:                        /* in out win. */
        !           271:                        printmsg(M_MEDPROTO, "Sending data packet %d", next);
        !           272:                        gspack(outbufs[next].sdata ? TT_SDATA : TT_DATA,
        !           273:                        next, recv, outbufs[next].bufloc, outbufs[next].length);
        !           274:                        needack = 0;
        !           275:                        next = (next + 1) & 7;
        !           276:                        if (OP_WRITE == why && next == nstuff)
        !           277:                                /* go back for more */
        !           278:                                return 0;
        !           279:                } else if (needack) {
        !           280:                        gspack(TT_CTRL, X_RR, recv, (unsigned char *)NULL, 0);
        !           281:                        needack = 0;
        !           282:                        printmsg(M_MEDPROTO, "Sending RR... recv=%d", recv);
        !           283:                } else if (OP_OPEN == why) {
        !           284:                        if (X_INITB == initpk)
        !           285:                                i = ilog2(RPKTSIZE) - 5;
        !           286:                                        /* INITB contains packet size, */
        !           287:                        else
        !           288:                                i = RWINDOW;
        !           289:                                        /* INITA, INITC contain window size */
        !           290:                        printmsg(M_MEDPROTO, "inita/b pkt/wndow i = %d", i);
        !           291:                        /* ??? examine for INITC */
        !           292:                        gspack(TT_CTRL, initpk, i, (unsigned char *)NULL, 0);
        !           293:                }
        !           294:                if (OP_READ == why && recv != lastread) {
        !           295:                        return 0;
        !           296:                }
        !           297:                shortdat = 0;
        !           298:                bufp = buf + ENV_LEN;
        !           299:                switch(grpack(&xxx, &yyy, &len)) {
        !           300:                case LOSTPKT:
        !           301:                        printmsg(M_MEDPROTO, "Lost packet...");
        !           302:                        if (nlost > MAXLOST) {
        !           303:                                plog(M_DATA, "Lost packets from other side");
        !           304:                                return -1;
        !           305:                        }
        !           306:                        next = send;    /* retransmit last un-ack'ed pkt, */
        !           307:                        if (OP_READ == why)     /* request retransmit */
        !           308:                                neednack = 1;
        !           309:                        skipping = 0;
        !           310:                        break;
        !           311:                case BADPKT:
        !           312:                        printmsg(M_MEDPROTO, "Bad packet...");
        !           313:                        bad_count++;
        !           314:                        total_errors ++;
        !           315:                        neednack = 1;   /* reject! */
        !           316:                        skipping = 1;   /* ignore the rest of the 'window' */
        !           317:                        if (bad_count > 20) {
        !           318:                                plog(M_DATA, "Too many errors");        
        !           319:                                return -1;                              
        !           320:                        }
        !           321:                        break;
        !           322:                case TT_SDATA:
        !           323:                        shortdat = 1;
        !           324:                        /* fall through */
        !           325:                case TT_DATA:
        !           326:                        bad_count = 0;
        !           327:                        send = (yyy + 1) & 7;   /* recieve acknowledgement */
        !           328:                        if (xxx != ((recv + 1) & 7)) {
        !           329:                                printmsg(M_MEDPROTO, 
        !           330:                                "Recieved data out of sequence (%d != %d)",
        !           331:                                xxx, (recv + 1) & 7);
        !           332:                                if (!skipping) {
        !           333:                                        neednack = 1;   /* we must have missed one */
        !           334:                                        skipping = 1;
        !           335:                                } else
        !           336:                                        printmsg(M_MEDPROTO, "(Ignoring)");
        !           337:                        } else {
        !           338:                                recv = xxx;
        !           339:                                        /* this is most recent correct pkt */
        !           340:                                needack = 1; /* we will ack it */
        !           341:                                skipping = 0;
        !           342:                                inpbufs[xxx].length = len;
        !           343:                                inpbufs[xxx].sdata = shortdat;
        !           344:                                memcpy(inpbufs[xxx].bufloc, bufp, len);
        !           345:                        }
        !           346:                        break;
        !           347:                case TT_CTRL:
        !           348:                        bad_count = 0;
        !           349:                        skipping = 0;
        !           350:                        switch(xxx) {
        !           351:                        case X_CLOSE:
        !           352:                                printmsg(M_MEDPROTO, "* CLOSE *");
        !           353:                                gspack(TT_CTRL, X_CLOSE, 0, NULL, 0);
        !           354:                                chanopen = 0;
        !           355:                                if (OP_CLOSE == why)    /* expected? */
        !           356:                                        return 0;
        !           357:                                else
        !           358:                                        return -1;      /* nope */
        !           359:                        case X_RJ:
        !           360:                                printmsg(M_MEDPROTO, "got RJ yyy=%d", yyy);
        !           361:                                next = send = (yyy + 1) & 7;
        !           362:                                break;
        !           363:                        case X_RR:
        !           364:                                printmsg(M_MEDPROTO, "got RR yyy=%d", yyy);
        !           365:                                send = (yyy + 1) & 7;
        !           366:                                break;
        !           367:                        case X_INITC:
        !           368:                                printmsg(M_MEDPROTO, "* INITC *");
        !           369:                                swindow = yyy;
        !           370:                                if (X_INITC == initpk) {
        !           371:                                        chanopen = 1;
        !           372:                                        return 0;
        !           373:                                }
        !           374:                                break;
        !           375:                        case X_INITB:
        !           376:                                spktsize = 32 << yyy;
        !           377:                                printmsg(M_MEDPROTO, "* INITB *, spktsz %d",
        !           378:                                        spktsize);
        !           379:                                if (X_INITB == initpk)
        !           380:                                    initpk = X_INITC;
        !           381:                                break;
        !           382:                        case X_INITA:
        !           383:                                printmsg(M_MEDPROTO, "* INITA *");
        !           384:                                swindow = yyy;
        !           385:                                initpk = X_INITB;
        !           386:                                break;  
        !           387:                        default:
        !           388:                                printmsg(M_MEDPROTO,
        !           389:                                "bad control packet: xxx=%d", xxx);
        !           390:                        }
        !           391:                        break;
        !           392:                default:
        !           393:                        break;
        !           394:                }
        !           395:        }
        !           396: }
        !           397: 
        !           398: /*
        !           399:  * |grpack()| is responsible for reading one 'g'-protocol packet from the
        !           400:  * input communications channel. This includes framing, detecting timeouts,
        !           401:  * and checksum validation.
        !           402:  * The basic strategy is to keep a count of how many bytes have currently
        !           403:  * been read and how many are needed. When enough bytes for a packet header
        !           404:  * ("envelope") have been read, it is validated. If it is valid, and it
        !           405:  * has a nonzero data segment, the data portion is read. When it has
        !           406:  * everything, it does a checksum test and returns, with the control 
        !           407:  * information stored in |*xxxp|, |*yyyp|, and the data segment length stored
        !           408:  * in |*lenp|.
        !           409:  */
        !           410: int grpack(xxxp, yyyp, lenp)
        !           411: int *xxxp, *yyyp; 
        !           412: int *lenp;
        !           413: {
        !           414:        int need;                       /* need how many bytes? */
        !           415:        int env;                        /* 'have pkt envelope' flag */
        !           416:        int gotdle;                     /* do we have envelope hdr? */
        !           417:        int tt;                         /* packet type */
        !           418:        unsigned sum;                   /* checksum */
        !           419:        int remain;                     /* bytes which we stil need */
        !           420:        int i;
        !           421: 
        !           422:        env = gotdle = 0;
        !           423:        need = ENV_LEN;                 /* initially, need a header */
        !           424: 
        !           425:        SETALRM(TIMEOUT);               /* time out if we don't have a packet */
        !           426: 
        !           427:        while(1) {
        !           428:                if (low == high) /* prevent framebuffer overruns */
        !           429:                        low = high = buf;
        !           430:                printmsg(M_LOWPROTO, "=> l=%d h=%d g=%d", (int)(low - buf),
        !           431:                        (int)(high - buf), gotdle);
        !           432:                while((remain = need - (high - low)) > 0) {
        !           433:                        if (timedout || (i = sread2(high, remain)) < 0) {
        !           434:                                CLRALRM();
        !           435:                                ++nlost;
        !           436:                                low = high = buf;
        !           437:                                /* empty out partial packet, if any */
        !           438:                                return env ? BADPKT : LOSTPKT;
        !           439:                        }
        !           440:                        high += i; /* got some data - move upper limit up */
        !           441:                }
        !           442:                if (!gotdle) {
        !           443:                        while(low < high) { /* look for header 'DLE' prefix */
        !           444:                                if (DLE == *low) {
        !           445:                                        gotdle = 1;
        !           446:                                        break;
        !           447:                                } else
        !           448:                                        ++low;
        !           449:                        }
        !           450:                        continue;
        !           451:                } else if (!env) {
        !           452:                        /* found DLE, but haven't found header yet */
        !           453:                        if (low > buf) { /* move envelope to buf beginning */
        !           454:                                register unsigned char *dst = buf;
        !           455:                                while(low < high)
        !           456:                                        *dst++ = *low++;
        !           457:                                low = buf;
        !           458:                                high = dst;
        !           459:                        }
        !           460:                        if (buf[ENV_X] != (buf[ENV_K]^buf[ENV_C0]^
        !           461:                                buf[ENV_C1]^buf[ENV_C]) || 
        !           462:                                buf[ENV_K] < 1 || buf[ENV_K] > 9) {
        !           463:                                        /* valid? */
        !           464:                                ++low;
        !           465:                                gotdle = 0;
        !           466:                                printmsg(M_LOWPROTO,
        !           467:                                "grpack: rejecting an envelope");
        !           468:                                continue;
        !           469:                        }
        !           470:                        env = 1;                /* we have an envelope */
        !           471:                        /* store away control info */
        !           472:                        tt    = (buf[ENV_C] >> 6) & 3;  
        !           473:                        *xxxp = (buf[ENV_C] >> 3) & 7;
        !           474:                        *yyyp = (buf[ENV_C]     ) & 7;
        !           475:                        if (buf[ENV_K] == 9)    /* does it have data? */
        !           476:                                *lenp = 0;
        !           477:                        else
        !           478:                                *lenp = 16 << buf[ENV_K];
        !           479:                        /* size = 32 * 2^(k-1) */
        !           480:                        need += *lenp;          /* now need that many more */
        !           481:                        printmsg(M_LOWPROTO,
        !           482:                        "grpack: tt=%d, xxx=%d, yyy=%d, need=%d",
        !           483:                        tt, *xxxp, *yyyp, need);
        !           484:                        continue;
        !           485:                } else {                        /* have everything we need */
        !           486:                        if (*lenp)
        !           487:                                sum = MAGIC - (cksum(buf + ENV_LEN, *lenp) ^
        !           488:                                buf[ENV_C]);
        !           489:                        else {
        !           490:                                sum = MAGIC - buf[ENV_C];
        !           491:                                printmsg(M_LOWPROTO,
        !           492:                                "0 length data, data %x, %x, %x", buf[ENV_C],
        !           493:                                buf[ENV_C0], buf[ENV_C1]);
        !           494:                        }
        !           495:                        if (((sum >> 8) & 0xFF) != buf[ENV_C1]
        !           496:                                || (sum & 0xFF) != buf[ENV_C0]) {
        !           497:                                CLRALRM();
        !           498:                                nlost = 0;
        !           499:                                printmsg(M_LOWPROTO,
        !           500:                                "grpack: bad check, sum is %x", sum);
        !           501:                                low += ENV_LEN;
        !           502:                                /* we will search bad data seg for a header */
        !           503:                                return BADPKT;
        !           504:                        } else {
        !           505:                                CLRALRM();      /* got it all... return */
        !           506:                                nlost = 0;
        !           507:                                low += need;
        !           508:                                if (*lenp)
        !           509:                                        printmsg(M_DATA, "|%s|",
        !           510:                                           visbuf(buf + ENV_LEN, *lenp));
        !           511:                                return tt;
        !           512:                        }
        !           513:                }
        !           514:        }
        !           515: }
        !           516: 
        !           517: /*
        !           518:  * gspack simply sends out a packet, by assembling an envelope and writing
        !           519:  * it, and the data segment, to the communications channel.
        !           520:  */
        !           521: gspack(tt, xxx, yyy, data, size)
        !           522: int tt, xxx, yyy; 
        !           523: unsigned char *data; 
        !           524: int size;
        !           525: {
        !           526:        unsigned char envelope[ENV_LEN];        /* packet envelope */
        !           527:        unsigned sum;                           /* checksum */
        !           528:        unsigned char ctrl;                     /* header control byte */
        !           529:        int k;                                  /* size = 32 * 2^(k-1) */
        !           530: 
        !           531:        ctrl = ((tt & 3) << 6) | ((xxx & 7) << 3) | (yyy & 7);
        !           532:        if (0 == size) {
        !           533:                k = 9;                          /* no data seg */
        !           534:                sum = MAGIC - ctrl;
        !           535:        } else {
        !           536:                int tmp = size;
        !           537:                for(k = -5; tmp != 0; ++k)              /* find k */
        !           538:                        tmp >>= 1;
        !           539:                sum = MAGIC - (cksum(data, size) ^ ctrl);
        !           540:        }
        !           541:        envelope[ENV_DLE] = DLE;
        !           542:        envelope[ENV_K]   = k;
        !           543:        envelope[ENV_C1]  = (sum >> 8) & 0xFF;
        !           544:        envelope[ENV_C0]  = sum & 0xFF;
        !           545:        envelope[ENV_C]   = ctrl;
        !           546:        envelope[ENV_X]   = k ^ envelope[ENV_C0] ^ envelope[ENV_C1] ^ ctrl;
        !           547:        swrite(envelope, ENV_LEN);              /* send envelope */
        !           548:        if (0 != size)
        !           549:                swrite(data, size);             /* send data segment */
        !           550:        printmsg(M_LOWPROTO, "gspack: tt=%d xxx=%d yyy=%d k=%d sum=%x",
        !           551:        tt, xxx, yyy, k, sum);
        !           552:        if (0 != size)
        !           553:                printmsg(M_DATA, "|%s|", visbuf(data, size));
        !           554: }
        !           555: 
        !           556: /*
        !           557:  * chksum(data, len) came directly from dcp. It checksums the given data
        !           558:  * area using the g protocol algorithm.
        !           559:  */
        !           560: unsigned cksum(data, len)
        !           561: int len; 
        !           562: unsigned char *data;
        !           563: {
        !           564:        unsigned int i, j, tmp, chk1, chk2;
        !           565:        chk1 = 0xffff;
        !           566:        chk2 = 0;
        !           567:        j = len;
        !           568:        for (i = 0; i < len; i++) {
        !           569:                if (chk1 & 0x8000) {
        !           570:                        chk1 <<= 1;
        !           571:                        chk1++;
        !           572:                } else
        !           573:                        chk1 <<= 1;
        !           574:                tmp = chk1;
        !           575:                chk1 += (data[i] & 0xff);
        !           576:                chk2 += chk1 ^ j;
        !           577:                if ((chk1 & 0xffff) <= (tmp & 0xffff))
        !           578:                        chk1 ^= chk2;
        !           579:                j--;
        !           580:        }
        !           581:        return (chk1 & 0xffff);
        !           582: }
        !           583: 
        !           584: /* |ilog2(value)| returns (int)floor(log2(value)).
        !           585:  */
        !           586: int ilog2(value)
        !           587: unsigned value;
        !           588: {
        !           589:        int i;
        !           590: 
        !           591:        if (value == 0)
        !           592:                return -1;
        !           593:        for(i = 0; value > 1; ++i)
        !           594:                value >>= 1;
        !           595:        return i;
        !           596: }

unix.superglobalmegacorp.com

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