srv->NewConnections = conn;
VFS_MarkAvaliable( &srv->Node, 1 );
SHORTREL(&srv->lConnections);
+ Semaphore_Signal(&srv->WaitingConnections, 1);
// Send the SYN ACK
hdr->Flags |= TCP_FLAG_ACK;
// Get length of data
dataLen = Length - (Header->DataOffset>>4)*4;
LOG("dataLen = %i", dataLen);
-// Log_Debug("TCP", "State %i, dataLen = %x", Connection->State, dataLen);
+ Log_Debug("TCP", "State %i, dataLen = %x", Connection->State, dataLen);
//
// State Machine
if( Header->Flags & TCP_FLAG_SYN )
{
Connection->NextSequenceRcv ++;
- 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;
- TCP_SendPacket( Connection, Header, 0, NULL );
if( Header->Flags & TCP_FLAG_ACK )
{
Log_Log("TCP", "ACKing SYN-ACK");
Connection->State = TCP_ST_OPEN;
+ VFS_MarkFull(&Connection->Node, 0);
}
else
{
Log_Log("TCP", "ACKing SYN");
Connection->State = TCP_ST_SYN_RCVD;
}
+ 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;
+ TCP_SendPacket( Connection, Header, 0, NULL );
}
break;
if( Header->Flags & TCP_FLAG_ACK )
{
// TODO: Handle max half-open limit
- Connection->State = TCP_ST_OPEN;
Log_Log("TCP", "Connection fully opened");
+ Connection->State = TCP_ST_OPEN;
+ VFS_MarkFull(&Connection->Node, 0);
}
break;
}
Connection->NextSequenceRcv ++; // TODO: Is this right? (empty packet counts as one byte)
Log_Log("TCP", "Empty Packet, inc and ACK the current sequence number");
+ TCP_INT_SendACK(Connection);
+ #if 0
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, Header, 0, NULL );
+ #endif
return ;
}
sequence_num = ntohl(Header->SequenceNumber);
- LOG("TCP", "0x%08x <= 0x%08x < 0x%08x",
+ LOG("0x%08x <= 0x%08x < 0x%08x",
Connection->NextSequenceRcv,
ntohl(Header->SequenceNumber),
Connection->NextSequenceRcv + TCP_WINDOW_SIZE
ENTER("pNode iPos", Node, Pos);
Log_Log("TCP", "Thread %i waiting for a connection", Threads_GetTID());
- for(;;)
- {
- SHORTLOCK( &srv->lConnections );
- if( srv->NewConnections != NULL ) break;
- SHORTREL( &srv->lConnections );
- Threads_Yield(); // TODO: Sleep until poked
- }
+ Semaphore_Wait( &srv->WaitingConnections, 1 );
-
+ SHORTLOCK(&srv->lConnections);
// Increment the new list (the current connection is still on the
// normal list)
conn = srv->NewConnections;
conn->Node.NumACLs = 1;
conn->Node.ACLs = &gVFS_ACL_EveryoneRW;
conn->Node.Type = &gTCP_ClientNodeType;
+ conn->Node.BufferFull = 1; // Cleared when connection opens
conn->RecievedBuffer = RingBuffer_Create( TCP_RECIEVE_BUFFER_SIZE );
#if 0
ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
LOG("conn = %p {State:%i}", conn, conn->State);
- // Check if connection is estabilishing
- // - TODO: Sleep instead (maybe using VFS_SelectNode to wait for the
- // data to be availiable
- while( conn->State == TCP_ST_SYN_RCVD || conn->State == TCP_ST_SYN_SENT )
- Threads_Yield();
-
- // If the conneciton is not open, then clean out the recieved buffer
- if( conn->State != TCP_ST_OPEN )
+ // If the connection has been closed (state > ST_OPEN) then clear
+ // any stale data in the buffer (until it is empty (until it is empty))
+ if( conn->State > TCP_ST_OPEN )
{
Mutex_Acquire( &conn->lRecievedPackets );
len = RingBuffer_Read( Buffer, conn->RecievedBuffer, Length );
// Buffer, Length);
// #endif
- // Check if connection is open
- while( conn->State == TCP_ST_SYN_RCVD || conn->State == TCP_ST_SYN_SENT )
- Threads_Yield();
-
- if( conn->State != TCP_ST_OPEN ) {
+ // Don't allow a write to a closed connection
+ if( conn->State > TCP_ST_OPEN ) {
VFS_MarkError(Node, 1);
LEAVE('i', -1);
return -1;
}
+ // Wait
+ VFS_SelectNode(Node, VFS_SELECT_WRITE|VFS_SELECT_ERROR, NULL, "TCP_Client_Write");
+
do
{
int len = (rem < TCP_MAX_PACKET_SIZE) ? rem : TCP_MAX_PACKET_SIZE;
LEAVE_RET('i', 0);
{
- tTime timeout_end = now() + conn->Interface->TimeoutDelay;
+ tTime timeout = conn->Interface->TimeoutDelay;
TCP_StartConnection(conn);
- // TODO: Wait for connection to open
- while( conn->State == TCP_ST_SYN_SENT && timeout_end > now() ) {
- Threads_Yield();
- }
+ VFS_SelectNode(&conn->Node, VFS_SELECT_WRITE, &timeout, "TCP Connection");
if( conn->State == TCP_ST_SYN_SENT )
LEAVE_RET('i', 0);
}
while( conn->State == TCP_ST_FIN_WAIT1 ) Threads_Yield();
break;
default:
- Log_Warning("TCP", "Unhandled connection state in TCP_Client_Close");
+ Log_Warning("TCP", "Unhandled connection state %i in TCP_Client_Close",
+ conn->State);
break;
}