X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;ds=sidebyside;f=Modules%2FIPStack%2Ftcp.c;h=23d028c9de9f75f069acd85b5b373f0b922b406f;hb=fe2794b4f932c0755674493b6a6da4b60a5c2433;hp=90f3dc9663d9fe62cb8abe7720fbc5d050203ef0;hpb=b98fbd4e9c71447d81fc9bd643fb174c76346e0f;p=tpg%2Facess2.git diff --git a/Modules/IPStack/tcp.c b/Modules/IPStack/tcp.c index 90f3dc96..23d028c9 100644 --- a/Modules/IPStack/tcp.c +++ b/Modules/IPStack/tcp.c @@ -28,7 +28,7 @@ Uint16 TCP_GetUnusedPort(); // --- Server tVFS_Node *TCP_Server_Init(tInterface *Interface); char *TCP_Server_ReadDir(tVFS_Node *Node, int Pos); -tVFS_Node *TCP_Server_FindDir(tVFS_Node *Node, char *Name); +tVFS_Node *TCP_Server_FindDir(tVFS_Node *Node, const char *Name); int TCP_Server_IOCtl(tVFS_Node *Node, int ID, void *Data); void TCP_Server_Close(tVFS_Node *Node); // --- Client @@ -44,9 +44,9 @@ tSocketFile gTCP_ClientFile = {NULL, "tcpc", TCP_Client_Init}; // === GLOBALS === int giTCP_NumHalfopen = 0; -tSpinlock glTCP_Listeners; +tShortSpinlock glTCP_Listeners; tTCPListener *gTCP_Listeners; -tSpinlock glTCP_OutbountCons; +tShortSpinlock glTCP_OutbountCons; tTCPConnection *gTCP_OutbountCons; Uint32 gaTCP_PortBitmap[0x800]; int giTCP_NextOutPort = TCP_MIN_DYNPORT; @@ -79,12 +79,12 @@ void TCP_SendPacket( tTCPConnection *Conn, size_t Length, tTCPHeader *Data ) case 4: // Append IPv4 Pseudo Header buflen = 4 + 4 + 4 + ((Length+1)&~1); buf = malloc( buflen ); - buf[0] = Conn->Interface->IP4.Address.L; + buf[0] = ((tIPv4*)Conn->Interface->Address)->L; buf[1] = Conn->RemoteIP.v4.L; buf[2] = (htons(Length)<<16) | (6<<8) | 0; Data->Checksum = 0; memcpy( &buf[3], Data, Length ); - Data->Checksum = IPv4_Checksum( buf, buflen ); + Data->Checksum = htons( IPv4_Checksum( buf, buflen ) ); free(buf); IPv4_SendPacket(Conn->Interface, Conn->RemoteIP.v4, IP4PROT_TCP, 0, Length, Data); break; @@ -104,26 +104,36 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe tTCPListener *srv; tTCPConnection *conn; - Log_Log("TCP", "SourcePort = %i, DestPort = %i", + Log_Log("TCP", "TCP_GetPacket: SourcePort = %i, DestPort = %i", ntohs(hdr->SourcePort), ntohs(hdr->DestPort)); /* - Log_Log("TCP", "SequenceNumber = 0x%x", ntohl(hdr->SequenceNumber)); - Log_Log("TCP", "AcknowlegementNumber = 0x%x", ntohl(hdr->AcknowlegementNumber)); - Log_Log("TCP", "DataOffset = %i", hdr->DataOffset >> 4); - Log_Log("TCP", "Flags = {"); - Log_Log("TCP", " CWR = %B, ECE = %B", + 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: Flags = {"); + Log_Log("TCP", "TCP_GetPacket: CWR = %B, ECE = %B", !!(hdr->Flags & TCP_FLAG_CWR), !!(hdr->Flags & TCP_FLAG_ECE)); - Log_Log("TCP", " URG = %B, ACK = %B", + Log_Log("TCP", "TCP_GetPacket: URG = %B, ACK = %B", !!(hdr->Flags & TCP_FLAG_URG), !!(hdr->Flags & TCP_FLAG_ACK)); - Log_Log("TCP", " PSH = %B, RST = %B", + Log_Log("TCP", "TCP_GetPacket: PSH = %B, RST = %B", !!(hdr->Flags & TCP_FLAG_PSH), !!(hdr->Flags & TCP_FLAG_RST)); - Log_Log("TCP", " SYN = %B, FIN = %B", + Log_Log("TCP", "TCP_GetPacket: SYN = %B, FIN = %B", !!(hdr->Flags & TCP_FLAG_SYN), !!(hdr->Flags & TCP_FLAG_FIN)); - Log_Log("TCP", "}"); - Log_Log("TCP", "WindowSize = %i", htons(hdr->WindowSize)); - Log_Log("TCP", "Checksum = 0x%x", htons(hdr->Checksum)); - Log_Log("TCP", "UrgentPointer = 0x%x", htons(hdr->UrgentPointer)); + Log_Log("TCP", "TCP_GetPacket: }"); + 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", + (hdr->Flags & TCP_FLAG_CWR) ? "CWR " : "", + (hdr->Flags & TCP_FLAG_ECE) ? "ECE " : "", + (hdr->Flags & TCP_FLAG_URG) ? "URG " : "", + (hdr->Flags & TCP_FLAG_ACK) ? "ACK " : "", + (hdr->Flags & TCP_FLAG_PSH) ? "PSH " : "", + (hdr->Flags & TCP_FLAG_RST) ? "RST " : "", + (hdr->Flags & TCP_FLAG_SYN) ? "SYN " : "", + (hdr->Flags & TCP_FLAG_FIN) ? "FIN " : "" + ); if( Length > (hdr->DataOffset >> 4)*4 ) { @@ -145,17 +155,17 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe // Check the destination port if(srv->Port != htons(hdr->DestPort)) continue; - Log_Log("TCP", "Matches server %p", srv); + Log_Log("TCP", "TCP_GetPacket: Matches server %p", srv); // Is this in an established connection? for( conn = srv->Connections; conn; conn = conn->Next ) { - Log_Log("TCP", "conn->Interface(%p) == Interface(%p)", + 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; // Check Source Port - Log_Log("TCP", "conn->RemotePort(%i) == hdr->SourcePort(%i)", + Log_Log("TCP", "TCP_GetPacket: conn->RemotePort(%i) == hdr->SourcePort(%i)", conn->RemotePort, ntohs(hdr->SourcePort)); if(conn->RemotePort != ntohs(hdr->SourcePort)) continue; @@ -165,17 +175,17 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe if(conn->Interface->Type == 4 && !IP4_EQU(conn->RemoteIP.v4, *(tIPv4*)Address)) continue; - Log_Log("TCP", "Matches connection %p", conn); + Log_Log("TCP", "TCP_GetPacket: Matches connection %p", conn); // We have a response! TCP_INT_HandleConnectionPacket(conn, hdr, Length); return; } - Log_Log("TCP", "Opening Connection"); + Log_Log("TCP", "TCP_GetPacket: Opening Connection"); // Open a new connection (well, check that it's a SYN) if(hdr->Flags != TCP_FLAG_SYN) { - Log_Log("TCP", "Packet is not a SYN"); + Log_Log("TCP", "TCP_GetPacket: Packet is not a SYN"); return ; } @@ -213,7 +223,7 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe // it, just in case // Oh, wait, there is a case where a wildcard can be used // (srv->Interface == NULL) so having the lock is a good idea - LOCK(&srv->lConnections); + SHORTLOCK(&srv->lConnections); if( !srv->Connections ) srv->Connections = conn; else @@ -221,7 +231,7 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe srv->ConnectionsTail = conn; if(!srv->NewConnections) srv->NewConnections = conn; - RELEASE(&srv->lConnections); + SHORTREL(&srv->lConnections); // Send the SYN ACK hdr->Flags |= TCP_FLAG_ACK; @@ -258,7 +268,7 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe } } - Log_Log("TCP", "No Match"); + Log_Log("TCP", "TCP_GetPacket: No Match"); } /** @@ -272,14 +282,16 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head tTCPStoredPacket *pkt; int dataLen; + // Syncronise sequence values if(Header->Flags & TCP_FLAG_SYN) { Connection->NextSequenceRcv = ntohl(Header->SequenceNumber) + 1; } + // Handle a server replying to our initial SYN if( Connection->State == TCP_ST_SYN_SENT ) { - if( (Header->Flags & (TCP_FLAG_SYN|TCP_FLAG_ACK)) == (TCP_FLAG_SYN|TCP_FLAG_ACK) ) { - + if( (Header->Flags & (TCP_FLAG_SYN|TCP_FLAG_ACK)) == (TCP_FLAG_SYN|TCP_FLAG_ACK) ) + { Header->DestPort = Header->SourcePort; Header->SourcePort = htons(Connection->LocalPort); Header->AcknowlegementNumber = htonl(Connection->NextSequenceRcv); @@ -293,6 +305,13 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head } } + // Handle a client confirming the connection + if( Connection->State == TCP_ST_HALFOPEN && (Header->Flags & TCP_FLAG_ACK) ) + { + Connection->State = TCP_ST_OPEN; + Log_Log("TCP", "Connection fully opened"); + } + // Get length of data dataLen = Length - (Header->DataOffset>>4)*4; Log_Log("TCP", "HandleConnectionPacket - dataLen = %i", dataLen); @@ -320,6 +339,7 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head } } + // Check for an empty packet if(dataLen == 0) { Log_Log("TCP", "Empty Packet"); return ; @@ -347,7 +367,7 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head pkt->Sequence, Connection->NextSequenceRcv); // No? Well, let's cache it and look at it later - LOCK( &Connection->lFuturePackets ); + SHORTLOCK( &Connection->lFuturePackets ); for(tmp = Connection->FuturePackets; tmp; prev = tmp, tmp = tmp->Next) @@ -359,7 +379,7 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head else Connection->FuturePackets = pkt; pkt->Next = tmp; - RELEASE( &Connection->lFuturePackets ); + SHORTREL( &Connection->lFuturePackets ); } else { @@ -395,7 +415,7 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head */ void TCP_INT_AppendRecieved(tTCPConnection *Connection, tTCPStoredPacket *Pkt) { - LOCK( &Connection->lRecievedPackets ); + Mutex_Acquire( &Connection->lRecievedPackets ); if(Connection->RecievedBuffer->Length + Pkt->Length > Connection->RecievedBuffer->Space ) { Log_Error("TCP", "Buffer filled, packet dropped (%s)", @@ -406,8 +426,12 @@ void TCP_INT_AppendRecieved(tTCPConnection *Connection, tTCPStoredPacket *Pkt) } RingBuffer_Write( Connection->RecievedBuffer, Pkt->Data, Pkt->Length ); + + #if USE_SELECT + VFS_MarkAvaliable(&Connection->Node, 1); + #endif - RELEASE( &Connection->lRecievedPackets ); + Mutex_Release( &Connection->lRecievedPackets ); } /** @@ -425,14 +449,14 @@ void TCP_INT_UpdateRecievedFromFuture(tTCPConnection *Connection) { prev = NULL; // Look for the next expected packet in the cache. - LOCK( &Connection->lFuturePackets ); + SHORTLOCK( &Connection->lFuturePackets ); for(pkt = Connection->FuturePackets; pkt && pkt->Sequence < Connection->NextSequenceRcv; prev = pkt, pkt = pkt->Next); // If we can't find the expected next packet, stop looking if(!pkt || pkt->Sequence > Connection->NextSequenceRcv) { - RELEASE( &Connection->lFuturePackets ); + SHORTREL( &Connection->lFuturePackets ); return; } @@ -443,7 +467,7 @@ void TCP_INT_UpdateRecievedFromFuture(tTCPConnection *Connection) Connection->FuturePackets = pkt->Next; // Release list - RELEASE( &Connection->lFuturePackets ); + SHORTREL( &Connection->lFuturePackets ); // Looks like we found one TCP_INT_AppendRecieved(Connection, pkt); @@ -538,10 +562,10 @@ tVFS_Node *TCP_Server_Init(tInterface *Interface) srv->Node.IOCtl = TCP_Server_IOCtl; srv->Node.Close = TCP_Server_Close; - LOCK(&glTCP_Listeners); + SHORTLOCK(&glTCP_Listeners); srv->Next = gTCP_Listeners; gTCP_Listeners = srv; - RELEASE(&glTCP_Listeners); + SHORTREL(&glTCP_Listeners); return &srv->Node; } @@ -563,10 +587,10 @@ char *TCP_Server_ReadDir(tVFS_Node *Node, int Pos) Log_Log("TCP", "Thread %i waiting for a connection", Threads_GetTID()); for(;;) { - LOCK( &srv->lConnections ); + SHORTLOCK( &srv->lConnections ); if( srv->NewConnections != NULL ) break; - RELEASE( &srv->lConnections ); - Threads_Yield(); + SHORTREL( &srv->lConnections ); + Threads_Yield(); // TODO: Sleep until poked continue; } @@ -576,12 +600,12 @@ char *TCP_Server_ReadDir(tVFS_Node *Node, int Pos) conn = srv->NewConnections; srv->NewConnections = conn->Next; + SHORTREL( &srv->lConnections ); + LOG("conn = %p", conn); LOG("srv->Connections = %p", srv->Connections); LOG("srv->NewConnections = %p", srv->NewConnections); LOG("srv->ConnectionsTail = %p", srv->ConnectionsTail); - - RELEASE( &srv->lConnections ); ret = malloc(9); itoa(ret, conn->Node.ImplInt, 16, 8, '0'); @@ -595,7 +619,7 @@ char *TCP_Server_ReadDir(tVFS_Node *Node, int Pos) * \param Node Server node * \param Name Hexadecimal ID of the node */ -tVFS_Node *TCP_Server_FindDir(tVFS_Node *Node, char *Name) +tVFS_Node *TCP_Server_FindDir(tVFS_Node *Node, const char *Name) { tTCPConnection *conn; tTCPListener *srv = Node->ImplPtr; @@ -617,7 +641,7 @@ tVFS_Node *TCP_Server_FindDir(tVFS_Node *Node, char *Name) Log_Debug("TCP", "srv->ConnectionsTail = %p", srv->ConnectionsTail); // Search - LOCK( &srv->lConnections ); + SHORTLOCK( &srv->lConnections ); for(conn = srv->Connections; conn; conn = conn->Next) @@ -625,7 +649,7 @@ tVFS_Node *TCP_Server_FindDir(tVFS_Node *Node, char *Name) LOG("conn->Node.ImplInt = %i", conn->Node.ImplInt); if(conn->Node.ImplInt == id) break; } - RELEASE( &srv->lConnections ); + SHORTREL( &srv->lConnections ); // If not found, ret NULL if(!conn) { @@ -709,10 +733,10 @@ tVFS_Node *TCP_Client_Init(tInterface *Interface) conn->RecievedBuffer = RingBuffer_Create( TCP_RECIEVE_BUFFER_SIZE ); - LOCK(&glTCP_OutbountCons); + SHORTLOCK(&glTCP_OutbountCons); conn->Next = gTCP_OutbountCons; gTCP_OutbountCons = conn; - RELEASE(&glTCP_OutbountCons); + SHORTREL(&glTCP_OutbountCons); return &conn->Node; } @@ -743,20 +767,32 @@ Uint64 TCP_Client_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buff // Poll packets for(;;) { + #if USE_SELECT + // Wait + VFS_SelectNode(Node, VFS_SELECT_READ, NULL); + // Lock list and read + Mutex_Acquire( &conn->lRecievedPackets ); + #else // Lock list and check if there is a packet - LOCK( &conn->lRecievedPackets ); + Mutex_Acquire( &conn->lRecievedPackets ); if( conn->RecievedBuffer->Length == 0 ) { // If not, release the lock, yield and try again - RELEASE( &conn->lRecievedPackets ); - Threads_Yield(); + Mutex_Release( &conn->lRecievedPackets ); + Threads_Yield(); // TODO: Less expensive wait continue; } + #endif // Attempt to read all `Length` bytes len = RingBuffer_Read( destbuf, conn->RecievedBuffer, Length ); + #if USE_SELECT + if( conn->RecievedBuffer->Length == 0 ) + VFS_MarkAvaliable(Node, 0); + #endif + // Release the lock (we don't need it any more) - RELEASE( &conn->lRecievedPackets ); + Mutex_Release( &conn->lRecievedPackets ); LEAVE('i', len); return len; @@ -823,7 +859,7 @@ Uint64 TCP_Client_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buf */ void TCP_StartConnection(tTCPConnection *Conn) { - tTCPHeader hdr; + tTCPHeader hdr = {0}; Conn->State = TCP_ST_SYN_SENT; @@ -835,7 +871,6 @@ void TCP_StartConnection(tTCPConnection *Conn) hdr.Flags = TCP_FLAG_SYN; hdr.WindowSize = htons(TCP_WINDOW_SIZE); // Max hdr.Checksum = 0; // TODO - hdr.UrgentPointer = 0; TCP_SendPacket( Conn, sizeof(tTCPHeader), &hdr ); @@ -850,53 +885,59 @@ void TCP_StartConnection(tTCPConnection *Conn) int TCP_Client_IOCtl(tVFS_Node *Node, int ID, void *Data) { tTCPConnection *conn = Node->ImplPtr; + + ENTER("pNode iID pData", Node, ID, Data); switch(ID) { case 4: // Get/Set local port if(!Data) - return conn->LocalPort; + LEAVE_RET('i', conn->LocalPort); if(conn->State != TCP_ST_CLOSED) - return -1; + LEAVE_RET('i', -1); if(!CheckMem(Data, sizeof(Uint16))) - return -1; + LEAVE_RET('i', -1); if(Threads_GetUID() != 0 && *(Uint16*)Data < 1024) - return -1; + LEAVE_RET('i', -1); conn->LocalPort = *(Uint16*)Data; - return 0; + LEAVE_RET('i', conn->LocalPort); case 5: // Get/Set remote port - if(!Data) return conn->RemotePort; - if(conn->State != TCP_ST_CLOSED) return -1; - if(!CheckMem(Data, sizeof(Uint16))) return -1; + if(!Data) LEAVE_RET('i', conn->RemotePort); + if(conn->State != TCP_ST_CLOSED) LEAVE_RET('i', -1); + if(!CheckMem(Data, sizeof(Uint16))) LEAVE_RET('i', -1); conn->RemotePort = *(Uint16*)Data; - return 0; + LEAVE_RET('i', conn->RemotePort); case 6: // Set Remote IP if( conn->State != TCP_ST_CLOSED ) - return -1; + LEAVE_RET('i', -1); if( conn->Interface->Type == 4 ) { - if(!CheckMem(Data, sizeof(tIPv4))) return -1; + if(!CheckMem(Data, sizeof(tIPv4))) LEAVE_RET('i', -1); conn->RemoteIP.v4 = *(tIPv4*)Data; } else if( conn->Interface->Type == 6 ) { - if(!CheckMem(Data, sizeof(tIPv6))) return -1; + if(!CheckMem(Data, sizeof(tIPv6))) LEAVE_RET('i', -1); conn->RemoteIP.v6 = *(tIPv6*)Data; } - return 0; + LEAVE_RET('i', 0); case 7: // Connect if(conn->LocalPort == 0xFFFF) conn->LocalPort = TCP_GetUnusedPort(); if(conn->RemotePort == -1) - return 0; + LEAVE_RET('i', 0); TCP_StartConnection(conn); - return 1; + LEAVE_RET('i', 1); + + // Get recieve buffer length + case 8: + LEAVE_RET('i', conn->RecievedBuffer->Length); } return 0; @@ -907,6 +948,8 @@ void TCP_Client_Close(tVFS_Node *Node) tTCPConnection *conn = Node->ImplPtr; tTCPHeader packet; + ENTER("pNode", Node); + packet.SourcePort = htons(conn->LocalPort); packet.DestPort = htons(conn->RemotePort); packet.DataOffset = (sizeof(tTCPHeader)/4)*16; @@ -923,4 +966,6 @@ void TCP_Client_Close(tVFS_Node *Node) while( conn->State == TCP_ST_FIN_SENT ) Threads_Yield(); free(conn); + + LEAVE('-'); }