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

📄 vjhc.c

📁 用于嵌入式系统的TCP/IP协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
  }  deltaA = ntohl(th->ack_num) - ntohl(oth->ack_num);  if (deltaA)  {    if (deltaA > 0xFFFF)      goto uncompressed;    ENCODE(deltaA);    changes |= NEW_A;  }  deltaS = ntohl(th->seq_num) - ntohl(oth->seq_num);  if (deltaS)  {    if (deltaS > 0xFFFF)      goto uncompressed;    ENCODE(deltaS);    changes |= NEW_S;  }  /*-------------------------------------------------------------------*/  /* Look for the special-case encodings.                              */  /*-------------------------------------------------------------------*/  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->length != cs->cs_ip.length &&          ntohs(cs->cs_ip.length) == hlen)        break;      /*lint -fallthrough */    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 == ntohs(cs->cs_ip.length) - hlen)      {        /*-------------------------------------------------------------*/        /* Special case for echoed terminal traffic.                   */        /*-------------------------------------------------------------*/        changes = SPECIAL_I;        cp = new_seq;      }      break;    case NEW_S:      if (deltaS == ntohs(cs->cs_ip.length) - hlen)      {        /*-------------------------------------------------------------*/        /* Special case for data transfer.                             */        /*-------------------------------------------------------------*/        changes = SPECIAL_D;        cp = new_seq;      }      break;  }  deltaS = ntohs(ip->ip_id) - ntohs(cs->cs_ip.ip_id);  if (deltaS != 1)  {    ENCODEZ(deltaS);    changes |= NEW_I;  }  if (th->flags & TCPF_PSH)    changes |= TCP_PUSH_BIT;  /*-------------------------------------------------------------------*/  /* Grab the checksum before we overwrite it below. Then update our   */  /* state with this packet's header.                                  */  /*-------------------------------------------------------------------*/  deltaA = ntohs(th->cksum);  memcpy(&cs->cs_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 = (ui8 *) ip;  if (comp_cid == 0 || comp->last_xmit != cs->cs_id)  {    comp->last_xmit = cs->cs_id;    hlen -= deltaS + 4;    cp += hlen;    *cp++ = changes | NEW_C;    *cp++ = cs->cs_id;  }  else  {    hlen -= deltaS + 3;    cp += hlen;    *cp++ = changes;  }  buf->length -= hlen;  buf->ip_pkt += hlen;  *cp++ = deltaA >> 8;  *cp++ = deltaA;  memcpy(cp, new_seq, deltaS);  return PPP_COMP_PROTO;  /*-------------------------------------------------------------------*/  /* Update connection state cs and send uncompressed packet (This is  */  /* a regular IP/TCP packet with the 'conversation id' we hope to use */  /* on future compressed packets in the protocol field).              */  /*-------------------------------------------------------------------*/uncompressed:  memcpy(&cs->cs_ip, ip, hlen);  ip->protocol = cs->cs_id;  comp->last_xmit = cs->cs_id;  return PPP_UNCOMP_PROTO;}/***********************************************************************//* vjhc_uncompress: Called if packet protocol is PPP_COMP_PROTO        *//*                                                                     *//*      Inputs: comp = points to line's compression state structure    *//*              buf = points to compressed packet                      *//*                                                                     *//*     Returns: 0 if no errors, else -1 to drop packet                 *//*                                                                     *//*  The new packet is constructed in-place. There must be 128 bytes of *//*  free space in front of bufp to allow room for the reconstructed IP *//*  and TCP headers. The reconstructed packet is aligned on a 32-bit   *//*  boundary. The compression state is updated.                        *//*                                                                     *//***********************************************************************/int vjhc_uncompress(struct vjcompress *comp, NetBuf *buf){  ui8 *cp;  uint hlen, changes;  Tcp *th;  struct cstate *cs;  /*-------------------------------------------------------------------*/  /* We've got a compressed packet.                                    */  /*-------------------------------------------------------------------*/  cp = buf->ip_pkt;  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 > comp->rslot_limit)      goto bad;    comp->flags &= ~VJHCF_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 & VJHCF_TOSS)      return -1;  }  /*-------------------------------------------------------------------*/  /* Find the state then fill in the TCP checksum and PUSH bit.        */  /*-------------------------------------------------------------------*/  cs = &comp->rstate[comp->last_recv];  hlen = (cs->cs_ip.ver_len & 0xF) << 2;  th = (Tcp *) &((ui8 *)&cs->cs_ip)[hlen];  th->cksum = htons((cp[0] << 8) | cp[1]);  cp += 2;  if (changes & TCP_PUSH_BIT)    th->flags |= TCPF_PSH;  else    th->flags &= ~TCPF_PSH;  /*-------------------------------------------------------------------*/  /* Fix up the state's ack, seq, urg and win fields based on the      */  /* change mask.                                                      */  /*-------------------------------------------------------------------*/  switch (changes & SPECIALS_MASK)  {    case SPECIAL_I:    {      uint i = ntohs(cs->cs_ip.length) - cs->cs_hlen;      th->ack_num = htonl(ntohl(th->ack_num) + i);      th->seq_num = htonl(ntohl(th->seq_num) + i);      break;    }    case SPECIAL_D:      th->seq_num = htonl(ntohl(th->seq_num) + ntohs(cs->cs_ip.length)                  - cs->cs_hlen);      break;    default:      if (changes & NEW_U)      {        th->flags |= TCPF_URG;        DECODEU(th->urg_ptr)      }      else        th->flags &= ~TCPF_URG;      if (changes & NEW_W)        DECODES(th->window)      if (changes & NEW_A)        DECODEL(th->ack_num)      if (changes & NEW_S)        DECODEL(th->seq_num)      break;  }  /*-------------------------------------------------------------------*/  /* Update the IP ID.                                                 */  /*-------------------------------------------------------------------*/  if (changes & NEW_I)    DECODES(cs->cs_ip.ip_id)  else    cs->cs_ip.ip_id = htons(ntohs(cs->cs_ip.ip_id) + 1);  /*-------------------------------------------------------------------*/  /* cp now points to first byte of packet data. Subtract compressed   */  /* header length to get just segment data length.                    */  /*-------------------------------------------------------------------*/  if (buf->length < (cp - buf->ip_pkt))  {    /*-----------------------------------------------------------------*/    /* We must have dropped some characters (CRC should detect this    */    /* but SLIP framing won't).                                        */    /*-----------------------------------------------------------------*/    goto bad;  }  buf->length -= (cp - buf->ip_pkt);  /*-------------------------------------------------------------------*/  /* Promote to 1st order buffer, recording start and length of data.  */  /*-------------------------------------------------------------------*/  buf->app_data = cp;  buf->order = 1;  buf->app_len = buf->length;  /*-------------------------------------------------------------------*/  /* Advance "cp" past segment data and round up to 4-byte boundary.   */  /*-------------------------------------------------------------------*/  cp += buf->length;  cp = (ui8 *)(((ui32)cp + 3) & ~3);  /*-------------------------------------------------------------------*/  /* Correct buffer and IP lengths and IP header pointer.              */  /*-------------------------------------------------------------------*/  buf->length += cs->cs_hlen;  cs->cs_ip.length = htons(buf->length);  buf->ip_pkt = cp;  /*-------------------------------------------------------------------*/  /* Copy saved and corrected IP/TCP headers to buffer (after data).   */  /*-------------------------------------------------------------------*/  memcpy(cp, &cs->cs_ip, cs->cs_hlen);  /*-------------------------------------------------------------------*/  /* Recompute the IP header checksum.                                 */  /*-------------------------------------------------------------------*/  {    ui16 *bp = (ui16 *)cp;    for (changes = 0; hlen > 0; hlen -= 2)      changes += *bp++;    changes = (changes & 0xFFFF) + (changes >> 16);    changes = (changes & 0xFFFF) + (changes >> 16);    ((Ip *) cp)->checksum = ~changes;  }  return 0;bad:  comp->flags |= VJHCF_TOSS;  return -1;}/***********************************************************************//* vjhc_remember: Called if packet protocol equals PPP_UNCOMP_PROTO,   *//*                regular TCP packet with connection ID in place of    *//*                protocol field. Updates saved context.               *//*                                                                     *//*     Returns: 0 if no errors, else -1 to drop packet                 *//*                                                                     *//***********************************************************************/int vjhc_remember(struct vjcompress *comp, const NetBuf *buf){  struct cstate *cs;  Ip *ip = (Ip *)buf->ip_pkt;  uint hlen = ip->ver_len & 0xF;  /*-------------------------------------------------------------------*/  /* Locate saved state. If index is legal, clear 'discard' flag.      */  /*-------------------------------------------------------------------*/  if (ip->protocol > comp->rslot_limit)    goto bad;  cs = &comp->rstate[comp->last_recv = ip->protocol];  comp->flags &= ~VJHCF_TOSS;  /*-------------------------------------------------------------------*/  /* Restore IP protocol field, then save a copy of packet header. The */  /* checksum is zeroed in the copy so we don't have to zero it each   */  /* time we process a compressed packet.                              */  /*-------------------------------------------------------------------*/  ip->protocol = IPT_TCP;  hlen += ((Tcp *) &((int *)ip)[hlen])->offset >> 4;  hlen <<= 2;  memcpy(&cs->cs_ip, ip, hlen);  cs->cs_ip.checksum = 0;  cs->cs_hlen = hlen;  return 0;bad:  comp->flags |= VJHCF_TOSS;  return -1;}/***********************************************************************//*   vjhc_toss: Called to record need to resynch compression ID        *//*                                                                     *//***********************************************************************/void vjhc_toss(struct vjcompress *comp){  comp->flags |= VJHCF_TOSS;}#endif /* MAX_PPP_INTF */

⌨️ 快捷键说明

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