|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)pk0.c 5.9 (Berkeley) 4/5/88"; ! 3: #endif ! 4: ! 5: #include "uucp.h" ! 6: #include "pk.h" ! 7: ! 8: /* ! 9: * packet driver ! 10: */ ! 11: ! 12: char next[8] = { 1, 2, 3, 4, 5, 6, 7, 0}; /* packet sequence numbers */ ! 13: char mask[8] = { 1, 2, 4, 010, 020, 040, 0100, 0200 }; ! 14: ! 15: struct pack *pklines[NPLINES]; ! 16: ! 17: int Reacks; ! 18: ! 19: #define PKRTIME 4 ! 20: #define PKWTIME 4 ! 21: #define PKRSKEW 3 ! 22: #define PKWSKEW 2 ! 23: extern int pktimeout, pktimeskew, Ntimeout; ! 24: ! 25: /* ! 26: * receive control messages ! 27: */ ! 28: pkcntl(c, pk) ! 29: register struct pack *pk; ! 30: { ! 31: register cntl, val; ! 32: ! 33: val = c & MOD8; ! 34: cntl = (c>>3) & MOD8; ! 35: ! 36: if (!ISCNTL(c)) { ! 37: logent("PK0", "not cntl"); ! 38: return; ! 39: } ! 40: ! 41: switch(cntl) { ! 42: case INITB: ! 43: val++; ! 44: pk->p_xsize = pksizes[val]; ! 45: pk->p_lpsize = val; ! 46: pk->p_bits = 1; ! 47: if (pk->p_state & LIVE) { ! 48: pk->p_msg |= M_INITC; ! 49: break; ! 50: } ! 51: pk->p_state |= INITb; ! 52: if ((pk->p_state & INITa)==0) { ! 53: break; ! 54: } ! 55: pk->p_rmsg &= ~M_INITA; ! 56: pk->p_msg |= M_INITC; ! 57: break; ! 58: ! 59: case INITC: ! 60: if ((pk->p_state&INITab)==INITab) { ! 61: pk->p_state = LIVE; ! 62: pk->p_rmsg &= ~M_INITB; ! 63: } else ! 64: pk->p_msg |= M_INITB; ! 65: if (val) ! 66: pk->p_swindow = val; ! 67: break; ! 68: case INITA: ! 69: if (val == 0 && pk->p_state&LIVE) { ! 70: logent("PK0", "alloc change not implemented"); ! 71: break; ! 72: } ! 73: if (val) { ! 74: pk->p_state |= INITa; ! 75: pk->p_msg |= M_INITB; ! 76: pk->p_rmsg |= M_INITB; ! 77: pk->p_swindow = val; ! 78: } ! 79: break; ! 80: case RJ: ! 81: pk->p_state |= RXMIT; ! 82: pk->p_msg |= M_RR; ! 83: pk->p_rpr = val; ! 84: (void) pksack(pk); ! 85: break; ! 86: case RR: ! 87: pk->p_rpr = val; ! 88: if (pk->p_rpr == pk->p_ps) { ! 89: DEBUG(9, "Reack count is %d\n", ++Reacks); ! 90: if (Reacks >= 4) { ! 91: DEBUG(6, "Reack overflow on %d\n", val); ! 92: pk->p_state |= RXMIT; ! 93: pk->p_msg |= M_RR; ! 94: Reacks = 0; ! 95: } ! 96: } else { ! 97: Reacks = 0; ! 98: (void) pksack(pk); ! 99: } ! 100: break; ! 101: case SRJ: ! 102: logent("PK0", "srj not implemented"); ! 103: break; ! 104: case CLOSE: ! 105: pk->p_state = DOWN+RCLOSE; ! 106: return; ! 107: } ! 108: if (pk->p_msg) ! 109: pkoutput(pk); ! 110: } ! 111: ! 112: pkaccept(pk) ! 113: register struct pack *pk; ! 114: { ! 115: register x, seq; ! 116: char m, cntl, *p, imask, **bp; ! 117: int bad, accept, skip, t, cc; ! 118: unsigned short sum; ! 119: ! 120: bad = accept = skip = 0; ! 121: /* ! 122: * wait for input ! 123: */ ! 124: x = next[pk->p_pr]; ! 125: while ((imask=pk->p_imap) == 0 && pk->p_rcount == 0) { ! 126: pkgetpack(pk); ! 127: } ! 128: pk->p_imap = 0; ! 129: ! 130: /* ! 131: * determine input window in m. ! 132: */ ! 133: t = (~(-1<<(int)(pk->p_rwindow))) <<x; ! 134: m = t; ! 135: m |= t>>8; ! 136: ! 137: /* ! 138: * mark newly accepted input buffers ! 139: */ ! 140: for(x=0; x<8; x++) { ! 141: if ((imask & mask[x]) == 0) ! 142: continue; ! 143: ! 144: if (((cntl=pk->p_is[x])&0200) == 0) { ! 145: bad++; ! 146: free: ! 147: bp = (char **)pk->p_ib[x]; ! 148: *bp = (char *)pk->p_ipool; ! 149: pk->p_ipool = bp; ! 150: pk->p_is[x] = 0; ! 151: continue; ! 152: } ! 153: ! 154: pk->p_is[x] = ~(B_COPY+B_MARK); ! 155: sum = (unsigned)chksum(pk->p_ib[x], pk->p_rsize) ^ (unsigned)(cntl&0377); ! 156: sum += pk->p_isum[x]; ! 157: if (sum == CHECK) { ! 158: seq = (cntl>>3) & MOD8; ! 159: if (m & mask[seq]) { ! 160: if (pk->p_is[seq] & (B_COPY | B_MARK)) { ! 161: dup: ! 162: pk->p_msg |= M_RR; ! 163: skip++; ! 164: goto free; ! 165: } ! 166: if (x != seq) { ! 167: p = pk->p_ib[x]; ! 168: pk->p_ib[x] = pk->p_ib[seq]; ! 169: pk->p_is[x] = pk->p_is[seq]; ! 170: pk->p_ib[seq] = p; ! 171: } ! 172: pk->p_is[seq] = B_MARK; ! 173: accept++; ! 174: cc = 0; ! 175: if (cntl&B_SHORT) { ! 176: pk->p_is[seq] = B_MARK+B_SHORT; ! 177: p = pk->p_ib[seq]; ! 178: cc = (unsigned)*p++ & 0377; ! 179: if (cc & 0200) { ! 180: cc &= 0177; ! 181: cc |= *p << 7; ! 182: } ! 183: } ! 184: pk->p_isum[seq] = pk->p_rsize - cc; ! 185: } else { ! 186: goto dup; ! 187: } ! 188: } else { ! 189: bad++; ! 190: goto free; ! 191: } ! 192: } ! 193: ! 194: /* ! 195: * scan window again turning marked buffers into ! 196: * COPY buffers and looking for missing sequence ! 197: * numbers. ! 198: */ ! 199: accept = 0; ! 200: t = -1; ! 201: for(x=next[pk->p_pr]; m & mask[x]; x = next[x]) { ! 202: if (pk->p_is[x] & B_MARK) ! 203: pk->p_is[x] |= B_COPY; ! 204: ! 205: if (pk->p_is[x] & B_COPY) { ! 206: if (t >= 0) { ! 207: bp = (char **)pk->p_ib[x]; ! 208: *bp = (char *)pk->p_ipool; ! 209: pk->p_ipool = bp; ! 210: pk->p_is[x] = 0; ! 211: skip++; ! 212: } else ! 213: accept++; ! 214: } else { ! 215: if (t<0) ! 216: t = x; ! 217: } ! 218: } ! 219: ! 220: if (bad) { ! 221: pk->p_msg |= M_RJ; ! 222: } ! 223: ! 224: if (skip) { ! 225: pk->p_msg |= M_RR; ! 226: } ! 227: ! 228: pk->p_rcount = accept; ! 229: return accept; ! 230: } ! 231: ! 232: /*ARGSUSED*/ ! 233: pkread(pk, ibuf, icount) ! 234: register struct pack *pk; ! 235: char *ibuf; ! 236: int icount; ! 237: { ! 238: register x; ! 239: int is, cc, xfr, count; ! 240: char *cp, **bp; ! 241: ! 242: xfr = 0; ! 243: count = 0; ! 244: pktimeout = PKRTIME; ! 245: pktimeskew = PKRSKEW; ! 246: Ntimeout = 0; ! 247: while (pkaccept(pk) == 0) ! 248: ; ! 249: ! 250: while (icount) { ! 251: x = next[pk->p_pr]; ! 252: is = pk->p_is[x]; ! 253: ! 254: if (is & B_COPY) { ! 255: cc = MIN(pk->p_isum[x], icount); ! 256: if (cc==0 && xfr) { ! 257: break; ! 258: } ! 259: if (is & B_RESID) ! 260: cp = pk->p_rptr; ! 261: else { ! 262: cp = pk->p_ib[x]; ! 263: if (is & B_SHORT) { ! 264: if (*cp++ & 0200) ! 265: cp++; ! 266: } ! 267: } ! 268: bcopy(cp, ibuf, cc); ! 269: ibuf += cc; ! 270: icount -= cc; ! 271: count += cc; ! 272: xfr++; ! 273: pk->p_isum[x] -= cc; ! 274: if (pk->p_isum[x] == 0) { ! 275: pk->p_pr = x; ! 276: bp = (char **)pk->p_ib[x]; ! 277: *bp = (char *)pk->p_ipool; ! 278: pk->p_ipool = bp; ! 279: pk->p_is[x] = 0; ! 280: pk->p_rcount--; ! 281: pk->p_msg |= M_RR; ! 282: } else { ! 283: pk->p_rptr = cp+cc; ! 284: pk->p_is[x] |= B_RESID; ! 285: } ! 286: if (cc==0) ! 287: break; ! 288: } else ! 289: break; ! 290: } ! 291: pkoutput(pk); ! 292: return count; ! 293: } ! 294: ! 295: /*ARGSUSED*/ ! 296: pkwrite(pk, ibuf, icount) ! 297: register struct pack *pk; ! 298: char *ibuf; ! 299: int icount; ! 300: { ! 301: register x; ! 302: int partial; ! 303: caddr_t cp; ! 304: int cc, fc, count; ! 305: ! 306: if (pk->p_state&DOWN || !pk->p_state&LIVE) { ! 307: return -1; ! 308: } ! 309: ! 310: pktimeout = PKWTIME; ! 311: pktimeskew = PKWSKEW; ! 312: Ntimeout = 0; ! 313: count = icount; ! 314: do { ! 315: while (pk->p_xcount>=pk->p_swindow) { ! 316: pkoutput(pk); ! 317: pkgetpack(pk); ! 318: } ! 319: x = next[pk->p_pscopy]; ! 320: while (pk->p_os[x]!=B_NULL) { ! 321: pkgetpack(pk); ! 322: } ! 323: pk->p_os[x] = B_MARK; ! 324: pk->p_pscopy = x; ! 325: pk->p_xcount++; ! 326: ! 327: cp = pk->p_ob[x] = malloc((unsigned)pk->p_xsize); ! 328: partial = 0; ! 329: if ((int)icount < pk->p_xsize) { ! 330: cc = icount; ! 331: fc = pk->p_xsize - cc; ! 332: *cp = fc&0177; ! 333: if (fc > 127) { ! 334: *cp++ |= 0200; ! 335: *cp++ = fc>>7; ! 336: } else ! 337: cp++; ! 338: partial = B_SHORT; ! 339: } else ! 340: cc = pk->p_xsize; ! 341: bcopy(ibuf, cp, cc); ! 342: ibuf += cc; ! 343: icount -= cc; ! 344: pk->p_osum[x] = chksum(pk->p_ob[x], pk->p_xsize); ! 345: pk->p_os[x] = B_READY+partial; ! 346: pkoutput(pk); ! 347: } while (icount); ! 348: ! 349: return count; ! 350: } ! 351: ! 352: pksack(pk) ! 353: register struct pack *pk; ! 354: { ! 355: register x, i; ! 356: ! 357: i = 0; ! 358: for(x=pk->p_ps; x!=pk->p_rpr; ) { ! 359: x = next[x]; ! 360: if (pk->p_os[x]&B_SENT) { ! 361: i++; ! 362: pk->p_os[x] = B_NULL; ! 363: pk->p_state &= ~WAITO; ! 364: pk->p_xcount--; ! 365: free((char *)pk->p_ob[x]); ! 366: pk->p_ps = x; ! 367: } ! 368: } ! 369: return i; ! 370: } ! 371: ! 372: pkoutput(pk) ! 373: register struct pack *pk; ! 374: { ! 375: register x; ! 376: int i; ! 377: char bstate; ! 378: ! 379: if (pk->p_obusy++) { ! 380: pk->p_obusy--; ! 381: return; ! 382: } ! 383: ! 384: /* ! 385: * find seq number and buffer state ! 386: * of next output packet ! 387: */ ! 388: if (pk->p_state&RXMIT) { ! 389: pk->p_nxtps = next[pk->p_rpr]; ! 390: } ! 391: x = pk->p_nxtps; ! 392: bstate = pk->p_os[x]; ! 393: ! 394: /* ! 395: * Send control packet if indicated ! 396: */ ! 397: if (pk->p_msg) { ! 398: if (pk->p_msg & ~M_RR || !(bstate&B_READY) ) { ! 399: x = pk->p_msg; ! 400: for(i=0; i<8; i++) ! 401: if (x&1) ! 402: break; ! 403: else ! 404: x >>= 1; ! 405: x = i; ! 406: x <<= 3; ! 407: switch(i) { ! 408: case CLOSE: ! 409: break; ! 410: case RJ: ! 411: case RR: ! 412: x += pk->p_pr; ! 413: break; ! 414: case SRJ: ! 415: break; ! 416: case INITB: ! 417: x += pksize(pk->p_rsize); ! 418: break; ! 419: case INITC: ! 420: x += pk->p_rwindow; ! 421: break; ! 422: case INITA: ! 423: x += pk->p_rwindow; ! 424: break; ! 425: } ! 426: ! 427: pk->p_msg &= ~mask[i]; ! 428: pkxstart(pk, x, -1); ! 429: goto out; ! 430: } ! 431: } ! 432: ! 433: ! 434: /* ! 435: * Don't send data packets if line is marked dead. ! 436: */ ! 437: if (pk->p_state&DOWN) { ! 438: goto out; ! 439: } ! 440: /* ! 441: * Start transmission (or retransmission) of data packets. ! 442: */ ! 443: if (bstate & (B_READY|B_SENT)) { ! 444: char seq; ! 445: ! 446: bstate |= B_SENT; ! 447: seq = x; ! 448: pk->p_nxtps = next[x]; ! 449: ! 450: x = 0200+pk->p_pr+(seq<<3); ! 451: if (bstate & B_SHORT) ! 452: x |= 0100; ! 453: pkxstart(pk, x, seq); ! 454: pk->p_os[seq] = bstate; ! 455: pk->p_state &= ~RXMIT; ! 456: goto out; ! 457: } ! 458: /* ! 459: * enable timeout if there's nothing to send ! 460: * and transmission buffers are languishing ! 461: */ ! 462: if (pk->p_xcount) { ! 463: pk->p_state |= WAITO; ! 464: } else ! 465: pk->p_state &= ~WAITO; ! 466: out: ! 467: pk->p_obusy = 0; ! 468: } ! 469: ! 470: /* ! 471: * shut down line by ! 472: * ignoring new input ! 473: * letting output drain ! 474: * releasing space and turning off line discipline ! 475: */ ! 476: /*ARGSUSED*/ ! 477: pkclose(pk) ! 478: register struct pack *pk; ! 479: { ! 480: register i; ! 481: char **bp; ! 482: int rcheck = 0; ! 483: ! 484: pk->p_state |= DRAINO; ! 485: ! 486: /* ! 487: * try to flush output ! 488: */ ! 489: i = 0; ! 490: while (pk->p_xcount && pk->p_state&LIVE) { ! 491: if (pk->p_state&(RCLOSE+DOWN) || ++i > 2) ! 492: break; ! 493: pkoutput(pk); ! 494: } ! 495: pk->p_state |= DOWN; ! 496: ! 497: /* ! 498: * try to exchange CLOSE messages ! 499: */ ! 500: i = 0; ! 501: while ((pk->p_state&RCLOSE)==0 && i<2) { ! 502: pk->p_msg = M_CLOSE; ! 503: pkoutput(pk); ! 504: i++; ! 505: } ! 506: ! 507: for(i=0;i<NPLINES;i++) ! 508: if (pklines[i]==pk) { ! 509: pklines[i] = NULL; ! 510: } ! 511: ! 512: /* ! 513: * free space ! 514: */ ! 515: rcheck = 0; ! 516: for (i=0;i<8;i++) { ! 517: if (pk->p_os[i] != B_NULL) { ! 518: free((char *)pk->p_ob[i]); ! 519: pk->p_xcount--; ! 520: } ! 521: if (pk->p_is[i] != B_NULL) { ! 522: free((char *)pk->p_ib[i]); ! 523: rcheck++; ! 524: } ! 525: } ! 526: while (pk->p_ipool != NULL) { ! 527: bp = pk->p_ipool; ! 528: pk->p_ipool = (char **)*bp; ! 529: rcheck++; ! 530: free((char *)bp); ! 531: } ! 532: if (rcheck != pk->p_rwindow) { ! 533: syslog(LOG_WARNING, "%s: pk0: rc %d rw %d", Rmtname, rcheck, ! 534: pk->p_rwindow); ! 535: } ! 536: free((char *)pk); ! 537: } ! 538: ! 539: pkreset(pk) ! 540: register struct pack *pk; ! 541: { ! 542: ! 543: pk->p_ps = pk->p_pr = pk->p_rpr = 0; ! 544: pk->p_nxtps = 1; ! 545: } ! 546: ! 547: #ifndef BSD4_2 ! 548: bzero(s,n) ! 549: register char *s; ! 550: register n; ! 551: { ! 552: while (n--) ! 553: *s++ = 0; ! 554: } ! 555: #endif !BSD4_2 ! 556: ! 557: pksize(n) ! 558: register n; ! 559: { ! 560: register k; ! 561: ! 562: n >>= 5; ! 563: for(k=0; n >>= 1; k++) ! 564: ; ! 565: return k; ! 566: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.