Modules/IPStack - TCP future byte handling
[tpg/acess2.git] / KernelLand / Modules / IPStack / tcp.c
1 /*
2  * Acess2 IP Stack
3  * - TCP Handling
4  */
5 #define DEBUG   0
6 #include "ipstack.h"
7 #include "ipv4.h"
8 #include "ipv6.h"
9 #include "tcp.h"
10
11 #define USE_SELECT      1
12 #define HEXDUMP_INCOMING        0
13 #define HEXDUMP_OUTGOING        0
14
15 #define TCP_MIN_DYNPORT 0xC000
16 #define TCP_MAX_HALFOPEN        1024    // Should be enough
17
18 #define TCP_MAX_PACKET_SIZE     1024
19 #define TCP_WINDOW_SIZE 0x2000
20 #define TCP_RECIEVE_BUFFER_SIZE 0x8000
21 #define TCP_DACK_THRESHOLD      4096
22 #define TCP_DACK_TIMEOUT        500
23
24 #define TCP_DEBUG       0       // Set to non-0 to enable TCP packet logging
25
26 // === PROTOTYPES ===
27 void    TCP_Initialise(void);
28 void    TCP_StartConnection(tTCPConnection *Conn);
29 void    TCP_SendPacket(tTCPConnection *Conn, tTCPHeader *Header, size_t DataLen, const void *Data);
30 void    TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer);
31 void    TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Header, int Length);
32 int     TCP_INT_AppendRecieved(tTCPConnection *Connection, const void *Data, size_t Length);
33 void    TCP_INT_UpdateRecievedFromFuture(tTCPConnection *Connection);
34 void    TCP_int_SendDelayedACK(void *ConnPtr);
35 void    TCP_INT_SendACK(tTCPConnection *Connection, const char *Reason);
36 Uint16  TCP_GetUnusedPort();
37  int    TCP_AllocatePort(Uint16 Port);
38  int    TCP_DeallocatePort(Uint16 Port);
39 tTCPConnection  *TCP_int_CreateConnection(tInterface *Interface, enum eTCPConnectionState State);
40 // --- Server
41 tVFS_Node       *TCP_Server_Init(tInterface *Interface);
42  int    TCP_Server_ReadDir(tVFS_Node *Node, int Pos, char Name[FILENAME_MAX]);
43 tVFS_Node       *TCP_Server_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
44  int    TCP_Server_IOCtl(tVFS_Node *Node, int ID, void *Data);
45 void    TCP_Server_Close(tVFS_Node *Node);
46 // --- Client
47 tVFS_Node       *TCP_Client_Init(tInterface *Interface);
48 size_t  TCP_Client_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);
49 size_t  TCP_Client_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags);
50  int    TCP_Client_IOCtl(tVFS_Node *Node, int ID, void *Data);
51 void    TCP_Client_Close(tVFS_Node *Node);
52 // --- Helpers
53  int    WrapBetween(Uint32 Lower, Uint32 Value, Uint32 Higher, Uint32 MaxValue);
54
55 // === TEMPLATES ===
56 tSocketFile     gTCP_ServerFile = {NULL, "tcps", TCP_Server_Init};
57 tSocketFile     gTCP_ClientFile = {NULL, "tcpc", TCP_Client_Init};
58 tVFS_NodeType   gTCP_ServerNodeType = {
59         .TypeName = "TCP Server",
60         .ReadDir = TCP_Server_ReadDir,
61         .FindDir = TCP_Server_FindDir,
62         .IOCtl   = TCP_Server_IOCtl,
63         .Close   = TCP_Server_Close
64         };
65 tVFS_NodeType   gTCP_ClientNodeType = {
66         .TypeName = "TCP Client/Connection",
67         .Read  = TCP_Client_Read,
68         .Write = TCP_Client_Write,
69         .IOCtl = TCP_Client_IOCtl,
70         .Close = TCP_Client_Close
71         };
72
73 // === GLOBALS ===
74  int    giTCP_NumHalfopen = 0;
75 tShortSpinlock  glTCP_Listeners;
76 tTCPListener    *gTCP_Listeners;
77 tShortSpinlock  glTCP_OutbountCons;
78 tTCPConnection  *gTCP_OutbountCons;
79 Uint32  gaTCP_PortBitmap[0x800];
80  int    giTCP_NextOutPort = TCP_MIN_DYNPORT;
81
82 // === CODE ===
83 /**
84  * \brief Initialise the TCP Layer
85  * 
86  * Registers the client and server files and the GetPacket callback
87  */
88 void TCP_Initialise(void)
89 {
90         giTCP_NextOutPort += rand()%32;
91         IPStack_AddFile(&gTCP_ServerFile);
92         IPStack_AddFile(&gTCP_ClientFile);
93         IPv4_RegisterCallback(IP4PROT_TCP, TCP_GetPacket);
94         IPv6_RegisterCallback(IP4PROT_TCP, TCP_GetPacket);
95 }
96
97 /**
98  * \brief Sends a packet from the specified connection, calculating the checksums
99  * \param Conn  Connection
100  * \param Length        Length of data
101  * \param Data  Packet data (cast as a TCP Header)
102  */
103 void TCP_SendPacket( tTCPConnection *Conn, tTCPHeader *Header, size_t Length, const void *Data )
104 {
105         tIPStackBuffer  *buffer;
106         Uint16  checksum[3];
107          int    packlen = sizeof(*Header) + Length;
108         
109         buffer = IPStack_Buffer_CreateBuffer(2 + IPV4_BUFFERS);
110         if( Data && Length )
111                 IPStack_Buffer_AppendSubBuffer(buffer, Length, 0, Data, NULL, NULL);
112         IPStack_Buffer_AppendSubBuffer(buffer, sizeof(*Header), 0, Header, NULL, NULL);
113
114         LOG("Sending %i+%i to %s:%i", sizeof(*Header), Length,
115                 IPStack_PrintAddress(Conn->Interface->Type, &Conn->RemoteIP),
116                 Conn->RemotePort
117                 );
118
119         Header->Checksum = 0;
120         checksum[1] = htons( ~IPv4_Checksum(Header, sizeof(tTCPHeader)) );
121         checksum[2] = htons( ~IPv4_Checksum(Data, Length) );
122         
123         // TODO: Fragment packet
124         
125         switch( Conn->Interface->Type )
126         {
127         case 4:
128                 // Get IPv4 pseudo-header checksum
129                 {
130                         Uint32  buf[3];
131                         buf[0] = ((tIPv4*)Conn->Interface->Address)->L;
132                         buf[1] = Conn->RemoteIP.v4.L;
133                         buf[2] = (htons(packlen)<<16) | (6<<8) | 0;
134                         checksum[0] = htons( ~IPv4_Checksum(buf, sizeof(buf)) );        // Partial checksum
135                 }
136                 // - Combine checksums
137                 Header->Checksum = htons( IPv4_Checksum(checksum, sizeof(checksum)) );
138                 IPv4_SendPacket(Conn->Interface, Conn->RemoteIP.v4, IP4PROT_TCP, 0, buffer);
139                 break;
140                 
141         case 6:
142                 // Append IPv6 Pseudo Header
143                 {
144                         Uint32  buf[4+4+1+1];
145                         memcpy(buf, Conn->Interface->Address, 16);
146                         memcpy(&buf[4], &Conn->RemoteIP, 16);
147                         buf[8] = htonl(packlen);
148                         buf[9] = htonl(6);
149                         checksum[0] = htons( ~IPv4_Checksum(buf, sizeof(buf)) );        // Partial checksum
150                 }
151                 Header->Checksum = htons( IPv4_Checksum(checksum, sizeof(checksum)) );  // Combine the two
152                 IPv6_SendPacket(Conn->Interface, Conn->RemoteIP.v6, IP4PROT_TCP, Length, Data);
153                 break;
154         }
155 }
156
157 /**
158  * \brief Handles a packet from the IP Layer
159  * \param Interface     Interface the packet arrived from
160  * \param Address       Pointer to the addres structure
161  * \param Length        Size of packet in bytes
162  * \param Buffer        Packet data
163  */
164 void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
165 {
166         tTCPHeader      *hdr = Buffer;
167         tTCPListener    *srv;
168         tTCPConnection  *conn;
169
170         #if TCP_DEBUG
171         Log_Log("TCP", "TCP_GetPacket: <Local>:%i from [%s]:%i, Flags = %s%s%s%s%s%s%s%s",
172                 ntohs(hdr->DestPort),
173                 IPStack_PrintAddress(Interface->Type, Address),
174                 ntohs(hdr->SourcePort),
175                 (hdr->Flags & TCP_FLAG_CWR) ? "CWR " : "",
176                 (hdr->Flags & TCP_FLAG_ECE) ? "ECE " : "",
177                 (hdr->Flags & TCP_FLAG_URG) ? "URG " : "",
178                 (hdr->Flags & TCP_FLAG_ACK) ? "ACK " : "",
179                 (hdr->Flags & TCP_FLAG_PSH) ? "PSH " : "",
180                 (hdr->Flags & TCP_FLAG_RST) ? "RST " : "",
181                 (hdr->Flags & TCP_FLAG_SYN) ? "SYN " : "",
182                 (hdr->Flags & TCP_FLAG_FIN) ? "FIN " : ""
183                 );
184         #endif
185
186         if( Length > (hdr->DataOffset >> 4)*4 )
187         {
188                 LOG("SequenceNumber = 0x%x", ntohl(hdr->SequenceNumber));
189 #if HEXDUMP_INCOMING
190                 Debug_HexDump(
191                         "TCP_GetPacket: Packet Data = ",
192                         (Uint8*)hdr + (hdr->DataOffset >> 4)*4,
193                         Length - (hdr->DataOffset >> 4)*4
194                         );
195 #endif
196         }
197
198         // Check Servers
199         for( srv = gTCP_Listeners; srv; srv = srv->Next )
200         {
201                 // Check if the server is active
202                 if(srv->Port == 0)      continue;
203                 // Check the interface
204                 if(srv->Interface && srv->Interface != Interface)       continue;
205                 // Check the destination port
206                 if(srv->Port != htons(hdr->DestPort))   continue;
207                 
208                 Log_Log("TCP", "TCP_GetPacket: Matches server %p", srv);
209                 // Is this in an established connection?
210                 for( conn = srv->Connections; conn; conn = conn->Next )
211                 {
212                         // Check that it is coming in on the same interface
213                         if(conn->Interface != Interface)        continue;
214
215                         // Check Source Port
216                         Log_Log("TCP", "TCP_GetPacket: conn->RemotePort(%i) == hdr->SourcePort(%i)",
217                                 conn->RemotePort, ntohs(hdr->SourcePort));
218                         if(conn->RemotePort != ntohs(hdr->SourcePort))  continue;
219
220                         // Check Source IP
221                         Log_Debug("TCP", "TCP_GetPacket: conn->RemoteIP(%s)",
222                                 IPStack_PrintAddress(conn->Interface->Type, &conn->RemoteIP));
223                         Log_Debug("TCP", "                == Address(%s)",
224                                 IPStack_PrintAddress(conn->Interface->Type, Address));
225                         if( IPStack_CompareAddress(conn->Interface->Type, &conn->RemoteIP, Address, -1) == 0 )
226                                 continue ;
227
228                         Log_Log("TCP", "TCP_GetPacket: Matches connection %p", conn);
229                         // We have a response!
230                         TCP_INT_HandleConnectionPacket(conn, hdr, Length);
231
232                         return;
233                 }
234
235                 Log_Log("TCP", "TCP_GetPacket: Opening Connection");
236                 // Open a new connection (well, check that it's a SYN)
237                 if(hdr->Flags != TCP_FLAG_SYN) {
238                         Log_Log("TCP", "TCP_GetPacket: Packet is not a SYN");
239                         return ;
240                 }
241                 
242                 // TODO: Check for halfopen max
243                 
244                 conn = TCP_int_CreateConnection(Interface, TCP_ST_SYN_RCVD);
245                 conn->LocalPort = srv->Port;
246                 conn->RemotePort = ntohs(hdr->SourcePort);
247                 
248                 switch(Interface->Type)
249                 {
250                 case 4: conn->RemoteIP.v4 = *(tIPv4*)Address;   break;
251                 case 6: conn->RemoteIP.v6 = *(tIPv6*)Address;   break;
252                 }
253                 
254                 conn->NextSequenceRcv = ntohl( hdr->SequenceNumber ) + 1;
255                 conn->HighestSequenceRcvd = conn->NextSequenceRcv;
256                 conn->NextSequenceSend = rand();
257                 
258                 conn->Node.ImplInt = srv->NextID ++;
259                 
260                 // Hmm... Theoretically, this lock will never have to wait,
261                 // as the interface is locked to the watching thread, and this
262                 // runs in the watching thread. But, it's a good idea to have
263                 // it, just in case
264                 // Oh, wait, there is a case where a wildcard can be used
265                 // (srv->Interface == NULL) so having the lock is a good idea
266                 SHORTLOCK(&srv->lConnections);
267                 if( !srv->Connections )
268                         srv->Connections = conn;
269                 else
270                         srv->ConnectionsTail->Next = conn;
271                 srv->ConnectionsTail = conn;
272                 if(!srv->NewConnections)
273                         srv->NewConnections = conn;
274                 VFS_MarkAvaliable( &srv->Node, 1 );
275                 SHORTREL(&srv->lConnections);
276                 Semaphore_Signal(&srv->WaitingConnections, 1);
277
278                 // Send the SYN ACK
279                 hdr->Flags |= TCP_FLAG_ACK;
280                 hdr->AcknowlegementNumber = htonl(conn->NextSequenceRcv);
281                 hdr->SequenceNumber = htonl(conn->NextSequenceSend);
282                 hdr->DestPort = hdr->SourcePort;
283                 hdr->SourcePort = htons(srv->Port);
284                 hdr->DataOffset = (sizeof(tTCPHeader)/4) << 4;
285                 TCP_SendPacket( conn, hdr, 0, NULL );
286                 conn->NextSequenceSend ++;
287                 return ;
288         }
289
290         // Check Open Connections
291         {
292                 for( conn = gTCP_OutbountCons; conn; conn = conn->Next )
293                 {
294                         // Check that it is coming in on the same interface
295                         if(conn->Interface != Interface)        continue;
296
297                         // Check Source Port
298                         if(conn->RemotePort != ntohs(hdr->SourcePort))  continue;
299
300                         // Check Source IP
301                         if(conn->Interface->Type == 6 && !IP6_EQU(conn->RemoteIP.v6, *(tIPv6*)Address))
302                                 continue;
303                         if(conn->Interface->Type == 4 && !IP4_EQU(conn->RemoteIP.v4, *(tIPv4*)Address))
304                                 continue;
305
306                         TCP_INT_HandleConnectionPacket(conn, hdr, Length);
307                         return ;
308                 }
309         }
310         
311         Log_Log("TCP", "TCP_GetPacket: No Match");
312 }
313
314 /**
315  * \brief Handles a packet sent to a specific connection
316  * \param Connection    TCP Connection pointer
317  * \param Header        TCP Packet pointer
318  * \param Length        Length of the packet
319  */
320 void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Header, int Length)
321 {
322          int    dataLen;
323         Uint32  sequence_num;
324         
325         // Silently drop once finished
326         // TODO: Check if this needs to be here
327         if( Connection->State == TCP_ST_FINISHED ) {
328                 Log_Log("TCP", "Packet ignored - connection finnished");
329                 return ;
330         }
331         
332         // Syncronise sequence values
333         if(Header->Flags & TCP_FLAG_SYN) {
334                 // TODO: What if the packet also has data?
335                 if( Connection->LastACKSequence != Connection->NextSequenceRcv )
336                         TCP_INT_SendACK(Connection, "SYN");
337                 Connection->NextSequenceRcv = ntohl(Header->SequenceNumber);
338                 // TODO: Process HighestSequenceRcvd
339                 // HACK!
340                 if( Connection->HighestSequenceRcvd == 0 )
341                         Connection->HighestSequenceRcvd = Connection->NextSequenceRcv;
342                 Connection->LastACKSequence = Connection->NextSequenceRcv;
343         }
344         
345         // Ackowledge a sent packet
346         if(Header->Flags & TCP_FLAG_ACK) {
347                 // TODO: Process an ACKed Packet
348                 LOG("Conn %p, Sent packet 0x%x ACKed", Connection, Header->AcknowlegementNumber);
349         }
350         
351         // Get length of data
352         dataLen = Length - (Header->DataOffset>>4)*4;
353         LOG("dataLen = %i", dataLen);
354         #if TCP_DEBUG
355         Log_Debug("TCP", "State %i, dataLen = %x", Connection->State, dataLen);
356         #endif
357         
358         // 
359         // State Machine
360         //
361         switch( Connection->State )
362         {
363         // Pre-init connection?
364         case TCP_ST_CLOSED:
365                 Log_Log("TCP", "Packets to a closed connection?!");
366                 break;
367         
368         // --- Init States ---
369         // SYN sent, expecting SYN-ACK Connection Opening
370         case TCP_ST_SYN_SENT:
371                 if( Header->Flags & TCP_FLAG_SYN )
372                 {
373                         if( Connection->HighestSequenceRcvd == Connection->NextSequenceRcv )
374                                 Connection->HighestSequenceRcvd ++;
375                         Connection->NextSequenceRcv ++;
376                         
377                         if( Header->Flags & TCP_FLAG_ACK )
378                         {       
379                                 Log_Log("TCP", "ACKing SYN-ACK");
380                                 Connection->State = TCP_ST_OPEN;
381                                 VFS_MarkFull(&Connection->Node, 0);
382                         }
383                         else
384                         {
385                                 Log_Log("TCP", "ACKing SYN");
386                                 Connection->State = TCP_ST_SYN_RCVD;
387                         }
388                         Header->DestPort = Header->SourcePort;
389                         Header->SourcePort = htons(Connection->LocalPort);
390                         Header->AcknowlegementNumber = htonl(Connection->NextSequenceRcv);
391                         Header->SequenceNumber = htonl(Connection->NextSequenceSend);
392                         Header->WindowSize = htons(TCP_WINDOW_SIZE);
393                         Header->Flags = TCP_FLAG_ACK;
394                         Header->DataOffset = (sizeof(tTCPHeader)/4) << 4;
395                         TCP_SendPacket( Connection, Header, 0, NULL );
396                 }
397                 break;
398         
399         // SYN-ACK sent, expecting ACK
400         case TCP_ST_SYN_RCVD:
401                 if( Header->Flags & TCP_FLAG_ACK )
402                 {
403                         // TODO: Handle max half-open limit
404                         Log_Log("TCP", "Connection fully opened");
405                         Connection->State = TCP_ST_OPEN;
406                         VFS_MarkFull(&Connection->Node, 0);
407                 }
408                 break;
409                 
410         // --- Established State ---
411         case TCP_ST_OPEN:
412                 // - Handle State changes
413                 //
414                 if( Header->Flags & TCP_FLAG_FIN ) {
415                         Log_Log("TCP", "Conn %p closed, recieved FIN", Connection);
416                         VFS_MarkError(&Connection->Node, 1);
417                         Connection->State = TCP_ST_CLOSE_WAIT;
418 //                      Header->Flags &= ~TCP_FLAG_FIN;
419                         // CLOSE WAIT requires the client to close (or does it?)
420                         #if 0
421                         
422                         #endif
423                 }
424         
425                 // Check for an empty packet
426                 if(dataLen == 0) {
427                         if( Header->Flags == TCP_FLAG_ACK )
428                         {
429                                 Log_Log("TCP", "ACK only packet");
430                                 return ;
431                         }
432                         // TODO: Is this right? (empty packet counts as one byte)
433                         if( Connection->HighestSequenceRcvd == Connection->NextSequenceRcv )
434                                 Connection->HighestSequenceRcvd ++;
435                         Connection->NextSequenceRcv ++;
436                         Log_Log("TCP", "Empty Packet, inc and ACK the current sequence number");
437                         TCP_INT_SendACK(Connection, "Empty");
438                         return ;
439                 }
440                 
441                 // NOTES:
442                 // Flags
443                 //    PSH - Has Data?
444                 // /NOTES
445                 
446                 sequence_num = ntohl(Header->SequenceNumber);
447                 
448                 LOG("0x%08x <= 0x%08x < 0x%08x",
449                         Connection->NextSequenceRcv,
450                         ntohl(Header->SequenceNumber),
451                         Connection->NextSequenceRcv + TCP_WINDOW_SIZE
452                         );
453                 
454                 // Is this packet the next expected packet?
455                 if( sequence_num == Connection->NextSequenceRcv )
456                 {
457                          int    rv;
458                         // Ooh, Goodie! Add it to the recieved list
459                         rv = TCP_INT_AppendRecieved(Connection,
460                                 (Uint8*)Header + (Header->DataOffset>>4)*4,
461                                 dataLen
462                                 );
463                         if(rv != 0) {
464                                 Log_Notice("TCP", "TCP_INT_AppendRecieved rv %i", rv);
465                                 break;
466                         }
467                         LOG("0x%08x += %i", Connection->NextSequenceRcv, dataLen);
468                         if( Connection->HighestSequenceRcvd == Connection->NextSequenceRcv )
469                                 Connection->HighestSequenceRcvd += dataLen;
470                         Connection->NextSequenceRcv += dataLen;
471                         
472                         // TODO: This should be moved out of the watcher thread,
473                         // so that a single lost packet on one connection doesn't cause
474                         // all connections on the interface to lag.
475                         // - Meh, no real issue, as the cache shouldn't be that large
476                         TCP_INT_UpdateRecievedFromFuture(Connection);
477
478                         #if 1
479                         // - Only send an ACK if we've had a burst
480                         if( Connection->NextSequenceRcv > (Uint32)(TCP_DACK_THRESHOLD + Connection->LastACKSequence) )
481                         {
482                                 TCP_INT_SendACK(Connection, "DACK Burst");
483                                 // - Extend TCP deferred ACK timer
484                                 Time_RemoveTimer(Connection->DeferredACKTimer);
485                         }
486                         // - Schedule the deferred ACK timer (if already scheduled, this is a NOP)
487                         Time_ScheduleTimer(Connection->DeferredACKTimer, TCP_DACK_TIMEOUT);
488                         #else
489                         TCP_INT_SendACK(Connection, "RX");
490                         #endif
491                 }
492                 // Check if the packet is in window
493                 else if( WrapBetween(Connection->NextSequenceRcv, sequence_num,
494                                 Connection->NextSequenceRcv+TCP_WINDOW_SIZE, 0xFFFFFFFF) )
495                 {
496                         Uint8   *dataptr = (Uint8*)Header + (Header->DataOffset>>4)*4;
497                         #if CACHE_FUTURE_PACKETS_IN_BYTES
498                         Uint32  index;
499                         
500                         index = sequence_num % TCP_WINDOW_SIZE;
501                         for( int i = 0; i < dataLen; i ++ )
502                         {
503                                 Connection->FuturePacketValidBytes[index/8] |= 1 << (index%8);
504                                 Connection->FuturePacketData[index] = dataptr[i];
505                                 // Do a wrap increment
506                                 index ++;
507                                 if(index == TCP_WINDOW_SIZE)    index = 0;
508                         }
509                         #else
510                         tTCPStoredPacket        *pkt, *tmp, *prev = NULL;
511                         
512                         // Allocate and fill cached packet
513                         pkt = malloc( sizeof(tTCPStoredPacket) + dataLen );
514                         pkt->Next = NULL;
515                         pkt->Sequence = ntohl(Header->SequenceNumber);
516                         pkt->Length = dataLen;
517                         memcpy(pkt->Data, dataptr, dataLen);
518                         
519                         Log_Log("TCP", "We missed a packet, caching",
520                                 pkt->Sequence, Connection->NextSequenceRcv);
521                         
522                         // No? Well, let's cache it and look at it later
523                         SHORTLOCK( &Connection->lFuturePackets );
524                         for(tmp = Connection->FuturePackets;
525                                 tmp;
526                                 prev = tmp, tmp = tmp->Next)
527                         {
528                                 if(tmp->Sequence >= pkt->Sequence)      break;
529                         }
530                         
531                         // Add if before first, or sequences don't match 
532                         if( !tmp || tmp->Sequence != pkt->Sequence )
533                         {
534                                 if(prev)
535                                         prev->Next = pkt;
536                                 else
537                                         Connection->FuturePackets = pkt;
538                                 pkt->Next = tmp;
539                         }
540                         // Replace if larger
541                         else if(pkt->Length > tmp->Length)
542                         {
543                                 if(prev)
544                                         prev->Next = pkt;
545                                 pkt->Next = tmp->Next;
546                                 free(tmp);
547                         }
548                         else
549                         {
550                                 free(pkt);      // TODO: Find some way to remove this
551                         }
552                         SHORTREL( &Connection->lFuturePackets );
553                         #endif
554                 }
555                 // Badly out of sequence packet
556                 else
557                 {
558                         Log_Log("TCP", "Fully out of sequence packet (0x%08x not between 0x%08x and 0x%08x), dropped",
559                                 sequence_num, Connection->NextSequenceRcv, Connection->NextSequenceRcv+TCP_WINDOW_SIZE);
560                         // Spec says we should send an empty ACK with the current state
561                         TCP_INT_SendACK(Connection, "Bad Seq");
562                 }
563                 break;
564         
565         // --- Remote close states
566         case TCP_ST_CLOSE_WAIT:
567                 
568                 // Ignore everything, CLOSE_WAIT is terminated by the client
569                 Log_Debug("TCP", "CLOSE WAIT - Ignoring packets");
570                 
571                 break;
572         
573         // LAST-ACK - Waiting for the ACK of FIN (from CLOSE WAIT)
574         case TCP_ST_LAST_ACK:
575                 if( Header->Flags & TCP_FLAG_ACK )
576                 {
577                         Connection->State = TCP_ST_FINISHED;    // Connection completed
578                         Log_Log("TCP", "LAST-ACK to CLOSED - Connection remote closed");
579                         // TODO: Destrory the TCB
580                 }
581                 break;
582         
583         // --- Local close States
584         case TCP_ST_FIN_WAIT1:
585                 if( Header->Flags & TCP_FLAG_FIN )
586                 {
587                         Connection->State = TCP_ST_CLOSING;
588                         Log_Debug("TCP", "Conn %p closed, sent FIN and recieved FIN", Connection);
589                         VFS_MarkError(&Connection->Node, 1);
590                         
591                         // ACK Packet
592                         Header->DestPort = Header->SourcePort;
593                         Header->SourcePort = htons(Connection->LocalPort);
594                         Header->AcknowlegementNumber = Header->SequenceNumber;
595                         Header->SequenceNumber = htonl(Connection->NextSequenceSend);
596                         Header->WindowSize = htons(TCP_WINDOW_SIZE);
597                         Header->Flags = TCP_FLAG_ACK;
598                         TCP_SendPacket( Connection, Header, 0, NULL );
599                         break ;
600                 }
601                 
602                 // TODO: Make sure that the packet is actually ACKing the FIN
603                 if( Header->Flags & TCP_FLAG_ACK )
604                 {
605                         Connection->State = TCP_ST_FIN_WAIT2;
606                         Log_Debug("TCP", "Conn %p closed, sent FIN ACKed", Connection);
607                         VFS_MarkError(&Connection->Node, 1);
608                         return ;
609                 }
610                 break;
611         
612         case TCP_ST_FIN_WAIT2:
613                 if( Header->Flags & TCP_FLAG_FIN )
614                 {
615                         Connection->State = TCP_ST_TIME_WAIT;
616                         Log_Debug("TCP", "FIN sent and recieved, ACKing and going into TIME WAIT %p FINWAIT-2 -> TIME WAIT", Connection);
617                         // Send ACK
618                         Header->DestPort = Header->SourcePort;
619                         Header->SourcePort = htons(Connection->LocalPort);
620                         Header->AcknowlegementNumber = Header->SequenceNumber;
621                         Header->SequenceNumber = htonl(Connection->NextSequenceSend);
622                         Header->WindowSize = htons(TCP_WINDOW_SIZE);
623                         Header->Flags = TCP_FLAG_ACK;
624                         TCP_SendPacket( Connection, Header, 0, NULL );
625                 }
626                 break;
627         
628         case TCP_ST_CLOSING:
629                 // TODO: Make sure that the packet is actually ACKing the FIN
630                 if( Header->Flags & TCP_FLAG_ACK )
631                 {
632                         Connection->State = TCP_ST_TIME_WAIT;
633                         Log_Debug("TCP", "Conn %p CLOSING -> TIME WAIT", Connection);
634                         VFS_MarkError(&Connection->Node, 1);
635                         return ;
636                 }
637                 break;
638         
639         // --- Closed (or near closed) states) ---
640         case TCP_ST_TIME_WAIT:
641                 Log_Log("TCP", "Packets on Time-Wait, ignored");
642                 break;
643         
644         case TCP_ST_FINISHED:
645                 Log_Log("TCP", "Packets when CLOSED, ignoring");
646                 break;
647         
648         //default:
649         //      Log_Warning("TCP", "Unhandled TCP state %i", Connection->State);
650         //      break;
651         }
652         
653 }
654
655 /**
656  * \brief Appends a packet to the recieved list
657  * \param Connection    Connection structure
658  * \param Data  Packet contents
659  * \param Length        Length of \a Data
660  */
661 int TCP_INT_AppendRecieved(tTCPConnection *Connection, const void *Data, size_t Length)
662 {
663         Mutex_Acquire( &Connection->lRecievedPackets );
664
665         if(Connection->RecievedBuffer->Length + Length > Connection->RecievedBuffer->Space )
666         {
667                 VFS_MarkAvaliable(&Connection->Node, 1);
668                 Log_Error("TCP", "Buffer filled, packet dropped (:%i) - %i + %i > %i",
669                         Connection->LocalPort, Connection->RecievedBuffer->Length, Length,
670                         Connection->RecievedBuffer->Space
671                         );
672                 Mutex_Release( &Connection->lRecievedPackets );
673                 return 1;
674         }
675         
676         RingBuffer_Write( Connection->RecievedBuffer, Data, Length );
677
678         VFS_MarkAvaliable(&Connection->Node, 1);
679         
680         Mutex_Release( &Connection->lRecievedPackets );
681         return 0;
682 }
683
684 /**
685  * \brief Updates the connections recieved list from the future list
686  * \param Connection    Connection structure
687  * 
688  * Updates the recieved packets list with packets from the future (out 
689  * of order) packets list that are now able to be added in direct
690  * sequence.
691  */
692 void TCP_INT_UpdateRecievedFromFuture(tTCPConnection *Connection)
693 {
694         #if CACHE_FUTURE_PACKETS_IN_BYTES
695         // Calculate length of contiguous bytes
696          int    length = Connection->HighestSequenceRcvd - Connection->NextSequenceRcv;
697         Uint32  index = Connection->NextSequenceRcv % TCP_WINDOW_SIZE;
698         LOG("length=%i, index=%i", length, index);
699         for( int i = 0; i < length; i ++ )
700         {
701                  int    bit = index % 8;
702                 Uint8   bitfield_byte = Connection->FuturePacketValidBytes[index / 8];
703                 if( (bitfield_byte & (1 << bit)) == 0 ) {
704                         length = i;
705                         break;
706                 }
707
708                 if( bitfield_byte == 0xFF ) {
709                          int    inc = 8 - bit;
710                         i += inc - 1;
711                         index += inc;
712                 }
713                 else {
714                         index ++;
715                 }
716                 if(index > TCP_WINDOW_SIZE)
717                         index -= TCP_WINDOW_SIZE;
718         }
719         
720         index = Connection->NextSequenceRcv % TCP_WINDOW_SIZE;
721         
722         // Write data to to the ring buffer
723         if( TCP_WINDOW_SIZE - index > length )
724         {
725                 // Simple case
726                 RingBuffer_Write( Connection->RecievedBuffer, Connection->FuturePacketData + index, length );
727         }
728         else
729         {
730                  int    endLen = TCP_WINDOW_SIZE - index;
731                 // 2-part case
732                 RingBuffer_Write( Connection->RecievedBuffer, Connection->FuturePacketData + index, endLen );
733                 RingBuffer_Write( Connection->RecievedBuffer, Connection->FuturePacketData, endLen - length );
734         }
735         
736         // Mark (now saved) bytes as invalid
737         // - Align index
738         while(index % 8 && length > 0)
739         {
740                 Connection->FuturePacketData[index] = 0;
741                 Connection->FuturePacketValidBytes[index/8] &= ~(1 << (index%8));
742                 index ++;
743                 if(index > TCP_WINDOW_SIZE)
744                         index -= TCP_WINDOW_SIZE;
745                 length --;
746         }
747         while( length > 7 )
748         {
749                 Connection->FuturePacketData[index] = 0;
750                 Connection->FuturePacketValidBytes[index/8] = 0;
751                 length -= 8;
752                 index += 8;
753                 if(index > TCP_WINDOW_SIZE)
754                         index -= TCP_WINDOW_SIZE;
755         }
756         while(length)
757         {
758                 Connection->FuturePacketData[index] = 0;
759                 Connection->FuturePacketData[index/8] &= ~(1 << (index%8));
760                 index ++;
761                 if(index > TCP_WINDOW_SIZE)
762                         index -= TCP_WINDOW_SIZE;
763                 length --;
764         }
765         
766         #else
767         tTCPStoredPacket        *pkt;
768         for(;;)
769         {
770                 SHORTLOCK( &Connection->lFuturePackets );
771                 
772                 // Clear out duplicates from cache
773                 // - If a packet has just been recieved, and it is expected, then
774                 //   (since NextSequenceRcv = rcvd->Sequence + rcvd->Length) all
775                 //   packets in cache that are smaller than the next expected
776                 //   are now defunct.
777                 pkt = Connection->FuturePackets;
778                 while(pkt && pkt->Sequence < Connection->NextSequenceRcv)
779                 {
780                         tTCPStoredPacket        *next = pkt->Next;
781                         free(pkt);
782                         pkt = next;
783                 }
784                 
785                 // If there's no packets left in cache, stop looking
786                 if(!pkt || pkt->Sequence > Connection->NextSequenceRcv) {
787                         SHORTREL( &Connection->lFuturePackets );
788                         return;
789                 }
790                 
791                 // Delete packet from future list
792                 Connection->FuturePackets = pkt->Next;
793                 
794                 // Release list
795                 SHORTREL( &Connection->lFuturePackets );
796                 
797                 // Looks like we found one
798                 TCP_INT_AppendRecieved(Connection, pkt->Data, pkt->Length);
799                 if( Connection->HighestSequenceRcvd == Connection->NextSequenceRcv )
800                         Connection->HighestSequenceRcvd += pkt->Length;
801                 Connection->NextSequenceRcv += pkt->Length;
802                 free(pkt);
803         }
804         #endif
805 }
806
807 void TCP_int_SendDelayedACK(void *ConnPtr)
808 {
809         TCP_INT_SendACK(ConnPtr, "DACK Timeout");
810 }
811
812 void TCP_INT_SendACK(tTCPConnection *Connection, const char *Reason)
813 {
814         tTCPHeader      hdr;
815         // ACK Packet
816         hdr.DataOffset = (sizeof(tTCPHeader)/4) << 4;
817         hdr.DestPort = htons(Connection->RemotePort);
818         hdr.SourcePort = htons(Connection->LocalPort);
819         hdr.AcknowlegementNumber = htonl(Connection->NextSequenceRcv);
820         hdr.SequenceNumber = htonl(Connection->NextSequenceSend);
821         hdr.WindowSize = htons(TCP_WINDOW_SIZE);
822         hdr.Flags = TCP_FLAG_ACK;       // TODO: Determine if SYN is wanted too
823         hdr.Checksum = 0;       // TODO: Checksum
824         hdr.UrgentPointer = 0;
825         Log_Debug("TCP", "Sending ACK for 0x%08x (%s)", Connection->NextSequenceRcv, Reason);
826         TCP_SendPacket( Connection, &hdr, 0, NULL );
827         //Connection->NextSequenceSend ++;
828         Connection->LastACKSequence = Connection->NextSequenceRcv;
829 }
830
831 /**
832  * \fn Uint16 TCP_GetUnusedPort()
833  * \brief Gets an unused port and allocates it
834  */
835 Uint16 TCP_GetUnusedPort()
836 {
837         Uint16  ret;
838
839         // Get Next outbound port
840         ret = giTCP_NextOutPort++;
841         while( gaTCP_PortBitmap[ret/32] & (1UL << (ret%32)) )
842         {
843                 ret ++;
844                 giTCP_NextOutPort++;
845                 if(giTCP_NextOutPort == 0x10000) {
846                         ret = giTCP_NextOutPort = TCP_MIN_DYNPORT;
847                 }
848         }
849
850         // Mark the new port as used
851         gaTCP_PortBitmap[ret/32] |= 1 << (ret%32);
852
853         return ret;
854 }
855
856 /**
857  * \fn int TCP_AllocatePort(Uint16 Port)
858  * \brief Marks a port as used
859  */
860 int TCP_AllocatePort(Uint16 Port)
861 {
862         // Check if the port has already been allocated
863         if( gaTCP_PortBitmap[Port/32] & (1 << (Port%32)) )
864                 return 0;
865
866         // Allocate
867         gaTCP_PortBitmap[Port/32] |= 1 << (Port%32);
868
869         return 1;
870 }
871
872 /**
873  * \fn int TCP_DeallocatePort(Uint16 Port)
874  * \brief Marks a port as unused
875  */
876 int TCP_DeallocatePort(Uint16 Port)
877 {
878         // Check if the port has already been allocated
879         if( !(gaTCP_PortBitmap[Port/32] & (1 << (Port%32))) )
880                 return 0;
881
882         // Allocate
883         gaTCP_PortBitmap[Port/32] &= ~(1 << (Port%32));
884
885         return 1;
886 }
887
888 tTCPConnection *TCP_int_CreateConnection(tInterface *Interface, enum eTCPConnectionState State)
889 {
890         tTCPConnection  *conn = calloc( sizeof(tTCPConnection) + TCP_WINDOW_SIZE + TCP_WINDOW_SIZE/8, 1 );
891
892         conn->State = State;
893         conn->Interface = Interface;
894         conn->LocalPort = -1;
895         conn->RemotePort = -1;
896
897         conn->Node.ReferenceCount = 1;
898         conn->Node.ImplPtr = conn;
899         conn->Node.NumACLs = 1;
900         conn->Node.ACLs = &gVFS_ACL_EveryoneRW;
901         conn->Node.Type = &gTCP_ClientNodeType;
902         conn->Node.BufferFull = 1;      // Cleared when connection opens
903
904         conn->RecievedBuffer = RingBuffer_Create( TCP_RECIEVE_BUFFER_SIZE );
905         #if 0
906         conn->SentBuffer = RingBuffer_Create( TCP_SEND_BUFFER_SIZE );
907         Semaphore_Init(conn->SentBufferSpace, 0, TCP_SEND_BUFFER_SIZE, "TCP SentBuffer", conn->Name);
908         #endif
909         
910         #if CACHE_FUTURE_PACKETS_IN_BYTES
911         // Future recieved data (ahead of the expected sequence number)
912         conn->FuturePacketData = (Uint8*)conn + sizeof(tTCPConnection);
913         conn->FuturePacketValidBytes = conn->FuturePacketData + TCP_WINDOW_SIZE;
914         #endif
915
916         conn->DeferredACKTimer = Time_AllocateTimer( TCP_int_SendDelayedACK, conn);
917         return conn;
918 }
919
920 // --- Server
921 tVFS_Node *TCP_Server_Init(tInterface *Interface)
922 {
923         tTCPListener    *srv;
924         
925         srv = calloc( 1, sizeof(tTCPListener) );
926
927         if( srv == NULL ) {
928                 Log_Warning("TCP", "malloc failed for listener (%i) bytes", sizeof(tTCPListener));
929                 return NULL;
930         }
931
932         srv->Interface = Interface;
933         srv->Port = 0;
934         srv->NextID = 0;
935         srv->Connections = NULL;
936         srv->ConnectionsTail = NULL;
937         srv->NewConnections = NULL;
938         srv->Next = NULL;
939         srv->Node.Flags = VFS_FFLAG_DIRECTORY;
940         srv->Node.Size = -1;
941         srv->Node.ImplPtr = srv;
942         srv->Node.NumACLs = 1;
943         srv->Node.ACLs = &gVFS_ACL_EveryoneRW;
944         srv->Node.Type = &gTCP_ServerNodeType;
945
946         SHORTLOCK(&glTCP_Listeners);
947         srv->Next = gTCP_Listeners;
948         gTCP_Listeners = srv;
949         SHORTREL(&glTCP_Listeners);
950
951         return &srv->Node;
952 }
953
954 /**
955  * \brief Wait for a new connection and return the connection ID
956  * \note Blocks until a new connection is made
957  * \param Node  Server node
958  * \param Pos   Position (ignored)
959  */
960 int TCP_Server_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
961 {
962         tTCPListener    *srv = Node->ImplPtr;
963         tTCPConnection  *conn;
964         
965         ENTER("pNode iPos", Node, Pos);
966
967         Log_Log("TCP", "Thread %i waiting for a connection", Threads_GetTID());
968         Semaphore_Wait( &srv->WaitingConnections, 1 );
969         
970         SHORTLOCK(&srv->lConnections);
971         // Increment the new list (the current connection is still on the 
972         // normal list)
973         conn = srv->NewConnections;
974         srv->NewConnections = conn->Next;
975
976         if( srv->NewConnections == NULL )
977                 VFS_MarkAvaliable( Node, 0 );
978         
979         SHORTREL( &srv->lConnections );
980         
981         LOG("conn = %p", conn);
982         LOG("srv->Connections = %p", srv->Connections);
983         LOG("srv->NewConnections = %p", srv->NewConnections);
984         LOG("srv->ConnectionsTail = %p", srv->ConnectionsTail);
985
986         itoa(Dest, conn->Node.ImplInt, 16, 8, '0');
987         Log_Log("TCP", "Thread %i got connection '%s'", Threads_GetTID(), Dest);
988         LEAVE('i', 0);
989         return 0;
990 }
991
992 /**
993  * \brief Gets a client connection node
994  * \param Node  Server node
995  * \param Name  Hexadecimal ID of the node
996  */
997 tVFS_Node *TCP_Server_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
998 {
999         tTCPConnection  *conn;
1000         tTCPListener    *srv = Node->ImplPtr;
1001         char    tmp[9];
1002          int    id = atoi(Name);
1003         
1004         ENTER("pNode sName", Node, Name);
1005
1006         // Check for a non-empty name
1007         if( Name[0] ) 
1008         {       
1009                 // Sanity Check
1010                 itoa(tmp, id, 16, 8, '0');
1011                 if(strcmp(tmp, Name) != 0) {
1012                         LOG("'%s' != '%s' (%08x)", Name, tmp, id);
1013                         LEAVE('n');
1014                         return NULL;
1015                 }
1016                 
1017                 Log_Debug("TCP", "srv->Connections = %p", srv->Connections);
1018                 Log_Debug("TCP", "srv->NewConnections = %p", srv->NewConnections);
1019                 Log_Debug("TCP", "srv->ConnectionsTail = %p", srv->ConnectionsTail);
1020                 
1021                 // Search
1022                 SHORTLOCK( &srv->lConnections );
1023                 for(conn = srv->Connections;
1024                         conn;
1025                         conn = conn->Next)
1026                 {
1027                         LOG("conn->Node.ImplInt = %i", conn->Node.ImplInt);
1028                         if(conn->Node.ImplInt == id)    break;
1029                 }
1030                 SHORTREL( &srv->lConnections );
1031
1032                 // If not found, ret NULL
1033                 if(!conn) {
1034                         LOG("Connection %i not found", id);
1035                         LEAVE('n');
1036                         return NULL;
1037                 }
1038         }
1039         // Empty Name - Check for a new connection and if it's there, open it
1040         else
1041         {
1042                 SHORTLOCK( &srv->lConnections );
1043                 conn = srv->NewConnections;
1044                 if( conn != NULL )
1045                         srv->NewConnections = conn->Next;
1046                 VFS_MarkAvaliable( Node, srv->NewConnections != NULL );
1047                 SHORTREL( &srv->lConnections );
1048                 if( !conn ) {
1049                         LOG("No new connections");
1050                         LEAVE('n');
1051                         return NULL;
1052                 }
1053         }
1054                 
1055         // Return node
1056         LEAVE('p', &conn->Node);
1057         return &conn->Node;
1058 }
1059
1060 /**
1061  * \brief Handle IOCtl calls
1062  */
1063 int TCP_Server_IOCtl(tVFS_Node *Node, int ID, void *Data)
1064 {
1065         tTCPListener    *srv = Node->ImplPtr;
1066
1067         switch(ID)
1068         {
1069         case 4: // Get/Set Port
1070                 if(!Data)       // Get Port
1071                         return srv->Port;
1072
1073                 if(srv->Port)   // Wait, you can't CHANGE the port
1074                         return -1;
1075
1076                 if(!CheckMem(Data, sizeof(Uint16)))     // Sanity check
1077                         return -1;
1078
1079                 // Permissions check
1080                 if(Threads_GetUID() != 0
1081                 && *(Uint16*)Data != 0
1082                 && *(Uint16*)Data < 1024)
1083                         return -1;
1084
1085                 // TODO: Check if a port is in use
1086
1087                 // Set Port
1088                 srv->Port = *(Uint16*)Data;
1089                 if(srv->Port == 0)      // Allocate a random port
1090                         srv->Port = TCP_GetUnusedPort();
1091                 else    // Else, mark this as used
1092                         TCP_AllocatePort(srv->Port);
1093                 
1094                 Log_Log("TCP", "Server %p listening on port %i", srv, srv->Port);
1095                 
1096                 return srv->Port;
1097         }
1098         return 0;
1099 }
1100
1101 void TCP_Server_Close(tVFS_Node *Node)
1102 {
1103         free(Node->ImplPtr);
1104 }
1105
1106 // --- Client
1107 /**
1108  * \brief Create a client node
1109  */
1110 tVFS_Node *TCP_Client_Init(tInterface *Interface)
1111 {
1112         tTCPConnection  *conn = TCP_int_CreateConnection(Interface, TCP_ST_CLOSED);
1113
1114         SHORTLOCK(&glTCP_OutbountCons);
1115         conn->Next = gTCP_OutbountCons;
1116         gTCP_OutbountCons = conn;
1117         SHORTREL(&glTCP_OutbountCons);
1118
1119         return &conn->Node;
1120 }
1121
1122 /**
1123  * \brief Wait for a packet and return it
1124  * \note If \a Length is smaller than the size of the packet, the rest
1125  *       of the packet's data will be discarded.
1126  */
1127 size_t TCP_Client_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
1128 {
1129         tTCPConnection  *conn = Node->ImplPtr;
1130         size_t  len;
1131         
1132         ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
1133         LOG("conn = %p {State:%i}", conn, conn->State);
1134         
1135         // If the connection has been closed (state > ST_OPEN) then clear
1136         // any stale data in the buffer (until it is empty (until it is empty))
1137         if( conn->State > TCP_ST_OPEN )
1138         {
1139                 Mutex_Acquire( &conn->lRecievedPackets );
1140                 len = RingBuffer_Read( Buffer, conn->RecievedBuffer, Length );
1141                 Mutex_Release( &conn->lRecievedPackets );
1142                 
1143                 if( len == 0 ) {
1144                         VFS_MarkAvaliable(Node, 0);
1145                         errno = 0;
1146                         LEAVE('i', -1);
1147                         return -1;
1148                 }
1149                 
1150                 LEAVE('i', len);
1151                 return len;
1152         }
1153         
1154         // Wait
1155         {
1156                 tTime   *timeout = NULL;
1157                 tTime   timeout_zero = 0;
1158                 if( Flags & VFS_IOFLAG_NOBLOCK )
1159                         timeout = &timeout_zero;
1160                 if( !VFS_SelectNode(Node, VFS_SELECT_READ|VFS_SELECT_ERROR, timeout, "TCP_Client_Read") ) {
1161                         errno = EWOULDBLOCK;
1162                         LEAVE('i', -1);
1163                         return -1;
1164                 }
1165         }
1166         
1167         // Lock list and read as much as possible (up to `Length`)
1168         Mutex_Acquire( &conn->lRecievedPackets );
1169         len = RingBuffer_Read( Buffer, conn->RecievedBuffer, Length );
1170         
1171         if( len == 0 || conn->RecievedBuffer->Length == 0 ) {
1172                 LOG("Marking as none avaliable (len = %i)", len);
1173                 VFS_MarkAvaliable(Node, 0);
1174         }
1175                 
1176         // Release the lock (we don't need it any more)
1177         Mutex_Release( &conn->lRecievedPackets );
1178
1179         LEAVE('i', len);
1180         return len;
1181 }
1182
1183 /**
1184  * \brief Send a data packet on a connection
1185  */
1186 void TCP_INT_SendDataPacket(tTCPConnection *Connection, size_t Length, const void *Data)
1187 {
1188         char    buf[sizeof(tTCPHeader)+Length];
1189         tTCPHeader      *packet = (void*)buf;
1190
1191         // - Stop Delayed ACK timer (as this data packet ACKs)
1192         Time_RemoveTimer(Connection->DeferredACKTimer);
1193         
1194         packet->SourcePort = htons(Connection->LocalPort);
1195         packet->DestPort = htons(Connection->RemotePort);
1196         packet->DataOffset = (sizeof(tTCPHeader)/4)*16;
1197         packet->WindowSize = htons(TCP_WINDOW_SIZE);
1198         
1199         packet->AcknowlegementNumber = htonl(Connection->NextSequenceRcv);
1200         packet->SequenceNumber = htonl(Connection->NextSequenceSend);
1201         packet->Flags = TCP_FLAG_PSH|TCP_FLAG_ACK;      // Hey, ACK if you can!
1202         packet->UrgentPointer = 0;
1203         
1204         memcpy(packet->Options, Data, Length);
1205         
1206         Log_Debug("TCP", "Send sequence 0x%08x", Connection->NextSequenceSend);
1207 #if HEXDUMP_OUTGOING
1208         Debug_HexDump("TCP_INT_SendDataPacket: Data = ", Data, Length);
1209 #endif
1210         
1211         TCP_SendPacket( Connection, packet, Length, Data );
1212         
1213         Connection->NextSequenceSend += Length;
1214 }
1215
1216 /**
1217  * \brief Send some bytes on a connection
1218  */
1219 size_t TCP_Client_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)
1220 {
1221         tTCPConnection  *conn = Node->ImplPtr;
1222         size_t  rem = Length;
1223         
1224         ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
1225         
1226 //      #if DEBUG
1227 //      Debug_HexDump("TCP_Client_Write: Buffer = ",
1228 //              Buffer, Length);
1229 //      #endif
1230         
1231         // Don't allow a write to a closed connection
1232         if( conn->State > TCP_ST_OPEN ) {
1233                 VFS_MarkError(Node, 1);
1234                 errno = 0;
1235                 LEAVE('i', -1);
1236                 return -1;
1237         }
1238         
1239         // Wait
1240         {
1241                 tTime   *timeout = NULL;
1242                 tTime   timeout_zero = 0;
1243                 if( Flags & VFS_IOFLAG_NOBLOCK )
1244                         timeout = &timeout_zero;
1245                 if( !VFS_SelectNode(Node, VFS_SELECT_WRITE|VFS_SELECT_ERROR, timeout, "TCP_Client_Write") ) {
1246                         errno = EWOULDBLOCK;
1247                         LEAVE('i', -1);
1248                         return -1;
1249                 }
1250         }
1251         
1252         do
1253         {
1254                  int    len = (rem < TCP_MAX_PACKET_SIZE) ? rem : TCP_MAX_PACKET_SIZE;
1255                 
1256                 #if 0
1257                 // Wait for space in the buffer
1258                 Semaphore_Signal( &Connection->SentBufferSpace, len );
1259                 
1260                 // Save data to buffer (and update the length read by the ammount written)
1261                 len = RingBuffer_Write( &Connection->SentBuffer, Buffer, len);
1262                 #endif
1263                 
1264                 // Send packet
1265                 TCP_INT_SendDataPacket(conn, len, Buffer);
1266                 
1267                 Buffer += len;
1268                 rem -= len;
1269         } while( rem > 0 );
1270         
1271         LEAVE('i', Length);
1272         return Length;
1273 }
1274
1275 /**
1276  * \brief Open a connection to another host using TCP
1277  * \param Conn  Connection structure
1278  */
1279 void TCP_StartConnection(tTCPConnection *Conn)
1280 {
1281         tTCPHeader      hdr = {0};
1282
1283         Conn->State = TCP_ST_SYN_SENT;
1284
1285         hdr.SourcePort = htons(Conn->LocalPort);
1286         hdr.DestPort = htons(Conn->RemotePort);
1287         Conn->NextSequenceSend = rand();
1288         hdr.SequenceNumber = htonl(Conn->NextSequenceSend);
1289         hdr.DataOffset = (sizeof(tTCPHeader)/4) << 4;
1290         hdr.Flags = TCP_FLAG_SYN;
1291         hdr.WindowSize = htons(TCP_WINDOW_SIZE);        // Max
1292         hdr.Checksum = 0;       // TODO
1293         
1294         TCP_SendPacket( Conn, &hdr, 0, NULL );
1295         
1296         Conn->NextSequenceSend ++;
1297         Conn->State = TCP_ST_SYN_SENT;
1298
1299         return ;
1300 }
1301
1302 /**
1303  * \brief Control a client socket
1304  */
1305 int TCP_Client_IOCtl(tVFS_Node *Node, int ID, void *Data)
1306 {
1307         tTCPConnection  *conn = Node->ImplPtr;
1308         
1309         ENTER("pNode iID pData", Node, ID, Data);
1310
1311         switch(ID)
1312         {
1313         case 4: // Get/Set local port
1314                 if(!Data)
1315                         LEAVE_RET('i', conn->LocalPort);
1316                 if(conn->State != TCP_ST_CLOSED)
1317                         LEAVE_RET('i', -1);
1318                 if(!CheckMem(Data, sizeof(Uint16)))
1319                         LEAVE_RET('i', -1);
1320
1321                 if(Threads_GetUID() != 0 && *(Uint16*)Data < 1024)
1322                         LEAVE_RET('i', -1);
1323
1324                 conn->LocalPort = *(Uint16*)Data;
1325                 LEAVE_RET('i', conn->LocalPort);
1326
1327         case 5: // Get/Set remote port
1328                 if(!Data)       LEAVE_RET('i', conn->RemotePort);
1329                 if(conn->State != TCP_ST_CLOSED)        LEAVE_RET('i', -1);
1330                 if(!CheckMem(Data, sizeof(Uint16)))     LEAVE_RET('i', -1);
1331                 conn->RemotePort = *(Uint16*)Data;
1332                 LEAVE_RET('i', conn->RemotePort);
1333
1334         case 6: // Set Remote IP
1335                 if( conn->State != TCP_ST_CLOSED )
1336                         LEAVE_RET('i', -1);
1337                 if( conn->Interface->Type == 4 )
1338                 {
1339                         if(!CheckMem(Data, sizeof(tIPv4)))      LEAVE_RET('i', -1);
1340                         conn->RemoteIP.v4 = *(tIPv4*)Data;
1341                 }
1342                 else if( conn->Interface->Type == 6 )
1343                 {
1344                         if(!CheckMem(Data, sizeof(tIPv6)))      LEAVE_RET('i', -1);
1345                         conn->RemoteIP.v6 = *(tIPv6*)Data;
1346                 }
1347                 LEAVE_RET('i', 0);
1348
1349         case 7: // Connect
1350                 if(conn->LocalPort == 0xFFFF)
1351                         conn->LocalPort = TCP_GetUnusedPort();
1352                 if(conn->RemotePort == -1)
1353                         LEAVE_RET('i', 0);
1354
1355                 {
1356                         tTime   timeout = conn->Interface->TimeoutDelay;
1357         
1358                         TCP_StartConnection(conn);
1359                         VFS_SelectNode(&conn->Node, VFS_SELECT_WRITE, &timeout, "TCP Connection");
1360                         if( conn->State == TCP_ST_SYN_SENT )
1361                                 LEAVE_RET('i', 0);
1362                 }
1363
1364                 LEAVE_RET('i', 1);
1365         
1366         // Get recieve buffer length
1367         case 8:
1368                 LEAVE_RET('i', conn->RecievedBuffer->Length);
1369         }
1370
1371         return 0;
1372 }
1373
1374 void TCP_Client_Close(tVFS_Node *Node)
1375 {
1376         tTCPConnection  *conn = Node->ImplPtr;
1377         tTCPHeader      packet;
1378         
1379         ENTER("pNode", Node);
1380         
1381         ASSERT(Node->ReferenceCount != 0);
1382
1383         if( Node->ReferenceCount > 1 ) {
1384                 Node->ReferenceCount --;
1385                 LOG("Dereference only");
1386                 LEAVE('-');
1387                 return ;
1388         }
1389         
1390         if( conn->State == TCP_ST_CLOSE_WAIT || conn->State == TCP_ST_OPEN )
1391         {
1392                 packet.SourcePort = htons(conn->LocalPort);
1393                 packet.DestPort = htons(conn->RemotePort);
1394                 packet.DataOffset = (sizeof(tTCPHeader)/4)*16;
1395                 packet.WindowSize = TCP_WINDOW_SIZE;
1396                 
1397                 packet.AcknowlegementNumber = 0;
1398                 packet.SequenceNumber = htonl(conn->NextSequenceSend);
1399                 packet.Flags = TCP_FLAG_FIN;
1400                 
1401                 TCP_SendPacket( conn, &packet, 0, NULL );
1402         }
1403         
1404         switch( conn->State )
1405         {
1406         case TCP_ST_CLOSED:
1407                 Log_Warning("TCP", "Closing connection that was never opened");
1408                 break;
1409         case TCP_ST_CLOSE_WAIT:
1410                 conn->State = TCP_ST_LAST_ACK;
1411                 break;
1412         case TCP_ST_OPEN:
1413                 conn->State = TCP_ST_FIN_WAIT1;
1414                 while( conn->State == TCP_ST_FIN_WAIT1 )        Threads_Yield();
1415                 break;
1416         default:
1417                 Log_Warning("TCP", "Unhandled connection state %i in TCP_Client_Close",
1418                         conn->State);
1419                 break;
1420         }
1421         
1422         Time_RemoveTimer(conn->DeferredACKTimer);
1423         Time_FreeTimer(conn->DeferredACKTimer);
1424         free(conn);
1425         
1426         LEAVE('-');
1427 }
1428
1429 /**
1430  * \brief Checks if a value is between two others (after taking into account wrapping)
1431  */
1432 int WrapBetween(Uint32 Lower, Uint32 Value, Uint32 Higher, Uint32 MaxValue)
1433 {
1434         if( MaxValue < 0xFFFFFFFF )
1435         {
1436                 Lower %= MaxValue + 1;
1437                 Value %= MaxValue + 1;
1438                 Higher %= MaxValue + 1;
1439         }
1440         
1441         // Simple Case, no wrap ?
1442         //       Lower Value Higher
1443         // | ... + ... + ... + ... |
1444
1445         if( Lower < Higher ) {
1446                 return Lower < Value && Value < Higher;
1447         }
1448         // Higher has wrapped below lower
1449         
1450         // Value > Lower ?
1451         //       Higher Lower Value
1452         // | ... +  ... + ... + ... |
1453         if( Value > Lower ) {
1454                 return 1;
1455         }
1456         
1457         // Value < Higher ?
1458         //       Value Higher Lower
1459         // | ... + ... +  ... + ... |
1460         if( Value < Higher ) {
1461                 return 1;
1462         }
1463         
1464         return 0;
1465 }

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