X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Modules%2FIPStack%2Ftcp.c;h=90f3dc9663d9fe62cb8abe7720fbc5d050203ef0;hb=95a530ccd8a001ca1488d7265268cf8bee2b650e;hp=ed103ec99e461ab13c1ba286f4c2581e0e585731;hpb=ede46f1819c8b3c51d04829cac8bd95bcc602d8f;p=tpg%2Facess2.git diff --git a/Modules/IPStack/tcp.c b/Modules/IPStack/tcp.c index ed103ec9..90f3dc96 100644 --- a/Modules/IPStack/tcp.c +++ b/Modules/IPStack/tcp.c @@ -64,28 +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; - - hdr.SourcePort = Conn->LocalPort; - hdr.DestPort = Conn->RemotePort; - Conn->NextSequenceSend = rand(); - hdr.SequenceNumber = Conn->NextSequenceSend; - hdr.DataOffset = (sizeof(tTCPHeader)/4) << 4; - hdr.Flags = TCP_FLAG_SYN; - hdr.WindowSize = 0xFFFF; // 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 @@ -128,9 +106,9 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe Log_Log("TCP", "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", @@ -294,11 +272,27 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head tTCPStoredPacket *pkt; int dataLen; - Connection->State = TCP_ST_OPEN; if(Header->Flags & TCP_FLAG_SYN) { Connection->NextSequenceRcv = ntohl(Header->SequenceNumber) + 1; } + if( Connection->State == TCP_ST_SYN_SENT ) + { + 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); + Header->SequenceNumber = htonl(Connection->NextSequenceSend); + Header->WindowSize = htons(TCP_WINDOW_SIZE); + Header->Flags = TCP_FLAG_ACK; + Header->DataOffset = (sizeof(tTCPHeader)/4) << 4; + Log_Log("TCP", "ACKing SYN-ACK"); + TCP_SendPacket( Connection, sizeof(tTCPHeader), Header ); + Connection->State = TCP_ST_OPEN; + } + } + // Get length of data dataLen = Length - (Header->DataOffset>>4)*4; Log_Log("TCP", "HandleConnectionPacket - dataLen = %i", dataLen); @@ -308,6 +302,24 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head Log_Log("TCP", "Conn %p, Packet 0x%x ACKed", Connection, Header->AcknowlegementNumber); } + // 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; + Header->DestPort = Header->SourcePort; + Header->SourcePort = htons(Connection->LocalPort); + Header->AcknowlegementNumber = htonl(Connection->NextSequenceRcv); + Header->SequenceNumber = htonl(Connection->NextSequenceSend); + Header->Flags = TCP_FLAG_ACK; + TCP_SendPacket( Connection, sizeof(tTCPHeader), Header ); + return ; + } + } + if(dataLen == 0) { Log_Log("TCP", "Empty Packet"); return ; @@ -355,7 +367,7 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head TCP_INT_AppendRecieved(Connection, pkt); free(pkt); Log_Log("TCP", "0x%08x += %i", Connection->NextSequenceRcv, dataLen); - Connection->NextSequenceRcv += dataLen + 1; + Connection->NextSequenceRcv += dataLen; // TODO: This should be moved out of the watcher thread, // so that a single lost packet on one connection doesn't cause @@ -363,6 +375,8 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head TCP_INT_UpdateRecievedFromFuture(Connection); // ACK Packet + Header->DestPort = Header->SourcePort; + Header->SourcePort = htons(Connection->LocalPort); Header->AcknowlegementNumber = htonl(Connection->NextSequenceRcv); Header->SequenceNumber = htonl(Connection->NextSequenceSend); Header->WindowSize = htons(TCP_WINDOW_SIZE); @@ -370,6 +384,7 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head Header->Flags |= TCP_FLAG_ACK; // Add ACK Log_Log("TCP", "Sending ACK for 0x%08x", Connection->NextSequenceRcv); TCP_SendPacket( Connection, sizeof(tTCPHeader), Header ); + //Connection->NextSequenceSend ++; } } @@ -680,8 +695,8 @@ tVFS_Node *TCP_Client_Init(tInterface *Interface) conn->State = TCP_ST_CLOSED; conn->Interface = Interface; - conn->LocalPort = 0; - conn->RemotePort = 0; + conn->LocalPort = -1; + conn->RemotePort = -1; memset( &conn->RemoteIP, 0, sizeof(conn->RemoteIP) ); conn->Node.ImplPtr = conn; @@ -692,6 +707,8 @@ tVFS_Node *TCP_Client_Init(tInterface *Interface) conn->Node.IOCtl = TCP_Client_IOCtl; conn->Node.Close = TCP_Client_Close; + conn->RecievedBuffer = RingBuffer_Create( TCP_RECIEVE_BUFFER_SIZE ); + LOCK(&glTCP_OutbountCons); conn->Next = gTCP_OutbountCons; gTCP_OutbountCons = conn; @@ -712,8 +729,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 || conn->State == TCP_ST_SYN_SENT ) + Threads_Yield(); if( conn->State != TCP_ST_OPEN ) { LEAVE('i', 0); return 0; @@ -755,10 +776,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); @@ -778,6 +798,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 || conn->State == TCP_ST_SYN_SENT ) + Threads_Yield(); if( conn->State != TCP_ST_OPEN ) { LEAVE('i', 0); return 0; @@ -795,6 +817,33 @@ 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; + + 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 ); + + Conn->NextSequenceSend ++; + Conn->State = TCP_ST_SYN_SENT; + return ; +} + /** * \brief Control a client socket */ @@ -841,7 +890,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; @@ -855,5 +904,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); }