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.6 1996/05/11 20:48:41 phk 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 61 while (len--) { 62 if (InputGuessTable[iHash] != *source) { 63 InputGuessTable[iHash] = *source; 64 } 65 IHASH(*dest++ = *source++); 66 } 67 } 68 69 static int 70 decompress(source, dest, len) 71 unsigned char *source, *dest; 72 int 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 99 void 100 Pred1Init(direction) 101 int 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 113 void 114 Pred1Output(pri, proto, bp) 115 int pri; 116 u_short proto; 117 struct 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 158 void 159 Pred1Input(bp) 160 struct 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