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