BSD 4_3 release
[unix-history] / usr / src / usr.bin / uucp / pk0.c
... / ...
CommitLineData
1#ifndef lint
2static char sccsid[] = "@(#)pk0.c 5.7 (Berkeley) 5/30/86";
3#endif
4
5#include "uucp.h"
6#include "pk.h"
7
8/*
9 * packet driver
10 */
11
12char next[8] = { 1, 2, 3, 4, 5, 6, 7, 0}; /* packet sequence numbers */
13char mask[8] = { 1, 2, 4, 010, 020, 040, 0100, 0200 };
14
15struct pack *pklines[NPLINES];
16
17int Reacks;
18
19#define PKRTIME 4
20#define PKWTIME 4
21#define PKRSKEW 3
22#define PKWSKEW 2
23extern int pktimeout, pktimeskew, Ntimeout;
24
25/*
26 * receive control messages
27 */
28pkcntl(c, pk)
29register 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
112pkaccept(pk)
113register 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++;
146free:
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*/
233pkread(pk, ibuf, icount)
234register struct pack *pk;
235char *ibuf;
236int 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 pkmove(cp, ibuf, cc, B_READ);
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*/
296pkwrite(pk, ibuf, icount)
297register struct pack *pk;
298char *ibuf;
299int 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 pkmove(cp, ibuf, cc, B_WRITE);
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
352pksack(pk)
353register 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
372pkoutput(pk)
373register 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 pk->p_nout++;
457 goto out;
458 }
459 /*
460 * enable timeout if there's nothing to send
461 * and transmission buffers are languishing
462 */
463 if (pk->p_xcount) {
464 pk->p_timer = 2;
465 pk->p_state |= WAITO;
466 } else
467 pk->p_state &= ~WAITO;
468out:
469 pk->p_obusy = 0;
470}
471
472/*
473 * shut down line by
474 * ignoring new input
475 * letting output drain
476 * releasing space and turning off line discipline
477 */
478/*ARGSUSED*/
479pkclose(pk)
480register struct pack *pk;
481{
482 register i;
483 char **bp;
484 int rcheck = 0;
485
486 pk->p_state |= DRAINO;
487
488 /*
489 * try to flush output
490 */
491 i = 0;
492 pk->p_timer = 2;
493 while (pk->p_xcount && pk->p_state&LIVE) {
494 if (pk->p_state&(RCLOSE+DOWN) || ++i > 2)
495 break;
496 pkoutput(pk);
497 }
498 pk->p_timer = 0;
499 pk->p_state |= DOWN;
500
501 /*
502 * try to exchange CLOSE messages
503 */
504 i = 0;
505 while ((pk->p_state&RCLOSE)==0 && i<2) {
506 pk->p_msg = M_CLOSE;
507 pk->p_timer = 2;
508 pkoutput(pk);
509 i++;
510 }
511
512 for(i=0;i<NPLINES;i++)
513 if (pklines[i]==pk) {
514 pklines[i] = NULL;
515 }
516
517 /*
518 * free space
519 */
520 rcheck = 0;
521 for (i=0;i<8;i++) {
522 if (pk->p_os[i] != B_NULL) {
523 free((char *)pk->p_ob[i]);
524 pk->p_xcount--;
525 }
526 if (pk->p_is[i] != B_NULL) {
527 free((char *)pk->p_ib[i]);
528 rcheck++;
529 }
530 }
531 while (pk->p_ipool != NULL) {
532 bp = pk->p_ipool;
533 pk->p_ipool = (char **)*bp;
534 rcheck++;
535 free((char *)bp);
536 }
537 if (rcheck != pk->p_rwindow) {
538 char buf[256];
539
540 sprintf(buf, "PK0: rc %d rw %d", rcheck, pk->p_rwindow);
541 logent(buf, "pkclose rcheck != p_rwindow");
542 }
543 free((char *)pk);
544}
545
546pkreset(pk)
547register struct pack *pk;
548{
549
550 pk->p_ps = pk->p_pr = pk->p_rpr = 0;
551 pk->p_nxtps = 1;
552}
553
554#ifndef BSD4_2
555bzero(s,n)
556register char *s;
557register n;
558{
559 while (n--)
560 *s++ = 0;
561}
562#endif !BSD4_2
563
564pksize(n)
565register n;
566{
567 register k;
568
569 n >>= 5;
570 for(k=0; n >>= 1; k++)
571 ;
572 return k;
573}