Yaroslav Kolomiietsmost modules lost draw.h70d7ad710 years agoHistory
262 lines · 4.6 KB · C
RawDownload
/* * lifted from /sys/src/cmd/ip/ppp/mppc.c (RFC 2118) * plus the RDP 5.0 64K history (3.1.8.4.2 RDP 5.0) */#include <u.h>#include <libc.h>#include "dat.h"#include "fns.h" #define DBG if(0)//#define DBG enum{	MaxHistorySize=	64*1024, 	Preset=			0x80,	/* reset history */	Pfront=			0x40,	/* move packet to front of history */	Pcompress=		0x20,	/* packet is compressed */	Pbulk64=			0x01,	/* RPD5 bulk compression (64K history) */}; enum{	Bits4=	0xf,	Bits5=	0x1f,	Bits6=	0x3f,	Bits7=	0x7f,	Bits8=	0xff,	Bits11=	0x7ff,	Bits13=	0x1fff,	Bits16=	0xffff,}; enum{	Lit7,		/* seven bit literal */	Lit8,		/* eight bit literal */	Off6,		/* six bit offset */	Off8,		/* eight bit offset */	Off11,		/* eleven bit offset (64K history) */	Off13,		/* thirteen bit offset (8K history) */	Off16,		/* sixteen bit offset (64K history) */}; /* decode first four bits (8K history) */static int decode8[16]={	Lit7, Lit7, Lit7, Lit7,	Lit7, Lit7, Lit7, Lit7,	Lit8, Lit8, Lit8, Lit8,		Off13, Off13, Off8, Off6,}; /* decode first five bits (64K history) */static int decode64[32]={	Lit7, Lit7, Lit7, Lit7,	Lit7, Lit7, Lit7, Lit7,	Lit7,	Lit7, Lit7, Lit7,	Lit7, Lit7, Lit7, Lit7,	Lit8, Lit8, Lit8, Lit8,		Lit8, Lit8, Lit8, Lit8,		Off16, Off16, Off16, Off16,	Off11, Off11, Off8, Off6,}; typedef struct Uncstate Uncstate;struct Uncstate{	uchar	his[MaxHistorySize];	int	indx;		/* current indx in history */	int	size;		/* current history size */}; static Uncstate uncstate;  #define NEXTBYTE	sreg = (sreg<<8) | *p++; n--; bits += 8uchar*uncomp(uchar* buf, int nbytes, int flags, int* psize){	int n, bits, off, len, ones, t;	int *decode, lookbits, lookmask, maxhis, maxones;	ulong sreg;	uchar *p, c, *hp, *hs, *he, *hq;	Uncstate *s; 	s = &uncstate;	p = buf;	n = nbytes; 	if(flags&Pbulk64){		maxhis = 64*1024;		maxones = 14;		decode = decode64;		lookbits = 5;		lookmask = Bits5;	}else{		maxhis = 8*1024;		maxones = 11;		decode = decode8;		lookbits = 4;		lookmask = Bits4;	} 	if(flags&Preset){		s->indx = 0;		s->size = 0;		memset(s->his, maxhis, 0);	}	if(flags&Pfront){		s->indx = 0;DBG		fprint(2, "mppc: front flag set\n"); 	}	if(!(flags&Pcompress)){		*psize = n;		return buf;	} 	bits = 0;	sreg = 0;	hs = s->his;			/* history start */	hp = hs+s->indx;		/* write pointer in history */	he = hs+maxhis;		/* history end */	for(;;){		if(bits<lookbits){			if(n==0) goto Done;			NEXTBYTE;		}		t = decode[(sreg>>(bits-lookbits))&lookmask];		switch(t){		default:			sysfatal("mppc: bad decode %d!", t);		case Lit7:			bits -= 1;			if(bits<7){				if(n==0) goto Done;				NEXTBYTE;			}			c = (sreg>>(bits-7))&Bits7;			bits -= 7;			if(hp >= he) goto His;			*hp++ = c;			continue;		case Lit8:			bits -= 2;			if(bits<7) {				if(n==0) goto Eof;				NEXTBYTE;			}			c = 0x80 | ((sreg>>(bits-7))&Bits7);			bits -= 7;			if(hp >= he) goto His;			*hp++ = c;			continue;		case Off6:			bits -= lookbits;			if(bits<6){				if(n==0) goto Eof;				NEXTBYTE;			}			off = (sreg>>(bits-6))&Bits6;			bits -= 6;			break;		case Off8:			bits -= lookbits;			if(bits<8){				if(n==0) goto Eof;				NEXTBYTE;			}			off = ((sreg>>(bits-8))&Bits8)+64;			bits -= 8;			break;		case Off13:	/* (8K history) */			bits -= 3;			while(bits<13){				if(n==0) goto Eof;				NEXTBYTE;			}			off = ((sreg>>(bits-13))&Bits13)+320;			bits -= 13;			break;		case Off11:	/* (64K history) */			bits -= 4;			while(bits<11){				if(n==0) goto Eof;				NEXTBYTE;			}			off = ((sreg>>(bits-11))&Bits11)+320;			bits -= 11;			break;		case Off16:	/* (64K history) */			bits -= 3;			while(bits<16){				if(n==0) goto Eof;				NEXTBYTE;			}			off = ((sreg>>(bits-16))&Bits16)+2368;			bits -= 16;			break;		}		for(ones=0;;ones++) {			if(bits == 0) {				if(n==0) goto Eof;				NEXTBYTE;			}			bits--;			if(!(sreg&(1<<bits)))				break;		}		if(ones>maxones){			werrstr("bad length %d\n", ones);			return nil;		}		if(ones == 0) {			len = 3;		} else {			ones++;			while(bits<ones) {				if(n==0) goto Eof;				NEXTBYTE;			}			len = (1<<ones) | ((sreg>>(bits-ones))&((1<<ones)-1));			bits -= ones;		} 		hq = hp-off;		if(hq < hs) {			hq += maxhis;			if(hq-hs+len > s->size){//				goto His;fprint(2, "mppc: reference past valid history\n");			}		}		if(hp+len > he)			goto His;		while(len) {			*hp++ = *hq++;			len--;		}	} Done:	hq = hs+s->indx;	len = hp-hq;DBG fprint(2, "mppc: len %d bits = %d n=%d\n", len, bits, n); 	s->indx += len;	if(s->indx > s->size)		s->size = s->indx; 	*psize = len;	return hq; Eof:	werrstr("unexpected end of data");	return nil;His:	werrstr("bad history reference");	return nil;}