Modules/IPStack - Abstract HW addr cache, IPv6 TX (no ND yet)
[tpg/acess2.git] / KernelLand / Modules / IPStack / tcp.c
index c10213c..fcff014 100644 (file)
@@ -8,10 +8,8 @@
 #include "ipv6.h"
 #include "tcp.h"
 
-#define USE_SELECT     1
 #define HEXDUMP_INCOMING       0
 #define HEXDUMP_OUTGOING       0
-#define        CACHE_FUTURE_PACKETS_IN_BYTES   1       // Use a ring buffer to cache out of order packets
 
 #define TCP_MIN_DYNPORT        0xC000
 #define TCP_MAX_HALFOPEN       1024    // Should be enough
@@ -37,6 +35,7 @@ void  TCP_INT_SendACK(tTCPConnection *Connection, const char *Reason);
 Uint16 TCP_GetUnusedPort();
  int   TCP_AllocatePort(Uint16 Port);
  int   TCP_DeallocatePort(Uint16 Port);
+tTCPConnection *TCP_int_CreateConnection(tInterface *Interface, enum eTCPConnectionState State);
 // --- Server
 tVFS_Node      *TCP_Server_Init(tInterface *Interface);
  int   TCP_Server_ReadDir(tVFS_Node *Node, int Pos, char Name[FILENAME_MAX]);
@@ -87,7 +86,7 @@ Uint32        gaTCP_PortBitmap[0x800];
  */
 void TCP_Initialise(void)
 {
-       giTCP_NextOutPort += rand()%32;
+       giTCP_NextOutPort += rand()%128;
        IPStack_AddFile(&gTCP_ServerFile);
        IPStack_AddFile(&gTCP_ClientFile);
        IPv4_RegisterCallback(IP4PROT_TCP, TCP_GetPacket);
@@ -149,7 +148,7 @@ void TCP_SendPacket( tTCPConnection *Conn, tTCPHeader *Header, size_t Length, co
                        checksum[0] = htons( ~IPv4_Checksum(buf, sizeof(buf)) );        // Partial checksum
                }
                Header->Checksum = htons( IPv4_Checksum(checksum, sizeof(checksum)) );  // Combine the two
-               IPv6_SendPacket(Conn->Interface, Conn->RemoteIP.v6, IP4PROT_TCP, Length, Data);
+               IPv6_SendPacket(Conn->Interface, Conn->RemoteIP.v6, IP4PROT_TCP, buffer);
                break;
        }
 }
@@ -241,11 +240,9 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
                
                // TODO: Check for halfopen max
                
-               conn = calloc(1, sizeof(tTCPConnection));
-               conn->State = TCP_ST_SYN_RCVD;
+               conn = TCP_int_CreateConnection(Interface, TCP_ST_SYN_RCVD);
                conn->LocalPort = srv->Port;
                conn->RemotePort = ntohs(hdr->SourcePort);
-               conn->Interface = Interface;
                
                switch(Interface->Type)
                {
@@ -253,17 +250,11 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
                case 6: conn->RemoteIP.v6 = *(tIPv6*)Address;   break;
                }
                
-               conn->RecievedBuffer = RingBuffer_Create( TCP_RECIEVE_BUFFER_SIZE );
-               
                conn->NextSequenceRcv = ntohl( hdr->SequenceNumber ) + 1;
+               conn->HighestSequenceRcvd = conn->NextSequenceRcv;
                conn->NextSequenceSend = rand();
                
-               // Create node
-               conn->Node.NumACLs = 1;
-               conn->Node.ACLs = &gVFS_ACL_EveryoneRW;
-               conn->Node.ImplPtr = conn;
                conn->Node.ImplInt = srv->NextID ++;
-               conn->Node.Type = &gTCP_ClientNodeType; // TODO: Special type for the server end?
                
                // Hmm... Theoretically, this lock will never have to wait,
                // as the interface is locked to the watching thread, and this
@@ -343,6 +334,10 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head
                if( Connection->LastACKSequence != Connection->NextSequenceRcv )
                        TCP_INT_SendACK(Connection, "SYN");
                Connection->NextSequenceRcv = ntohl(Header->SequenceNumber);
+               // TODO: Process HighestSequenceRcvd
+               // HACK!
+               if( Connection->HighestSequenceRcvd == 0 )
+                       Connection->HighestSequenceRcvd = Connection->NextSequenceRcv;
                Connection->LastACKSequence = Connection->NextSequenceRcv;
        }
        
@@ -374,6 +369,8 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head
        case TCP_ST_SYN_SENT:
                if( Header->Flags & TCP_FLAG_SYN )
                {
+                       if( Connection->HighestSequenceRcvd == Connection->NextSequenceRcv )
+                               Connection->HighestSequenceRcvd ++;
                        Connection->NextSequenceRcv ++;
                        
                        if( Header->Flags & TCP_FLAG_ACK )
@@ -431,17 +428,12 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head
                                Log_Log("TCP", "ACK only packet");
                                return ;
                        }
-                       Connection->NextSequenceRcv ++; // TODO: Is this right? (empty packet counts as one byte)
+                       // TODO: Is this right? (empty packet counts as one byte)
+                       if( Connection->HighestSequenceRcvd == Connection->NextSequenceRcv )
+                               Connection->HighestSequenceRcvd ++;
+                       Connection->NextSequenceRcv ++;
                        Log_Log("TCP", "Empty Packet, inc and ACK the current sequence number");
                        TCP_INT_SendACK(Connection, "Empty");
-                       #if 0
-                       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, Header, 0, NULL );
-                       #endif
                        return ;
                }
                
@@ -472,6 +464,8 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head
                                break;
                        }
                        LOG("0x%08x += %i", Connection->NextSequenceRcv, dataLen);
+                       if( Connection->HighestSequenceRcvd == Connection->NextSequenceRcv )
+                               Connection->HighestSequenceRcvd += dataLen;
                        Connection->NextSequenceRcv += dataLen;
                        
                        // TODO: This should be moved out of the watcher thread,
@@ -501,10 +495,9 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head
                        Uint8   *dataptr = (Uint8*)Header + (Header->DataOffset>>4)*4;
                        #if CACHE_FUTURE_PACKETS_IN_BYTES
                        Uint32  index;
-                        int    i;
                        
                        index = sequence_num % TCP_WINDOW_SIZE;
-                       for( i = 0; i < dataLen; i ++ )
+                       for( int i = 0; i < dataLen; i ++ )
                        {
                                Connection->FuturePacketValidBytes[index/8] |= 1 << (index%8);
                                Connection->FuturePacketData[index] = dataptr[i];
@@ -698,26 +691,30 @@ int TCP_INT_AppendRecieved(tTCPConnection *Connection, const void *Data, size_t
 void TCP_INT_UpdateRecievedFromFuture(tTCPConnection *Connection)
 {
        #if CACHE_FUTURE_PACKETS_IN_BYTES
-        int    i, length = 0;
-       Uint32  index;
-       
        // Calculate length of contiguous bytes
-       length = Connection->HighestSequenceRcvd - Connection->NextSequenceRcv;
-       index = Connection->NextSequenceRcv % TCP_WINDOW_SIZE;
-       for( i = 0; i < length; i ++ )
+        int    length = Connection->HighestSequenceRcvd - Connection->NextSequenceRcv;
+       Uint32  index = Connection->NextSequenceRcv % TCP_WINDOW_SIZE;
+       LOG("length=%i, index=%i", length, index);
+       for( int i = 0; i < length; i ++ )
        {
-               if( Connection->FuturePacketValidBytes[i / 8] == 0xFF ) {
-                       i += 7; index += 7;
-                       continue;
-               }
-               else if( !(Connection->FuturePacketValidBytes[i / 8] & (1 << (i%8))) )
+                int    bit = index % 8;
+               Uint8   bitfield_byte = Connection->FuturePacketValidBytes[index / 8];
+               if( (bitfield_byte & (1 << bit)) == 0 ) {
+                       length = i;
                        break;
-               
-               index ++;
+               }
+
+               if( bitfield_byte == 0xFF ) {
+                        int    inc = 8 - bit;
+                       i += inc - 1;
+                       index += inc;
+               }
+               else {
+                       index ++;
+               }
                if(index > TCP_WINDOW_SIZE)
                        index -= TCP_WINDOW_SIZE;
        }
-       length = i;
        
        index = Connection->NextSequenceRcv % TCP_WINDOW_SIZE;
        
@@ -737,10 +734,10 @@ void TCP_INT_UpdateRecievedFromFuture(tTCPConnection *Connection)
        
        // Mark (now saved) bytes as invalid
        // - Align index
-       while(index % 8 && length)
+       while(index % 8 && length > 0)
        {
                Connection->FuturePacketData[index] = 0;
-               Connection->FuturePacketData[index/8] &= ~(1 << (index%8));
+               Connection->FuturePacketValidBytes[index/8] &= ~(1 << (index%8));
                index ++;
                if(index > TCP_WINDOW_SIZE)
                        index -= TCP_WINDOW_SIZE;
@@ -797,7 +794,9 @@ void TCP_INT_UpdateRecievedFromFuture(tTCPConnection *Connection)
                SHORTREL( &Connection->lFuturePackets );
                
                // Looks like we found one
-               TCP_INT_AppendRecieved(Connection, pkt);
+               TCP_INT_AppendRecieved(Connection, pkt->Data, pkt->Length);
+               if( Connection->HighestSequenceRcvd == Connection->NextSequenceRcv )
+                       Connection->HighestSequenceRcvd += pkt->Length;
                Connection->NextSequenceRcv += pkt->Length;
                free(pkt);
        }
@@ -885,6 +884,38 @@ int TCP_DeallocatePort(Uint16 Port)
        return 1;
 }
 
+tTCPConnection *TCP_int_CreateConnection(tInterface *Interface, enum eTCPConnectionState State)
+{
+       tTCPConnection  *conn = calloc( sizeof(tTCPConnection) + TCP_WINDOW_SIZE + TCP_WINDOW_SIZE/8, 1 );
+
+       conn->State = State;
+       conn->Interface = Interface;
+       conn->LocalPort = -1;
+       conn->RemotePort = -1;
+
+       conn->Node.ReferenceCount = 1;
+       conn->Node.ImplPtr = conn;
+       conn->Node.NumACLs = 1;
+       conn->Node.ACLs = &gVFS_ACL_EveryoneRW;
+       conn->Node.Type = &gTCP_ClientNodeType;
+       conn->Node.BufferFull = 1;      // Cleared when connection opens
+
+       conn->RecievedBuffer = RingBuffer_Create( TCP_RECIEVE_BUFFER_SIZE );
+       #if 0
+       conn->SentBuffer = RingBuffer_Create( TCP_SEND_BUFFER_SIZE );
+       Semaphore_Init(conn->SentBufferSpace, 0, TCP_SEND_BUFFER_SIZE, "TCP SentBuffer", conn->Name);
+       #endif
+       
+       #if CACHE_FUTURE_PACKETS_IN_BYTES
+       // Future recieved data (ahead of the expected sequence number)
+       conn->FuturePacketData = (Uint8*)conn + sizeof(tTCPConnection);
+       conn->FuturePacketValidBytes = conn->FuturePacketData + TCP_WINDOW_SIZE;
+       #endif
+
+       conn->DeferredACKTimer = Time_AllocateTimer( TCP_int_SendDelayedACK, conn);
+       return conn;
+}
+
 // --- Server
 tVFS_Node *TCP_Server_Init(tInterface *Interface)
 {
@@ -1077,33 +1108,7 @@ void TCP_Server_Close(tVFS_Node *Node)
  */
 tVFS_Node *TCP_Client_Init(tInterface *Interface)
 {
-       tTCPConnection  *conn = calloc( sizeof(tTCPConnection) + TCP_WINDOW_SIZE + TCP_WINDOW_SIZE/8, 1 );
-
-       conn->State = TCP_ST_CLOSED;
-       conn->Interface = Interface;
-       conn->LocalPort = -1;
-       conn->RemotePort = -1;
-
-       conn->Node.ReferenceCount = 1;
-       conn->Node.ImplPtr = conn;
-       conn->Node.NumACLs = 1;
-       conn->Node.ACLs = &gVFS_ACL_EveryoneRW;
-       conn->Node.Type = &gTCP_ClientNodeType;
-       conn->Node.BufferFull = 1;      // Cleared when connection opens
-
-       conn->RecievedBuffer = RingBuffer_Create( TCP_RECIEVE_BUFFER_SIZE );
-       #if 0
-       conn->SentBuffer = RingBuffer_Create( TCP_SEND_BUFFER_SIZE );
-       Semaphore_Init(conn->SentBufferSpace, 0, TCP_SEND_BUFFER_SIZE, "TCP SentBuffer", conn->Name);
-       #endif
-       
-       #if CACHE_FUTURE_PACKETS_IN_BYTES
-       // Future recieved data (ahead of the expected sequence number)
-       conn->FuturePacketData = (Uint8*)conn + sizeof(tTCPConnection);
-       conn->FuturePacketValidBytes = conn->FuturePacketData + TCP_WINDOW_SIZE;
-       #endif
-
-       conn->DeferredACKTimer = Time_AllocateTimer( TCP_int_SendDelayedACK, conn);
+       tTCPConnection  *conn = TCP_int_CreateConnection(Interface, TCP_ST_CLOSED);
 
        SHORTLOCK(&glTCP_OutbountCons);
        conn->Next = gTCP_OutbountCons;
@@ -1181,6 +1186,9 @@ void TCP_INT_SendDataPacket(tTCPConnection *Connection, size_t Length, const voi
 {
        char    buf[sizeof(tTCPHeader)+Length];
        tTCPHeader      *packet = (void*)buf;
+
+       // - Stop Delayed ACK timer (as this data packet ACKs)
+       Time_RemoveTimer(Connection->DeferredACKTimer);
        
        packet->SourcePort = htons(Connection->LocalPort);
        packet->DestPort = htons(Connection->RemotePort);
@@ -1190,6 +1198,7 @@ void TCP_INT_SendDataPacket(tTCPConnection *Connection, size_t Length, const voi
        packet->AcknowlegementNumber = htonl(Connection->NextSequenceRcv);
        packet->SequenceNumber = htonl(Connection->NextSequenceSend);
        packet->Flags = TCP_FLAG_PSH|TCP_FLAG_ACK;      // Hey, ACK if you can!
+       packet->UrgentPointer = 0;
        
        memcpy(packet->Options, Data, Length);
        

UCC git Repository :: git.ucc.asn.au