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