|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.