File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / ccp_pred1.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 08:44:29 2013 UTC (10 years, 11 months ago) by misho
Branches: mpd, MAIN
CVS tags: v5_8p7, v5_8p1_cross, v5_8p1, v5_8, v5_7p0, v5_7, v5_6, HEAD
5.7

    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>