8 typedef struct Cstate Cstate;
13 ulong stats[ThwStats];
16 typedef struct Uncstate Uncstate;
19 QLock ackl; /* lock for acks sent back to compressor */
20 int doack; /* send an ack? */
21 int badpacks; /* bad packets seen in a row */
22 ulong ackseq; /* packets to ack */
25 int active; /* 0 => waiting for resetack */
26 int resetid; /* id of most recent reset */
33 ThwCompMask = 3UL << 21,
34 ThwCompressed = 0UL << 21,
35 ThwUncomp = 1UL << 21,
36 ThwUncompAdd = 2UL << 21, /* uncompressed, but add to decompression buffer */
37 ThwSeqMask = 0x0fffff,
41 static void *compinit(PPP*);
42 static Block* comp(PPP*, ushort, Block*, int*);
43 static Block *compresetreq(void*, Block*);
44 static void compcompack(void*, Block*);
45 static void compfini(void*);
47 static void *uncinit(PPP*);
48 static Block* uncomp(PPP*, Block*, int *protop, Block**);
49 static void uncfini(void*);
50 static void uncresetack(void*, Block*);
59 Uncomptype uncthwack = {
71 cs = mallocz(sizeof(Cstate), 1);
82 thwackcleanup(&cs->th);
88 compresetreq(void *as, Block *b)
102 netlog("thwack resetreq id=%d \n", id);
104 b = alloclcp(Lresetack, id, 4, &m);
111 comp(PPP *ppp, ushort proto, Block *b, int *protop)
122 /* put ack and protocol into b */
124 if(b->rptr - (2+4) < b->base)
125 sysfatal("thwack: not enough header in block");
127 if(ppp->unctype == &uncthwack){
128 uncs = ppp->uncstate;
133 b->rptr[0] = uncs->ackseq >> 16;
134 b->rptr[1] = uncs->ackseq >> 8;
135 b->rptr[2] = uncs->ackseq;
136 b->rptr[3] = uncs->ackmask;
139 qunlock(&uncs->ackl);
143 b->rptr[0] = proto >> 8;
150 bb = allocb(BLEN(b) + 3);
157 mustadd = n < ThwSmallPack;
158 nn = thwack(&cs->th, mustadd, bb->wptr + 3, n - 3, b, seq, cs->stats);
160 if(nn < 0 && !mustadd){
161 if(!acked || BLEN(b) + 1 > ppp->mtu){
172 bb->wptr[0] = (ThwUncomp | ThwAcked) >> 16;
174 memmove(bb->wptr + 1, b->rptr, BLEN(b));
176 bb->wptr += BLEN(b) + 1;
179 cs->seq = (seq + 1) & ThwSeqMask;
182 memmove(bb->wptr + 3, b->rptr, nn);
185 seq |= ThwCompressed;
187 bb->wptr[0] = seq>>16;
188 bb->wptr[1] = seq>>8;
203 s = mallocz(sizeof(Uncstate), 1);
207 unthwackinit(&s->ut);
219 uncresetack(void *as, Block *b)
225 m = (Lcpmsg*)b->rptr;
228 * rfc 1962 says we must reset every message
229 * we don't since we may have acked some messages
230 * which the compressor will use in the future.
232 netlog("unthwack resetack id=%d resetid=%d active=%d\n", m->id, s->resetid, s->active);
233 if(m->id == (uchar)s->resetid && !s->active){
235 unthwackinit(&s->ut);
240 uncomp(PPP *ppp, Block *bb, int *protop, Block **reply)
253 uncs = ppp->uncstate;
256 syslog(0, "ppp", ": thwack: short packet");
262 netlog("unthwack: inactive, killing packet\n");
264 r = alloclcp(Lresetreq, uncs->resetid, 4, &m);
270 seq = bb->rptr[0] << 16;
271 if((seq & ThwCompMask) == ThwUncomp){
275 seq |= (bb->rptr[1]<<8) | bb->rptr[2];
277 if((seq & ThwCompMask) == ThwCompressed){
278 b = allocb(ThwMaxBlock);
279 n = unthwack(&uncs->ut, b->wptr, ThwMaxBlock, bb->rptr, BLEN(bb), seq & ThwSeqMask);
282 syslog(0, "ppp", ": unthwack: short or corrupted packet %d seq=%ld", n, seq);
283 netlog("unthwack: short or corrupted packet n=%d seq=%ld: %s\n", n, seq, uncs->ut.err);
286 r = alloclcp(Lresetreq, ++uncs->resetid, 4, &m);
294 unthwackadd(&uncs->ut, bb->rptr, BLEN(bb), seq & ThwSeqMask);
301 mseq = unthwackstate(&uncs->ut, &mask);
304 uncs->ackmask = mask;
306 qunlock(&uncs->ackl);
310 * grab the compressed protocol field
314 proto = (proto << 8) | *b->rptr++;
318 * decode the ack, and forward to compressor
321 if(ppp->ctype == &cthwack){
323 mseq = (b->rptr[0]<<16) | (b->rptr[1]<<8) | b->rptr[2];
325 thwackack(&cs->th, mseq, mask);