- }
-
- if(dataLen == 0) {
- Log_Log("TCP", "Empty Packet");
- 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);
+ // Check if the packet is in window
+ else if( WrapBetween(Connection->NextSequenceRcv, pkt->Sequence,
+ Connection->NextSequenceRcv+TCP_WINDOW_SIZE, 0xFFFFFFFF) )
+ {
+ #if CACHE_FUTURE_PACKETS_IN_BYTES
+ Uint32 index;
+ int i;
+
+ index = pkt->Sequence % TCP_WINDOW_SIZE;
+ for( i = 0; i < pkt->Length; i ++ )
+ {
+ Connection->FuturePacketValidBytes[index/8] |= 1 << (index%8);
+ Connection->FuturePacketValidBytes[index] = pkt->Data[i];
+ // Do a wrap increment
+ index ++;
+ if(index == TCP_WINDOW_SIZE) index = 0;
+ }
+ #else
+ tTCPStoredPacket *tmp, *prev = NULL;
+
+ Log_Log("TCP", "We missed a packet, caching",
+ pkt->Sequence, Connection->NextSequenceRcv);
+
+ // No? Well, let's cache it and look at it later
+ SHORTLOCK( &Connection->lFuturePackets );
+ for(tmp = Connection->FuturePackets;
+ tmp;
+ prev = tmp, tmp = tmp->Next)
+ {
+ if(tmp->Sequence >= pkt->Sequence) break;
+ }
+
+ // Add if before first, or sequences don't match
+ if( !tmp || tmp->Sequence != pkt->Sequence )
+ {
+ if(prev)
+ prev->Next = pkt;
+ else
+ Connection->FuturePackets = pkt;
+ pkt->Next = tmp;
+ }
+ // Replace if larger
+ else if(pkt->Length > tmp->Length)
+ {
+ if(prev)
+ prev->Next = pkt;
+ pkt->Next = tmp->Next;
+ free(tmp);
+ }
+ else
+ {
+ free(pkt);
+ }
+ SHORTREL( &Connection->lFuturePackets );
+ #endif
+ }
+ // Badly out of sequence packet
+ else
+ {
+ Log_Log("TCP", "Fully out of sequence packet (0x%08x not between 0x%08x and 0x%08x), dropped",
+ pkt->Sequence, Connection->NextSequenceRcv, Connection->NextSequenceRcv+TCP_WINDOW_SIZE);
+ free(pkt);
+ // TODO: Spec says we should send an empty ACK with the current state
+ }
+ break;