Exemplo n.º 1
0
        private unsafe void OnMessageReceived(int receivedLength)
        {
            if (receivedLength < (IPHeader.MinimumIPHeaderSize + TCPHeader.MinimumTCPHeaderSize))
                return;

            fixed(byte *pBuffer = m_buffer)
            {
                var ipHeader = IPHeader.ParseIPHeader(pBuffer);

                if (ipHeader.Protocol != IPProtocol.TCP)
                {
                    return;
                }

                if (m_filterAddress)
                {
                    if (ipHeader.DestinationAddress != m_address ||
                        ipHeader.SourceAddress != m_address)
                    {
                        return;
                    }
                }

                var tcpHeader = TCPHeader.ParseTCPHeader(&pBuffer[ipHeader.Length]);

                if (tcpHeader.SourcePort == m_port || tcpHeader.DestinationPort == m_port)
                {
                    var offset = ipHeader.Length + tcpHeader.Length;

                    var length = receivedLength - offset;

                    ProcessReceivedMessage(ipHeader, tcpHeader, pBuffer, offset, length);
                }
            }
        }
 private PacketDirection GetDirection(IPHeader ipHeader, TCPHeader tcpHeader)
 {
     if (m_filterAddress)
     {
         if (ipHeader.DestinationAddress.Equals(m_address) && tcpHeader.DestinationPort == m_port)
         {
             return(PacketDirection.Outgoing);
         }
         else if (ipHeader.SourceAddress.Equals(m_address) && tcpHeader.SourcePort == m_port)
         {
             return(PacketDirection.Incoming);
         }
     }
     else
     {
         if (tcpHeader.DestinationPort == m_port)
         {
             return(PacketDirection.Outgoing);
         }
         else if (tcpHeader.SourcePort == m_port)
         {
             return(PacketDirection.Incoming);
         }
     }
     return(PacketDirection.Unknown);
 }
 public W2PacketEventArgs(PacketHeader packetHeader, PacketDirection direction, IPHeader ipHeader,
                          TCPHeader tcpHeader, byte[] buffer)
 {
     PacketHeader = packetHeader;
     Direction    = direction;
     IPHeader     = ipHeader;
     TCPHeader    = tcpHeader;
     Buffer       = buffer;
 }
        private IPAddress GetAddress(PacketDirection direction, IPHeader ipHeader)
        {
            IPAddress address;

            if (direction == PacketDirection.Incoming)
            {
                address = ipHeader.SourceAddress;
            }
            else if (direction == PacketDirection.Outgoing)
            {
                address = ipHeader.DestinationAddress;
            }
            else
            {
                address = IPAddress.Any;
            }

            return(address);
        }
Exemplo n.º 5
0
 protected abstract unsafe void ProcessReceivedMessage(
     IPHeader ipHeader, TCPHeader tcpHeader, byte *data, int dataOffset, int dataLength);
Exemplo n.º 6
0
        /// <summary>
        /// Parses a buffer containing the IPHeader data.
        /// </summary>
        /// <param name="buffer">The unsafe pointer to the first element of the buffer.</param>
        /// <returns>A new IPHeader object.</returns>
        public unsafe static IPHeader ParseIPHeader(byte *buffer)
        {
            var header             = new IPHeader();
            var ipVersionAndLength = buffer[0];

            header.TypeOfService  = buffer[1];
            header.TotalLength    = (ushort)IPAddress.NetworkToHostOrder(*(short *)&buffer[2]);
            header.Id             = (ushort)IPAddress.NetworkToHostOrder(*(short *)&buffer[4]);
            header.FlagsAndOffset = (ushort)IPAddress.NetworkToHostOrder(*(short *)&buffer[6]);
            header.TTL            = buffer[8];
            var protocol = buffer[9];

            header.Checksum = (ushort)IPAddress.NetworkToHostOrder(*(short *)&buffer[10]);
            var sourceAddress      = *(uint *)&buffer[12];
            var destinationAddress = *(uint *)&buffer[16];

            header.SourceAddress      = new IPAddress(sourceAddress);
            header.DestinationAddress = new IPAddress(destinationAddress);

            if (protocol == 6)
            {
                header.Protocol = IPProtocol.TCP;
            }
            else if (protocol == 17)
            {
                header.Protocol = IPProtocol.UDP;
            }
            else
            {
                header.Protocol = IPProtocol.Unknown;
            }

            if ((ipVersionAndLength >> 4) == 4)
            {
                header.Version = IPVersion.IPv4;
            }
            else if ((ipVersionAndLength >> 4) == 6)
            {
                header.Version = IPVersion.IPv6;
            }
            else
            {
                header.Version = IPVersion.Unknown;
            }

            // get the last 4 bits
            ipVersionAndLength <<= 4;
            ipVersionAndLength >>= 4;
            ipVersionAndLength  *= 4;
            header.Length        = ipVersionAndLength;

            int flags = header.FlagsAndOffset >> 13;

            header.DontFragment  = (flags & 2) == 2;
            header.MoreFragments = (flags & 1) == 1;

            int offset = (header.FlagsAndOffset << 3);

            offset >>= 3;

            header.FragmentationOffset = offset;

            return(header);
        }
        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);
                }
            }
        }