pred.c revision 25630
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.9 1997/02/22 16:10:47 peter 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) do {iHash = (iHash << 4) ^ (x);} while(0)
24#define OHASH(x) do {oHash = (oHash << 4) ^ (x);} while(0)
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(int pri, u_short proto, struct mbuf *bp)
115{
116  struct mbuf *mwp;
117  u_char *cp, *wp, *hp;
118  int orglen, len;
119  u_char bufp[SIZ1];
120  u_short fcs;
121
122  orglen = plength(bp) + 2;	/* add count of proto */
123  mwp = mballoc((orglen+2)/8*9+12, MB_HDLCOUT);
124  hp = wp = MBUF_CTOP(mwp);
125  cp = bufp;
126  *wp++ = *cp++ = orglen >> 8;
127  *wp++ = *cp++ = orglen & 0377;
128  *cp++ = proto >> 8;
129  *cp++ = proto & 0377;
130  mbread(bp, cp, orglen-2);
131  fcs = HdlcFcs(INITFCS, bufp, 2+orglen);
132  fcs = ~fcs;
133
134  len = compress(bufp + 2, wp, orglen);
135#ifdef DEBUG
136  logprintf("orglen (%d) --> len (%d)\n", orglen, len);
137#endif
138  CcpInfo.orgout += orglen;
139  if (len < orglen) {
140    *hp |= 0x80;
141    wp += len;
142    CcpInfo.compout += len;
143  } else {
144    bcopy(bufp+2, wp, orglen);
145    wp += orglen;
146    CcpInfo.compout += orglen;
147  }
148
149  *wp++ = fcs & 0377;
150  *wp++ = fcs >> 8;
151  mwp->cnt = wp - MBUF_CTOP(mwp);
152  HdlcOutput(PRI_NORMAL, PROTO_COMPD, mwp);
153}
154
155void
156Pred1Input(bp)
157struct mbuf *bp;
158{
159  u_char *cp, *pp;
160  int len, olen, len1;
161  struct mbuf *wp;
162  u_char *bufp;
163  u_short fcs, proto;
164
165  wp = mballoc(SIZ1, MB_IPIN);
166  cp = MBUF_CTOP(bp);
167  olen = plength(bp);
168  pp = bufp = MBUF_CTOP(wp);
169  *pp++ = *cp & 0177;
170  len = *cp++ << 8;
171  *pp++ = *cp;
172  len += *cp++;
173  CcpInfo.orgin += len & 0x7fff;
174  if (len & 0x8000) {
175    len1 = decompress(cp, pp, olen - 4);
176    CcpInfo.compin += olen;
177    len &= 0x7fff;
178    if (len != len1) {	/* Error is detected. Send reset request */
179      LogPrintf(LOG_LCP_BIT, "%s: Length Error\n", CcpFsm.name);
180      CcpSendResetReq(&CcpFsm);
181      pfree(bp);
182      pfree(wp);
183      return;
184    }
185    cp += olen - 4;
186    pp += len1;
187  } else {
188    CcpInfo.compin += len;
189    SyncTable(cp, pp, len);
190    cp += len;
191    pp += len;
192  }
193  *pp++ = *cp++;	/* CRC */
194  *pp++ = *cp++;
195  fcs = HdlcFcs(INITFCS, bufp, wp->cnt = pp - bufp);
196#ifdef DEBUG
197  if (fcs != GOODFCS)
198  logprintf("fcs = 0x%04x (%s), len = 0x%x, olen = 0x%x\n",
199       fcs, (fcs == GOODFCS)? "good" : "bad", len, olen);
200#endif
201  if (fcs == GOODFCS) {
202    wp->offset += 2;		/* skip length */
203    wp->cnt -= 4;		/* skip length & CRC */
204    pp = MBUF_CTOP(wp);
205    proto = *pp++;
206    if (proto & 1) {
207      wp->offset++;
208      wp->cnt--;
209    } else {
210      wp->offset += 2;
211      wp->cnt -= 2;
212      proto = (proto << 8) | *pp++;
213    }
214    DecodePacket(proto, wp);
215  }
216  else
217  {
218      LogDumpBp(LOG_HDLC, "Bad FCS", wp);
219      CcpSendResetReq(&CcpFsm);
220      pfree(wp);
221  }
222  pfree(bp);
223}
224