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

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: 
1.1.1.2 ! misho     155:     if ((id = NgGetNodeID(-1, path)) == 0) {
        !           156:        Perror("[%s] Cannot get %s node id", b->name, NG_PRED1_NODE_TYPE);
        !           157:        goto fail;
        !           158:     }
        !           159: 
1.1       misho     160:     if (dir == COMP_DIR_XMIT) {
                    161:        b->ccp.comp_node_id = id;
                    162:     } else {
                    163:        b->ccp.decomp_node_id = id;
                    164:     }
                    165: 
                    166:     /* Configure PRED1 node */
                    167:     snprintf(path, sizeof(path), "[%x]:", id);
                    168:     if (NgSendMsg(gCcpCsock, path,
                    169:            NGM_PRED1_COOKIE, NGM_PRED1_CONFIG, &conf, sizeof(conf)) < 0) {
                    170:        Perror("[%s] can't config %s node at %s",
                    171:            b->name, NG_PRED1_NODE_TYPE, path);
1.1.1.2 ! misho     172:        goto fail;
1.1       misho     173:     }
                    174: #endif
                    175:     return 0;
1.1.1.2 ! misho     176: 
        !           177: fail:
        !           178:     NgFuncShutdownNode(gCcpCsock, b->name, path);
        !           179:     return(-1);
1.1       misho     180: }
                    181: 
                    182: /*
                    183:  * Pred1Cleanup()
                    184:  */
                    185: 
                    186: void
                    187: Pred1Cleanup(Bund b, int dir)
                    188: {
                    189: #ifndef USE_NG_PRED1
                    190:     Pred1Info  p = &b->ccp.pred1;
                    191: 
                    192:     if (dir == COMP_DIR_XMIT) {
                    193:        assert(p->OutputGuessTable);
                    194:        Freee(p->OutputGuessTable);
                    195:        p->OutputGuessTable = NULL;
                    196:        memset(&p->xmit_stats, 0, sizeof(p->xmit_stats));
                    197:     } else {
                    198:        assert(p->InputGuessTable);
                    199:        Freee(p->InputGuessTable);
                    200:        p->InputGuessTable = NULL;
                    201:        memset(&p->recv_stats, 0, sizeof(p->recv_stats));
                    202:     }
                    203: #else
                    204:     char               path[NG_PATHSIZ];
                    205: 
                    206:     /* Remove node */
                    207:     if (dir == COMP_DIR_XMIT) {
                    208:        snprintf(path, sizeof(path), "[%x]:", b->ccp.comp_node_id);
                    209:        b->ccp.comp_node_id = 0;
                    210:     } else {
                    211:        snprintf(path, sizeof(path), "[%x]:", b->ccp.decomp_node_id);
                    212:        b->ccp.decomp_node_id = 0;
                    213:     }
                    214:     NgFuncShutdownNode(gCcpCsock, b->name, path);
                    215: #endif
                    216: }
                    217: 
                    218: #ifndef USE_NG_PRED1
                    219: /*
                    220:  * Pred1Compress()
                    221:  *
                    222:  * Compress a packet and return a compressed version.
                    223:  * The original is untouched.
                    224:  */
                    225: 
                    226: Mbuf
                    227: Pred1Compress(Bund b, Mbuf plain)
                    228: {
                    229:   u_char       *wp, *uncomp, *comp;
                    230:   u_int16_t    fcs;
                    231:   int          len;
                    232:   Mbuf         res;
                    233:   int          orglen;
                    234:   Pred1Info    p = &b->ccp.pred1;
                    235:   
                    236:   orglen = MBLEN(plain);
                    237:   uncomp = MBDATA(plain);
                    238:   
                    239:   p->xmit_stats.InOctets += orglen;
                    240:   p->xmit_stats.FramesPlain++;
                    241:   
                    242:   res = mballoc(PRED1_MAX_BLOWUP(orglen + 2));
                    243:   comp = MBDATA(res);
                    244: 
                    245:   wp = comp;
                    246: 
                    247:   *wp++ = (orglen >> 8) & 0x7F;
                    248:   *wp++ = orglen & 0xFF;
                    249: 
                    250: /* Compute FCS */
                    251: 
                    252:   fcs = Crc16(PPP_INITFCS, comp, 2);
                    253:   fcs = Crc16(fcs, uncomp, orglen);
                    254:   fcs = ~fcs;
                    255: 
                    256: /* Compress data */
                    257: 
                    258:   len = Compress(b, uncomp, wp, orglen);
                    259: 
                    260: /* What happened? */
                    261: 
                    262:   if (len < orglen)
                    263:   {
                    264:     *comp |= 0x80;
                    265:     wp += len;
                    266:     p->xmit_stats.FramesComp++;
                    267:   }
                    268:   else
                    269:   {
                    270:     memcpy(wp, uncomp, orglen);
                    271:     wp += orglen;
                    272:     p->xmit_stats.FramesUncomp++;
                    273:   }
                    274: 
                    275: /* Add FCS */
                    276: 
                    277:   *wp++ = fcs & 0xFF;
                    278:   *wp++ = fcs >> 8;
                    279: 
                    280:   res->cnt = (wp - comp);
                    281:   
                    282:   mbfree(plain);
                    283:   Log(LG_CCP2, ("[%s] Pred1: orig (%d) --> comp (%d)", b->name, orglen, res->cnt));
                    284: 
                    285:   p->xmit_stats.OutOctets += res->cnt;
                    286: 
                    287:   return res;
                    288: }
                    289: 
                    290: /*
                    291:  * Pred1Decompress()
                    292:  *
                    293:  * Decompress a packet and return a compressed version.
                    294:  * The original is untouched.
                    295:  */
                    296: 
                    297: Mbuf
                    298: Pred1Decompress(Bund b, Mbuf mbcomp)
                    299: {
                    300:   u_char       *uncomp, *comp;
                    301:   u_char       *cp;
                    302:   u_int16_t    len, len1, cf, lenn;
                    303:   u_int16_t    fcs;
                    304:   int           orglen;
                    305:   Mbuf         mbuncomp;
                    306:   Pred1Info    p = &b->ccp.pred1;
                    307: 
                    308:   orglen = MBLEN(mbcomp);
                    309:   comp = MBDATA(mbcomp);
                    310:   cp = comp;
                    311:   
                    312:   p->recv_stats.InOctets += orglen;
                    313:   
                    314:   mbuncomp = mballoc(PRED1_DECOMP_BUF_SIZE);
                    315:   uncomp = MBDATA(mbuncomp);
                    316: 
                    317: /* Get initial length value */
                    318:   len = *cp++ << 8;
                    319:   len += *cp++;
                    320:   
                    321:   cf = (len & 0x8000);
                    322:   len &= 0x7fff;
                    323:   
                    324: /* Is data compressed or not really? */
                    325:   if (cf)
                    326:   {
                    327:     p->recv_stats.FramesComp++;
                    328:     len1 = Decompress(b, cp, uncomp, orglen - 4, PRED1_DECOMP_BUF_SIZE);
                    329:     if (len != len1)   /* Error is detected. Send reset request */
                    330:     {
                    331:       Log(LG_CCP2, ("[%s] Length error (%d) --> len (%d)", b->name, len, len1));
                    332:       p->recv_stats.Errors++;
                    333:       mbfree(mbcomp);
                    334:       mbfree(mbuncomp);
                    335:       CcpSendResetReq(b);
                    336:       return NULL;
                    337:     }
                    338:     cp += orglen - 4;
                    339:   }
                    340:   else
                    341:   {
                    342:     p->recv_stats.FramesUncomp++;
                    343:     SyncTable(b, cp, uncomp, len);
                    344:     cp += len;
                    345:   }
                    346: 
                    347:   mbuncomp->cnt = len;
                    348: 
                    349:   /* Check CRC */
                    350:   lenn = htons(len);
                    351:   fcs = Crc16(PPP_INITFCS, (u_char *)&lenn, 2);
                    352:   fcs = Crc16(fcs, uncomp, len);
                    353:   fcs = Crc16(fcs, cp, 2);
                    354: 
                    355: #ifdef DEBUG
                    356:     if (fcs != PPP_GOODFCS)
                    357:       Log(LG_CCP2, ("fcs = %04x (%s), len = %x, olen = %x",
                    358:           fcs, (fcs == PPP_GOODFCS)? "good" : "bad", len, orglen));
                    359: #endif
                    360: 
                    361:   if (fcs != PPP_GOODFCS)
                    362:   {
                    363:     Log(LG_CCP2, ("[%s] Pred1: Bad CRC-16", b->name));
                    364:     p->recv_stats.Errors++;
                    365:     mbfree(mbcomp);
                    366:     mbfree(mbuncomp);
                    367:     CcpSendResetReq(b);
                    368:     return NULL;
                    369:   }
                    370: 
                    371:   Log(LG_CCP2, ("[%s] Pred1: orig (%d) <-- comp (%d)", b->name, mbuncomp->cnt, orglen));
                    372:   mbfree(mbcomp);
                    373:   
                    374:   p->recv_stats.FramesPlain++;
                    375:   p->recv_stats.OutOctets += mbuncomp->cnt;
                    376:     
                    377:   return mbuncomp;
                    378: }
                    379: #endif
                    380: 
                    381: /*
                    382:  * Pred1RecvResetReq()
                    383:  */
                    384: 
                    385: static Mbuf
                    386: Pred1RecvResetReq(Bund b, int id, Mbuf bp, int *noAck)
                    387: {
1.1.1.2 ! misho     388:   (void)id;
        !           389:   (void)bp;
        !           390:   (void)noAck;
1.1       misho     391: #ifndef USE_NG_PRED1
                    392:   Pred1Info     p = &b->ccp.pred1;
1.1.1.2 ! misho     393: 
        !           394:   (void)id;
        !           395:   (void)bp;
        !           396:   (void)noAck;
        !           397: 
1.1       misho     398:   Pred1Init(b, COMP_DIR_XMIT);
                    399:   p->xmit_stats.Errors++;
                    400: #else
                    401:     char               path[NG_PATHSIZ];
1.1.1.2 ! misho     402: 
        !           403:     (void)id;
        !           404:     (void)bp;
        !           405:     (void)noAck;
        !           406: 
1.1       misho     407:     /* Forward ResetReq to the Predictor1 compression node */
                    408:     snprintf(path, sizeof(path), "[%x]:", b->ccp.comp_node_id);
                    409:     if (NgSendMsg(gCcpCsock, path,
                    410:            NGM_PRED1_COOKIE, NGM_PRED1_RESETREQ, NULL, 0) < 0) {
                    411:        Perror("[%s] reset to %s node", b->name, NG_PRED1_NODE_TYPE);
                    412:     }
                    413: #endif
1.1.1.2 ! misho     414:     return(NULL);
1.1       misho     415: }
                    416: 
                    417: /*
                    418:  * Pred1SendResetReq()
                    419:  */
                    420: 
                    421: static Mbuf
                    422: Pred1SendResetReq(Bund b)
                    423: {
                    424: #ifndef USE_NG_PRED1
                    425:     Pred1Init(b, COMP_DIR_RECV);
1.1.1.2 ! misho     426: #else
        !           427:     (void)b;
1.1       misho     428: #endif
                    429:     return(NULL);
                    430: }
                    431: 
                    432: /*
                    433:  * Pred1RecvResetAck()
                    434:  */
                    435: 
                    436: static void
                    437: Pred1RecvResetAck(Bund b, int id, Mbuf bp)
                    438: {
                    439: #ifndef USE_NG_PRED1
1.1.1.2 ! misho     440:     (void)id;
        !           441:     (void)bp;
1.1       misho     442:     Pred1Init(b, COMP_DIR_RECV);
                    443: #else
                    444:     char               path[NG_PATHSIZ];
1.1.1.2 ! misho     445: 
        !           446:     (void)id;
        !           447:     (void)bp;
        !           448: 
1.1       misho     449:     /* Forward ResetReq to the Predictor1 decompression node */
                    450:     snprintf(path, sizeof(path), "[%x]:", b->ccp.decomp_node_id);
                    451:     if (NgSendMsg(gCcpCsock, path,
                    452:            NGM_PRED1_COOKIE, NGM_PRED1_RESETREQ, NULL, 0) < 0) {
                    453:        Perror("[%s] reset to %s node", b->name, NG_PRED1_NODE_TYPE);
                    454:     }
                    455: #endif
                    456: }
                    457: 
                    458: /*
                    459:  * Pred1BuildConfigReq()
                    460:  */
                    461: 
                    462: static u_char *
                    463: Pred1BuildConfigReq(Bund b, u_char *cp, int *ok)
                    464: {
1.1.1.2 ! misho     465:   (void)b;
1.1       misho     466:   cp = FsmConfValue(cp, CCP_TY_PRED1, 0, NULL);
                    467:   *ok = 1;
                    468:   return (cp);
                    469: }
                    470: 
                    471: /*
                    472:  * Pred1DecodeConfigReq()
                    473:  */
                    474: 
                    475: static void
                    476: Pred1DecodeConfigReq(Fsm fp, FsmOption opt, int mode)
                    477: {
                    478:   /* Deal with it */
                    479:   switch (mode) {
                    480:     case MODE_REQ:
                    481:        FsmAck(fp, opt);
                    482:       break;
                    483: 
                    484:     case MODE_NAK:
                    485:       break;
                    486:   }
                    487: }
                    488: 
                    489: /*
                    490:  * Pred1Negotiated()
                    491:  */
                    492: 
                    493: static int
                    494: Pred1Negotiated(Bund b, int dir)
                    495: {
1.1.1.2 ! misho     496:   (void)b;
        !           497:   (void)dir;
        !           498: 
1.1       misho     499:   return 1;
                    500: }
                    501: 
                    502: /*
                    503:  * Pred1SubtractBloat()
                    504:  */
                    505: 
                    506: static int
                    507: Pred1SubtractBloat(Bund b, int size)
                    508: {
1.1.1.2 ! misho     509:   (void)b;
1.1       misho     510:   return(size - 4);
                    511: }
                    512: 
                    513: static int
                    514: Pred1Stat(Context ctx, int dir) 
                    515: {
                    516: #ifndef USE_NG_PRED1
                    517:     Pred1Info  p = &ctx->bund->ccp.pred1;
                    518:     
                    519:     switch (dir) {
                    520:        case COMP_DIR_XMIT:
                    521:            Printf("\tBytes\t: %llu -> %llu (%+lld%%)\r\n",
                    522:                (unsigned long long)p->xmit_stats.InOctets,
                    523:                (unsigned long long)p->xmit_stats.OutOctets,
                    524:                ((p->xmit_stats.InOctets!=0)?
                    525:                    ((long long)(p->xmit_stats.OutOctets - p->xmit_stats.InOctets)
                    526:                        *100/(long long)p->xmit_stats.InOctets):
                    527:                    0));
                    528:            Printf("\tFrames\t: %llu -> %lluc + %lluu\r\n",
                    529:                (unsigned long long)p->xmit_stats.FramesPlain,
                    530:                (unsigned long long)p->xmit_stats.FramesComp,
                    531:                (unsigned long long)p->xmit_stats.FramesUncomp);
                    532:            Printf("\tErrors\t: %llu\r\n",
                    533:                (unsigned long long)p->recv_stats.Errors);
                    534:            break;
                    535:        case COMP_DIR_RECV:
                    536:            Printf("\tBytes\t: %llu <- %llu (%+lld%%)\r\n",
                    537:                (unsigned long long)p->recv_stats.OutOctets,
                    538:                (unsigned long long)p->recv_stats.InOctets,
                    539:                ((p->recv_stats.OutOctets!=0)?
                    540:                    ((long long)(p->recv_stats.InOctets - p->recv_stats.OutOctets)
                    541:                        *100/(long long)p->recv_stats.OutOctets):
                    542:                    0));
                    543:            Printf("\tFrames\t: %llu <- %lluc + %lluu\r\n",
                    544:                (unsigned long long)p->xmit_stats.FramesPlain,
                    545:                (unsigned long long)p->xmit_stats.FramesComp,
                    546:                (unsigned long long)p->xmit_stats.FramesUncomp);
                    547:            Printf("\tErrors\t: %llu\r\n",
                    548:                (unsigned long long)p->recv_stats.Errors);
                    549:            break;
                    550:        default:
                    551:            assert(0);
                    552:     }
                    553:     return (0);
                    554: #else
                    555:     Bund                       b = ctx->bund;
                    556:     char                       path[NG_PATHSIZ];
                    557:     struct ng_pred1_stats      stats;
                    558:     union {
                    559:        u_char                  buf[sizeof(struct ng_mesg) + sizeof(stats)];
                    560:        struct ng_mesg          reply;
                    561:     }                          u;
                    562: 
                    563:     switch (dir) {
                    564:        case COMP_DIR_XMIT:
                    565:            snprintf(path, sizeof(path), "mpd%d-%s:%s", gPid, b->name,
                    566:                NG_PPP_HOOK_COMPRESS);
                    567:            break;
                    568:        case COMP_DIR_RECV:
                    569:            snprintf(path, sizeof(path), "mpd%d-%s:%s", gPid, b->name,
                    570:                NG_PPP_HOOK_DECOMPRESS);
                    571:            break;
                    572:        default:
                    573:            assert(0);
                    574:     }
                    575:     if (NgFuncSendQuery(path, NGM_PRED1_COOKIE, NGM_PRED1_GET_STATS, NULL, 0, 
                    576:        &u.reply, sizeof(u), NULL) < 0) {
                    577:            Perror("[%s] can't get %s stats", b->name, NG_PRED1_NODE_TYPE);
                    578:            return(0);
                    579:     }
                    580:     memcpy(&stats, u.reply.data, sizeof(stats));
                    581:     switch (dir) {
                    582:        case COMP_DIR_XMIT:
                    583:            Printf("\tBytes\t: %llu -> %llu (%+lld%%)\r\n",
                    584:                stats.InOctets,
                    585:                stats.OutOctets,
                    586:                ((stats.InOctets!=0)?
                    587:                    ((int64_t)(stats.OutOctets - stats.InOctets)*100/(int64_t)stats.InOctets):
                    588:                    0));
                    589:            Printf("\tFrames\t: %llu -> %lluc + %lluu\r\n",
                    590:                stats.FramesPlain,
                    591:                stats.FramesComp,
                    592:                stats.FramesUncomp);
                    593:            Printf("\tErrors\t: %llu\r\n",
                    594:                stats.Errors);
                    595:            break;
                    596:        case COMP_DIR_RECV:
                    597:            Printf("\tBytes\t: %llu <- %llu (%+lld%%)\r\n",
                    598:                stats.OutOctets,
                    599:                stats.InOctets,
                    600:                ((stats.OutOctets!=0)?
                    601:                    ((int64_t)(stats.InOctets - stats.OutOctets)*100/(int64_t)stats.OutOctets):
                    602:                    0));
                    603:            Printf("\tFrames\t: %llu <- %lluc + %lluu\r\n",
                    604:                stats.FramesPlain,
                    605:                stats.FramesComp,
                    606:                stats.FramesUncomp);
                    607:            Printf("\tErrors\t: %llu\r\n",
                    608:                stats.Errors);
                    609:            break;
                    610:        default:
                    611:            assert(0);
                    612:     }
                    613:     return (0);
                    614: #endif
                    615: }
                    616: 
                    617: #ifndef USE_NG_PRED1
                    618: /*
                    619:  * Compress()
                    620:  */
                    621: 
                    622: static int
                    623: Compress(Bund b, u_char *source, u_char *dest, int len)
                    624: {
                    625:   Pred1Info    p = &b->ccp.pred1;
                    626:   int          i, bitmask;
                    627:   u_char       flags;
                    628:   u_char       *flagdest, *orgdest;
                    629: 
                    630:   orgdest = dest;
                    631:   while (len)
                    632:   {
                    633:     flagdest = dest++; flags = 0;   /* All guess wrong initially */
                    634:     for (bitmask=1, i=0; i < 8 && len; i++, bitmask <<= 1) {
                    635:       if (p->OutputGuessTable[p->oHash] == *source)
                    636:        flags |= bitmask;       /* Guess was right - don't output */
                    637:       else
                    638:       {
                    639:        p->OutputGuessTable[p->oHash] = *source;
                    640:        *dest++ = *source;      /* Guess wrong, output char */
                    641:       }
                    642:       OHASH(*source++);
                    643:       len--;
                    644:     }
                    645:     *flagdest = flags;
                    646:   }
                    647:   return(dest - orgdest);
                    648: }
                    649: 
                    650: /*
                    651:  * Decompress()
                    652:  *
                    653:  * Returns decompressed size, or -1 if we ran out of space
                    654:  */
                    655: 
                    656: static int
                    657: Decompress(Bund b, u_char *source, u_char *dest, int slen, int dlen)
                    658: {
                    659:   Pred1Info    p = &b->ccp.pred1;
                    660:   int          i, bitmask;
                    661:   u_char       flags, *orgdest;
                    662: 
                    663:   orgdest = dest;
                    664:   while (slen)
                    665:   {
                    666:     flags = *source++;
                    667:     slen--;
                    668:     for (i=0, bitmask = 1; i < 8; i++, bitmask <<= 1)
                    669:     {
                    670:       if (dlen <= 0)
                    671:        return(-1);
                    672:       if (flags & bitmask)
                    673:        *dest = p->InputGuessTable[p->iHash];           /* Guess correct */
                    674:       else
                    675:       {
                    676:        if (!slen)
                    677:          break;                        /* we seem to be really done -- cabo */
                    678:        p->InputGuessTable[p->iHash] = *source;         /* Guess wrong */
                    679:        *dest = *source++;                              /* Read from source */
                    680:        slen--;
                    681:       }
                    682:       IHASH(*dest++);
                    683:       dlen--;
                    684:     }
                    685:   }
                    686:   return(dest - orgdest);
                    687: }
                    688: 
                    689: /*
                    690:  * SyncTable()
                    691:  */
                    692: 
                    693: static void
                    694: SyncTable(Bund b, u_char *source, u_char *dest, int len)
                    695: {
                    696:   Pred1Info    p = &b->ccp.pred1;
                    697: 
                    698:   while (len--)
                    699:   {
                    700:     if (p->InputGuessTable[p->iHash] != *source)
                    701:       p->InputGuessTable[p->iHash] = *source;
                    702:     IHASH(*dest++ = *source++);
                    703:   }
                    704: }
                    705: #endif

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