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

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