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

📄 vjcomp.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 3 页
字号:
    hlen = IpHdrLen(&cs->cs_ip);

    th = (struct TCPHeader *)&((BYTE *)&cs->cs_ip)[ hlen ];

	// cp[0] and cp[1] contain the new tcp xsum
	if ((cp +  1) >= pBufEnd)
		goto bad;

	memcpy(&th->tcp_xsum, cp, 2);
	cp += 2;

	tcp_flags = th->tcp_flags;
    tcp_flags &= ~TCP_FLAG_PUSH;
    if (changes & TCP_PUSH_BIT)
		tcp_flags |= TCP_FLAG_PUSH;

    // Fix up the state's ack, seq, urg and win fields based on the changemask.

	// The amount of user data in the last packet is calculated by
	// subtracting the TCP and IP header lengths from the IP total
	// length in the saved header. This value will be used in the
	// SPECIAL_I and SPECIAL_D cases below. We calculate it once here
	// to minimize size.
	cbUserDataInLastPacket = ntohs(cs->cs_ip.iph_length) - cs->cs_hlen;

    switch(changes & SPECIALS_MASK)
    {
    case SPECIAL_I:
		//
		// Terminal traffic special case
		// The amount of user data in the last packet is added to
		// both the TCP sequence number and ACK fields in the saved header.
		//
		th->tcp_ack = NetLongAdd(th->tcp_ack, cbUserDataInLastPacket);
        // FALLTHROUGH
	case SPECIAL_D:
		//
		// Unidirectional special case
		// The amount of user data in the last packet is added to
		// the TCP sequence number in the saved header.
		//
		th->tcp_seq = NetLongAdd(th->tcp_seq, cbUserDataInLastPacket);
        break;

    default:
       tcp_flags &= ~TCP_FLAG_URG;
       if (changes & NEW_U) 
        {
            tcp_flags |= TCP_FLAG_URG;
			th->tcp_urgent = NetShortAddCompressed(&cp, pBufEnd, 0);
        } 

        if (changes & NEW_W)
			th->tcp_window = NetShortAddCompressed(&cp, pBufEnd, th->tcp_window);

        if (changes & NEW_A)
			th->tcp_ack = NetLongAddCompressed(&cp, pBufEnd, th->tcp_ack);

        if (changes & NEW_S)
			th->tcp_seq = NetLongAddCompressed(&cp, pBufEnd, th->tcp_seq);
        break;
    }

	th->tcp_flags = tcp_flags;

	//
    // Update the IP ID, by default it will increment by 1, but if the
	// NEW_I flag was set in the changes byte then it increments by the
	// amount encoded in the packet as a compressed value.
	//
	IpIdIncrement = 1;
    if (changes & NEW_I)
		IpIdIncrement = CompressedValueGet(&cp, pBufEnd);
	cs->cs_ip.iph_id = NetShortAdd(cs->cs_ip.iph_id, IpIdIncrement);

	if (cp > pBufEnd)
	{
		// 
		// The VJ compressed header was too short / incomplete.
		//
#ifdef DEBUG
		if (ZONE_WARN)
		{
			DEBUGMSG(1, (L"PPP: WARNING - Incomplete VJ header received, discarding packet\n"));
			DumpMem(bufp, cp - bufp);
		}
#endif
		goto bad;
	}

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

	cbData = pBufEnd - cp;

	// If data is not DWORD aligned, then copy it down 1-3 bytes to where it is aligned

    if ((int)cp & 3) 
    {
		// Perform safe overlapping copy
        memmove((BYTE *)((int)cp & ~3), cp, cbData);    
		cp = (BYTE *)((int)cp & ~3);
    }

	// Now fill in the TCP/IP header in front of the data
    cp = cp - cs->cs_hlen;
    cbPacket = cs->cs_hlen + cbData;
	*lenp = cbPacket;
    cs->cs_ip.iph_length = (USHORT) htons(cbPacket);

    memcpy(cp, &cs->cs_ip, cs->cs_hlen);

    // Recompute the ip header checksum 

    {
        USHORT *bp = (USHORT *)cp;

        for(changes = 0; hlen > 0; hlen -= 2, bp++)
		{
			changes = changes + *bp;
		}
        changes = (changes & 0xffff) + (changes >> 16);
        changes = (changes & 0xffff) + (changes >> 16);
        ((struct IPHeader *)cp)->iph_xsum = ~changes;
    }
    return cp;


bad://--------------------------------------------------------------------------
    // Bad Packet

    comp->LastRxFrameBad = TRUE;
    return NULL;
}

// Initialization
//
// This routine initializes the state structure for both the transmit and
// receive halves of some serial line.  It must be called each time the
// line is brought up.

void
sl_compress_init(
	OUT	slcompress_t *comp,
	IN  BYTE          MaxStatesRx,
	IN  BYTE          MaxStatesTx,
	IN  BOOL          CompressSlotIdsRx,
	IN  BOOL          CompressSlotIdsTx)
{
    u_int i;
    cstate_t *tstate = comp->tstate;

    // Reset the compression record 

    CTEMemSet((char *) comp, 0, sizeof(slcompress_t));

	if (MaxStatesRx > MAX_STATES)
		MaxStatesRx = MAX_STATES;

	if (MaxStatesTx > MAX_STATES)
		MaxStatesTx = MAX_STATES;

    // Link the transmit states into a circular list.

    for(i = MaxStatesTx - 1; i > 0; --i) 
    {
         tstate[i].cs_id   = i;
         tstate[i].cs_next = &tstate[ i-1 ];
    }

    tstate[0].cs_next = &tstate[ MaxStatesTx - 1 ];
    tstate[0].cs_id   = 0;
    comp->last_cs     = &tstate[ 0 ];

    // Make sure we don't accidentally do CID compression
    // (assumes MAX_STATES < 255).
         
    comp->last_recv = 255;
    comp->last_xmit = 255;

	comp->LastRxFrameBad = TRUE;
	if (CompressSlotIdsRx)
		comp->flags |= SLF_ENABLE_SLOTID_COMPRESSION_RX;
	if (CompressSlotIdsTx)
		comp->flags |= SLF_ENABLE_SLOTID_COMPRESSION_TX;

	comp->MaxStatesTx = MaxStatesTx;
	comp->MaxStatesRx = MaxStatesRx;
}

/*
   A.5  Berkeley Unix dependencies

   Note:  The following is of interest only if you are trying to bring the
   sample code up on a system that is not derived from 4BSD (Berkeley
   Unix).

   The code uses the normal Berkeley Unix header files (from
   /usr/include/netinet) for definitions of the structure of IP and TCP
   headers.  The structure tags tend to follow the protocol RFCs closely
   and should be obvious even if you do not have access to a 4BSD
   system./48/

   ----------------------------
    48. In the event they are not obvious, the header files (and all the
   Berkeley networking code) can be anonymous ftp'd from host


   The macro BCOPY(src, dst, amt) is invoked to copy amt bytes from src to
   dst.  In BSD, it translates into a call to bcopy.  If you have the
   misfortune to be running System-V Unix, it can be translated into a call
   to memcpy.  The macro OVBCOPY(src, dst, amt) is used to copy when src
   and dst overlap (i.e., when doing the 4-byte alignment copy).  In the
   BSD kernel, it translates into a call to ovbcopy.  Since AT&T botched
   the definition of memcpy, this should probably translate into a copy
   loop under System-V.

   The macro BCMP(src, dst, amt) is invoked to compare amt bytes of src and
   dst for equality.  In BSD, it translates into a call to bcmp.  In
   System-V, it can be translated into a call to memcmp or you can write a
   routine to do the compare.  The routine should return zero if all bytes
   of src and dst are equal and non-zero otherwise.

   The routine ntohl(dat) converts (4 byte) long dat from network byte
   order to host byte order.  On a reasonable cpu this can be the no-op
   macro:
                           #define ntohl(dat) (dat)

   On a Vax or IBM PC (or anything with Intel byte order), you will have to
   define a macro or routine to rearrange bytes.

   The routine ntohs(dat) is like ntohl but converts (2 byte) shorts
   instead of longs.  The routines htonl(dat) and htons(dat) do the inverse
   transform (host to network byte order) for longs and shorts.

   A struct mbuf is used in the call to sl_compress_tcp because that
   routine needs to modify both the start address and length if the
   incoming packet is compressed.  In BSD, an mbuf is the kernel's buffer
   management structure.  If other systems, the following definition should
   be sufficient:

struct mbuf 
{
    BYTE  *m_off;     // pointer to start of data 
    int     m_len;      // length of dat
};


#define mtod(m, t) ((t)(m->m_off))

   ----------------------------
   ucbarpa.berkeley.edu, files pub/4.3/tcp.tar and pub/4.3/inet.tar.
   ----------------------------

   B  Compatibility with past mistakes

   When combined with the modern PPP serial line protocol[9], the use of
   header compression is automatic and invisible to the user.
   Unfortunately, many sites have existing users of the SLIP described in
   [12] which doesn't allow for different protocol types to distinguish
   header compressed packets from IP packets or for version numbers or an
   option exchange that could be used to automatically negotiate header
   compression.

   The 
   to interoperate with the existing servers and clients.  Note that these
   are hacks for compatibility with past mistakes and should be offensive
   to any right thinking person.  They are offered solely to ease the pain
   of running SLIP while users wait patiently for vendors to release PPP.


   B.1  Living without a framing `type' byte

   The bizarre packet type numbers in sec. A.1 were chosen to allow a
   `packet type' to be sent on lines where it is undesirable or impossible
   to add an explicit type byte.  Note that the first byte of an IP packet
   always contains `4' (the IP protocol version) in the top four bits.  And
   that the most significant bit of the first byte of the compressed header
   is ignored.  Using the packet types in sec. A.1, the type can be encoded
   in the most significant bits of the outgoing packet using the code

                    p->dat[0] |= sl_compress_tcp(p, comp);

    and decoded on the receive side by

                  if (p->dat[0] & 0x80)
                          type = TYPE_COMPRESSED_TCP;
                  else if (p->dat[0] >= 0x70) {
                          type = TYPE_UNCOMPRESSED_TCP;
                          p->dat[0] &=~ 0x30;
                  } else
                          type = TYPE_IP;
                  status = sl_uncompress_tcp(p, type, comp);


   B.2  Backwards compatible SLIP servers

   The SLIP described in [12] doesn't include any mechanism that could be
   used to automatically negotiate header compression.  It would be nice to
   allow users of this SLIP to use header compression but, when users of
   the two SLIP varients share a common server, it would be annoying and
   difficult to manually configure both ends of each connection to enable
   compression.  The following procedure can be used to avoid manual
   configuration.

   Since there are two types of dial-in clients (those that implement
   compression and those that don't) but one server for both types, it's
   clear that the server will be reconfiguring for each new client session
   but clients change configuration seldom if ever.  If manual
   configuration has to be done, it should be done on the side that changes
   infrequently --- the client.  This suggests that the server should
   somehow learn from the client whether to use header compression.
   Assuming symmetry (i.e., if compression is used at all it should be used
   both directions) the server can use the receipt of a compressed packet
   from some client to indicate that it can send compressed packets to that
   client.  This leads to the following algorithm:

   There are two bits per line to control header compression:  allowed and
   on.  If on is set, compressed packets are sent, otherwise not.  If
   allowed is set, compressed packets can be received and, if an
   UNCOMPRESSED_TCP packet arrives when on is clear, on will be set./49/
   If a compressed packet arrives when allowed is clear, it will be
   ignored.

   Clients are configured with both bits set (allowed is always set if on
   is set) and the server starts each session with allowed set and on
   clear.  The first compressed packet from the client (which must be a
   UNCOMPRESSED_TCP packet) turns on compression for the server.


   ----------------------------
    49. Since [12] framing doesn't include error detection, one should be
   careful not to `false trigger' compression on the server.  The
   UNCOMPRESSED_TCP packet should checked for consistency (e.g., IP
   checksum correctness) before compression is enabled.  Arrival of
   COMPRESSED_TCP packets should not be used to enable compression.
   ----------------------------


   As noted in sec. 3.2.2, easily detected patterns exist in the stream of
   compressed headers, indicating that more compression could be done.
   Would this be worthwhile?

   The average compressed datagram has only seven bits of header./50/  The
   framing must be at least one bit (to encode the `type') and will
   probably be more like two to three bytes.  In most interesting cases
   there will be at least one byte of data.  Finally, the end-to-end
   check---the TCP checksum---must be passed through unmodified./51/

   The framing, data and checksum will remain even if the header is
   completely compressed out so the change in average packet size is, at
   best, four bytes down to three bytes and one bit --- roughly a 25%
   improvement in delay./52/  While this may seem significant, on a 2400
   bps line it means that typing echo response takes 25 rather than 29 ms.
   At the present stage of human evolution, this difference is not
   detectable.

   However, the 
   scheme for a very special case data-acquisition problem:  We had an
   instrument and control package floating at 200KV, communicating with
   ground level via a telemetry system.  For many reasons (multiplexed
   communication, pipelining, error recovery, availability of well tested
   implementations, etc.), it was convenient to talk to the package using
   TCP/IP. However, since the primary use of the telemetry link was data
   acquisition, it was designed with an uplink channel capacity <0.5% the
   downlink's.  To meet application delay budgets, data packets were 100
   bytes and, since TCP acks every other packet, the relative uplink
   bandwidth for acks is a/200 where `a' is the total size of ack packets.
   Using the scheme in this paper, the smallest ack is four bytes which
   would imply an uplink bandwidth 2% of the downlink.  This wasn't

   ----------------------------
    50. Tests run with several million packets from a mixed traffic load
   (i.e., statistics kept on a year's traffic from my home to work) show
   that 80% of packets use one of the two special encodings and, thus, the
   only header is the change mask.
    51. If someone tries to sell you a scheme that compresses the TCP
   checksum `Just say no'.  Some poor fool has yet to have the sad
   experience that reveals the end-to-end argument is gospel truth.  Worse,
   since the fool is subverting your end-to-end error check, you may pay
   the price for this education and they will be none the wiser.  What does
   it profit a man to gain two byte times of delay and lose peace of mind?
    52. Note again that we must be concerned about interactive delay to be
   making this argument:  Bulk data transfer performance will be dominated
   by the time to send the data and the difference between three and four
   byte headers on a datagram containing tens or hundreds of data bytes is,
   practically, no difference.
   ----------------------------

   possible so we used the scheme described in footnote 15:  If the first
   bit of the frame was one, it meant `same compressed header as last
   time'.  Otherwise the next two bits gave one of the types described in
   sec. 3.2.  Since the link had excellent forward error correction and
   traffic made only a single hop, the TCP checksum was compressed out
   (blush!) of the `same header' packet types/53/ so the total header size
   for these packets was one bit.  Over several months of operation, more
   than 99% of the 40 byte TCP/IP headers were compressed down to one
   bit./54/

   ----------------------------
    53. The checksum was re-generated in the decompressor and, of course,
   the `toss' logic was made considerably more aggressive to prevent error
   propagation.
    54. We have heard the suggestion that `real-time' needs require
   abandoning TCP/IP in favor of a `light-weight' protocol with smaller
   headers.  It is difficult to envision a protocol that averages less than
   one header bit per packet.
   ----------------------------
*/

⌨️ 快捷键说明

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