double INMAX and OUTMAX (from thomas@utah-cs)
[unix-history] / usr / src / usr.bin / uucp / uucico / pk0.c
CommitLineData
b0b08d43 1#ifndef lint
2af814a5 2static char sccsid[] = "@(#)pk0.c 5.5 (Berkeley) %G%";
b0b08d43
SL
3#endif
4
1a85e9d2 5#include "uucp.h"
b0b08d43 6#include "pk.h"
b0b08d43 7
b0b08d43
SL
8/*
9 * packet driver
10 */
11
46b15d8a
RC
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 };
b0b08d43
SL
14
15struct pack *pklines[NPLINES];
2af814a5
JB
16
17#define PKTIME 4
18extern int pktimeout, Ntimeout;
b0b08d43
SL
19
20/*
21 * receive control messages
22 */
23pkcntl(c, pk)
24register struct pack *pk;
25{
46b15d8a 26 register cntl, val;
b0b08d43
SL
27
28 val = c & MOD8;
29 cntl = (c>>3) & MOD8;
30
46b15d8a
RC
31 if (!ISCNTL(c)) {
32 logent("PK0", "not cntl");
b0b08d43
SL
33 return;
34 }
35
b0b08d43 36 switch(cntl) {
b0b08d43
SL
37 case INITB:
38 val++;
39 pk->p_xsize = pksizes[val];
40 pk->p_lpsize = val;
46b15d8a 41 pk->p_bits = 1;
b0b08d43
SL
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;
b0b08d43
SL
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:
46b15d8a
RC
64 if (val == 0 && pk->p_state&LIVE) {
65 logent("PK0", "alloc change not implemented");
b0b08d43
SL
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;
46b15d8a 80 (void) pksack(pk);
b0b08d43
SL
81 break;
82 case SRJ:
46b15d8a 83 logent("PK0", "srj not implemented");
b0b08d43
SL
84 break;
85 case CLOSE:
86 pk->p_state = DOWN+RCLOSE;
b0b08d43
SL
87 return;
88 }
b0b08d43
SL
89 if (pk->p_msg)
90 pkoutput(pk);
91}
92
b0b08d43
SL
93pkaccept(pk)
94register struct pack *pk;
95{
46b15d8a
RC
96 register x, seq;
97 char m, cntl, *p, imask, **bp;
98 int bad, accept, skip, t, cc;
99 unsigned short sum;
b0b08d43
SL
100
101 bad = accept = skip = 0;
102 /*
103 * wait for input
104 */
b0b08d43 105 x = next[pk->p_pr];
46b15d8a
RC
106 while ((imask=pk->p_imap) == 0 && pk->p_rcount == 0) {
107 pkgetpack(pk);
b0b08d43
SL
108 }
109 pk->p_imap = 0;
b0b08d43
SL
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
b0b08d43
SL
118 /*
119 * mark newly accepted input buffers
120 */
121 for(x=0; x<8; x++) {
b0b08d43
SL
122 if ((imask & mask[x]) == 0)
123 continue;
124
46b15d8a 125 if (((cntl=pk->p_is[x])&0200) == 0) {
b0b08d43
SL
126 bad++;
127free:
128 bp = (char **)pk->p_ib[x];
b0b08d43
SL
129 *bp = (char *)pk->p_ipool;
130 pk->p_ipool = bp;
131 pk->p_is[x] = 0;
b0b08d43
SL
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) {
b0b08d43
SL
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;
b0b08d43
SL
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;
46b15d8a
RC
181 t = -1;
182 for(x=next[pk->p_pr]; m & mask[x]; x = next[x]) {
b0b08d43
SL
183 if (pk->p_is[x] & B_MARK)
184 pk->p_is[x] |= B_COPY;
46b15d8a 185
b0b08d43
SL
186 if (pk->p_is[x] & B_COPY) {
187 if (t >= 0) {
188 bp = (char **)pk->p_ib[x];
b0b08d43
SL
189 *bp = (char *)pk->p_ipool;
190 pk->p_ipool = bp;
191 pk->p_is[x] = 0;
b0b08d43 192 skip++;
46b15d8a 193 } else
b0b08d43
SL
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;
46b15d8a 210 return accept;
b0b08d43
SL
211}
212
46b15d8a 213/*ARGSUSED*/
98dff38c
JB
214pkread(pk, ibuf, icount)
215register struct pack *pk;
46b15d8a 216char *ibuf;
98dff38c 217int icount;
b0b08d43 218{
46b15d8a
RC
219 register x;
220 int is, cc, xfr, count;
221 char *cp, **bp;
b0b08d43 222
b0b08d43
SL
223 xfr = 0;
224 count = 0;
2af814a5
JB
225 pktimeout = PKTIME;
226 Ntimeout = 0;
46b15d8a
RC
227 while (pkaccept(pk) == 0)
228 ;
b0b08d43 229
46b15d8a 230 while (icount) {
b0b08d43
SL
231 x = next[pk->p_pr];
232 is = pk->p_is[x];
233
234 if (is & B_COPY) {
46b15d8a 235 cc = MIN(pk->p_isum[x], icount);
b0b08d43
SL
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 }
46b15d8a
RC
248 pkmove(cp, ibuf, cc, B_READ);
249 ibuf += cc;
250 icount -= cc;
b0b08d43
SL
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];
b0b08d43
SL
257 *bp = (char *)pk->p_ipool;
258 pk->p_ipool = bp;
259 pk->p_is[x] = 0;
260 pk->p_rcount--;
b0b08d43
SL
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);
46b15d8a 272 return count;
b0b08d43
SL
273}
274
46b15d8a 275/*ARGSUSED*/
98dff38c
JB
276pkwrite(pk, ibuf, icount)
277register struct pack *pk;
46b15d8a
RC
278char *ibuf;
279int icount;
b0b08d43 280{
46b15d8a
RC
281 register x;
282 int partial;
283 caddr_t cp;
284 int cc, fc, count;
b0b08d43 285
b0b08d43 286 if (pk->p_state&DOWN || !pk->p_state&LIVE) {
46b15d8a 287 return -1;
b0b08d43
SL
288 }
289
2af814a5
JB
290 pktimeout = PKTIME;
291 Ntimeout = 0;
46b15d8a 292 count = icount;
b0b08d43 293 do {
b0b08d43
SL
294 while (pk->p_xcount>=pk->p_swindow) {
295 pkoutput(pk);
46b15d8a 296 pkgetpack(pk);
b0b08d43
SL
297 }
298 x = next[pk->p_pscopy];
299 while (pk->p_os[x]!=B_NULL) {
46b15d8a 300 pkgetpack(pk);
b0b08d43
SL
301 }
302 pk->p_os[x] = B_MARK;
303 pk->p_pscopy = x;
304 pk->p_xcount++;
b0b08d43 305
46b15d8a 306 cp = pk->p_ob[x] = malloc((unsigned)pk->p_xsize);
b0b08d43 307 partial = 0;
46b15d8a
RC
308 if ((int)icount < pk->p_xsize) {
309 cc = icount;
b0b08d43
SL
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;
46b15d8a
RC
320 pkmove(cp, ibuf, cc, B_WRITE);
321 ibuf += cc;
322 icount -= cc;
b0b08d43
SL
323 pk->p_osum[x] = chksum(pk->p_ob[x], pk->p_xsize);
324 pk->p_os[x] = B_READY+partial;
325 pkoutput(pk);
46b15d8a 326 } while (icount);
b0b08d43 327
46b15d8a 328 return count;
b0b08d43
SL
329}
330
331pksack(pk)
332register struct pack *pk;
333{
46b15d8a 334 register x, i;
b0b08d43
SL
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--;
46b15d8a 344 free((char *)pk->p_ob[x]);
b0b08d43 345 pk->p_ps = x;
b0b08d43
SL
346 }
347 }
46b15d8a 348 return i;
b0b08d43
SL
349}
350
b0b08d43
SL
351pkoutput(pk)
352register struct pack *pk;
353{
46b15d8a
RC
354 register x;
355 int i;
356 char bstate;
357
358 if (pk->p_obusy++) {
b0b08d43 359 pk->p_obusy--;
b0b08d43
SL
360 return;
361 }
b0b08d43
SL
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];
b0b08d43
SL
369 }
370 x = pk->p_nxtps;
371 bstate = pk->p_os[x];
372
b0b08d43
SL
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;
46b15d8a 379 for(i=0; i<8; i++)
b0b08d43 380 if (x&1)
46b15d8a
RC
381 break;
382 else
383 x >>= 1;
b0b08d43
SL
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) {
b0b08d43
SL
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;
b0b08d43
SL
447out:
448 pk->p_obusy = 0;
449}
450
b0b08d43
SL
451/*
452 * shut down line by
453 * ignoring new input
454 * letting output drain
455 * releasing space and turning off line discipline
456 */
46b15d8a 457/*ARGSUSED*/
98dff38c
JB
458pkclose(pk)
459register struct pack *pk;
b0b08d43 460{
1a85e9d2 461 register i;
46b15d8a 462 char **bp;
1a85e9d2 463 int rcheck = 0;
b0b08d43 464
b0b08d43
SL
465 pk->p_state |= DRAINO;
466
b0b08d43
SL
467 /*
468 * try to flush output
469 */
470 i = 0;
b0b08d43
SL
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);
b0b08d43
SL
476 }
477 pk->p_timer = 0;
478 pk->p_state |= DOWN;
b0b08d43
SL
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);
b0b08d43
SL
488 i++;
489 }
490
b0b08d43
SL
491 for(i=0;i<NPLINES;i++)
492 if (pklines[i]==pk) {
493 pklines[i] = NULL;
494 }
b0b08d43
SL
495
496 /*
497 * free space
498 */
b0b08d43
SL
499 rcheck = 0;
500 for (i=0;i<8;i++) {
46b15d8a
RC
501 if (pk->p_os[i] != B_NULL) {
502 free((char *)pk->p_ob[i]);
b0b08d43
SL
503 pk->p_xcount--;
504 }
46b15d8a
RC
505 if (pk->p_is[i] != B_NULL) {
506 free((char *)pk->p_ib[i]);
b0b08d43
SL
507 rcheck++;
508 }
509 }
b0b08d43
SL
510 while (pk->p_ipool != NULL) {
511 bp = pk->p_ipool;
512 pk->p_ipool = (char **)*bp;
513 rcheck++;
46b15d8a 514 free((char *)bp);
b0b08d43 515 }
46b15d8a
RC
516 if (rcheck != pk->p_rwindow) {
517 logent("PK0", "pkclose rcheck != p_rwindow");
b0b08d43 518 }
46b15d8a 519 free((char *)pk);
b0b08d43
SL
520}
521
b0b08d43
SL
522pkreset(pk)
523register struct pack *pk;
524{
525
526 pk->p_ps = pk->p_pr = pk->p_rpr = 0;
527 pk->p_nxtps = 1;
528}
529
46b15d8a
RC
530#ifndef BSD4_2
531bzero(s,n)
b0b08d43
SL
532register char *s;
533register n;
534{
535 while (n--)
536 *s++ = 0;
537}
46b15d8a 538#endif !BSD4_2
b0b08d43
SL
539
540pksize(n)
541register n;
542{
46b15d8a 543 register k;
b0b08d43
SL
544
545 n >>= 5;
46b15d8a
RC
546 for(k=0; n >>= 1; k++)
547 ;
548 return k;
b0b08d43 549}