Annotation of embedaddon/mpd/src/ccp_pred1.c, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * ccp_pred1.c
                      4:  *
                      5:  * Rewritten by Alexander Motin <mav@FreeBSD.org>
                      6:  * Written by Archie Cobbs <archie@freebsd.org>
                      7:  * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
                      8:  * See ``COPYRIGHT.whistle''
                      9:  */
                     10: 
                     11: /*
                     12:  * pred1.c
                     13:  *
                     14:  * Test program for Dave Rand's rendition of the predictor algorithm
                     15:  *
                     16:  * Updated by: archie@freebsd.org (Archie Cobbs)
                     17:  * Updated by: iand@labtam.labtam.oz.au (Ian Donaldson)
                     18:  * Updated by: Carsten Bormann <cabo@cs.tu-berlin.de>
                     19:  * Original  : Dave Rand <dlr@bungi.com>/<dave_rand@novell.com>
                     20:  */
                     21: 
                     22: #include "ppp.h"
                     23: #include "ccp.h"
                     24: #include "util.h"
                     25: #include "ngfunc.h"
                     26: 
                     27: #ifdef USE_NG_PRED1
                     28: #include <netgraph/ng_message.h>
                     29: #include <netgraph.h>
                     30: #endif
                     31: 
                     32: /*
                     33:  * DEFINITIONS
                     34:  */
                     35: 
                     36:   #define PRED1_DECOMP_BUF_SIZE        4096
                     37: 
                     38:   #define PRED1_MAX_BLOWUP(n)  ((n) * 9 / 8 + 24)
                     39: 
                     40: /*
                     41:  * The following hash code is the heart of the algorithm:
                     42:  * It builds a sliding hash sum of the previous 3-and-a-bit characters
                     43:  * which will be used to index the guess table.
                     44:  * A better hash function would result in additional compression,
                     45:  * at the expense of time.
                     46:  */
                     47: 
                     48:   #define IHASH(x) p->iHash = (p->iHash << 4) ^ (x)
                     49:   #define OHASH(x) p->oHash = (p->oHash << 4) ^ (x)
                     50: 
                     51: /*
                     52:  * INTERNAL FUNCTIONS
                     53:  */
                     54: 
                     55:   static int   Pred1Init(Bund b, int direction);
                     56:   static void  Pred1Cleanup(Bund b, int direction);
                     57: #ifndef USE_NG_PRED1
                     58:   static Mbuf  Pred1Compress(Bund b, Mbuf plain);
                     59:   static Mbuf  Pred1Decompress(Bund b, Mbuf comp);
                     60: #endif
                     61: 
                     62:   static u_char        *Pred1BuildConfigReq(Bund b, u_char *cp, int *ok);
                     63:   static void   Pred1DecodeConfigReq(Fsm fp, FsmOption opt, int mode);
                     64:   static Mbuf  Pred1RecvResetReq(Bund b, int id, Mbuf bp, int *noAck);
                     65:   static Mbuf  Pred1SendResetReq(Bund b);
                     66:   static void  Pred1RecvResetAck(Bund b, int id, Mbuf bp);
                     67:   static int    Pred1Negotiated(Bund b, int xmit);
                     68:   static int    Pred1SubtractBloat(Bund b, int size);
                     69:   static int    Pred1Stat(Context ctx, int dir);
                     70: 
                     71: #ifndef USE_NG_PRED1
                     72:   static int   Compress(Bund b, u_char *source, u_char *dest, int len);
                     73:   static int   Decompress(Bund b, u_char *source, u_char *dest, int slen, int dlen);
                     74:   static void  SyncTable(Bund b, u_char *source, u_char *dest, int len);
                     75: #endif
                     76: 
                     77: /*
                     78:  * GLOBAL VARIABLES
                     79:  */
                     80: 
                     81:   const struct comptype        gCompPred1Info =
                     82:   {
                     83:     "pred1",
                     84:     CCP_TY_PRED1,
                     85:     1,
                     86:     Pred1Init,
                     87:     NULL,
                     88:     NULL,
                     89:     NULL,
                     90:     Pred1SubtractBloat,
                     91:     Pred1Cleanup,
                     92:     Pred1BuildConfigReq,
                     93:     Pred1DecodeConfigReq,
                     94:     Pred1SendResetReq,
                     95:     Pred1RecvResetReq,
                     96:     Pred1RecvResetAck,
                     97:     Pred1Negotiated,
                     98:     Pred1Stat,
                     99: #ifndef USE_NG_PRED1
                    100:     Pred1Compress,
                    101:     Pred1Decompress,
                    102: #else
                    103:     NULL,
                    104:     NULL,
                    105: #endif
                    106:   };
                    107: 
                    108: /*
                    109:  * Pred1Init()
                    110:  */
                    111: 
                    112: static int
                    113: Pred1Init(Bund b, int dir)
                    114: {
                    115: #ifndef USE_NG_PRED1
                    116:     Pred1Info  p = &b->ccp.pred1;
                    117: 
                    118:     if (dir == COMP_DIR_XMIT) {
                    119:        p->oHash = 0;
                    120:        p->OutputGuessTable = Malloc(MB_COMP, PRED1_TABLE_SIZE);
                    121:     } else {
                    122:        p->iHash = 0;
                    123:        p->InputGuessTable = Malloc(MB_COMP, PRED1_TABLE_SIZE);
                    124:     }
                    125: #else
                    126:     struct ngm_mkpeer  mp;
                    127:     struct ng_pred1_config conf;
                    128:     const char         *pred1hook, *ppphook;
                    129:     char               path[NG_PATHSIZ];
                    130:     ng_ID_t             id;
                    131: 
                    132:     memset(&conf, 0, sizeof(conf));
                    133:     conf.enable = 1;
                    134:     if (dir == COMP_DIR_XMIT) {
                    135:         ppphook = NG_PPP_HOOK_COMPRESS;
                    136:         pred1hook = NG_PRED1_HOOK_COMP;
                    137:     } else {
                    138:         ppphook = NG_PPP_HOOK_DECOMPRESS;
                    139:         pred1hook = NG_PRED1_HOOK_DECOMP;
                    140:     }
                    141: 
                    142:     /* Attach a new PRED1 node to the PPP node */
                    143:     snprintf(path, sizeof(path), "[%x]:", b->nodeID);
                    144:     strcpy(mp.type, NG_PRED1_NODE_TYPE);
                    145:     strcpy(mp.ourhook, ppphook);
                    146:     strcpy(mp.peerhook, pred1hook);
                    147:     if (NgSendMsg(gCcpCsock, path,
                    148:            NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
                    149:        Perror("[%s] can't create %s node", b->name, mp.type);
                    150:        return(-1);
                    151:     }
                    152: 
                    153:     strlcat(path, ppphook, sizeof(path));
                    154: 
                    155:     id = NgGetNodeID(-1, path);
                    156:     if (dir == COMP_DIR_XMIT) {
                    157:        b->ccp.comp_node_id = id;
                    158:     } else {
                    159:        b->ccp.decomp_node_id = id;
                    160:     }
                    161: 
                    162:     /* Configure PRED1 node */
                    163:     snprintf(path, sizeof(path), "[%x]:", id);
                    164:     if (NgSendMsg(gCcpCsock, path,
                    165:            NGM_PRED1_COOKIE, NGM_PRED1_CONFIG, &conf, sizeof(conf)) < 0) {
                    166:        Perror("[%s] can't config %s node at %s",
                    167:            b->name, NG_PRED1_NODE_TYPE, path);
                    168:        NgFuncShutdownNode(gCcpCsock, b->name, path);
                    169:        return(-1);
                    170:     }
                    171: #endif
                    172:     return 0;
                    173: }
                    174: 
                    175: /*
                    176:  * Pred1Cleanup()
                    177:  */
                    178: 
                    179: void
                    180: Pred1Cleanup(Bund b, int dir)
                    181: {
                    182: #ifndef USE_NG_PRED1
                    183:     Pred1Info  p = &b->ccp.pred1;
                    184: 
                    185:     if (dir == COMP_DIR_XMIT) {
                    186:        assert(p->OutputGuessTable);
                    187:        Freee(p->OutputGuessTable);
                    188:        p->OutputGuessTable = NULL;
                    189:        memset(&p->xmit_stats, 0, sizeof(p->xmit_stats));
                    190:     } else {
                    191:        assert(p->InputGuessTable);
                    192:        Freee(p->InputGuessTable);
                    193:        p->InputGuessTable = NULL;
                    194:        memset(&p->recv_stats, 0, sizeof(p->recv_stats));
                    195:     }
                    196: #else
                    197:     char               path[NG_PATHSIZ];
                    198: 
                    199:     /* Remove node */
                    200:     if (dir == COMP_DIR_XMIT) {
                    201:        snprintf(path, sizeof(path), "[%x]:", b->ccp.comp_node_id);
                    202:        b->ccp.comp_node_id = 0;
                    203:     } else {
                    204:        snprintf(path, sizeof(path), "[%x]:", b->ccp.decomp_node_id);
                    205:        b->ccp.decomp_node_id = 0;
                    206:     }
                    207:     NgFuncShutdownNode(gCcpCsock, b->name, path);
                    208: #endif
                    209: }
                    210: 
                    211: #ifndef USE_NG_PRED1
                    212: /*
                    213:  * Pred1Compress()
                    214:  *
                    215:  * Compress a packet and return a compressed version.
                    216:  * The original is untouched.
                    217:  */
                    218: 
                    219: Mbuf
                    220: Pred1Compress(Bund b, Mbuf plain)
                    221: {
                    222:   u_char       *wp, *uncomp, *comp;
                    223:   u_int16_t    fcs;
                    224:   int          len;
                    225:   Mbuf         res;
                    226:   int          orglen;
                    227:   Pred1Info    p = &b->ccp.pred1;
                    228:   
                    229:   orglen = MBLEN(plain);
                    230:   uncomp = MBDATA(plain);
                    231:   
                    232:   p->xmit_stats.InOctets += orglen;
                    233:   p->xmit_stats.FramesPlain++;
                    234:   
                    235:   res = mballoc(PRED1_MAX_BLOWUP(orglen + 2));
                    236:   comp = MBDATA(res);
                    237: 
                    238:   wp = comp;
                    239: 
                    240:   *wp++ = (orglen >> 8) & 0x7F;
                    241:   *wp++ = orglen & 0xFF;
                    242: 
                    243: /* Compute FCS */
                    244: 
                    245:   fcs = Crc16(PPP_INITFCS, comp, 2);
                    246:   fcs = Crc16(fcs, uncomp, orglen);
                    247:   fcs = ~fcs;
                    248: 
                    249: /* Compress data */
                    250: 
                    251:   len = Compress(b, uncomp, wp, orglen);
                    252: 
                    253: /* What happened? */
                    254: 
                    255:   if (len < orglen)
                    256:   {
                    257:     *comp |= 0x80;
                    258:     wp += len;
                    259:     p->xmit_stats.FramesComp++;
                    260:   }
                    261:   else
                    262:   {
                    263:     memcpy(wp, uncomp, orglen);
                    264:     wp += orglen;
                    265:     p->xmit_stats.FramesUncomp++;
                    266:   }
                    267: 
                    268: /* Add FCS */
                    269: 
                    270:   *wp++ = fcs & 0xFF;
                    271:   *wp++ = fcs >> 8;
                    272: 
                    273:   res->cnt = (wp - comp);
                    274:   
                    275:   mbfree(plain);
                    276:   Log(LG_CCP2, ("[%s] Pred1: orig (%d) --> comp (%d)", b->name, orglen, res->cnt));
                    277: 
                    278:   p->xmit_stats.OutOctets += res->cnt;
                    279: 
                    280:   return res;
                    281: }
                    282: 
                    283: /*
                    284:  * Pred1Decompress()
                    285:  *
                    286:  * Decompress a packet and return a compressed version.
                    287:  * The original is untouched.
                    288:  */
                    289: 
                    290: Mbuf
                    291: Pred1Decompress(Bund b, Mbuf mbcomp)
                    292: {
                    293:   u_char       *uncomp, *comp;
                    294:   u_char       *cp;
                    295:   u_int16_t    len, len1, cf, lenn;
                    296:   u_int16_t    fcs;
                    297:   int           orglen;
                    298:   Mbuf         mbuncomp;
                    299:   Pred1Info    p = &b->ccp.pred1;
                    300: 
                    301:   orglen = MBLEN(mbcomp);
                    302:   comp = MBDATA(mbcomp);
                    303:   cp = comp;
                    304:   
                    305:   p->recv_stats.InOctets += orglen;
                    306:   
                    307:   mbuncomp = mballoc(PRED1_DECOMP_BUF_SIZE);
                    308:   uncomp = MBDATA(mbuncomp);
                    309: 
                    310: /* Get initial length value */
                    311:   len = *cp++ << 8;
                    312:   len += *cp++;
                    313:   
                    314:   cf = (len & 0x8000);
                    315:   len &= 0x7fff;
                    316:   
                    317: /* Is data compressed or not really? */
                    318:   if (cf)
                    319:   {
                    320:     p->recv_stats.FramesComp++;
                    321:     len1 = Decompress(b, cp, uncomp, orglen - 4, PRED1_DECOMP_BUF_SIZE);
                    322:     if (len != len1)   /* Error is detected. Send reset request */
                    323:     {
                    324:       Log(LG_CCP2, ("[%s] Length error (%d) --> len (%d)", b->name, len, len1));
                    325:       p->recv_stats.Errors++;
                    326:       mbfree(mbcomp);
                    327:       mbfree(mbuncomp);
                    328:       CcpSendResetReq(b);
                    329:       return NULL;
                    330:     }
                    331:     cp += orglen - 4;
                    332:   }
                    333:   else
                    334:   {
                    335:     p->recv_stats.FramesUncomp++;
                    336:     SyncTable(b, cp, uncomp, len);
                    337:     cp += len;
                    338:   }
                    339: 
                    340:   mbuncomp->cnt = len;
                    341: 
                    342:   /* Check CRC */
                    343:   lenn = htons(len);
                    344:   fcs = Crc16(PPP_INITFCS, (u_char *)&lenn, 2);
                    345:   fcs = Crc16(fcs, uncomp, len);
                    346:   fcs = Crc16(fcs, cp, 2);
                    347: 
                    348: #ifdef DEBUG
                    349:     if (fcs != PPP_GOODFCS)
                    350:       Log(LG_CCP2, ("fcs = %04x (%s), len = %x, olen = %x",
                    351:           fcs, (fcs == PPP_GOODFCS)? "good" : "bad", len, orglen));
                    352: #endif
                    353: 
                    354:   if (fcs != PPP_GOODFCS)
                    355:   {
                    356:     Log(LG_CCP2, ("[%s] Pred1: Bad CRC-16", b->name));
                    357:     p->recv_stats.Errors++;
                    358:     mbfree(mbcomp);
                    359:     mbfree(mbuncomp);
                    360:     CcpSendResetReq(b);
                    361:     return NULL;
                    362:   }
                    363: 
                    364:   Log(LG_CCP2, ("[%s] Pred1: orig (%d) <-- comp (%d)", b->name, mbuncomp->cnt, orglen));
                    365:   mbfree(mbcomp);
                    366:   
                    367:   p->recv_stats.FramesPlain++;
                    368:   p->recv_stats.OutOctets += mbuncomp->cnt;
                    369:     
                    370:   return mbuncomp;
                    371: }
                    372: #endif
                    373: 
                    374: /*
                    375:  * Pred1RecvResetReq()
                    376:  */
                    377: 
                    378: static Mbuf
                    379: Pred1RecvResetReq(Bund b, int id, Mbuf bp, int *noAck)
                    380: {
                    381: #ifndef USE_NG_PRED1
                    382:   Pred1Info     p = &b->ccp.pred1;
                    383:   Pred1Init(b, COMP_DIR_XMIT);
                    384:   p->xmit_stats.Errors++;
                    385: #else
                    386:     char               path[NG_PATHSIZ];
                    387:     /* Forward ResetReq to the Predictor1 compression node */
                    388:     snprintf(path, sizeof(path), "[%x]:", b->ccp.comp_node_id);
                    389:     if (NgSendMsg(gCcpCsock, path,
                    390:            NGM_PRED1_COOKIE, NGM_PRED1_RESETREQ, NULL, 0) < 0) {
                    391:        Perror("[%s] reset to %s node", b->name, NG_PRED1_NODE_TYPE);
                    392:     }
                    393: #endif
                    394: return(NULL);
                    395: }
                    396: 
                    397: /*
                    398:  * Pred1SendResetReq()
                    399:  */
                    400: 
                    401: static Mbuf
                    402: Pred1SendResetReq(Bund b)
                    403: {
                    404: #ifndef USE_NG_PRED1
                    405:     Pred1Init(b, COMP_DIR_RECV);
                    406: #endif
                    407:     return(NULL);
                    408: }
                    409: 
                    410: /*
                    411:  * Pred1RecvResetAck()
                    412:  */
                    413: 
                    414: static void
                    415: Pred1RecvResetAck(Bund b, int id, Mbuf bp)
                    416: {
                    417: #ifndef USE_NG_PRED1
                    418:     Pred1Init(b, COMP_DIR_RECV);
                    419: #else
                    420:     char               path[NG_PATHSIZ];
                    421:     /* Forward ResetReq to the Predictor1 decompression node */
                    422:     snprintf(path, sizeof(path), "[%x]:", b->ccp.decomp_node_id);
                    423:     if (NgSendMsg(gCcpCsock, path,
                    424:            NGM_PRED1_COOKIE, NGM_PRED1_RESETREQ, NULL, 0) < 0) {
                    425:        Perror("[%s] reset to %s node", b->name, NG_PRED1_NODE_TYPE);
                    426:     }
                    427: #endif
                    428: }
                    429: 
                    430: /*
                    431:  * Pred1BuildConfigReq()
                    432:  */
                    433: 
                    434: static u_char *
                    435: Pred1BuildConfigReq(Bund b, u_char *cp, int *ok)
                    436: {
                    437:   cp = FsmConfValue(cp, CCP_TY_PRED1, 0, NULL);
                    438:   *ok = 1;
                    439:   return (cp);
                    440: }
                    441: 
                    442: /*
                    443:  * Pred1DecodeConfigReq()
                    444:  */
                    445: 
                    446: static void
                    447: Pred1DecodeConfigReq(Fsm fp, FsmOption opt, int mode)
                    448: {
                    449:   /* Deal with it */
                    450:   switch (mode) {
                    451:     case MODE_REQ:
                    452:        FsmAck(fp, opt);
                    453:       break;
                    454: 
                    455:     case MODE_NAK:
                    456:       break;
                    457:   }
                    458: }
                    459: 
                    460: /*
                    461:  * Pred1Negotiated()
                    462:  */
                    463: 
                    464: static int
                    465: Pred1Negotiated(Bund b, int dir)
                    466: {
                    467:   return 1;
                    468: }
                    469: 
                    470: /*
                    471:  * Pred1SubtractBloat()
                    472:  */
                    473: 
                    474: static int
                    475: Pred1SubtractBloat(Bund b, int size)
                    476: {
                    477:   return(size - 4);
                    478: }
                    479: 
                    480: static int
                    481: Pred1Stat(Context ctx, int dir) 
                    482: {
                    483: #ifndef USE_NG_PRED1
                    484:     Pred1Info  p = &ctx->bund->ccp.pred1;
                    485:     
                    486:     switch (dir) {
                    487:        case COMP_DIR_XMIT:
                    488:            Printf("\tBytes\t: %llu -> %llu (%+lld%%)\r\n",
                    489:                (unsigned long long)p->xmit_stats.InOctets,
                    490:                (unsigned long long)p->xmit_stats.OutOctets,
                    491:                ((p->xmit_stats.InOctets!=0)?
                    492:                    ((long long)(p->xmit_stats.OutOctets - p->xmit_stats.InOctets)
                    493:                        *100/(long long)p->xmit_stats.InOctets):
                    494:                    0));
                    495:            Printf("\tFrames\t: %llu -> %lluc + %lluu\r\n",
                    496:                (unsigned long long)p->xmit_stats.FramesPlain,
                    497:                (unsigned long long)p->xmit_stats.FramesComp,
                    498:                (unsigned long long)p->xmit_stats.FramesUncomp);
                    499:            Printf("\tErrors\t: %llu\r\n",
                    500:                (unsigned long long)p->recv_stats.Errors);
                    501:            break;
                    502:        case COMP_DIR_RECV:
                    503:            Printf("\tBytes\t: %llu <- %llu (%+lld%%)\r\n",
                    504:                (unsigned long long)p->recv_stats.OutOctets,
                    505:                (unsigned long long)p->recv_stats.InOctets,
                    506:                ((p->recv_stats.OutOctets!=0)?
                    507:                    ((long long)(p->recv_stats.InOctets - p->recv_stats.OutOctets)
                    508:                        *100/(long long)p->recv_stats.OutOctets):
                    509:                    0));
                    510:            Printf("\tFrames\t: %llu <- %lluc + %lluu\r\n",
                    511:                (unsigned long long)p->xmit_stats.FramesPlain,
                    512:                (unsigned long long)p->xmit_stats.FramesComp,
                    513:                (unsigned long long)p->xmit_stats.FramesUncomp);
                    514:            Printf("\tErrors\t: %llu\r\n",
                    515:                (unsigned long long)p->recv_stats.Errors);
                    516:            break;
                    517:        default:
                    518:            assert(0);
                    519:     }
                    520:     return (0);
                    521: #else
                    522:     Bund                       b = ctx->bund;
                    523:     char                       path[NG_PATHSIZ];
                    524:     struct ng_pred1_stats      stats;
                    525:     union {
                    526:        u_char                  buf[sizeof(struct ng_mesg) + sizeof(stats)];
                    527:        struct ng_mesg          reply;
                    528:     }                          u;
                    529: 
                    530:     switch (dir) {
                    531:        case COMP_DIR_XMIT:
                    532:            snprintf(path, sizeof(path), "mpd%d-%s:%s", gPid, b->name,
                    533:                NG_PPP_HOOK_COMPRESS);
                    534:            break;
                    535:        case COMP_DIR_RECV:
                    536:            snprintf(path, sizeof(path), "mpd%d-%s:%s", gPid, b->name,
                    537:                NG_PPP_HOOK_DECOMPRESS);
                    538:            break;
                    539:        default:
                    540:            assert(0);
                    541:     }
                    542:     if (NgFuncSendQuery(path, NGM_PRED1_COOKIE, NGM_PRED1_GET_STATS, NULL, 0, 
                    543:        &u.reply, sizeof(u), NULL) < 0) {
                    544:            Perror("[%s] can't get %s stats", b->name, NG_PRED1_NODE_TYPE);
                    545:            return(0);
                    546:     }
                    547:     memcpy(&stats, u.reply.data, sizeof(stats));
                    548:     switch (dir) {
                    549:        case COMP_DIR_XMIT:
                    550:            Printf("\tBytes\t: %llu -> %llu (%+lld%%)\r\n",
                    551:                stats.InOctets,
                    552:                stats.OutOctets,
                    553:                ((stats.InOctets!=0)?
                    554:                    ((int64_t)(stats.OutOctets - stats.InOctets)*100/(int64_t)stats.InOctets):
                    555:                    0));
                    556:            Printf("\tFrames\t: %llu -> %lluc + %lluu\r\n",
                    557:                stats.FramesPlain,
                    558:                stats.FramesComp,
                    559:                stats.FramesUncomp);
                    560:            Printf("\tErrors\t: %llu\r\n",
                    561:                stats.Errors);
                    562:            break;
                    563:        case COMP_DIR_RECV:
                    564:            Printf("\tBytes\t: %llu <- %llu (%+lld%%)\r\n",
                    565:                stats.OutOctets,
                    566:                stats.InOctets,
                    567:                ((stats.OutOctets!=0)?
                    568:                    ((int64_t)(stats.InOctets - stats.OutOctets)*100/(int64_t)stats.OutOctets):
                    569:                    0));
                    570:            Printf("\tFrames\t: %llu <- %lluc + %lluu\r\n",
                    571:                stats.FramesPlain,
                    572:                stats.FramesComp,
                    573:                stats.FramesUncomp);
                    574:            Printf("\tErrors\t: %llu\r\n",
                    575:                stats.Errors);
                    576:            break;
                    577:        default:
                    578:            assert(0);
                    579:     }
                    580:     return (0);
                    581: #endif
                    582: }
                    583: 
                    584: #ifndef USE_NG_PRED1
                    585: /*
                    586:  * Compress()
                    587:  */
                    588: 
                    589: static int
                    590: Compress(Bund b, u_char *source, u_char *dest, int len)
                    591: {
                    592:   Pred1Info    p = &b->ccp.pred1;
                    593:   int          i, bitmask;
                    594:   u_char       flags;
                    595:   u_char       *flagdest, *orgdest;
                    596: 
                    597:   orgdest = dest;
                    598:   while (len)
                    599:   {
                    600:     flagdest = dest++; flags = 0;   /* All guess wrong initially */
                    601:     for (bitmask=1, i=0; i < 8 && len; i++, bitmask <<= 1) {
                    602:       if (p->OutputGuessTable[p->oHash] == *source)
                    603:        flags |= bitmask;       /* Guess was right - don't output */
                    604:       else
                    605:       {
                    606:        p->OutputGuessTable[p->oHash] = *source;
                    607:        *dest++ = *source;      /* Guess wrong, output char */
                    608:       }
                    609:       OHASH(*source++);
                    610:       len--;
                    611:     }
                    612:     *flagdest = flags;
                    613:   }
                    614:   return(dest - orgdest);
                    615: }
                    616: 
                    617: /*
                    618:  * Decompress()
                    619:  *
                    620:  * Returns decompressed size, or -1 if we ran out of space
                    621:  */
                    622: 
                    623: static int
                    624: Decompress(Bund b, u_char *source, u_char *dest, int slen, int dlen)
                    625: {
                    626:   Pred1Info    p = &b->ccp.pred1;
                    627:   int          i, bitmask;
                    628:   u_char       flags, *orgdest;
                    629: 
                    630:   orgdest = dest;
                    631:   while (slen)
                    632:   {
                    633:     flags = *source++;
                    634:     slen--;
                    635:     for (i=0, bitmask = 1; i < 8; i++, bitmask <<= 1)
                    636:     {
                    637:       if (dlen <= 0)
                    638:        return(-1);
                    639:       if (flags & bitmask)
                    640:        *dest = p->InputGuessTable[p->iHash];           /* Guess correct */
                    641:       else
                    642:       {
                    643:        if (!slen)
                    644:          break;                        /* we seem to be really done -- cabo */
                    645:        p->InputGuessTable[p->iHash] = *source;         /* Guess wrong */
                    646:        *dest = *source++;                              /* Read from source */
                    647:        slen--;
                    648:       }
                    649:       IHASH(*dest++);
                    650:       dlen--;
                    651:     }
                    652:   }
                    653:   return(dest - orgdest);
                    654: }
                    655: 
                    656: /*
                    657:  * SyncTable()
                    658:  */
                    659: 
                    660: static void
                    661: SyncTable(Bund b, u_char *source, u_char *dest, int len)
                    662: {
                    663:   Pred1Info    p = &b->ccp.pred1;
                    664: 
                    665:   while (len--)
                    666:   {
                    667:     if (p->InputGuessTable[p->iHash] != *source)
                    668:       p->InputGuessTable[p->iHash] = *source;
                    669:     IHASH(*dest++ = *source++);
                    670:   }
                    671: }
                    672: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>