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

📄 vjcomp.c

📁 在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LEA_4S的驱动,位置速寻算法,语音芯片ISD4004的录放音驱动,LED页面管理等等.从启动代码到操作系统的移植以及到业
💻 C
📖 第 1 页 / 共 2 页
字号:
      goto uncompressed;
   if (((u_short *)ip)[4] != ((u_short *)&cs->slcs_u.csu_ip)[4])
      goto uncompressed;
   if (((th->th_doff & 0xF0) != (oth->th_doff & 0xF0)))
      goto uncompressed;

   if ((deltaS > 5 &&
       MEMCMP(ip + 1, (void*)(&cs->slcs_u.csu_ip + 1), (int)((deltaS - 5) << 2))))
   {
      goto uncompressed;
   }

   if ((GET_TH_OFF(th) > 5 &&
       MEMCMP(th + 1, oth + 1, (int)((GET_TH_OFF(th) - 5) << 2))))
   {
      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->th_flags & TH_URG) 
   {
      deltaS = ntohs(th->th_urp);
      ENCODEZ(deltaS);
      changes |= NEW_U;
   } else if (th->th_urp != oth->th_urp)
      /* 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;

   deltaS = (u_short)(ntohs(th->th_win) - ntohs(oth->th_win));
   if (deltaS)
   {
      ENCODE(deltaS);
      changes |= NEW_W;
   }

   deltaA = ntohl(th->th_ack) - ntohl(oth->th_ack);
   if (deltaA)
   {
      if (deltaA > 0xffff)
         goto uncompressed;
      ENCODE(deltaA);
      changes |= NEW_A;
   }

   deltaS = ntohl(th->th_seq) - ntohl(oth->th_seq);
   if (deltaS)
   {
      if (deltaS > 0xffff)
         goto uncompressed;
      ENCODE(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
       * in case the other side missed the compressed version.
       */
      if ((ip->ip_len != cs->slcs_u.csu_ip.ip_len) &&
          ntohs(cs->slcs_u.csu_ip.ip_len) == (u_short)hlen)
      {
         break;
      }

      /* (fall through) */

   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 == ((u_long)ntohs(cs->slcs_u.csu_ip.ip_len) - hlen)) 
      {
         /* special case for echoed terminal traffic */
         changes = SPECIAL_I;
         cp = new_seq;
      }
      break;

   case NEW_S:
      if (deltaS == ((u_long)ntohs(cs->slcs_u.csu_ip.ip_len) - hlen)) 
      {
         /* special case for data xfer */
         changes = SPECIAL_D;
         cp = new_seq;
      }
      break;
   }

   deltaS = ((u_long)ntohs(ip->ip_id) - ntohs(cs->slcs_u.csu_ip.ip_id));
   if (deltaS != 1) 
   {
      ENCODEZ(deltaS);
      changes |= NEW_I;
   }
   if (th->th_flags & TH_PUSH)
      changes |= TCP_PUSH_BIT;
   /*
    * Grab the cksum before we overwrite it below.  Then update our
    * state with this packet's header.
    */
   deltaA = ntohs(th->th_sum);
   MEMCPY(&cs->slcs_u.csu_ip, ip, hlen);

   /*
    * 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.  hlen is how
    * many bytes of the original packet to toss so subtract the two to
    * get the new packet size.
    */
   deltaS = cp - new_seq;
   cp = (u_char *)ip;
   if (compress_cid == 0 || comp->last_xmit != cs->cs_id) 
   {
      comp->last_xmit = cs->cs_id;
      hlen -= (unsigned)deltaS + 4;
      cp += hlen;
      *cp++ = (u_char)(changes | NEW_C);
      *cp++ = cs->cs_id;
   } else 
   {
      hlen -= (unsigned)(deltaS + 3);
      cp += hlen;
      *cp++ = (u_char)changes;
   }
   *buflen -= hlen;
   *buf += hlen;
   *cp++ = (u_char)(deltaA >> 8);
   *cp++ = (u_char)deltaA;
   MEMCPY(cp, (char*)(&new_seq[0]), (unsigned)deltaS);
   INCR(sls_compressed)
   return (PPP_VJC_COMP);

   /*
    * Update connection state cs & send uncompressed packet ('uncompressed'
    * means a regular ip/tcp packet but with the 'conversation id' we hope
    * to use on future compressed packets in the protocol field).
    */
uncompressed:
   MEMCPY(&cs->slcs_u.csu_ip, ip, hlen);
   ip->ip_prot = cs->cs_id;
   comp->last_xmit = cs->cs_id;
   return (PPP_VJC_UNCOMP);
}



/* FUNCTION: vj_uncompress_tcp_part()
 *
 * Uncompress a packet of total length total_len.  The first buflen
 * bytes are at *bufp; this must include the entire (compressed or
 * uncompressed) TCP/IP header.  In addition, there must be enough
 * clear space before *bufp to build a full-length TCP/IP header.
 *
 * 
 * PARAM1: u_char ** bufp
 * PARAM2: int   buflen
 * PARAM3: int   total_len
 * PARAM4: unsigned type
 * PARAM5: struct slcompress *  comp
 *
 * RETURNS: 
 */

int
vj_uncompress_tcp_part(u_char ** bufp, 
   int   buflen, 
   int   total_len,
   unsigned type,
   struct slcompress *  comp)
{
   u_char * cp;
   unsigned hlen, changes;
   struct tcphdr *   th;
   struct cstate *   cs;
   struct ip * ip;

   switch (type) 
   {
   case PPP_VJC_UNCOMP:
      ip = (struct ip *) *bufp;
      if (ip->ip_prot >= MAX_STATES)
         goto bad;
      cs = &comp->rstate[comp->last_recv = ip->ip_prot];
      comp->flags &=~ SLF_TOSS;
      ip->ip_prot = IPPROTO_TCP;    /* put prot ID back over state field */
      hlen = ip->ip_ver_ihl & 0x0F; /* extract IP hdr len in dwords */
      th = (struct tcphdr *)(ip+1); /* find tcp header */
      /* Add tcp data offset (high 4 bits of byte) to IP header len */
      hlen += ((th->th_doff & 0xf0) >> 4);   
      hlen <<= 2; /* adjust 32 bit word count to byte count */
      MEMCPY(&cs->slcs_u.csu_ip, ip, hlen);
      cs->slcs_u.csu_ip.ip_chksum = 0;
      cs->cs_hlen = (u_short)hlen;
      INCR(sls_uncompressedin)
      return (total_len);

   default:
      goto bad;

   case PPP_VJC_COMP:
      break;
   }
   /* We've got a compressed packet. */
   INCR(sls_compressedin)
   cp = *bufp;
   changes = *cp++;
   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. */
      if (*cp >= MAX_STATES)
         goto bad;

      comp->flags &=~ SLF_TOSS;
      comp->last_recv = *cp++;
   } 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) 
      {
         INCR(sls_tossed)
         return (0);
      }
   }
   cs = &comp->rstate[comp->last_recv];
   hlen = (cs->slcs_u.csu_ip.ip_ver_ihl & 0x0f) << 2;
   th = (struct tcphdr *)&((u_char *)&cs->slcs_u.csu_ip)[hlen];
   th->th_sum = htons((*cp << 8) | cp[1]);
   cp += 2;
   if (changes & TCP_PUSH_BIT)
      th->th_flags |= TH_PUSH;
   else
      th->th_flags &=~ TH_PUSH;

   switch (changes & SPECIALS_MASK) 
   {
   case SPECIAL_I:
      {
         unsigned i = ntohs(cs->slcs_u.csu_ip.ip_len) - cs->cs_hlen;
         th->th_ack = htonl(ntohl(th->th_ack) + i);
         th->th_seq = htonl(ntohl(th->th_seq) + i);
      }
      break;

   case SPECIAL_D:
      th->th_seq = htonl(ntohl(th->th_seq) + ntohs(cs->slcs_u.csu_ip.ip_len)
       - cs->cs_hlen);
      break;

      default:
      if (changes & NEW_U) 
      {
         th->th_flags |= TH_URG;
         DECODEU(th->th_urp)
      } else
         th->th_flags &=~ TH_URG;
      if (changes & NEW_W)
         DECODES(th->th_win)
      if (changes & NEW_A)
         DECODEL(th->th_ack)
      if (changes & NEW_S)
         DECODEL(th->th_seq)
      break;
   }

   if (changes & NEW_I) 
   {
      DECODES(cs->slcs_u.csu_ip.ip_id)
   }
   else
   {
      cs->slcs_u.csu_ip.ip_id = htons(ntohs(cs->slcs_u.csu_ip.ip_id) + 1);
   }

   /*
    * At this point, cp points to the first byte of data in the
    * packet.  If we're not aligned on a 4-byte boundary, copy the
    * data down so the ip & tcp headers will be aligned.  Then back up
    * cp by the tcp/ip header length to make room for the reconstructed
    * header (we assume the packet we were handed has enough space to
    * prepend 128 bytes of header).  Adjust the length to account for
    * the new header & fill in the IP total length.
    */
   buflen -= (cp - *bufp);
   total_len -= (cp - *bufp);

   /* If len is <0 we must have dropped some characters (crc should detect
    * this but the old slip framing won't)
    */
   if (buflen < 0)
      goto bad;

   if ((long)cp & 3) 
   {
      if (buflen > 0)
         MEMMOVE( (void*)((long)cp &~ 3), cp, buflen);

         cp = (u_char *)((long)cp &~ 3);
   }
   cp -= cs->cs_hlen;
   total_len += cs->cs_hlen;
   cs->slcs_u.csu_ip.ip_len = htons(total_len);
   MEMCPY(cp, &cs->slcs_u.csu_ip, cs->cs_hlen);
   *bufp = cp;

   /* recompute the ip header checksum */
   ip = (struct ip *)cp;
   ip->ip_chksum = 0;
   ip->ip_chksum = ~cksum(cp, (unshort)(hlen/2));

   return (total_len);
bad:
   comp->flags |= SLF_TOSS;
   INCR(sls_errorin)
   return (0);
}

/* FUNCTION: vj_uncompress_tcp()
 *
 * See vj_uncompress_tcp_part()
 *
 * PARAM1: u_char ** bufp
 * PARAM2: int len
 * PARAM3: unsigned type
 * PARAM4: struct slcompress *comp
 *
 * RETURNS: 
 */

int
vj_uncompress_tcp(u_char ** bufp, 
   int   len,
   unsigned type,
   struct slcompress *  comp)
{
   return vj_uncompress_tcp_part(bufp, len, len, type, comp);
}


#endif   /* PPP_VJC - whole file can be ifdeffed out */
/* end of file slcompre.c */


⌨️ 快捷键说明

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