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; }
/// <summary> /// Parses a buffer containing the TCP Header data. /// </summary> /// <param name="buffer">The unsafe pointer to the first element of the buffer.</param> /// <returns>A new TCPHeader object.</returns> public static unsafe TCPHeader ParseTCPHeader(byte *buffer) { var tcpHeader = new TCPHeader(); tcpHeader.SourcePort = (ushort)IPAddress.NetworkToHostOrder(*(short *)&buffer[0]); tcpHeader.DestinationPort = (ushort)IPAddress.NetworkToHostOrder(*(short *)&buffer[2]); tcpHeader.SequenceNumber = (uint)IPAddress.NetworkToHostOrder(*(int *)&buffer[4]); tcpHeader.AcknowledgmentNumber = (uint)IPAddress.NetworkToHostOrder(*(int *)&buffer[8]); var dataOffsetAndFlags = (ushort)IPAddress.NetworkToHostOrder(*(short *)&buffer[12]); tcpHeader.Window = (ushort)IPAddress.NetworkToHostOrder(*(short *)&buffer[14]); tcpHeader.Checksum = (ushort)IPAddress.NetworkToHostOrder(*(short *)&buffer[16]); tcpHeader.UrgentPointer = (ushort)IPAddress.NetworkToHostOrder(*(short *)&buffer[18]); tcpHeader.Length = ((dataOffsetAndFlags >> 12) * 4); var flags = dataOffsetAndFlags & 0x3F; if ((flags & 0x01) != 0) { tcpHeader.Flags |= TCPFlags.FIN; } if ((flags & 0x02) != 0) { tcpHeader.Flags |= TCPFlags.SYN; } if ((flags & 0x04) != 0) { tcpHeader.Flags |= TCPFlags.RST; } if ((flags & 0x08) != 0) { tcpHeader.Flags |= TCPFlags.PSH; } if ((flags & 0x10) != 0) { tcpHeader.Flags |= TCPFlags.ACK; } if ((flags & 0x20) != 0) { tcpHeader.Flags |= TCPFlags.URG; } return(tcpHeader); }
protected abstract unsafe void ProcessReceivedMessage( IPHeader ipHeader, TCPHeader tcpHeader, byte *data, int dataOffset, int dataLength);
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); } } }