|
|
1.1 root 1: #ifndef lint
2: static 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:
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: 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*/
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: 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:
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: 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;
468: out:
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*/
479: pkclose(pk)
480: register 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:
546: pkreset(pk)
547: register 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
555: bzero(s,n)
556: register char *s;
557: register n;
558: {
559: while (n--)
560: *s++ = 0;
561: }
562: #endif !BSD4_2
563:
564: pksize(n)
565: register n;
566: {
567: register k;
568:
569: n >>= 5;
570: for(k=0; n >>= 1; k++)
571: ;
572: return k;
573: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.