private void AddFragment(IPAddress address, int id, int offset, int length)
        {
            if (!m_fragmentedBuffers.ContainsKey(address))
            {
                m_fragmentedBuffers.Add(address, new SortedList <int, byte[]>());
            }

            m_fragmentedBuffers[address].Add(id, new byte[length]);

            W2MarshalHelper.BufferCopy(m_buffer, offset, m_fragmentedBuffers[address][id], 0, length);

            m_totalFragmentsSize += length;
        }
        private byte[] ConsolidateFragments(IPAddress address)
        {
            if (!m_fragmentedBuffers.ContainsKey(address))
            {
                return(null);
            }

            // Sort based on ipheader id
            m_fragmentedBuffers[address].OrderBy(kvp => kvp.Key);

            // Gets the length of all the fragments together
            var totalLength   = m_fragmentedBuffers[address].Sum(kvp => kvp.Value.Length);
            var buffer        = new byte[totalLength];
            var currentOffset = 0;

            foreach (var kvp in m_fragmentedBuffers[address])
            {
                W2MarshalHelper.BufferCopy(kvp.Value, 0, buffer, currentOffset, kvp.Value.Length);
                currentOffset += kvp.Value.Length;
            }

            return(buffer);
        }
        protected unsafe override void ProcessReceivedMessage(
            IPHeader ipHeader, TCPHeader tcpHeader, byte *data, int dataOffset, int dataLength)
        {
            // OK, get the packet direction.
            var direction = GetDirection(ipHeader, tcpHeader);

            // OK, get the right address according to the direction.
            var address = GetAddress(direction, ipHeader);

            // Start the fight!
            if (dataLength <= 0)
            {
                return;
            }
            else if (dataLength == 4) // Hand-shake packet.
            {
                var helloPacket = *(uint *)&data[dataOffset];
                if (helloPacket == 0x1F11F311)
                {
                    return;
                }
            }
            else if (dataLength < PacketHeaderSize) // Not a valid 12-byte header.
            {
                return;
            }
            else // Data >= sizeof(PacketHeader)
            {
                if (m_isFragmenting) // Is a fragment
                {
                    // If the received length is less than the first fragment length
                    // and the total fragments can carry at least 1 full header specified message
                    if (dataLength < m_firstFragmentSize &&
                        (m_totalFragmentsSize + dataLength) >= m_fragmentHeaderSize)
                    { // Add the last fragment to the list
                        AddFragment(address, ipHeader.Id, dataOffset, dataLength);
                        // Consolidate the message into a single buffer.
                        var msgBuffer = ConsolidateFragments(address);

                        if (msgBuffer == null)
                        {
                            return;
                        }

                        var remaining     = msgBuffer.Length;
                        var currentOffset = 0;

                        fixed(byte *pMsgBuffer = msgBuffer)
                        {   // We need a do-while loop, because we may get two messages
                            // glued together by tcp-fragmentation.
                            do
                            {
                                var pSize = *(ushort *)&pMsgBuffer[currentOffset];

                                W2PacketSecurity.Decrypt(pMsgBuffer, pSize, currentOffset);

                                var pHeader = PacketHeader.Parse(&pMsgBuffer[currentOffset]);

                                remaining -= pSize;

                                // Creates a new buffer, with only the current packet.
                                // This ensures that we will not use the same underlyng buffer
                                // because this buffer will be stored by the forms...
                                byte[] packetBuffer = new byte[pSize];

                                W2MarshalHelper.BufferCopy(msgBuffer, currentOffset, packetBuffer, 0, pSize);

                                PacketReceived.Raise(this, new W2PacketEventArgs(pHeader, direction, ipHeader,
                                                                                 tcpHeader, packetBuffer));

                                currentOffset += pSize;
                            } while (remaining >= PacketHeaderSize);
                        }

                        m_isFragmenting      = false;
                        m_fragmentHeaderSize = 0;
                        m_totalFragmentsSize = 0;
                        m_fragmentedBuffers[address].Clear();
                        return;
                    }
                    else
                    {
                        AddFragment(address, ipHeader.Id, dataOffset, dataLength);
                        return;
                    }
                }

                if (dataLength == 120)
                {
                    var helloPacket = *(uint *)&data[dataOffset];
                    if (helloPacket == 0x1F11F311)
                    {
                        dataOffset += 4;
                    }
                }

                // Gets the first ushort, which is supposed to carry the size of the packet.
                var headerSize = *(ushort *)&data[dataOffset];
                // Not a valid packet size.
                if (headerSize < PacketHeaderSize || headerSize > MaxPacketSize)
                {
                    return;
                }

                if (headerSize > dataLength) // The packet will be fragmented.
                {
                    AddFragment(address, ipHeader.Id, dataOffset, dataLength);
                    m_isFragmenting      = true;
                    m_firstFragmentSize  = dataLength;
                    m_fragmentHeaderSize = headerSize;
                    return;
                }
                else // No Fragmentation...
                {
                    var remaining     = dataLength;
                    var currentOffset = dataOffset;

                    do
                    {
                        var pSize = *(ushort *)&data[currentOffset];

                        W2PacketSecurity.Decrypt(data, pSize, currentOffset);

                        var pHeader = PacketHeader.Parse(&data[currentOffset]);

                        remaining -= pSize;

                        // Creates a temp. buffer for the handler.
                        byte[] packetBuffer = new byte[pSize];

                        W2MarshalHelper.BufferCopy(m_buffer, currentOffset, packetBuffer, 0, pSize);

                        PacketReceived.Raise(this, new W2PacketEventArgs(pHeader, direction, ipHeader, tcpHeader,
                                                                         packetBuffer));

                        currentOffset += pSize;
                    } while (remaining >= PacketHeaderSize);
                }
            }
        }