|
|
1.1 root 1: /*
2: * C H P A C K E T
3: *
4: * Packet handling utilities for the Chaosnet line discipline.
5: *
6: *
7: * (c) Copyright 1985 Nirvonics, Inc.
8: *
9: * Written by Kurt Gollhardt
10: * Last update Thu Feb 28 14:44:14 1985
11: *
12: * This software is the property of Nirvonics, Inc.
13: * All rights reserved.
14: *
15: */
16:
17: #include "ch.h"
18: #if NCH > 0
19: #include "../h/param.h"
20: #include "../h/systm.h"
21: #include "../h/stream.h"
22: #include "../h/conf.h"
23: #include "../chaosld/types.h"
24: #include "../chaosld/constants.h"
25: #include "../chaosld/globals.h"
26:
27: #define CAREFUL
28:
29:
30: /*
31: * Get blocks from a queue, up to the next delimiter,
32: * and place them into a packet structure.
33: */
34:
35: struct packet *get_packet(q, wflag)
36: register struct queue *q;
37: {
38: register struct packet *pk;
39: register struct block *bp, **nextbp;
40: register int len;
41:
42: len = wflag? 1 : sizeof(struct pkt_header);
43: if ((bp = getq(q)) == NOBLOCK)
44: return NOPKT;
45:
46: #ifdef CAREFUL
47: if (bp->type != M_DATA ||
48: bp->wptr - bp->rptr < len) {
49: freeb(bp);
50: printf("bad block in get_packet()\n");
51: return NOPKT;
52: }
53: #endif CAREFUL
54:
55: if ((pk = pkalloc()) == NOPKT) {
56: freeb(bp);
57: flush_packet(q);
58: return NOPKT;
59: }
60:
61: if (wflag)
62: pk->pk_op = *bp->rptr++;
63: else {
64: pk->ph = *(struct pkt_header *)(bp->rptr);
65: bp->rptr += sizeof(struct pkt_header);
66: }
67: if (bp->rptr >= bp->wptr) {
68: freeb(bp);
69: bp = getq(q);
70: }
71:
72: pk->pk_lenword = 0;
73: nextbp = &pk->data;
74: while (bp != NOBLOCK && bp->type != M_DELIM) {
75: pk->pk_lenword += bp->wptr - bp->rptr;
76: *nextbp = bp;
77: nextbp = &bp->next;
78: bp = getq(q);
79: }
80: *nextbp = NOBLOCK;
81: if (bp != NOBLOCK)
82: freeb(bp); /* Throw away the delimiter */
83:
84: pk->time = Chclock;
85: pk->next = NOPKT;
86: return pk;
87: }
88:
89:
90: /*
91: * Take the header and data blocks from a packet
92: * and put them onto the queue.
93: * Any storage associated with the packet is freed.
94: */
95:
96: put_packet(q, pk)
97: struct queue *q;
98: struct packet *pk;
99: {
100: putcpy(q->next, &pk->ph, sizeof(struct pkt_header));
101: put_pkdata(q, pk);
102: }
103:
104:
105: /*
106: * Take the data blocks from a packet
107: * and put them onto the queue.
108: * Any storage associated with the packet is freed.
109: */
110:
111: put_pkdata(q, pk)
112: register struct queue *q;
113: register struct packet *pk;
114: {
115: register struct block *bp, *nextb;
116:
117: for (bp = pk->data; bp != NOBLOCK; bp = nextb) {
118: nextb = bp->next;
119: (*q->next->qinfo->putp) (q->next, bp);
120: }
121:
122: if (q->flag & QDELIM)
123: putctl(q->next, M_DELIM);
124:
125: pk->data = NOBLOCK;
126: free_packet(pk);
127: }
128:
129:
130: /*
131: * Copy the header and data blocks from a packet onto a queue.
132: */
133:
134: copy_packet(q, pk)
135: struct queue *q;
136: struct packet *pk;
137: {
138: putcpy(q->next, &pk->ph, sizeof(struct pkt_header));
139: copy_pkdata(q, pk);
140: }
141:
142:
143: /*
144: * Copy the data blocks from a packet onto a queue.
145: */
146:
147: copy_pkdata(q, pk)
148: register struct queue *q;
149: register struct packet *pk;
150: {
151: register struct block *bp;
152:
153: for (bp = pk->data; bp != NOBLOCK; bp = bp->next)
154: putcpy(q->next, bp->rptr, bp->wptr - bp->rptr);
155: putctl(q->next, M_DELIM);
156: }
157:
158:
159: /*
160: * Obtain storage for a packet and perfrom minimal initialization.
161: */
162:
163: struct packet *
164: new_packet()
165: {
166: register struct packet *pk;
167:
168: if ((pk = pkalloc()) == NOPKT)
169: return NOPKT;
170: bfill(pk, sizeof(struct packet), 0);
171: pk->time = Chclock;
172: return pk;
173: }
174:
175:
176: /*
177: * Release all storage associated with a packet structure.
178: */
179:
180: free_packet(pk)
181: register struct packet *pk;
182: {
183: free_pkdata(pk);
184: pkfree(pk);
185: }
186:
187:
188: /*
189: * Release all data blocks in packet.
190: */
191:
192: free_pkdata(pk)
193: register struct packet *pk;
194: {
195: register struct block *bp, *nextb;
196:
197: for (bp = pk->data; bp != NOBLOCK; bp = nextb) {
198: nextb = bp->next;
199: freeb(bp);
200: }
201: pk->data = NOBLOCK;
202: pk->pk_lenword = 0;
203: }
204:
205:
206: /*
207: * Collapse all of the data blocks for a packet
208: * into a single block if possible
209: */
210:
211: flatten(pk)
212: register struct packet *pk;
213: {
214: register struct block *bp, *bigb, *nextb;
215: register int n;
216: int ps;
217:
218: debug(DPKT,printf("flatten packet of length %d\n", pk->pk_len));
219: if (pk->data->wptr - pk->data->rptr >= pk->pk_len)
220: return 0;
221: if ((bigb = allocb(pk->pk_len)) == NOBLOCK) {
222: debug(DPKT|DABNOR,printf("flatten: can't alloc block\n"));
223: return -1;
224: }
225: bigb->next = NOBLOCK;
226: bp = pk->data;
227: ps = spl6();
228: pk->data = bigb;
229:
230: while (bp != NOBLOCK) {
231: n = bp->wptr - bp->rptr;
232: if (bigb->lim - bigb->wptr < n)
233: n = bigb->lim - bigb->wptr;
234: bcopy(bp->rptr, bigb->wptr, n);
235: bigb->wptr += n;
236: bp->rptr += n;
237: if (bp->rptr < bp->wptr) {
238: bigb->next = bp;
239: splx(ps);
240: debug(DPKT|DABNOR,printf("flatten: not enough room in block\n"));
241: return -1;
242: }
243: nextb = bp->next;
244: freeb(bp);
245: bp = nextb;
246: }
247:
248: splx(ps);
249: return 0;
250: }
251:
252:
253: /*
254: * Add some bytes of data to the end of a packet.
255: * Allocate blocks as necessary.
256: */
257:
258: append_packet(pkt, buf, n)
259: register struct packet *pkt;
260: char *buf;
261: int n;
262: {
263: register struct block *bp;
264: register int nmin;
265:
266: if (pkt->data == NOBLOCK) {
267: if ((bp = allocb(n)) == NOBLOCK)
268: return;
269: pkt->data = bp;
270: bp->next = NOBLOCK;
271: } else {
272: for (bp = pkt->data; bp->next != NOBLOCK; bp = bp->next)
273: ;
274: }
275:
276: while (n > 0) {
277: if (bp->wptr == bp->lim) {
278: if ((bp->next = allocb(n)) == NOBLOCK)
279: return;
280: bp = bp->next;
281: bp->next = NOBLOCK;
282: }
283: nmin = bp->lim - bp->wptr;
284: if (nmin > n)
285: nmin = n;
286: bcopy(buf, bp->wptr, nmin);
287: buf += nmin;
288: bp->wptr += nmin;
289: pkt->pk_lenword += nmin;
290: n -= nmin;
291: }
292: }
293:
294:
295: /*
296: * Free a list of packets
297: */
298: freelist(pkt)
299: register struct packet *pkt;
300: {
301: register struct packet *opkt;
302:
303: while ((opkt = pkt) != NOPKT) {
304: pkt = pkt->next;
305: free_packet(opkt);
306: }
307: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.