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

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