void TCP_SendPacket(tTCPConnection *Conn, size_t Length, tTCPHeader *Data);
void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer);
void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Header, int Length);
-void TCP_INT_AppendRecieved(tTCPConnection *Connection, const void *Data, size_t Length);
+int TCP_INT_AppendRecieved(tTCPConnection *Connection, const void *Data, size_t Length);
void TCP_INT_UpdateRecievedFromFuture(tTCPConnection *Connection);
Uint16 TCP_GetUnusedPort();
int TCP_AllocatePort(Uint16 Port);
// --- Client
tVFS_Node *TCP_Client_Init(tInterface *Interface);
Uint64 TCP_Client_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
-Uint64 TCP_Client_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
+Uint64 TCP_Client_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer);
int TCP_Client_IOCtl(tVFS_Node *Node, int ID, void *Data);
void TCP_Client_Close(tVFS_Node *Node);
// --- Helpers
// === TEMPLATES ===
tSocketFile gTCP_ServerFile = {NULL, "tcps", TCP_Server_Init};
tSocketFile gTCP_ClientFile = {NULL, "tcpc", TCP_Client_Init};
+tVFS_NodeType gTCP_ServerNodeType = {
+ .TypeName = "TCP Server",
+ .ReadDir = TCP_Server_ReadDir,
+ .FindDir = TCP_Server_FindDir,
+ .IOCtl = TCP_Server_IOCtl,
+ .Close = TCP_Server_Close
+ };
+tVFS_NodeType gTCP_ClientNodeType = {
+ .TypeName = "TCP Client/Connection",
+ .Read = TCP_Client_Read,
+ .Write = TCP_Client_Write,
+ .IOCtl = TCP_Client_IOCtl,
+ .Close = TCP_Client_Close
+ };
// === GLOBALS ===
int giTCP_NumHalfopen = 0;
tTCPListener *srv;
tTCPConnection *conn;
- Log_Log("TCP", "TCP_GetPacket: SourcePort = %i, DestPort = %i",
- ntohs(hdr->SourcePort), ntohs(hdr->DestPort));
-/*
- Log_Log("TCP", "TCP_GetPacket: SequenceNumber = 0x%x", ntohl(hdr->SequenceNumber));
- Log_Log("TCP", "TCP_GetPacket: AcknowlegementNumber = 0x%x", ntohl(hdr->AcknowlegementNumber));
- Log_Log("TCP", "TCP_GetPacket: DataOffset = %i", hdr->DataOffset >> 4);
- Log_Log("TCP", "TCP_GetPacket: WindowSize = %i", htons(hdr->WindowSize));
- Log_Log("TCP", "TCP_GetPacket: Checksum = 0x%x", htons(hdr->Checksum));
- Log_Log("TCP", "TCP_GetPacket: UrgentPointer = 0x%x", htons(hdr->UrgentPointer));
-*/
- Log_Log("TCP", "TCP_GetPacket: Flags = %s%s%s%s%s%s%s%s",
+ Log_Log("TCP", "TCP_GetPacket: <Local>:%i from [%s]:%i, Flags= %s%s%s%s%s%s%s%s",
+ ntohs(hdr->DestPort),
+ IPStack_PrintAddress(Interface->Type, Address),
+ ntohs(hdr->SourcePort),
(hdr->Flags & TCP_FLAG_CWR) ? "CWR " : "",
(hdr->Flags & TCP_FLAG_ECE) ? "ECE " : "",
(hdr->Flags & TCP_FLAG_URG) ? "URG " : "",
// Is this in an established connection?
for( conn = srv->Connections; conn; conn = conn->Next )
{
- Log_Log("TCP", "TCP_GetPacket: conn->Interface(%p) == Interface(%p)",
- conn->Interface, Interface);
// Check that it is coming in on the same interface
if(conn->Interface != Interface) continue;
if(conn->RemotePort != ntohs(hdr->SourcePort)) continue;
// Check Source IP
- if( IPStack_CompareAddress(conn->Interface->Type, &conn->RemoteIP, Address, -1) != 0 )
+ Log_Debug("TCP", "TCP_GetPacket: conn->RemoteIP(%s)",
+ IPStack_PrintAddress(conn->Interface->Type, &conn->RemoteIP));
+ Log_Debug("TCP", " == Address(%s)",
+ IPStack_PrintAddress(conn->Interface->Type, Address));
+ if( IPStack_CompareAddress(conn->Interface->Type, &conn->RemoteIP, Address, -1) == 0 )
continue ;
Log_Log("TCP", "TCP_GetPacket: Matches connection %p", conn);
conn->Node.ACLs = &gVFS_ACL_EveryoneRW;
conn->Node.ImplPtr = conn;
conn->Node.ImplInt = srv->NextID ++;
- conn->Node.Read = TCP_Client_Read;
- conn->Node.Write = TCP_Client_Write;
- //conn->Node.Close = TCP_SrvConn_Close;
+ conn->Node.Type = &gTCP_ClientNodeType; // TODO: Special type for the server end?
// Hmm... Theoretically, this lock will never have to wait,
// as the interface is locked to the watching thread, and this
srv->ConnectionsTail = conn;
if(!srv->NewConnections)
srv->NewConnections = conn;
+ VFS_MarkAvaliable( &srv->Node, 1 );
SHORTREL(&srv->lConnections);
// Send the SYN ACK
// Is this packet the next expected packet?
if( sequence_num == Connection->NextSequenceRcv )
{
+ int rv;
// Ooh, Goodie! Add it to the recieved list
- TCP_INT_AppendRecieved(Connection,
+ rv = TCP_INT_AppendRecieved(Connection,
(Uint8*)Header + (Header->DataOffset>>4)*4,
dataLen
);
+ if(rv != 0) {
+ break;
+ }
Log_Log("TCP", "0x%08x += %i", Connection->NextSequenceRcv, dataLen);
Connection->NextSequenceRcv += dataLen;
* \param Data Packet contents
* \param Length Length of \a Data
*/
-void TCP_INT_AppendRecieved(tTCPConnection *Connection, const void *Data, size_t Length)
+int TCP_INT_AppendRecieved(tTCPConnection *Connection, const void *Data, size_t Length)
{
Mutex_Acquire( &Connection->lRecievedPackets );
+
if(Connection->RecievedBuffer->Length + Length > Connection->RecievedBuffer->Space )
{
- Log_Error("TCP", "Buffer filled, packet dropped (%s)",
- // TCP_INT_DumpConnection(Connection)
- ""
+ VFS_MarkAvaliable(&Connection->Node, 1);
+ Log_Error("TCP", "Buffer filled, packet dropped (:%i) - %i + %i > %i",
+ Connection->LocalPort, Connection->RecievedBuffer->Length, Length,
+ Connection->RecievedBuffer->Space
);
- return ;
+ Mutex_Release( &Connection->lRecievedPackets );
+ return 1;
}
RingBuffer_Write( Connection->RecievedBuffer, Data, Length );
VFS_MarkAvaliable(&Connection->Node, 1);
Mutex_Release( &Connection->lRecievedPackets );
+ return 0;
}
/**
// Get Next outbound port
ret = giTCP_NextOutPort++;
- while( gaTCP_PortBitmap[ret/32] & (1 << (ret%32)) )
+ while( gaTCP_PortBitmap[ret/32] & (1UL << (ret%32)) )
{
ret ++;
giTCP_NextOutPort++;
{
tTCPListener *srv;
- srv = malloc( sizeof(tTCPListener) );
+ srv = calloc( 1, sizeof(tTCPListener) );
if( srv == NULL ) {
Log_Warning("TCP", "malloc failed for listener (%i) bytes", sizeof(tTCPListener));
srv->Node.ImplPtr = srv;
srv->Node.NumACLs = 1;
srv->Node.ACLs = &gVFS_ACL_EveryoneRW;
- srv->Node.ReadDir = TCP_Server_ReadDir;
- srv->Node.FindDir = TCP_Server_FindDir;
- srv->Node.IOCtl = TCP_Server_IOCtl;
- srv->Node.Close = TCP_Server_Close;
+ srv->Node.Type = &gTCP_ServerNodeType;
SHORTLOCK(&glTCP_Listeners);
srv->Next = gTCP_Listeners;
if( srv->NewConnections != NULL ) break;
SHORTREL( &srv->lConnections );
Threads_Yield(); // TODO: Sleep until poked
- continue;
}
// normal list)
conn = srv->NewConnections;
srv->NewConnections = conn->Next;
+
+ if( srv->NewConnections == NULL )
+ VFS_MarkAvaliable( Node, 0 );
SHORTREL( &srv->lConnections );
int id = atoi(Name);
ENTER("pNode sName", Node, Name);
-
- // Sanity Check
- itoa(tmp, id, 16, 8, '0');
- if(strcmp(tmp, Name) != 0) {
- LOG("'%s' != '%s' (%08x)", Name, tmp, id);
- LEAVE('n');
- return NULL;
+
+ // Check for a non-empty name
+ if( Name[0] )
+ {
+ // Sanity Check
+ itoa(tmp, id, 16, 8, '0');
+ if(strcmp(tmp, Name) != 0) {
+ LOG("'%s' != '%s' (%08x)", Name, tmp, id);
+ LEAVE('n');
+ return NULL;
+ }
+
+ Log_Debug("TCP", "srv->Connections = %p", srv->Connections);
+ Log_Debug("TCP", "srv->NewConnections = %p", srv->NewConnections);
+ Log_Debug("TCP", "srv->ConnectionsTail = %p", srv->ConnectionsTail);
+
+ // Search
+ SHORTLOCK( &srv->lConnections );
+ for(conn = srv->Connections;
+ conn;
+ conn = conn->Next)
+ {
+ LOG("conn->Node.ImplInt = %i", conn->Node.ImplInt);
+ if(conn->Node.ImplInt == id) break;
+ }
+ SHORTREL( &srv->lConnections );
+
+ // If not found, ret NULL
+ if(!conn) {
+ LOG("Connection %i not found", id);
+ LEAVE('n');
+ return NULL;
+ }
}
-
- Log_Debug("TCP", "srv->Connections = %p", srv->Connections);
- Log_Debug("TCP", "srv->NewConnections = %p", srv->NewConnections);
- Log_Debug("TCP", "srv->ConnectionsTail = %p", srv->ConnectionsTail);
-
- // Search
- SHORTLOCK( &srv->lConnections );
- for(conn = srv->Connections;
- conn;
- conn = conn->Next)
+ // Empty Name - Check for a new connection and if it's there, open it
+ else
{
- LOG("conn->Node.ImplInt = %i", conn->Node.ImplInt);
- if(conn->Node.ImplInt == id) break;
- }
- SHORTREL( &srv->lConnections );
-
- // If not found, ret NULL
- if(!conn) {
- LOG("Connection %i not found", id);
- LEAVE('n');
- return NULL;
+ SHORTLOCK( &srv->lConnections );
+ conn = srv->NewConnections;
+ if( conn != NULL )
+ srv->NewConnections = conn->Next;
+ VFS_MarkAvaliable( Node, srv->NewConnections != NULL );
+ SHORTREL( &srv->lConnections );
+ if( !conn ) {
+ LOG("No new connections");
+ LEAVE('n');
+ return NULL;
+ }
}
-
+
// Return node
LEAVE('p', &conn->Node);
return &conn->Node;
conn->Node.ImplPtr = conn;
conn->Node.NumACLs = 1;
conn->Node.ACLs = &gVFS_ACL_EveryoneRW;
- conn->Node.Read = TCP_Client_Read;
- conn->Node.Write = TCP_Client_Write;
- conn->Node.IOCtl = TCP_Client_IOCtl;
- conn->Node.Close = TCP_Client_Close;
+ conn->Node.Type = &gTCP_ClientNodeType;
conn->RecievedBuffer = RingBuffer_Create( TCP_RECIEVE_BUFFER_SIZE );
#if 0
/**
* \brief Send a data packet on a connection
*/
-void TCP_INT_SendDataPacket(tTCPConnection *Connection, size_t Length, void *Data)
+void TCP_INT_SendDataPacket(tTCPConnection *Connection, size_t Length, const void *Data)
{
char buf[sizeof(tTCPHeader)+Length];
tTCPHeader *packet = (void*)buf;
/**
* \brief Send some bytes on a connection
*/
-Uint64 TCP_Client_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+Uint64 TCP_Client_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer)
{
tTCPConnection *conn = Node->ImplPtr;
size_t rem = Length;