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

📄 vjcomp.c

📁 在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LEA_4S的驱动,位置速寻算法,语音芯片ISD4004的录放音驱动,LED页面管理等等.从启动代码到操作系统的移植以及到业
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * FILENAME: vjcomp.c
 *
 * Copyright 1997- 2001 By InterNiche Technologies Inc. All rights reserved
 *
 * The VJ TCP/IP header compression code.
 * Routines to compress and uncompess tcp/ip headers (for transmission
 * over low speed serial lines).
 *
 * MODULE: PPP
 *
 * ROUTINES: vj_compress_init(), sifvjcomp(), match_connection(), 
 * ROUTINES: vj_compress_tcp(), vj_uncompress_tcp(), 
 * ROUTINES: vj_uncompress_tcp_part(),
 *
 * PORTABLE: yes
 */

/* Additional Copyrights: */

/* Portions Copyright 1996 by NetPort Software, All rights reserved 
 * Portions Copyright (c) 1989 The Regents of the University of 
 * California. All rights reserved. Redistribution and use in source 
 * and binary forms, with or without modification, are permitted 
 * provided that the following conditions are met: 1. Redistributions 
 * of source code must retain the above copyright notice, this list 
 * of conditions and the following disclaimer. 2. Redistributions in 
 * binary form must reproduce the above copyright notice, this list 
 * of conditions and the following disclaimer in the documentation 
 * and/or other materials provided with the distribution. 3. All 
 * advertising materials mentioning features or use of this software 
 * must display the following acknowledgement: This product includes 
 * software developed by the University of California, Berkeley and 
 * its contributors. 4. Neither the name of the University nor the 
 * names of its contributors may be used to endorse or promote 
 * products derived from this software without specific prior written 
 * permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND 
 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
 * SUCH DAMAGE. 
 */


#include "ppp_port.h"

#ifdef PPP_VJC    /* whole file can be ifdeffed out */

#include "ppp_port.h"
#include "mppp.h"

#include "tcpapp.h"

#ifdef MINI_TCP
#include "../mtcp/mtcp.h"
#else
#include "tcp.h"
#endif

#ifndef IPPROTO_TCP
#define     IPPROTO_TCP    6
#endif

/* Undef the item based version of TCP offset macro and replace with
 * pointer based version for VJ code:
 */
#undef   GET_TH_OFF
#define  GET_TH_OFF(th) (th->th_doff   >> 4)


/* FUNCTION: vj_compress_init()
 * 
 * PARAM1: struct slcompress * comp
 * PARAM2: u_char maxslotindex
 *
 * RETURNS: void
 */

void
vj_compress_init(struct slcompress * comp, u_char maxslotindex)
{
   unsigned i;
   struct cstate *   tstate   =  comp->tstate;

   MEMSET(comp, 0, sizeof(*comp));
   if (maxslotindex > MAX_STATES - 1)
      maxslotindex = MAX_STATES - 1;
   for (i = maxslotindex; i > 0; --i) 
   {
      tstate[i].cs_id = (u_char)i;
      tstate[i].cs_next = &tstate[i - 1];
   }
   tstate[0].cs_next = &tstate[maxslotindex];
   tstate[0].cs_id = 0;
   comp->last_cs = &tstate[0];
   comp->last_recv = 255;
   comp->last_xmit = 255;
   comp->flags = SLF_TOSS;
}


/* FUNCTION: sifvjcomp()
 *
 * sifvjcomp - config tcp header compression
 *
 * 
 * PARAM1: M_PPP mppp
 * PARAM2: int vjcomp      (bool) negitiated VJ comp 
 * PARAM3: u_char maxslotindex  number of VJ slots 
 * PARAM4: int cidcomp     
 *
 * RETURNS: 
 */

int
sifvjcomp(M_PPP mppp, int vjcomp, u_char maxslotindex, int cidcomp)
{
   int      x;    /* local copy of sc_flags */

   /* set bits in sc_flags based on passed parms */
   x = mppp->sc_flags;
   if(vjcomp)
      x |= SC_COMP_TCP;
   else
      x &= ~SC_COMP_TCP;
   if(cidcomp)
      x &= ~SC_NO_TCP_CCID;
   else
      x |= SC_NO_TCP_CCID;
   mppp->sc_flags = x;

   if(vjcomp || cidcomp)
      vj_compress_init( &(mppp->sc_comp), maxslotindex);

   return 1;
}



#ifndef SL_NO_STATS
#define  INCR(counter)  ++comp->counter;
#else
#define  INCR(counter)
#endif


/* ENCODE encodes a number that is known to be non-zero.  ENCODEZ
 * checks for zero (since zero has to be encoded in the long, 3 byte
 * form).
 */
#define ENCODE(n) { \
   if ((u_short)(n) >= 256) { \
      *cp++ = 0; \
      cp[1] = (u_char)(n); \
      cp[0] = (u_char)((n) >> 8); \
      cp += 2; \
   } else { \
      *cp++ = (u_char)(n); \
   } \
}
#define ENCODEZ(n) { \
   if ((u_short)(n) >= 256 || (u_short)(n) == 0) { \
      *cp++ = 0; \
      cp[1] = (u_char)(n); \
      cp[0] = (u_char)((n) >> 8); \
      cp += 2; \
   } else { \
      *cp++ = (u_char)(n); \
   } \
}

#define DECODEL(f) { \
   if (*cp == 0) {\
      (f) = htonl(ntohl(f) + (((u_long)cp[1] << 8) | cp[2])); \
      cp += 3; \
   } else { \
      (f) = htonl(ntohl(f) + (u_long)*cp); \
      cp++; \
   } \
}

#define DECODES(f) { \
   if (*cp == 0) {\
      (f) = htons(ntohs(f) + ((cp[1] << 8) | cp[2])); \
      cp += 3; \
   } else { \
      (f) = htons(ntohs(f) + (u_short)(*cp)); \
      cp++; \
   } \
}

#define DECODEU(f) { \
   if (*cp == 0) { \
      (f) = htons((cp[1] << 8) | cp[2]); \
      cp += 3; \
   } else { \
      (f) = htons((u_short)(*cp)); \
      cp++; \
   } \
}



/* FUNCTION: match_connection()
 *
 * match_connection() - return TRUE if passed state matches
 * passedIP packet, else FALSE
 * 
 * PARAM1: struct ip * ip
 * PARAM2: struct cstate * cs
 *
 * RETURNS: return TRUE if passed state matches passed IP
 * packet, else FALSE
 */

static int
match_connection(struct ip * ip, struct cstate * cs)
{
   struct tcphdr *   th;
   struct tcphdr *   tmp;

   /* check IP addresses */
   if (ip->ip_src != cs->slcs_u.csu_ip.ip_src)
      return FALSE;
   if (ip->ip_dest != cs->slcs_u.csu_ip.ip_dest)
      return FALSE;

   /* check TCP ports */
   th = (struct tcphdr *)(ip + 1);
   tmp = (struct tcphdr*)(&cs->slcs_u.csu_ip + 1);
   if (th->th_sport != tmp->th_sport)
      return FALSE;
   if (th->th_dport != tmp->th_dport)
      return FALSE;

   return TRUE;   /* no test failed, it's a match */
}



/* FUNCTION: vj_compress_tcp()
 * 
 * PARAM1: u_char ** buf
 * PARAM2: unsigned * buflen
 * PARAM3: struct ip * ip
 * PARAM4: struct slcompress * comp
 * PARAM5: int compress_cid
 *
 * RETURNS: 
 */

u_char
vj_compress_tcp(u_char ** buf, 
   unsigned *  buflen,
   struct vj_ip * ip,
   struct slcompress *  comp,
   int      compress_cid)
{
   struct cstate *   cs =  comp->last_cs->cs_next;
   unsigned hlen = (ip->ip_ver_ihl & 0x0F);
   struct tcphdr *   oth;
   struct tcphdr *   th;
   u_long   deltaS,  deltaA;
   unsigned changes = 0;
   u_char   new_seq[16];
   u_char * cp =  new_seq;

   /*
    * Bail if this is an IP fragment or if the TCP packet isn't
    * `compressible' (i.e., ACK isn't set or some other control bit is
    * set).  (We assume that the caller has already made sure the
    * packet is IP proto TCP).
    */
   if ((ip->ip_flgs_foff & htons(0x3fff)) || *buflen < 40)
      return (PPP_IP);

   th = (struct tcphdr *)(ip+1);
   if ((th->th_flags & (TH_SYN|TH_FIN|TH_RST|TH_ACK)) != TH_ACK)
      return (PPP_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.  Special case the
    * most recently used connection since it's most likely to be used
    * again & we don't have to do any reordering if it's used.
    */
   INCR(sls_packets)
   if (!match_connection((struct ip *)ip, cs))
   {
      /*
       * Wasn't the first -- search for it.
       *
       * States are kept in a circularly linked list with
       * last_cs 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.
       */
      struct cstate *   lcs;
      struct cstate *   lastcs   =  comp->last_cs;

      do 
      {
         lcs = cs; cs = cs->cs_next;
         INCR(sls_searches)
         if (match_connection((struct ip *)ip, cs))
            goto found;
      } while (cs != lastcs);

      /*
       * 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
       * last_cs to update the lru linkage.
       */
      INCR(sls_misses)
      comp->last_cs = lcs;
      hlen += GET_TH_OFF(th);
      hlen <<= 2;
      if (hlen > *buflen)
         return (PPP_IP);
      goto uncompressed;

      found:
      /*
       * Found it -- move to the front on the connection list.
       */
      if (cs == lastcs)
         comp->last_cs = lcs;
      else 
      {
         lcs->cs_next = cs->cs_next;
         cs->cs_next = lastcs->cs_next;
         lastcs->cs_next = cs;
      }
   }

   /*
    * Make sure that only what we expect to change changed. The first
    * set of `ifs' below checks the IP protocol version, header length &
    * type of service.  The 2nd  checks the "Don't fragment" bit.
    * The 3rd line checks the time-to-live and protocol (the protocol
    * check is unnecessary but costless).  The 4th line checks the TCP
    * header length.  The 5th line checks IP options, if any.  The 6th
    * line checks TCP options, if any.  If any of these things are
    * different between the previous & current datagram, we send the
    * current datagram `uncompressed'.
    */
   oth = (struct tcphdr *)(&cs->slcs_u.csu_ip + 1);
   deltaS = hlen;
   hlen += GET_TH_OFF(th);
   hlen <<= 2;
   if (hlen > *buflen)
      return (PPP_IP);

   if (((u_short *)ip)[0] != ((u_short *)&cs->slcs_u.csu_ip)[0])
      goto uncompressed;
   if (((u_short *)ip)[3] != ((u_short *)&cs->slcs_u.csu_ip)[3])

⌨️ 快捷键说明

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