+ Connection->State = TCP_ST_OPEN;
+ if(Header->Flags & TCP_FLAG_SYN) {
+ Connection->NextSequenceRcv = Header->SequenceNumber + 1;
+ }
+
+ // Get length of data
+ dataLen = Length - (Header->DataOffset>>4)*4;
+ Log("[TCP ] HandleConnectionPacket - dataLen = %i", dataLen);
+
+ if(Header->Flags & TCP_FLAG_ACK) {
+ // TODO: Process an ACKed Packet
+ Log("[TCP ] Conn %p, Packet 0x%x ACKed", Connection, Header->AcknowlegementNumber);
+ }
+
+ if(dataLen == 0) return ;
+
+ // NOTES:
+ // Flags
+ // PSH - Has Data?
+ // /NOTES
+
+ // Allocate and fill cached packet
+ pkt = malloc( dataLen + sizeof(tTCPStoredPacket) );
+ pkt->Next = NULL;
+ pkt->Sequence = ntohl(Header->SequenceNumber);
+ pkt->Length = dataLen;
+ memcpy(pkt->Data, (Uint8*)Header + (Header->DataOffset>>4)*4, dataLen);
+
+ // Is this packet the next expected packet?
+ if( pkt->Sequence != Connection->NextSequenceRcv )
+ {
+ tTCPStoredPacket *tmp, *prev = NULL;
+
+ Log("[TCP ] Out of sequence packet (0x%08x != 0x%08x)",
+ pkt->Sequence, Connection->NextSequenceRcv);
+
+ // No? Well, let's cache it and look at it later
+ LOCK( &Connection->lFuturePackets );
+ for(tmp = Connection->FuturePackets;
+ tmp;
+ prev = tmp, tmp = tmp->Next)
+ {
+ if(tmp->Sequence > pkt->Sequence) break;
+ }
+ if(prev)
+ prev->Next = pkt;
+ else
+ Connection->FuturePackets = pkt;
+ pkt->Next = tmp;
+ RELEASE( &Connection->lFuturePackets );
+ }
+ else
+ {
+ // Ooh, Goodie! Add it to the recieved list
+ TCP_INT_AppendRecieved(Connection, pkt);
+ Connection->NextSequenceRcv ++;
+
+ // TODO: This should be moved out of the watcher thread,
+ // so that a single lost packet on one connection doesn't cause
+ // all connections on the interface to lag.
+ TCP_INT_UpdateRecievedFromFuture(Connection);
+ }
+
+ // TODO: Check ACK code validity
+ Header->AcknowlegementNumber = ntohl(pkt->Sequence);
+ Header->SequenceNumber = ntohl(Connection->NextSequenceSend);
+ Header->Flags &= TCP_FLAG_SYN;
+ Header->Flags = TCP_FLAG_ACK;
+ TCP_SendPacket( Connection, sizeof(tTCPHeader), Header );
+}
+
+/**
+ * \brief Appends a packet to the recieved list
+ * \param Connection Connection structure
+ * \param Pkt Packet structure on heap
+ */
+void TCP_INT_AppendRecieved(tTCPConnection *Connection, tTCPStoredPacket *Pkt)
+{
+ LOCK( &Connection->lRecievedPackets );
+ if(Connection->RecievedPackets)
+ {
+ Connection->RecievedPacketsTail->Next = Pkt;
+ Connection->RecievedPacketsTail = Pkt;
+ }
+ else
+ {
+ Connection->RecievedPackets = Pkt;
+ Connection->RecievedPacketsTail = Pkt;
+ }
+ RELEASE( &Connection->lRecievedPackets );
+}
+
+/**
+ * \brief Updates the connections recieved list from the future list
+ * \param Connection Connection structure
+ *
+ * Updates the recieved packets list with packets from the future (out
+ * of order) packets list that are now able to be added in direct
+ * sequence.
+ */
+void TCP_INT_UpdateRecievedFromFuture(tTCPConnection *Connection)
+{
+ tTCPStoredPacket *pkt, *prev;
+ for(;;)
+ {
+ prev = NULL;
+ // Look for the next expected packet in the cache.
+ LOCK( &Connection->lFuturePackets );
+ for(pkt = Connection->FuturePackets;
+ pkt && pkt->Sequence < Connection->NextSequenceRcv;
+ prev = pkt, pkt = pkt->Next);
+
+ // If we can't find the expected next packet, stop looking
+ if(!pkt || pkt->Sequence > Connection->NextSequenceRcv) {
+ RELEASE( &Connection->lFuturePackets );
+ return;
+ }
+
+ // Delete packet from future list
+ if(prev)
+ prev->Next = pkt->Next;
+ else
+ Connection->FuturePackets = pkt->Next;
+
+ // Release list
+ RELEASE( &Connection->lFuturePackets );
+
+ // Looks like we found one
+ TCP_INT_AppendRecieved(Connection, pkt);
+ Connection->NextSequenceRcv ++;
+ }