📄 slhc.c
字号:
* in case the other side missed the compressed version.
*/
if(iph.length != cs->cs_ip.length && cs->cs_ip.length == hlen)
break;
goto uncompressed;
case SPECIAL_I:
case SPECIAL_D:
/* actual changes match one of our special case encodings --
* send packet uncompressed.
*/
goto uncompressed;
case NEW_S|NEW_A:
if(deltaS == deltaA &&
deltaS == cs->cs_ip.length - hlen){
/* special case for echoed terminal traffic */
changes = SPECIAL_I;
cp = new_seq;
}
break;
case NEW_S:
if(deltaS == cs->cs_ip.length - hlen){
/* special case for data xfer */
changes = SPECIAL_D;
cp = new_seq;
}
break;
}
deltaS = iph.id - cs->cs_ip.id;
if(deltaS != 1){
cp = encode(cp,deltaS);
changes |= NEW_I;
}
if(th.flags.psh)
changes |= TCP_PUSH_BIT;
/* Grab the cksum before we overwrite it below. Then update our
* state with this packet's header.
*/
deltaA = th.checksum;
ASSIGN(cs->cs_ip,iph);
ASSIGN(cs->cs_tcp,th);
/* We want to use the original packet as our compressed packet.
* (cp - new_seq) is the number of bytes we need for compressed
* sequence numbers. In addition we need one byte for the change
* mask, one for the connection id and two for the tcp checksum.
* So, (cp - new_seq) + 4 bytes of header are needed.
*/
deltaS = cp - new_seq;
pullup(bpp,NULL,hlen); /* Strip TCP/IP headers */
if(compress_cid == 0 || comp->xmit_current != cs->this){
pushdown(bpp,NULL,deltaS + 4);
cp = (*bpp)->data;
*cp++ = changes | NEW_C;
*cp++ = cs->this;
comp->xmit_current = cs->this;
} else {
pushdown(bpp,NULL,deltaS + 3);
cp = (*bpp)->data;
*cp++ = changes;
}
cp = put16(cp,deltaA); /* Write TCP checksum */
memcpy(cp,new_seq,deltaS); /* Write list of deltas */
comp->sls_o_compressed++;
return SL_TYPE_COMPRESSED_TCP;
/* Update connection state cs & send uncompressed packet (i.e.,
* a regular ip/tcp packet but with the 'conversation id' we hope
* to use on future compressed packets in the protocol field).
*/
uncompressed:
iph.protocol = cs->this;
ASSIGN(cs->cs_ip,iph);
ASSIGN(cs->cs_tcp,th);
comp->xmit_current = cs->this;
comp->sls_o_uncompressed++;
pullup(bpp,NULL,iplen); /* Strip old IP header */
htonip(&iph,bpp,IP_CS_OLD); /* replace with new one */
return SL_TYPE_UNCOMPRESSED_TCP;
}
int
slhc_uncompress(comp, bpp)
struct slcompress *comp;
struct mbuf **bpp;
{
int changes;
long x;
struct tcp *thp;
struct cstate *cs;
int len;
if(bpp == NULL){
comp->sls_i_error++;
return 0;
}
/* We've got a compressed packet; read the change byte */
comp->sls_i_compressed++;
if(len_p(*bpp) < 3){
comp->sls_i_error++;
return 0;
}
changes = PULLCHAR(bpp); /* "Can't fail" */
if(changes & NEW_C){
/* Make sure the state index is in range, then grab the state.
* If we have a good state index, clear the 'discard' flag.
*/
x = PULLCHAR(bpp); /* Read conn index */
if(x < 0 || x > comp->rslot_limit)
goto bad;
comp->flags &=~ SLF_TOSS;
comp->recv_current = x;
} else {
/* this packet has an implicit state index. If we've
* had a line error since the last time we got an
* explicit state index, we have to toss the packet. */
if(comp->flags & SLF_TOSS){
comp->sls_i_tossed++;
return 0;
}
}
cs = &comp->rstate[comp->recv_current];
thp = &cs->cs_tcp;
if((x = pull16(bpp)) == -1) /* Read the TCP checksum */
goto bad;
thp->checksum = x;
thp->flags.psh = (changes & TCP_PUSH_BIT) ? 1 : 0;
switch(changes & SPECIALS_MASK){
case SPECIAL_I: /* Echoed terminal traffic */
{
uint i;
i = cs->cs_ip.length;
i -= (cs->cs_ip.optlen + IPLEN + TCPLEN);
thp->ack += i;
thp->seq += i;
}
break;
case SPECIAL_D: /* Unidirectional data */
thp->seq += cs->cs_ip.length - (cs->cs_ip.optlen +IPLEN + TCPLEN);
break;
default:
if(changes & NEW_U){
thp->flags.urg = 1;
if((x = decode(bpp)) == -1)
goto bad;
thp->up = x;
} else
thp->flags.urg = 0;
if(changes & NEW_W){
if((x = decode(bpp)) == -1)
goto bad;
thp->wnd += x;
}
if(changes & NEW_A){
if((x = decode(bpp)) == -1)
goto bad;
thp->ack += x;
}
if(changes & NEW_S){
if((x = decode(bpp)) == -1)
goto bad;
thp->seq += x;
}
break;
}
if(changes & NEW_I){
if((x = decode(bpp)) == -1)
goto bad;
cs->cs_ip.id += x;
} else
cs->cs_ip.id++;
/*
* At this point, bpp points to the first byte of data in the
* packet. Put the reconstructed TCP and IP headers back on the
* packet. Recalculate IP checksum (but not TCP checksum).
*/
len = len_p(*bpp) + IPLEN + TCPLEN + cs->cs_ip.optlen;
cs->cs_ip.length = len;
htontcp(thp,bpp,0,0);
htonip(&cs->cs_ip,bpp,IP_CS_NEW);
return len;
bad:
comp->sls_i_error++;
return slhc_toss( comp );
}
int
slhc_remember(comp, bpp)
struct slcompress *comp;
struct mbuf **bpp;
{
struct cstate *cs;
struct ip iph;
struct tcp th;
uint len;
uint hdrlen;
int slot;
if(bpp == NULL){
comp->sls_i_error++;
return slhc_toss(comp);
}
/* Sneak a peek at the IP header's IHL field to find its length */
hdrlen = ((*bpp)->data[0] & 0xf) << 2;
if(hdrlen < IPLEN){
/* The IP header length field is too small to be valid */
comp->sls_i_error++;
return slhc_toss(comp);
}
len = len_p(*bpp); /* Actual length of whole packet */
ntohip(&iph,bpp); /* Extract IP header */
/* Verify indicated length <= actual length */
if(iph.length > len){
/* Packet has been truncated, or header is garbage */
comp->sls_i_error++;
return slhc_toss(comp);
}
/* Verify conn ID */
slot = iph.protocol;
if(slot > comp->rslot_limit){
/* Out of range */
comp->sls_i_error++;
return slhc_toss(comp);
}
iph.protocol = TCP_PTCL; /* Replace conn ID with TCP_PTCL */
/* Extract TCP header and replace both headers
* Neither header checksum is recalculated
*/
ntohtcp(&th,bpp);
htontcp(&th,bpp,0,0);
htonip(&iph,bpp,IP_CS_OLD);
/* Checksum IP header (now that protocol field is TCP again) */
if(cksum(NULL,*bpp,hdrlen) != 0){
/* Bad IP header checksum; discard */
comp->sls_i_error++;
return slhc_toss(comp);
}
/* Update local state */
comp->recv_current = slot;
cs = &comp->rstate[slot];
comp->flags &=~ SLF_TOSS;
ASSIGN(cs->cs_ip,iph);
ASSIGN(cs->cs_tcp,th);
comp->sls_i_uncompressed++;
return len;
}
int
slhc_toss(comp)
struct slcompress *comp;
{
if ( comp == NULL )
return 0;
comp->flags |= SLF_TOSS;
return 0;
}
void
slhc_i_status(comp)
struct slcompress *comp;
{
if (comp != NULL) {
printf("\t%10ld Cmp,"
" %10ld Uncmp,"
" %10ld Bad, "
" %10ld Tossed\n",
comp->sls_i_compressed,
comp->sls_i_uncompressed,
comp->sls_i_error,
comp->sls_i_tossed);
}
}
void
slhc_o_status(comp)
struct slcompress *comp;
{
if (comp != NULL) {
printf("\t%10ld Cmp,"
" %10ld Uncmp,"
" %10ld AsIs,"
" %10ld NotTCP\n",
comp->sls_o_compressed,
comp->sls_o_uncompressed,
comp->sls_o_tcp,
comp->sls_o_nontcp);
printf("\t%10ld Searches,"
" %10ld Misses\n",
comp->sls_o_searches,
comp->sls_o_misses);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -