⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 slhc.c

📁 一百多个例子很好的verilog 学习资料
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * Routines to compress and uncompress tcp packets (for transmission
 * over low speed serial lines).
 *
 * Copyright (c) 1989 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 *	Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
 *	- Initial distribution.
 *
 *
 * modified for KA9Q Internet Software Package by
 * Katie Stevens (dkstevens@ucdavis.edu)
 * University of California, Davis
 * Computing Services
 *	- 01-31-90	initial adaptation (from 1.19)
 *	PPP.05	02-15-90 [ks]
 *	PPP.08	05-02-90 [ks]	use PPP protocol field to signal compression
 *	PPP.15	09-90	 [ks]	improve mbuf handling
 *	PPP.16	11-02	 [karn]	substantially rewritten to use NOS facilities
 *
 *	- Feb 1991	Bill_Simpson@um.cc.umich.edu
 *			variable number of conversation slots
 *			allow zero or one slots
 *			separate routines
 *			status display
 */

#include "global.h"
#include "mbuf.h"
#include "internet.h"
#include "ip.h"
#include "tcp.h"
#include "slhc.h"

static uint8 *encode(uint8 *cp,uint n);
static long decode(struct mbuf **bpp);


/* Initialize compression data structure
 *	slots must be in range 0 to 255 (zero meaning no compression)
 */
struct slcompress *
slhc_init(rslots,tslots)
int rslots;
int tslots;
{
	uint i;
	struct cstate *ts;
	struct slcompress *comp;

	comp = callocw( 1, sizeof(struct slcompress) );

	if ( rslots > 0  &&  rslots < 256 ) {
		comp->rstate = callocw( rslots, sizeof(struct cstate) );
		comp->rslot_limit = rslots - 1;
	}

	if ( tslots > 0  &&  tslots < 256 ) {
		comp->tstate = callocw( tslots, sizeof(struct cstate) );
		comp->tslot_limit = tslots - 1;
	}

	comp->xmit_oldest = 0;
	comp->xmit_current = 255;
	comp->recv_current = 255;

	if ( tslots > 0 ) {
		ts = comp->tstate;
		for(i = comp->tslot_limit; i > 0; --i){
			ts[i].this = i;
			ts[i].next = &(ts[i - 1]);
		}
		ts[0].next = &(ts[comp->tslot_limit]);
		ts[0].this = 0;
	}
	return comp;
}


/* Free a compression data structure */
void
slhc_free(comp)
struct slcompress *comp;
{
	if ( comp == NULL )
		return;

	if ( comp->rstate != NULL )
		free( comp->rstate );

	if ( comp->tstate != NULL )
		free( comp->tstate );

	free( comp );
}


/* Encode a number */
static uint8 *
encode(cp,n)
uint8 *cp;
uint n;
{
	if(n >= 256 || n == 0){
		*cp++ = 0;
		cp = put16(cp,n);
	} else {
		*cp++ = n;
	}
	return cp;
}

/* Decode a number */
static long
decode(bpp)
struct mbuf **bpp;
{
	int x;

	x = PULLCHAR(bpp);
	if(x == 0){
		return pull16(bpp);	/* pull16 returns -1 on error */
	} else {
		return (long)x;		/* -1 if PULLCHAR returned error */
	}
}

int
slhc_compress(comp, bpp, compress_cid)
struct slcompress *comp;
struct mbuf **bpp;
int compress_cid;
{
	struct cstate *ocs = &(comp->tstate[comp->xmit_oldest]);
	struct cstate *lcs = ocs;
	struct cstate *cs = lcs->next;
	uint hlen,iplen;
	struct tcp *oth;
	unsigned long deltaS, deltaA;
	uint changes = 0;
	uint8 new_seq[16];
	uint8 *cp = new_seq;
	struct tcp th;
	struct ip iph;
	struct mbuf *copy;

	/* Copy TCP/IP header, allowing for worst-case options in both
	 * Using dup_p seemed to result in unexplained
	 * memory leaks -- but only some of the time. Must find out why.
	 */
/*	dup_p(&copy,*bpp,0,IPLEN+IP_MAXOPT+TCPLEN+TCP_MAXOPT); */
	copy = copy_p(*bpp,IPLEN+IP_MAXOPT+TCPLEN+TCP_MAXOPT);

	/* Peek at IP header */
	iplen = hlen = ntohip(&iph,&copy);

	/* Bail if this packet isn't TCP, or is an IP fragment */
	if(iph.protocol != TCP_PTCL || iph.offset != 0 || iph.flags.mf){
		/* Send as regular IP */
		if(iph.protocol != TCP_PTCL)
			comp->sls_o_nontcp++;
		else
			comp->sls_o_tcp++;
		free_p(&copy);
		return SL_TYPE_IP;
	}
	/* Extract TCP header */
	hlen += ntohtcp(&th,&copy);
	free_p(&copy);	/* Done with copy */

	/*  Bail if the TCP packet isn't `compressible' (i.e., ACK isn't set or
	 *  some other control bit is set, or has options).
	 */
	if(th.flags.syn || th.flags.fin || th.flags.rst || !th.flags.ack
	 || th.flags.mss || th.flags.wscale || th.flags.tstamp){
		/* TCP connection stuff; send as regular IP */
		comp->sls_o_tcp++;
		return SL_TYPE_IP;
	}
	/*
	 * Packet is compressible -- we're going to send either a
	 * COMPRESSED_TCP or UNCOMPRESSED_TCP packet.  Either way,
	 * we need to locate (or create) the connection state.
	 *
	 * States are kept in a circularly linked list with
	 * xmit_oldest pointing to the end of the list.  The
	 * list is kept in lru order by moving a state to the
	 * head of the list whenever it is referenced.  Since
	 * the list is short and, empirically, the connection
	 * we want is almost always near the front, we locate
	 * states via linear search.  If we don't find a state
	 * for the datagram, the oldest state is (re-)used.
	 */
	for ( ; ; ) {
		if( iph.source == cs->cs_ip.source
		 && iph.dest == cs->cs_ip.dest
		 && th.source == cs->cs_tcp.source
		 && th.dest == cs->cs_tcp.dest)
			goto found;

		/* if current equal oldest, at end of list */
		if ( cs == ocs )
			break;
		lcs = cs;
		cs = cs->next;
		comp->sls_o_searches++;
	};
	/*
	 * Didn't find it -- re-use oldest cstate.  Send an
	 * uncompressed packet that tells the other side what
	 * connection number we're using for this conversation.
	 *
	 * Note that since the state list is circular, the oldest
	 * state points to the newest and we only need to set
	 * xmit_oldest to update the lru linkage.
	 */
	comp->sls_o_misses++;
	comp->xmit_oldest = lcs->this;

	goto uncompressed;

found:
	/*
	 * Found it -- move to the front on the connection list.
	 */
	if(lcs == ocs) {
		/* found at most recently used */
	} else if (cs == ocs) {
		/* found at least recently used */
		comp->xmit_oldest = lcs->this;
	} else {
		/* more than 2 elements */
		lcs->next = cs->next;
		cs->next = ocs->next;
		ocs->next = cs;
	}

	/*
	 * Make sure that only what we expect to change changed.
	 * Check the following:
	 * IP protocol version, header length & type of service.
	 * The "Don't fragment" bit.
	 * The time-to-live field.
	 * The TCP header length.
	 * IP options, if any.
	 * TCP options, if any.
	 * If any of these things are different between the previous &
	 * current datagram, we send the current datagram `uncompressed'.
	 */
	oth = &cs->cs_tcp;

	if(iph.version != cs->cs_ip.version || iph.optlen != cs->cs_ip.optlen
	 || iph.tos != cs->cs_ip.tos
	 || iph.flags.df != cs->cs_ip.flags.df
	 || iph.ttl != cs->cs_ip.ttl
	 || (iph.optlen > 0 && memcmp(iph.options,cs->cs_ip.options,iph.optlen) != 0)){
		goto uncompressed;
	}
	/*
	 * Figure out which of the changing fields changed.  The
	 * receiver expects changes in the order: urgent, window,
	 * ack, seq (the order minimizes the number of temporaries
	 * needed in this section of code).
	 */
	if(th.flags.urg){
		deltaS = th.up;
		cp = encode(cp,deltaS);
		changes |= NEW_U;
	} else if(th.up != oth->up){
		/* argh! URG not set but urp changed -- a sensible
		 * implementation should never do this but RFC793
		 * doesn't prohibit the change so we have to deal
		 * with it. */
		goto uncompressed;
	}
	if((deltaS = th.wnd - oth->wnd) != 0){
		cp = encode(cp,deltaS);
		changes |= NEW_W;
	}
	if((deltaA = th.ack - oth->ack) != 0L){
		if(deltaA > 0x0000ffff)
			goto uncompressed;
		cp = encode(cp,deltaA);
		changes |= NEW_A;
	}
	if((deltaS = th.seq - oth->seq) != 0L){
		if(deltaS > 0x0000ffff)
			goto uncompressed;
		cp = encode(cp,deltaS);
		changes |= NEW_S;
	}

	switch(changes){
	case 0:	/* Nothing changed. If this packet contains data and the
		 * last one didn't, this is probably a data packet following
		 * an ack (normal on an interactive connection) and we send
		 * it compressed.  Otherwise it's probably a retransmit,
		 * retransmitted ack or window probe.  Send it uncompressed

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -