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
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",
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);
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 ;
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
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);
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 ++;
}
}
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;
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;
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;
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);
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;
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
*/
return 0;
case 7: // Connect
- if(conn->LocalPort == -1)
+ if(conn->LocalPort == 0xFFFF)
conn->LocalPort = TCP_GetUnusedPort();
if(conn->RemotePort == -1)
return 0;
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);
}