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); }
protected abstract unsafe void ProcessReceivedMessage( IPHeader ipHeader, TCPHeader tcpHeader, byte *data, int dataOffset, int dataLength);
/// <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); } } }