+ // Pre-init connection?
+ case TCP_ST_CLOSED:
+ Log_Log("TCP", "Packets to a closed connection?!");
+ break;
+
+ // --- Init States ---
+ // SYN sent, expecting SYN-ACK Connection Opening
+ case TCP_ST_SYN_SENT:
+ if( Header->Flags & TCP_FLAG_SYN )
+ {
+ Connection->NextSequenceRcv ++;
+ Header->DestPort = Header->SourcePort;
+ Header->SourcePort = htons(Connection->LocalPort);
+ Header->AcknowlegementNumber = htonl(Connection->NextSequenceRcv);
+ Header->SequenceNumber = htonl(Connection->NextSequenceSend);
+ Header->WindowSize = htons(TCP_WINDOW_SIZE);
+ Header->Flags = TCP_FLAG_ACK;
+ Header->DataOffset = (sizeof(tTCPHeader)/4) << 4;
+ TCP_SendPacket( Connection, sizeof(tTCPHeader), Header );
+
+ if( Header->Flags & TCP_FLAG_ACK )
+ {
+ Log_Log("TCP", "ACKing SYN-ACK");
+ Connection->State = TCP_ST_OPEN;
+ }
+ else
+ {
+ Log_Log("TCP", "ACKing SYN");
+ Connection->State = TCP_ST_SYN_RCVD;
+ }
+ }
+ break;
+
+ // SYN-ACK sent, expecting ACK
+ case TCP_ST_SYN_RCVD:
+ if( Header->Flags & TCP_FLAG_ACK )
+ {
+ // TODO: Handle max half-open limit
+ Connection->State = TCP_ST_OPEN;
+ Log_Log("TCP", "Connection fully opened");
+ }
+ break;
+
+ // --- Established State ---
+ case TCP_ST_OPEN:
+ // - Handle State changes
+ //
+ if( Header->Flags & TCP_FLAG_FIN ) {
+ Log_Log("TCP", "Conn %p closed, recieved FIN", Connection);
+ VFS_MarkError(&Connection->Node, 1);
+ Connection->State = TCP_ST_CLOSE_WAIT;
+// Header->Flags &= ~TCP_FLAG_FIN;
+ // CLOSE WAIT requires the client to close (or does it?)
+ #if 0
+
+ #endif
+ }
+
+ // Check for an empty packet
+ if(dataLen == 0) {
+ if( Header->Flags == TCP_FLAG_ACK )
+ {
+ Log_Log("TCP", "ACK only packet");
+ return ;
+ }
+ Connection->NextSequenceRcv ++; // TODO: Is this right? (empty packet counts as one byte)
+ Log_Log("TCP", "Empty Packet, inc and ACK the current sequence number");
+ Header->DestPort = Header->SourcePort;
+ Header->SourcePort = htons(Connection->LocalPort);
+ Header->AcknowlegementNumber = htonl(Connection->NextSequenceRcv);
+ Header->SequenceNumber = htonl(Connection->NextSequenceSend);
+ Header->Flags |= TCP_FLAG_ACK;
+ TCP_SendPacket( Connection, sizeof(tTCPHeader), Header );
+ return ;
+ }
+
+ // NOTES:
+ // Flags
+ // PSH - Has Data?
+ // /NOTES
+
+ sequence_num = ntohl(Header->SequenceNumber);
+
+ Log_Log("TCP", "0x%08x <= 0x%08x < 0x%08x",
+ Connection->NextSequenceRcv,
+ ntohl(Header->SequenceNumber),
+ Connection->NextSequenceRcv + TCP_WINDOW_SIZE
+ );
+
+ // Is this packet the next expected packet?
+ if( sequence_num == Connection->NextSequenceRcv )
+ {
+ int rv;
+ // Ooh, Goodie! Add it to the recieved list
+ rv = TCP_INT_AppendRecieved(Connection,
+ (Uint8*)Header + (Header->DataOffset>>4)*4,
+ dataLen
+ );
+ if(rv != 0) {
+ break;
+ }
+ Log_Log("TCP", "0x%08x += %i", Connection->NextSequenceRcv, dataLen);
+ Connection->NextSequenceRcv += dataLen;
+
+ // 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.
+ // - Meh, no real issue, as the cache shouldn't be that large
+ TCP_INT_UpdateRecievedFromFuture(Connection);
+
+ // ACK Packet
+ Header->DestPort = Header->SourcePort;
+ Header->SourcePort = htons(Connection->LocalPort);
+ Header->AcknowlegementNumber = htonl(Connection->NextSequenceRcv);
+ Header->SequenceNumber = htonl(Connection->NextSequenceSend);
+ Header->WindowSize = htons(TCP_WINDOW_SIZE);
+ Header->Flags &= TCP_FLAG_SYN; // Eliminate all flags save for SYN
+ Header->Flags |= TCP_FLAG_ACK; // Add ACK
+ Log_Log("TCP", "Sending ACK for 0x%08x", Connection->NextSequenceRcv);
+ TCP_SendPacket( Connection, sizeof(tTCPHeader), Header );
+ //Connection->NextSequenceSend ++;
+ }
+ // Check if the packet is in window
+ else if( WrapBetween(Connection->NextSequenceRcv, sequence_num,
+ Connection->NextSequenceRcv+TCP_WINDOW_SIZE, 0xFFFFFFFF) )