* \brief Open a connection to another host using TCP
*/
void TCP_StartConnection(tTCPConnection *Conn)
-{
+{
+ tTCPHeader hdr;
+
+ hdr->SourcePort = Conn->LocalPort;
+ hdr->DestPort = Conn->RemotePort;
+ hdr->SequenceNumber = rand();
+ hdr->DataOffset = (sizeof(tTCPHeader)+3)/4;
+ hdr->Flags = TCP_FLAG_SYN;
// SEND PACKET
// Send a TCP SYN to the target to open the connection
return ;
{
for( srv = gTCP_Listeners; srv; srv = srv->Next )
{
+ // Check if the server is active
+ if(srv->Port == 0) continue;
// Check the interface
if(srv->Interface && srv->Interface != Interface) continue;
// Check the destination port
srv->Interface = Interface;
srv->Port = 0;
+ srv->NextID = 0;
srv->Connections = NULL;
srv->Next = NULL;
srv->Node.ImplPtr = srv;
return &srv->Node;
}
+/**
+ * \brief Wait for a new connection and return the connection ID
+ * \note Blocks until a new connection is made
+ * \param Node Server node
+ * \param Pos Position (ignored)
+ */
char *TCP_Server_ReadDir(tVFS_Node *Node, int Pos)
{
- return NULL;
+ tTCPListener *srv = Node->ImplPtr;
+ tTCPConnection *conn;
+ char *ret;
+
+ while( srv->NewConnections == NULL ) Threads_Yield();
+
+ conn = srv->NewConnections;
+ srv->NewConnections = conn->Next;
+
+ ret = malloc(9);
+ itoa(ret, conn->ImplInt, 16, '0', 8);
+ return ret;
}
+/**
+ * \brief Gets a client connection node
+ * \param Node Server node
+ * \param Name Hexadecimal ID of the node
+ */
tVFS_Node *TCP_Server_FindDir(tVFS_Node *Node, char *Name)
{
return NULL;
switch(ID)
{
case 4: // Get/Set Port
- if(!Data)
+ if(!Data) // Get Port
return srv->Port;
- if(srv->Port)
+ if(srv->Port) // Wait, you can't CHANGE the port
return -1;
- if(!CheckMem(Data, sizeof(Uint16)))
+ if(!CheckMem(Data, sizeof(Uint16))) // Sanity check
return -1;
- if(Threads_GetUID() != 0 && *(Uint16*)Data < 1024)
+ // Permissions check
+ if(Threads_GetUID() != 0
+ && *(Uint16*)Data != 0
+ && *(Uint16*)Data < 1024)
return -1;
+ // TODO: Check if a port is in use
+
+ // Set Port
srv->Port = *(Uint16*)Data;
- if(srv->Port == 0)
+ if(srv->Port == 0) // Allocate a random port
srv->Port = TCP_GetUnusedPort();
- else
+ else // Else, mark this as used
TCP_AllocatePort(srv->Port);
return srv->Port;
}
struct sTCPListener
{
- struct sTCPListener *Next;
- Uint16 Port;
- tInterface *Interface;
- tVFS_Node Node;
- int NextID;
- tTCPConnection *Connections;
+ struct sTCPListener *Next; //!< Next server in the list
+ Uint16 Port; //!< Listening port (0 disables the server)
+ tInterface *Interface; //!< Listening Interface
+ tVFS_Node Node; //!< Server Directory node
+ int NextID; //!< Name of the next connection
+ tSpinlock lConnections; //!< Spinlock for connections
+ tTCPConnection *Connections; //!< Connections (linked list)
+ volatile tTCPConnection *NewConnections;
};
struct sTCPConnection
{
struct sTCPConnection *Next;
- int State;
- Uint16 LocalPort;
- Uint16 RemotePort;
- tVFS_Node Node;
+ int State; //!< Connection state (see ::eTCPConnectionState)
+ Uint16 LocalPort; //!< Local port
+ Uint16 RemotePort; //!< Remote port
+ tInterface *Interface; //!< Listening Interface
+ tVFS_Node Node; //!< Node
- int NextSequenceSend;
- int NextSequenceRcv;
+ int NextSequenceSend; //!< Next sequence value for outbound packets
+ int NextSequenceRcv; //!< Next expected sequence value for inbound
- int nQueuedPackets;
+ int nQueuedPackets; //!< Number of packets not ACKed
struct {
int Sequence;
void *Data;
- } *QueuedPackets;
+ } *QueuedPackets; //!< Non-ACKed packets
- int nFuturePackets;
+ int nFuturePackets; //!< Number of packets recieved that are out of sequence
struct {
int SequenceNum;
void *Data;
- } **FuturePackets;
+ } **FuturePackets; //!< Out of sequence packets
- tInterface *Interface;
union {
tIPv4 v4;
tIPv6 v6;
- } RemoteIP; // Type is determined by LocalInterface->Type
+ } RemoteIP; //!< Remote IP Address
+ // Type is determined by LocalInterface->Type
};
enum eTCPConnectionState