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