xref: /freebsd/usr.sbin/ppp/pred.c (revision 5ebc7e6281887681c3a348a5a4c902e262ccd656)
1 #include "fsm.h"
2 #include "hdlc.h"
3 #include "lcpproto.h"
4 #include "ccp.h"
5 
6 /*
7  *
8  * $Id: pred.c,v 1.2 1995/02/26 12:17:55 amurai Exp $
9  *
10  * pred.c -- Test program for Dave Rand's rendition of the
11  * predictor algorithm
12  * Updated by: iand@labtam.labtam.oz.au (Ian Donaldson)
13  * Updated by: Carsten Bormann <cabo@cs.tu-berlin.de>
14  * Original  : Dave Rand <dlr@bungi.com>/<dave_rand@novell.com>
15  */
16 
17 /* The following hash code is the heart of the algorithm:
18  * It builds a sliding hash sum of the previous 3-and-a-bit characters
19  * which will be used to index the guess table.
20  * A better hash function would result in additional compression,
21  * at the expense of time.
22  */
23 #define IHASH(x) iHash = (iHash << 4) ^ (x)
24 #define OHASH(x) oHash = (oHash << 4) ^ (x)
25 
26 static unsigned short int iHash, oHash;
27 static unsigned char InputGuessTable[65536];
28 static unsigned char OutputGuessTable[65536];
29 
30 static int
31 compress(source, dest, len)
32 unsigned char *source, *dest;
33 int len;
34 {
35     int i, bitmask;
36     unsigned char *flagdest, flags, *orgdest;
37 
38     orgdest = dest;
39     while (len) {
40         flagdest = dest++; flags = 0;   /* All guess wrong initially */
41         for (bitmask=1, i=0; i < 8 && len; i++, bitmask <<= 1) {
42             if (OutputGuessTable[oHash] == *source) {
43                 flags |= bitmask;       /* Guess was right - don't output */
44             } else {
45                 OutputGuessTable[oHash] = *source;
46                 *dest++ = *source;      /* Guess wrong, output char */
47             }
48             OHASH(*source++);len--;
49         }
50         *flagdest = flags;
51     }
52     return(dest - orgdest);
53 }
54 
55 static void
56 SyncTable(source, dest, len)
57 unsigned char *source, *dest;
58 int len;
59 {
60     int i;
61 
62     while (len--) {
63         if (InputGuessTable[iHash] != *source) {
64             InputGuessTable[iHash] = *source;
65         }
66         IHASH(*dest++ = *source++);
67     }
68 }
69 
70 static int
71 decompress(source, dest, len)
72 unsigned char *source, *dest;
73 int len;
74 {
75     int i, bitmask;
76     unsigned char flags, *orgdest;
77 
78     orgdest = dest;
79     while (len) {
80         flags = *source++;
81         len--;
82         for (i=0, bitmask = 1; i < 8; i++, bitmask <<= 1) {
83             if (flags & bitmask) {
84                 *dest = InputGuessTable[iHash];       /* Guess correct */
85             } else {
86                 if (!len)
87                     break;      /* we seem to be really done -- cabo */
88                 InputGuessTable[iHash] = *source;     /* Guess wrong */
89                 *dest = *source++;              /* Read from source */
90                 len--;
91             }
92             IHASH(*dest++);
93         }
94     }
95     return(dest - orgdest);
96 }
97 
98 #define SIZ1 2048
99 
100 void
101 Pred1Init(direction)
102 int direction;
103 {
104   if (direction & 1) {	/* Input part */
105     iHash = 0;
106     bzero(InputGuessTable, sizeof(InputGuessTable));
107   }
108   if (direction & 2) { /* Output part */
109     oHash = 0;
110     bzero(OutputGuessTable, sizeof(OutputGuessTable));
111   }
112 }
113 
114 void
115 Pred1Output(pri, proto, bp)
116 int pri;
117 u_short proto;
118 struct mbuf *bp;
119 {
120   struct mbuf *mwp;
121   u_char *cp, *wp, *hp;
122   int orglen, len;
123   u_char bufp[SIZ1];
124   u_short fcs;
125 
126   orglen = plength(bp) + 2;	/* add count of proto */
127   mwp = mballoc((orglen+2)/8*9+12, MB_HDLCOUT);
128   hp = wp = MBUF_CTOP(mwp);
129   cp = bufp;
130   *wp++ = *cp++ = orglen >> 8;
131   *wp++ = *cp++ = orglen & 0377;
132   *cp++ = proto >> 8;
133   *cp++ = proto & 0377;
134   mbread(bp, cp, orglen-2);
135   fcs = HdlcFcs(INITFCS, bufp, 2+orglen);
136   fcs = ~fcs;
137 
138   len = compress(bufp + 2, wp, orglen);
139 #ifdef DEBUG
140   logprintf("orglen (%d) --> len (%d)\n", orglen, len);
141 #endif
142   CcpInfo.orgout += orglen;
143   if (len < orglen) {
144     *hp |= 0x80;
145     wp += len;
146     CcpInfo.compout += len;
147   } else {
148     bcopy(bufp+2, wp, orglen);
149     wp += orglen;
150     CcpInfo.compout += orglen;
151   }
152 
153   *wp++ = fcs & 0377;
154   *wp++ = fcs >> 8;
155   mwp->cnt = wp - MBUF_CTOP(mwp);
156   HdlcOutput(pri, PROTO_COMPD, mwp);
157 }
158 
159 void
160 Pred1Input(bp)
161 struct mbuf *bp;
162 {
163   u_char *cp, *pp;
164   int len, olen, len1;
165   struct mbuf *wp;
166   u_char *bufp;
167   u_short fcs, proto;
168 
169   wp = mballoc(SIZ1, MB_IPIN);
170   cp = MBUF_CTOP(bp);
171   olen = plength(bp);
172   pp = bufp = MBUF_CTOP(wp);
173   *pp++ = *cp & 0177;
174   len = *cp++ << 8;
175   *pp++ = *cp;
176   len += *cp++;
177   CcpInfo.orgin += len & 0x7fff;
178   if (len & 0x8000) {
179     len1 = decompress(cp, pp, olen - 4);
180     CcpInfo.compin += olen;
181     len &= 0x7fff;
182     if (len != len1) {	/* Error is detected. Send reset request */
183       CcpSendResetReq(&CcpFsm);
184       pfree(bp);
185       return;
186     }
187     cp += olen - 4;
188     pp += len1;
189   } else {
190     CcpInfo.compin += len;
191     SyncTable(cp, pp, len);
192     cp += len;
193     pp += len;
194   }
195   *pp++ = *cp++;	/* CRC */
196   *pp++ = *cp++;
197   fcs = HdlcFcs(INITFCS, bufp, wp->cnt = pp - bufp);
198 #ifdef DEBUG
199   logprintf("fcs = %04x (%s), len = %x, olen = %x\n",
200        fcs, (fcs == GOODFCS)? "good" : "bad", len, olen);
201 #endif
202   if (fcs == GOODFCS) {
203     wp->offset += 2;		/* skip length */
204     wp->cnt -= 4;		/* skip length & CRC */
205     pp = MBUF_CTOP(wp);
206     proto = *pp++;
207     if (proto & 1) {
208       wp->offset++;
209       wp->cnt--;
210     } else {
211       wp->offset += 2;
212       wp->cnt -= 2;
213       proto = (proto << 8) | *pp++;
214     }
215     DecodePacket(proto, wp);
216   }
217   pfree(bp);
218 }
219