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