pred.c revision 21673
1#include "fsm.h"
2#include "hdlc.h"
3#include "lcpproto.h"
4#include "ccp.h"
5
6/*
7 *
8 * $FreeBSD: head/usr.sbin/ppp/pred.c 21673 1997-01-14 07:20:47Z jkh $
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
26static unsigned short int iHash, oHash;
27static unsigned char InputGuessTable[65536];
28static unsigned char OutputGuessTable[65536];
29
30static int
31compress(source, dest, len)
32unsigned char *source, *dest;
33int 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
55static void
56SyncTable(source, dest, len)
57unsigned char *source, *dest;
58int len;
59{
60
61    while (len--) {
62        if (InputGuessTable[iHash] != *source) {
63            InputGuessTable[iHash] = *source;
64        }
65        IHASH(*dest++ = *source++);
66    }
67}
68
69static int
70decompress(source, dest, len)
71unsigned char *source, *dest;
72int len;
73{
74    int i, bitmask;
75    unsigned char flags, *orgdest;
76
77    orgdest = dest;
78    while (len) {
79        flags = *source++;
80        len--;
81        for (i=0, bitmask = 1; i < 8; i++, bitmask <<= 1) {
82            if (flags & bitmask) {
83                *dest = InputGuessTable[iHash];       /* Guess correct */
84            } else {
85                if (!len)
86                    break;      /* we seem to be really done -- cabo */
87                InputGuessTable[iHash] = *source;     /* Guess wrong */
88                *dest = *source++;              /* Read from source */
89                len--;
90            }
91            IHASH(*dest++);
92        }
93    }
94    return(dest - orgdest);
95}
96
97#define SIZ1 2048
98
99void
100Pred1Init(direction)
101int direction;
102{
103  if (direction & 1) {	/* Input part */
104    iHash = 0;
105    bzero(InputGuessTable, sizeof(InputGuessTable));
106  }
107  if (direction & 2) { /* Output part */
108    oHash = 0;
109    bzero(OutputGuessTable, sizeof(OutputGuessTable));
110  }
111}
112
113void
114Pred1Output(pri, proto, bp)
115int pri;
116u_short proto;
117struct mbuf *bp;
118{
119  struct mbuf *mwp;
120  u_char *cp, *wp, *hp;
121  int orglen, len;
122  u_char bufp[SIZ1];
123  u_short fcs;
124
125  orglen = plength(bp) + 2;	/* add count of proto */
126  mwp = mballoc((orglen+2)/8*9+12, MB_HDLCOUT);
127  hp = wp = MBUF_CTOP(mwp);
128  cp = bufp;
129  *wp++ = *cp++ = orglen >> 8;
130  *wp++ = *cp++ = orglen & 0377;
131  *cp++ = proto >> 8;
132  *cp++ = proto & 0377;
133  mbread(bp, cp, orglen-2);
134  fcs = HdlcFcs(INITFCS, bufp, 2+orglen);
135  fcs = ~fcs;
136
137  len = compress(bufp + 2, wp, orglen);
138#ifdef DEBUG
139  logprintf("orglen (%d) --> len (%d)\n", orglen, len);
140#endif
141  CcpInfo.orgout += orglen;
142  if (len < orglen) {
143    *hp |= 0x80;
144    wp += len;
145    CcpInfo.compout += len;
146  } else {
147    bcopy(bufp+2, wp, orglen);
148    wp += orglen;
149    CcpInfo.compout += orglen;
150  }
151
152  *wp++ = fcs & 0377;
153  *wp++ = fcs >> 8;
154  mwp->cnt = wp - MBUF_CTOP(mwp);
155  HdlcOutput(PRI_NORMAL, PROTO_COMPD, mwp);
156}
157
158void
159Pred1Input(bp)
160struct mbuf *bp;
161{
162  u_char *cp, *pp;
163  int len, olen, len1;
164  struct mbuf *wp;
165  u_char *bufp;
166  u_short fcs, proto;
167
168  wp = mballoc(SIZ1, MB_IPIN);
169  cp = MBUF_CTOP(bp);
170  olen = plength(bp);
171  pp = bufp = MBUF_CTOP(wp);
172  *pp++ = *cp & 0177;
173  len = *cp++ << 8;
174  *pp++ = *cp;
175  len += *cp++;
176  CcpInfo.orgin += len & 0x7fff;
177  if (len & 0x8000) {
178    len1 = decompress(cp, pp, olen - 4);
179    CcpInfo.compin += olen;
180    len &= 0x7fff;
181    if (len != len1) {	/* Error is detected. Send reset request */
182      LogPrintf(LOG_LCP_BIT, "%s: Length Error\n", CcpFsm.name);
183      CcpSendResetReq(&CcpFsm);
184      pfree(bp);
185      pfree(wp);
186      return;
187    }
188    cp += olen - 4;
189    pp += len1;
190  } else {
191    CcpInfo.compin += len;
192    SyncTable(cp, pp, len);
193    cp += len;
194    pp += len;
195  }
196  *pp++ = *cp++;	/* CRC */
197  *pp++ = *cp++;
198  fcs = HdlcFcs(INITFCS, bufp, wp->cnt = pp - bufp);
199#ifdef DEBUG
200  if (fcs != GOODFCS)
201  logprintf("fcs = 0x%04x (%s), len = 0x%x, olen = 0x%x\n",
202       fcs, (fcs == GOODFCS)? "good" : "bad", len, olen);
203#endif
204  if (fcs == GOODFCS) {
205    wp->offset += 2;		/* skip length */
206    wp->cnt -= 4;		/* skip length & CRC */
207    pp = MBUF_CTOP(wp);
208    proto = *pp++;
209    if (proto & 1) {
210      wp->offset++;
211      wp->cnt--;
212    } else {
213      wp->offset += 2;
214      wp->cnt -= 2;
215      proto = (proto << 8) | *pp++;
216    }
217    DecodePacket(proto, wp);
218  }
219  else
220  {
221      LogDumpBp(LOG_HDLC, "Bad FCS", wp);
222      CcpSendResetReq(&CcpFsm);
223      pfree(wp);
224  }
225  pfree(bp);
226}
227