/* NOTE: this function processes incoming frames and stores flags/data; the TcpStateMachine function processes stored flags, advances the state machine as necessary, and sends out responses */ internal void OnPacketReceived(UInt32 sourceIPAddress, UInt32 destinationIPAddress, byte[] buffer, Int32 index, Int32 count) { if (_isDisposed) { return; } if (count < TCP_HEADER_MIN_LENGTH) { return; } UInt16 packetHeaderChecksum = (UInt16)((((UInt16)buffer[index + 16]) << 8) + buffer[index + 17]); // calculate checksum to verify packet integrity. UInt16 calculateChecksum; lock (_tcpPseudoHeaderBufferLockObject) { // create temporary pseudo header _tcpPseudoHeaderBuffer[0] = (byte)((sourceIPAddress >> 24) & 0xFF); _tcpPseudoHeaderBuffer[1] = (byte)((sourceIPAddress >> 16) & 0xFF); _tcpPseudoHeaderBuffer[2] = (byte)((sourceIPAddress >> 8) & 0xFF); _tcpPseudoHeaderBuffer[3] = (byte)(sourceIPAddress & 0xFF); _tcpPseudoHeaderBuffer[4] = (byte)((destinationIPAddress >> 24) & 0xFF); _tcpPseudoHeaderBuffer[5] = (byte)((destinationIPAddress >> 16) & 0xFF); _tcpPseudoHeaderBuffer[6] = (byte)((destinationIPAddress >> 8) & 0xFF); _tcpPseudoHeaderBuffer[7] = (byte)(destinationIPAddress & 0xFF); _tcpPseudoHeaderBuffer[8] = 0; // ZERO _tcpPseudoHeaderBuffer[9] = (byte)IPv4Layer.ProtocolType.Tcp; // Protocol Number _tcpPseudoHeaderBuffer[10] = (byte)((count >> 8) & 0xFF); _tcpPseudoHeaderBuffer[11] = (byte)(count & 0xFF); // calculate checksum over entire pseudo-header, TCP header and data _checksumBufferArray[0] = _tcpPseudoHeaderBuffer; _checksumOffsetArray[0] = 0; _checksumCountArray[0] = TCP_PSEUDO_HEADER_LENGTH; _checksumBufferArray[1] = buffer; _checksumOffsetArray[1] = index; _checksumCountArray[1] = count; calculateChecksum = Utility.CalculateInternetChecksum(_checksumBufferArray, _checksumOffsetArray, _checksumCountArray, 2); } if (calculateChecksum != 0x0000) { return; // drop packet } // find the source and destination port #s for our packet (looking into the packet) UInt16 sourceIPPort = (UInt16)((((UInt16)buffer[index + 0]) << 8) + buffer[index + 1]); UInt16 destinationIPPort = (UInt16)((((UInt16)buffer[index + 2]) << 8) + buffer[index + 3]); TcpSocket socket = null; for (int i = 0; i < IPv4Layer.MAX_SIMULTANEOUS_SOCKETS; i++) { if ((IPv4Layer._sockets[i] != null) && (IPv4Layer._sockets[i].ProtocolType == IPv4Layer.ProtocolType.Tcp) && (IPv4Layer._sockets[i].SourceIPAddress == destinationIPAddress) && (IPv4Layer._sockets[i].SourceIPPort == destinationIPPort) && (IPv4Layer._sockets[i].DestinationIPAddress == sourceIPAddress) && (IPv4Layer._sockets[i].DestinationIPPort == sourceIPPort)) { socket = (TcpSocket)IPv4Layer._sockets[i]; socket.OnPacketReceived(sourceIPAddress, destinationIPAddress, buffer, index, count); break; } } /* TODO: if this packet is a request to connect to a listening port, pass it along now */ if (socket == null) { for (int i = 0; i < IPv4Layer.MAX_SIMULTANEOUS_SOCKETS; i++) { if ((IPv4Layer._sockets[i] != null) && (IPv4Layer._sockets[i].ProtocolType == IPv4Layer.ProtocolType.Tcp) && (IPv4Layer._sockets[i].SourceIPAddress == destinationIPAddress) && (IPv4Layer._sockets[i].SourceIPPort == destinationIPPort) && (((TcpSocket)IPv4Layer._sockets[i]).IsListening == true) ) { socket = (TcpSocket)IPv4Layer._sockets[i]; socket.OnPacketReceived(sourceIPAddress, destinationIPAddress, buffer, index, count); break; } } } /* if this packet is otherwise invalid, respond a TCP "RESET" packet */ if (socket == null) { /* send a TCP "RESET" packet */ UInt32 sequenceNumber = ((UInt32)buffer[index + 4] << 24) + ((UInt32)buffer[index + 5] << 16) + ((UInt32)buffer[index + 6] << 8) + (UInt32)buffer[index + 7]; UInt32 acknowledgmentNumber = ((UInt32)buffer[index + 8] << 24) + ((UInt32)buffer[index + 9] << 16) + ((UInt32)buffer[index + 10] << 8) + (UInt32)buffer[index + 11]; SendTcpSegment(destinationIPAddress, sourceIPAddress, destinationIPPort, sourceIPPort, acknowledgmentNumber, sequenceNumber, 0, false, false, true, false, false, null, new byte[] { }, 0, 0, Int64.MaxValue); } }