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

📄 vjcomp.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 3 页
字号:
        {
            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. 
    //
    // Line 1: checks the IP protocol version, header length & TOS
    // Line 2: checks the "Don't fragment" bit.
    // Line 3: checks the time-to-live and protocol - unnecessary but free.
    // Line 4: checks the TCP header length.  
    // Line 5: checks IP options, if any.  '
    // Line 6: checks TCP options, if any.  
    //
    // If any of these things are different between the previous & current 
    // datagram, we send the current datagram `uncompressed'.
         
    if (((USHORT *)ip)[ 0 ]  != ((USHORT *)&cs->cs_ip)[ 0 ]  ||
        ((USHORT *)ip)[ 3 ]  != ((USHORT *)&cs->cs_ip)[ 3 ]  ||
        ((USHORT *)ip)[ 4 ]  != ((USHORT *)&cs->cs_ip)[ 4 ]  ||
        (tcpLen           != cs->cs_tcpLen)                ||
        ((ipLen  > 20) && memcmp(ip+1, &(cs->cs_ip) +1, ipLen  - 20)) ||
        ((tcpLen > 20) && memcmp(tcp+1,  cs->cs_tcp +1, tcpLen - 20)) ) 
    {
		DEBUGMSG(ZONE_VJ, (L"PPP: TX VJ slot %x Header changed, uncompressed\n", cs->cs_id));
        goto uncompressed;
    }

    // Figure out which of the changing fields changed.  The receiver
    // expects changes in the order: urgent, window, ack, seq.
         
    if (tcp->tcp_flags & TCP_FLAG_URG) 
    {
        deltaS = ntohs(tcp->tcp_urgent);
        ENCODEZ(deltaS);
        changes |= NEW_U;
    } 
    else if (tcp->tcp_urgent != cs->cs_tcp->tcp_urgent)
    {
        // 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.
              
		DEBUGMSG(ZONE_VJ, (L"PPP: TX VJ slot %x URG not set but urp changed, uncompressed\n", cs->cs_id));
        goto uncompressed;
    }

    // Window size change

    deltaW = ntohs(tcp->tcp_window) - ntohs(cs->cs_tcp->tcp_window);
    if (deltaW)
    {
        ENCODE(deltaW);
        changes |= NEW_W;
    }

    // Ack changes

    deltaA = ntohl(tcp->tcp_ack) - ntohl(cs->cs_tcp->tcp_ack);
    if (deltaA > 0xffff)
	{
		DEBUGMSG(ZONE_VJ, (L"PPP: TX VJ slot %x deltaA %x > 0xffff, uncompressed\n", cs->cs_id, deltaA));
        goto uncompressed;
	}
	if (deltaA)
    {
        ENCODE(deltaA);
        changes |= NEW_A;
    }

    // Sequence # changes

    deltaS = ntohl(tcp->tcp_seq) - ntohl(cs->cs_tcp->tcp_seq);
    if (deltaS > 0xffff)
	{
		DEBUGMSG(ZONE_VJ, (L"PPP: TX VJ slot %x tcp_seq deltaS %x > 0xffff, uncompressed\n", cs->cs_id, deltaS));
        goto uncompressed;
	}
	if (deltaS)
	{
        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->iph_length != cs->cs_ip.iph_length)  &&
            (ntohs(cs->cs_ip.iph_length) == totalLen))        
        {
            break;
        }

        // (fall through) 

    case SPECIAL_I:
    case SPECIAL_D:
        
        // Actual changes match one of our special case encodings --
        // send packet uncompressed.
              
		DEBUGMSG(ZONE_VJ, (L"PPP: TX VJ slot %x special case or retransmit (changes=%x), uncompressed\n", cs->cs_id, changes));
        goto uncompressed;
        break;

    case NEW_S | NEW_A:

         if (deltaS == deltaA &&
             deltaS == (u_int)(ntohs(cs->cs_ip.iph_length) - totalLen)) 
         {
			// special case for echoed terminal traffic 

            changes = SPECIAL_I;
            cp = new_seq;
         }
         break;

    case NEW_S:

         if (deltaS == (u_int)(ntohs(cs->cs_ip.iph_length) - totalLen)) 
         {
			// special case for data xfer 

			changes = SPECIAL_D;
			cp = new_seq;
         }
         break;
    }


    deltaS = ntohs(ip->iph_id) - ntohs(cs->cs_ip.iph_id);

    if (deltaS != 1) 
    {
        ENCODEZ(deltaS);
        changes |= NEW_I;
    }

    if (tcp->tcp_flags & TCP_FLAG_PUSH)
    {
        changes |= TCP_PUSH_BIT;
    }

    // Save the cksum before we overwrite it below. 
    // Then update our state with this packet's header.

    orig_xsum = ntohs(tcp->tcp_xsum);

    // Save connection's state

    CTEMemCopy(&cs->cs_ip, ip, ipLen + tcpLen);
    cs->cs_tcp    = (struct TCPHeader *)(cs->slcs_u.hdr + ipLen);        
    cs->cs_ipLen  = ipLen;
    cs->cs_tcpLen = tcpLen;

    // 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.  totalLen is how many bytes
    // of the original packet to toss so subtract the two to get the new
    // packet size.

    newHdrLen = cp - new_seq;                   // compute new header length
    cp = (BYTE *)ip;

    if ((0 == (comp->flags & SLF_ENABLE_SLOTID_COMPRESSION_TX)) || (comp->last_xmit != cs->cs_id)) 
    {
        // Add compressed header with cid

         comp->last_xmit = cs->cs_id;

         totalLen -= newHdrLen + 4;             // adjust total header size
         cp += totalLen;                        // update start of packet
		 changes |= NEW_C;
         *cp++ = changes;                       // add change mask + cid flag 
         *cp++ = cs->cs_id;                     // add cid
    } 
    else 
    {
        // Add compressed header 

         totalLen -= newHdrLen + 3;             // adjust total header size
         cp += totalLen;                        // update start of packet
         *cp++ = changes;                       // add change mask
    }

	DEBUGMSG(ZONE_VJ, (L"PPP: TX VJ slot %x %c%c%c%c%c%c deltaS=%d deltaA=%d, deltaW=%d\n", cs->cs_id, DEBUG_OUTPUT_CHANGES(changes), deltaS, deltaA, deltaW));

    *cp++ = orig_xsum >> 8;                     // Put back the checksum
    *cp++ = orig_xsum;

    CTEMemCopy(cp, new_seq, newHdrLen);       // Copy in the new header 

    // Update TX buffer elements 

    pPacket->CurrentLength -= totalLen;
    (BYTE *)pPacket->CurrentBuffer += totalLen;

    return PPP_PROTOCOL_COMPRESSED_TCP;              // packet is compressed


uncompressed: //---------------------------------------------------------------

    // 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).

    // Save connection's state

    CTEMemCopy(&cs->cs_ip, ip, ipLen + tcpLen);
    cs->cs_tcp    = (struct TCPHeader *)(cs->slcs_u.hdr + ipLen);        
    cs->cs_ipLen  = ipLen;
    cs->cs_tcpLen = tcpLen;

    // Update the protocol field with the 'conversation id'

    ip->iph_protocol = cs->cs_id;

    // Save this id as the last

    comp->last_xmit = cs->cs_id;

    return PPP_PROTOCOL_UNCOMPRESSED_TCP;
}

//   A.3  Decompression
//
//   This routine decompresses a received packet.  It is called with a
//   pointer to the packet, the packet length and type, and a pointer to the
//   compression state structure for the incoming serial line.  It returns a
//   pointer to the resulting packet or zero if there were errors in the
//   incoming packet.  If the packet is COMPRESSED_TCP or UNCOMPRESSED_TCP,
//   the compression state will be updated.
//
//   The new packet will be constructed in-place.  That means that 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 will be
//   aligned on a 32-bit boundary.
//
//   NOTE: The received packet is NOT necessarily even aligned. All access
//         must take this into account.

BOOL
sl_update_tcp(
	IN      BYTE         *bufp,
	IN      DWORD         len,
	IN OUT  slcompress_t *comp)
//
//  Handle an PPP_PROTOCOL_UNCOMPRESSED_TCP packet header used to update our state.
//
//  The TCP/IP header of a VJUIP packet will be unmodified except for the IPHeader
//  iph_protocol field which the sender will have changed from 0x06 (TCP) to the
//  index of the state element to be updated. This function will
//  restore the protocol field to 0x06.
//
//  If the packet is invalid return FALSE. If it is valid return TRUE.
//
{
	u_int               hlen;
	struct IPHeader     *ip;
	cstate_t            *cs;
	BYTE                iState;

    // Locate the saved state for this connection.  If the state
    // index is legal, clear the 'discard' flag.

	if (len < sizeof(struct IPHeader))
		return FALSE;

	ip = (struct IPHeader *)bufp;
	hlen = IpHdrLen(ip);

	if (hlen + sizeof(TCPHeader) > len)
		return FALSE;

    hlen += TcpHdrLen((TCPHeader *)(((BYTE *)ip) + hlen));
	if (hlen > len)
		return FALSE;

	iState = ip->iph_protocol;
    if (iState >= MAX_STATES) 
        return FALSE;

	if (iState >= comp->MaxStatesRx)
	{
		DEBUGMSG(ZONE_WARN, (L"PPP: WARNING - Peer sent VJ uncompressed packet slot=%u > negotiated max=%u\n", iState, comp->MaxStatesRx - 1));
	}

	DEBUGMSG(ZONE_VJ, (L"PPP: RX VJ slot %x uncompressed\n", iState));

	comp->last_recv = iState;
    cs = &comp->rstate[ iState ];

    comp->LastRxFrameBad = FALSE;

    // Restore the IP protocol field then save a copy of this 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->iph_protocol = IPPROTO_TCP;

    CTEMemCopy(&cs->cs_ip, ip, hlen);

    cs->cs_ip.iph_xsum = 0;
    cs->cs_hlen = hlen;

	return TRUE;
}

BYTE *
sl_uncompress_tcp(
	IN      BYTE         *bufp,
	IN OUT  DWORD        *lenp,
	IN OUT  slcompress_t *comp)
//
//  Handle an PPP_PROTOCOL_COMPRESSED_TCP packet header.
//
//  Returns a pointer to the uncompressed packet header if successful,
//  NULL if it fails.
//
//  Format of compressed header:
//		BYTE    Changes
//		BYTE    StateIndex (present iff NEW_C is set in Changes)
//      BYTE[2] TCPChecksum
// 
{
	BYTE                *cp;
	cstate_t            *cs;
	struct TCPHeader    *th;
	u_int               hlen;
	u_int               changes;
	DWORD               cbBuf = *lenp;
	USHORT              cbData,
						cbPacket,
						cbUserDataInLastPacket;
	PBYTE               pBufEnd = bufp + cbBuf;
	BYTE                iState;
	USHORT              IpIdIncrement;
	USHORT              tcp_flags;

    // Compressed packet - set frame pointer

    cp = bufp;

	if (cp >= pBufEnd)
		goto bad;
    changes = *cp++;

    if (changes & NEW_C) 
    {
		if (cp >= pBufEnd)
			goto bad;
		iState = *cp++;

        // Make sure the state index is in range, then grab the state. 
        // If we have a good state index, clear the 'discard' flag.

        if (iState >= MAX_STATES)
		{
			DEBUGMSG(ZONE_WARN, (L"PPP: WARNING - Peer sent VJ compressed packet slot=%u >= MAX_STATES(%u)\n", iState, MAX_STATES));
            goto bad;
		}

        if (iState >= comp->MaxStatesRx)
		{
			// Since we allocated MAX_STATES slots, we can handle this slotID. However, the peer
			// is technically in violation of the negotiated value so log a debug message.
			DEBUGMSG(ZONE_WARN, (L"PPP: WARNING - Peer sent VJ compressed packet slot=%u >= negotiated max=%u\n", iState, comp->MaxStatesRx));
		}

		comp->LastRxFrameBad = FALSE;
        comp->last_recv = iState;
    } 
    else 
    {
		DEBUGMSG(ZONE_WARN && (!(comp->flags & SLF_ENABLE_SLOTID_COMPRESSION_RX)), (L"PPP: RX VJ compressed slot ID, but we requested no slot ID compression\n"));

        // 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->LastRxFrameBad)
		{
			DEBUGMSG(ZONE_VJ, (L"PPP: RX VJ implicit state index but no prior state, toss\n"));
            return NULL;
		}

		iState = comp->last_recv;

		//
		// If no previous packet was received to initialize the last_recv
		// state index, then it will be 255 and this packet is invalid. However,
		// the LastRxFrameBad flag which was checked above should have been set at
		// init time, so we shouldn't get here.
		//
		ASSERT(iState < comp->MaxStatesRx);
    }

	DEBUGMSG(ZONE_VJ, (L"PPP: RX VJ slot %x %c%c%c%c%c%c\n", iState, DEBUG_OUTPUT_CHANGES(changes)));

    // Find the state then fill in the TCP checksum and PUSH bit.

    cs = &comp->rstate[iState];

⌨️ 快捷键说明

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