X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Modules%2FIPStack%2Ftcp.c;h=8b486d23aecfc89fdcfdcaae1968f05e63e33b99;hb=25f7e9ab0f31ca486c0c981a406d381e160637a4;hp=a6fb60e44d7d7cdf9b80752702af9146874c005e;hpb=7d41780946656e59eac1771e667ddf281ea73f63;p=tpg%2Facess2.git diff --git a/Modules/IPStack/tcp.c b/Modules/IPStack/tcp.c index a6fb60e4..8b486d23 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; @@ -64,30 +64,6 @@ void TCP_Initialise() IPv4_RegisterCallback(IP4PROT_TCP, TCP_GetPacket); } -/** - * \brief Open a connection to another host using TCP - * \param Conn Connection structure - */ -void TCP_StartConnection(tTCPConnection *Conn) -{ - tTCPHeader hdr; - - Conn->State = TCP_ST_SYN_SENT; - - hdr.SourcePort = htons(Conn->LocalPort); - hdr.DestPort = htons(Conn->RemotePort); - Conn->NextSequenceSend = rand(); - hdr.SequenceNumber = htonl(Conn->NextSequenceSend); - hdr.DataOffset = (sizeof(tTCPHeader)/4) << 4; - 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 ); - return ; -} - /** * \brief Sends a packet from the specified connection, calculating the checksums * \param Conn Connection @@ -148,6 +124,16 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe Log_Log("TCP", "Checksum = 0x%x", htons(hdr->Checksum)); Log_Log("TCP", "UrgentPointer = 0x%x", htons(hdr->UrgentPointer)); */ + Log_Log("TCP", "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 ) { @@ -237,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 @@ -245,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); + SHORTLOCK(&srv->lConnections); // Send the SYN ACK hdr->Flags |= TCP_FLAG_ACK; @@ -302,7 +288,7 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head if( Connection->State == TCP_ST_SYN_SENT ) { - if( Header->Flags & (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); @@ -313,8 +299,8 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head Header->DataOffset = (sizeof(tTCPHeader)/4) << 4; Log_Log("TCP", "ACKing SYN-ACK"); TCP_SendPacket( Connection, sizeof(tTCPHeader), Header ); + Connection->State = TCP_ST_OPEN; } - Connection->State = TCP_ST_OPEN; } // Get length of data @@ -329,7 +315,8 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head // TODO: Check what to do here if(Header->Flags & TCP_FLAG_FIN) { if( Connection->State == TCP_ST_FIN_SENT ) { - + Connection->State = TCP_ST_FINISHED; + return ; } else { Connection->State = TCP_ST_FINISHED; @@ -370,7 +357,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) @@ -382,7 +369,7 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head else Connection->FuturePackets = pkt; pkt->Next = tmp; - RELEASE( &Connection->lFuturePackets ); + SHORTREL( &Connection->lFuturePackets ); } else { @@ -418,7 +405,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)", @@ -430,7 +417,7 @@ void TCP_INT_AppendRecieved(tTCPConnection *Connection, tTCPStoredPacket *Pkt) RingBuffer_Write( Connection->RecievedBuffer, Pkt->Data, Pkt->Length ); - RELEASE( &Connection->lRecievedPackets ); + Mutex_Release( &Connection->lRecievedPackets ); } /** @@ -448,14 +435,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; } @@ -466,7 +453,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); @@ -561,10 +548,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; } @@ -586,10 +573,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; } @@ -599,12 +586,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'); @@ -618,7 +605,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; @@ -640,7 +627,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) @@ -648,7 +635,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) { @@ -730,10 +717,12 @@ tVFS_Node *TCP_Client_Init(tInterface *Interface) conn->Node.IOCtl = TCP_Client_IOCtl; conn->Node.Close = TCP_Client_Close; - LOCK(&glTCP_OutbountCons); + conn->RecievedBuffer = RingBuffer_Create( TCP_RECIEVE_BUFFER_SIZE ); + + SHORTLOCK(&glTCP_OutbountCons); conn->Next = gTCP_OutbountCons; gTCP_OutbountCons = conn; - RELEASE(&glTCP_OutbountCons); + SHORTREL(&glTCP_OutbountCons); return &conn->Node; } @@ -750,9 +739,12 @@ Uint64 TCP_Client_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buff size_t len; ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); + LOG("conn = %p", conn); + LOG("conn->State = %i", conn->State); // Check if connection is open - while( conn->State == TCP_ST_HALFOPEN ) Threads_Yield(); + while( conn->State == TCP_ST_HALFOPEN || conn->State == TCP_ST_SYN_SENT ) + Threads_Yield(); if( conn->State != TCP_ST_OPEN ) { LEAVE('i', 0); return 0; @@ -762,11 +754,11 @@ Uint64 TCP_Client_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buff for(;;) { // 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; } @@ -774,7 +766,7 @@ Uint64 TCP_Client_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buff len = RingBuffer_Read( destbuf, conn->RecievedBuffer, Length ); // Release the lock (we don't need it any more) - RELEASE( &conn->lRecievedPackets ); + Mutex_Release( &conn->lRecievedPackets ); LEAVE('i', len); return len; @@ -794,10 +786,9 @@ void TCP_INT_SendDataPacket(tTCPConnection *Connection, size_t Length, void *Dat packet->DataOffset = (sizeof(tTCPHeader)/4)*16; packet->WindowSize = TCP_WINDOW_SIZE; - //packet->AcknowlegementNumber = htonl(Connection->NextSequenceRcv); - packet->AcknowlegementNumber = 0; + packet->AcknowlegementNumber = htonl(Connection->NextSequenceRcv); packet->SequenceNumber = htonl(Connection->NextSequenceSend); - packet->Flags = TCP_FLAG_PSH; // Hey, ACK if you can! + packet->Flags = TCP_FLAG_PSH|TCP_FLAG_ACK; // Hey, ACK if you can! memcpy(packet->Options, Data, Length); @@ -817,7 +808,8 @@ Uint64 TCP_Client_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buf ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); // Check if connection is open - while( conn->State == TCP_ST_HALFOPEN ) Threads_Yield(); + while( conn->State == TCP_ST_HALFOPEN || conn->State == TCP_ST_SYN_SENT ) + Threads_Yield(); if( conn->State != TCP_ST_OPEN ) { LEAVE('i', 0); return 0; @@ -835,6 +827,32 @@ Uint64 TCP_Client_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buf return Length; } +/** + * \brief Open a connection to another host using TCP + * \param Conn Connection structure + */ +void TCP_StartConnection(tTCPConnection *Conn) +{ + tTCPHeader hdr = {0}; + + Conn->State = TCP_ST_SYN_SENT; + + hdr.SourcePort = htons(Conn->LocalPort); + hdr.DestPort = htons(Conn->RemotePort); + Conn->NextSequenceSend = rand(); + hdr.SequenceNumber = htonl(Conn->NextSequenceSend); + hdr.DataOffset = (sizeof(tTCPHeader)/4) << 4; + hdr.Flags = TCP_FLAG_SYN; + hdr.WindowSize = htons(TCP_WINDOW_SIZE); // Max + hdr.Checksum = 0; // TODO + + TCP_SendPacket( Conn, sizeof(tTCPHeader), &hdr ); + + Conn->NextSequenceSend ++; + Conn->State = TCP_ST_SYN_SENT; + return ; +} + /** * \brief Control a client socket */ @@ -881,7 +899,7 @@ int TCP_Client_IOCtl(tVFS_Node *Node, int ID, void *Data) return 0; case 7: // Connect - if(conn->LocalPort == -1) + if(conn->LocalPort == 0xFFFF) conn->LocalPort = TCP_GetUnusedPort(); if(conn->RemotePort == -1) return 0; @@ -895,5 +913,23 @@ int TCP_Client_IOCtl(tVFS_Node *Node, int ID, void *Data) void TCP_Client_Close(tVFS_Node *Node) { - free(Node->ImplPtr); + tTCPConnection *conn = Node->ImplPtr; + tTCPHeader packet; + + packet.SourcePort = htons(conn->LocalPort); + packet.DestPort = htons(conn->RemotePort); + packet.DataOffset = (sizeof(tTCPHeader)/4)*16; + packet.WindowSize = TCP_WINDOW_SIZE; + + packet.AcknowlegementNumber = 0; + packet.SequenceNumber = htonl(conn->NextSequenceSend); + packet.Flags = TCP_FLAG_FIN; + + conn->State = TCP_ST_FIN_SENT; + + TCP_SendPacket( conn, sizeof(tTCPHeader), &packet ); + + while( conn->State == TCP_ST_FIN_SENT ) Threads_Yield(); + + free(conn); }