Annotation of coherent/a/usr/bob/uusrc/dcp/gpkt.c, revision 1.1.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.