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