|
|
1.1 root 1: # include "defs.h"
2: struct packet *xptr, *gptr;
3: # define PACKETLENGTH (datasize + sizeof *xptr - 1)
4: # define ACKLENGTH (sizeof *xptr - 1)
5: static int bufleft;
6: int atime = ATIME;
7: int maxbread = MAXBREAD;
8: int datasize;
9: static char savebuf[BUFSIZ], retransmit;
10: static jmp_buf env;
11: short masterseqno, lastseqno;
12: FILE *readtty,*writetty;
13: struct dumpstruc dump;
14:
15: /*
16: one problem has been character loss on
17: overloaded systems due to the daemon
18: taking too long to swap in
19: and losing characters.
20: A high priority process of small size
21: with a pipe would do the job.
22: */
23: alarmint(){
24: errno = 100;
25: signal(SIGCLK,SIG_IGN); /* alarm off */
26: longjmp(env,0); /* ugh */
27: }
28: /* returns number of bytes written, error returns WRITEFAIL (-3) */
29: xwrite(inbuf,size,amt)
30: char *inbuf;
31: {
32: struct packet *rpp;
33: int cnt, num, savetime;
34: register char *p, *b;
35: register int i;
36: if(xptr == NULL)xptr = (struct packet *)calloc((PACKETLENGTH+20)/4,4);
37: if(xptr == NULL){error("xptr NULL"); return(WRITEFAIL); }
38: amt = amt * size;
39: cnt = 0;
40: retransmit = 0;
41: savetime = atime;
42: while(amt > 0){
43: if(retransmit > maxbread){
44: debug("xwrite fail");
45: return(WRITEFAIL);
46: }
47: b = inbuf+cnt;
48: num = min(datasize,amt);
49: xptr->pcode = REQUEST;
50: xptr->seqno = masterseqno;
51: xptr->len = num;
52: p = xptr->data;
53: i = num;
54: while(i--)*p++ = *b++;
55: sendpacket(xptr);
56: rpp = getpacket();
57: if(rpp == NULL){
58: atime += 3; /* wait three more secs */
59: retransmit++;
60: dump.nretrans++;
61: continue;
62: }
63: if(rpp->chksum != 0 || rpp->pcode != ACK
64: || rpp->seqno != xptr->seqno ){
65: if(rpp->pcode == RESET){
66: error("reset");
67: return(WRITEFAIL);
68: }
69: if(rpp->seqno == 1 && rpp->pcode == REQUEST){
70: error("collision");
71: return(WRITEFAIL);
72: }
73: if(rpp->chksum != 0)
74: error("chksum %d",rpp->seqno);
75: else if(rpp->pcode != ACK)
76: error("not ack %d %d",rpp->pcode,rpp->seqno);
77: else if(rpp->seqno != xptr ->seqno)
78: error("WRSQNO got %d request %d",rpp->seqno,
79: xptr->seqno);
80: atime += 3;
81: retransmit++;
82: dump.nretrans++;
83: continue;
84: }
85: masterseqno++;
86: amt -= num;
87: retransmit = 0;
88: cnt += num;
89: }
90: atime = savetime;
91: return(cnt/size);
92: }
93: /* return the number of bytes read, or error = BROKENREAD (-2) */
94: nread(b,size,num)
95: register char *b;
96: {
97: register char *p;
98: int bcnt = 0;
99: char *q;
100: register struct packet *pp;
101: int n,j,cnt;
102: num = num * size;
103: cnt = 0;
104: if(bufleft > 0){
105: p = savebuf;
106: cnt = n = min(bufleft,num);
107: while(n--)*b++ = *p++;
108: num -= cnt;
109: bufleft -= cnt;
110: if(bufleft > 0){
111: q = savebuf;
112: n = bufleft;
113: while(n--)*q++ = *p++;
114: }
115: }
116: if(num <= 0)
117: return(cnt/size);
118: retransmit = 0;
119: for(;;){
120: pp = getpacket();
121: if(pp == NULL){
122: if(++bcnt >= maxbread){
123: debug("read timeout");
124: return(BROKENREAD);
125: }
126: continue;
127: }
128: if(pp->chksum != 0){
129: error("chksum %d",pp->seqno);
130: retransmit++;
131: continue;
132: }
133: if(pp->pcode & ~(REQUEST|RESET)){
134: error("pcode %d %d",pp->pcode,pp->seqno);
135: retransmit++;
136: continue;
137: }
138: else if(pp->pcode == RESET)break;
139: else { /* else was a REQUEST packet, no chksum errs */
140: pp->pcode = ACK;
141: n = pp->len;
142: pp->len = 0;
143: sendpacket(pp); /* send ACK */
144: pp->len = n;
145: break;
146: }
147: }
148: retransmit = 0;
149: j = n = min(num,pp->len);
150: cnt += j;
151: p = pp->data;
152: while(n--)*b++ = *p++;
153: if(pp->len > num){
154: n = bufleft = pp->len - num;
155: q = savebuf;
156: while(n--)*q++ = *p++;
157: }
158: return(cnt/size);
159: }
160: printpacket(pp,dest)
161: char *dest;
162: struct packet *pp; {
163: char *s;
164: int i;
165: char c;
166: dest[0] = 0;
167: if(pp == NULL)return;
168: if(pp->pcode == REQUEST)c='r';
169: else if(pp->pcode == ACK)c = 'a';
170: else if(pp->pcode == RESET)c = 'x';
171: else if(pp->pcode == PURGE)c = 'p';
172: else c = 'u';
173: sprintf(dest,"p:%d len:%d c:%c d:", pp->seqno, pp->len, c);
174: s = dest + strlen(dest);
175: for(i=0; i<pp->len && pp->data[i]; i++)*s++ = pp->data[i];
176: *s = 0;
177: }
178: /*
179: * A purge can always be sent -
180: * the receiver totally ignores it.
181: * It is used to push the packet terminator
182: * down the wire in case of a crash
183: * leaving the receiver half reading.
184: */
185: sendpurge()
186: {
187: if(xptr == NULL)xptr = (struct packet *)calloc((PACKETLENGTH+20)/4,4);
188: if(xptr == NULL){
189: error("bad xptr");
190: return;
191: }
192: xptr->pcode = PURGE;
193: xptr->seqno = 0;
194: xptr->len = 0;
195: debug("send purge");
196: sendpacket(xptr);
197: }
198: /*
199: * A reset is sent by the sender whenever he begins to send.
200: * It is not acknowledged.
201: * The receiver must be prepared, when he receives a reset,
202: * to receive a new transmission.
203: */
204: sendreset()
205: {
206: if(xptr == NULL)xptr = (struct packet *)calloc((PACKETLENGTH+20)/4,4);
207: if(xptr == NULL){
208: error("bad xptr");
209: return;
210: }
211: xptr->pcode = RESET;
212: xptr->seqno = 0;
213: xptr->len = 0;
214: debug("send reset");
215: sendpacket(xptr);
216: }
217: /*
218: * Getreset returns in either of two cases:
219: * 1) the read times out (return BROKENREAD)
220: * 2) a reset packet is received (return 0)
221: * all other packets received are ignored.
222: */
223: getreset() {
224: register struct packet *pp;
225: register int bcnt = 0;
226: bufleft = 0; /* if any chars are left in buffer, flush them*/
227: atime = ATIME + ((rand()>>8)%15);
228: lastseqno = -1; /* forces non-RESET pks to not be ACK-ed */
229: for(;;){
230: pp = getpacket();
231: if(pp == NULL){
232: if(++bcnt >= maxbread){
233: debug("reset timeout");
234: return(BROKENREAD);
235: }
236: continue;
237: }
238: if(pp->pcode == RESET){
239: debug("got reset");
240: addtolog(remote,"^R%c ",remote);
241: lastseqno = 0;
242: return(0);
243: }
244: }
245: }
246: /*
247: * Just sends packet pp
248: * Calculates the chksum
249: */
250: sendpacket(pp)
251: struct packet *pp; {
252: char buf[BUFSIZ];
253: int len, n, i;
254: long nt,ot;
255: register char *q, *p;
256: register int j;
257: dump.nbytesent += pp->len;
258: dump.npacksent++;
259: pp->chksum = 0;
260: n = 0;
261: p = (char *)pp;
262: len = ACKLENGTH + pp->len;
263: for(j = 0; j < len; j++)n ^= *p++;
264: pp->chksum = n;
265: p = buf;
266: q = (char *)pp;
267: len = n = (len+2)/3;
268: while(n--){
269: *p++ = (*q & 077) + INCR;
270: j = (*q++ >> 6) &03;
271: *p++ = (((*q << 2) | j) & 077) + INCR;
272: j = (*q++ >> 4) & 017;
273: *p++ = (((*q << 4) | j) & 077) + INCR;
274: *p++ = ((*q++ >> 2) & 077) + INCR;
275: }
276: *p++ = '\n';
277: *p = 0;
278: /* because of bugs in processing around erase and kill in v6 */
279: for(p=buf; *p; p++)
280: if(*p == '\\')*p = '}';
281: /*
282: debug("send %d %s",len*4+1,buf);
283: */
284: ot = gettime();
285: i = fwrite(buf,1,len*4+1, writetty);
286: nt = gettime();
287: dump.waittime += (nt - ot); /* add time writing */
288: /*
289: debug("count %d",i);
290: */
291: fflush(writetty);
292: }
293: /*
294: * returns NULL if couldn't get a packet with correct seqno
295: * chksum not checked here
296: * because other programs may want to interrogate checksum
297: */
298: struct packet *getpacket() {
299: char buf[BUFSIZ];
300: int i,n,j, len, plen;
301: int bcnt;
302: register char *q, *p;
303: long ot, nt;
304: if(gptr == NULL)gptr = (struct packet *)calloc((PACKETLENGTH+20)/4,4);
305: if(gptr == NULL){error("gptr NULL"); return(NULL); }
306: bcnt = 0;
307: errno = 0;
308: setjmp(env);
309: alarm(0);
310: signal(SIGCLK,alarmint);
311: for(;;){
312: if(bcnt++ > maxbread)errno = 100; /* give up */
313: if(errno == 100){
314: if(debugflg)putchar('^');
315: return(NULL);
316: }
317: alarm(atime);
318: ot = gettime();
319: p = fgets(buf,BUFSIZ,readtty);
320: alarm(0);
321: nt = gettime();
322: dump.waittime += (nt - ot);
323: if(p == NULL){error("getpacket fails"); return(NULL); }
324: plen = strlen(buf);
325: /*
326: debug("receive %d %s",plen,buf);
327: */
328: /* remove this loop later */
329: for(p=buf; *p; p++)
330: if(*p == '}')*p = '\\';
331: p = buf;
332: q = (char *)gptr;
333: n = (strlen(buf)+3) /4;
334: while(n--){
335: if(*p == '\n')break;
336: if(*p < INCR || *p & 0200)error("bad char %o\n",*p);
337: i = *p++ - INCR;
338: j = *p++ - INCR;
339: *q++ = ((j & 03) << 6) | (i & 077);
340: i = *p++ -INCR;
341: *q++ = ((i & 017) << 4) | ((j >> 2) & 017);
342: j = *p++ - INCR;
343: *q++ = ((j & 077) << 2) | ((i >> 4) & 03);
344: }
345: *q = 0;
346: if(plen != ((ACKLENGTH + gptr->len + 2)/3)*4 + 1){
347: error("too short %d",gptr->seqno);
348: continue;
349: }
350: if(gptr->pcode == PURGE){
351: debug("got purge");
352: continue; /* never seen */
353: }
354: if(gptr->pcode == RESET)
355: break;
356: if(gptr->seqno == lastseqno){
357: if(retransmit)break;
358: /* send ACK - it was lost first time thru */
359: len = gptr->len;
360: n = gptr->pcode;
361: gptr->len = 0;
362: gptr->pcode = ACK;
363: sendpacket(gptr);
364: gptr->len = len;
365: gptr->pcode = n;
366: error("sendlostack %d",lastseqno);
367: break;
368: }
369: if(gptr->seqno == lastseqno + 1)break;
370: error("Wrong seq no g: %d last: %d",gptr->seqno,
371: lastseqno);
372: }
373: lastseqno = gptr->seqno;
374: n = 0;
375: len = gptr->len + ACKLENGTH;
376: p = (char *)gptr;
377: for(i=0; i < len; i++)n ^= *p++;
378: gptr->chksum = n;
379: if(n != 0)dump.ncksum++;
380: dump.nbytercv += gptr->len;
381: dump.npackrcv++;
382: return(gptr);
383: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.