- TCPIP lock rewrite (part 3 of 3)

- Use a spin lock to protect the signalled connections list
 - Add a debug ASSERT into each function that depends on the TCPLock being held
 - Release TCPLock before completing the IRP
 - Add some locking where it was forgotten
 - Optimize HandleSignalledConnection

svn path=/trunk/; revision=41752
This commit is contained in:
Cameron Gutman 2009-07-03 06:28:59 +00:00
parent 4c8e421fe9
commit 5e7a8d3a1a
8 changed files with 253 additions and 208 deletions

View file

@ -84,7 +84,8 @@ typedef struct _SLEEPING_THREAD {
#define SRF_FIN TCP_FIN #define SRF_FIN TCP_FIN
extern LONG TCP_IPIdentification; extern LONG TCP_IPIdentification;
extern LIST_ENTRY SignalledConnections; extern LIST_ENTRY SignalledConnectionsList;
extern KSPIN_LOCK SignalledConnectionsLock;
extern LIST_ENTRY SleepingThreadsList; extern LIST_ENTRY SleepingThreadsList;
extern FAST_MUTEX SleepingThreadsLock; extern FAST_MUTEX SleepingThreadsLock;
extern RECURSIVE_MUTEX TCPLock; extern RECURSIVE_MUTEX TCPLock;

View file

@ -24,4 +24,6 @@ extern VOID RecursiveMutexInit( PRECURSIVE_MUTEX RecMutex );
extern SIZE_T RecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex, BOOLEAN ToRead ); extern SIZE_T RecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex, BOOLEAN ToRead );
extern VOID RecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex ); extern VOID RecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex );
#define ASSERT_LOCKED(x) ASSERT((x)->Locked)
#endif/*_ROSRTL_RECMUTEX_H*/ #endif/*_ROSRTL_RECMUTEX_H*/

View file

@ -106,6 +106,7 @@ VOID DispDoDisconnect( PVOID Data ) {
PDISCONNECT_TYPE DisType = (PDISCONNECT_TYPE)Data; PDISCONNECT_TYPE DisType = (PDISCONNECT_TYPE)Data;
TI_DbgPrint(DEBUG_IRP, ("PostCancel: DoDisconnect\n")); TI_DbgPrint(DEBUG_IRP, ("PostCancel: DoDisconnect\n"));
TcpipRecursiveMutexEnter(&TCPLock, TRUE);
TCPDisconnect TCPDisconnect
( DisType->Context, ( DisType->Context,
DisType->Type, DisType->Type,
@ -113,6 +114,7 @@ VOID DispDoDisconnect( PVOID Data ) {
NULL, NULL,
DispDataRequestComplete, DispDataRequestComplete,
DisType->Irp ); DisType->Irp );
TcpipRecursiveMutexLeave(&TCPLock);
TI_DbgPrint(DEBUG_IRP, ("PostCancel: DoDisconnect done\n")); TI_DbgPrint(DEBUG_IRP, ("PostCancel: DoDisconnect done\n"));
DispDataRequestComplete(DisType->Irp, STATUS_CANCELLED, 0); DispDataRequestComplete(DisType->Irp, STATUS_CANCELLED, 0);
@ -405,13 +407,13 @@ NTSTATUS DispTdiConnect(
Irp ); Irp );
done: done:
TcpipRecursiveMutexLeave( &TCPLock );
if (Status != STATUS_PENDING) { if (Status != STATUS_PENDING) {
DispDataRequestComplete(Irp, Status, 0); DispDataRequestComplete(Irp, Status, 0);
} else } else
IoMarkIrpPending(Irp); IoMarkIrpPending(Irp);
TcpipRecursiveMutexLeave( &TCPLock );
TI_DbgPrint(MAX_TRACE, ("TCP Connect returned %08x\n", Status)); TI_DbgPrint(MAX_TRACE, ("TCP Connect returned %08x\n", Status));
return Status; return Status;
@ -513,13 +515,13 @@ NTSTATUS DispTdiDisconnect(
Irp ); Irp );
done: done:
TcpipRecursiveMutexLeave( &TCPLock );
if (Status != STATUS_PENDING) { if (Status != STATUS_PENDING) {
DispDataRequestComplete(Irp, Status, 0); DispDataRequestComplete(Irp, Status, 0);
} else } else
IoMarkIrpPending(Irp); IoMarkIrpPending(Irp);
TcpipRecursiveMutexLeave( &TCPLock );
TI_DbgPrint(MAX_TRACE, ("TCP Disconnect returned %08x\n", Status)); TI_DbgPrint(MAX_TRACE, ("TCP Disconnect returned %08x\n", Status));
return Status; return Status;
@ -618,13 +620,13 @@ NTSTATUS DispTdiListen(
} }
done: done:
TcpipRecursiveMutexLeave( &TCPLock );
if (Status != STATUS_PENDING) { if (Status != STATUS_PENDING) {
DispDataRequestComplete(Irp, Status, 0); DispDataRequestComplete(Irp, Status, 0);
} else } else
IoMarkIrpPending(Irp); IoMarkIrpPending(Irp);
TcpipRecursiveMutexLeave( &TCPLock );
TI_DbgPrint(MID_TRACE,("Leaving %x\n", Status)); TI_DbgPrint(MID_TRACE,("Leaving %x\n", Status));
return Status; return Status;
@ -834,13 +836,13 @@ NTSTATUS DispTdiReceive(
} }
done: done:
TcpipRecursiveMutexLeave( &TCPLock );
if (Status != STATUS_PENDING) { if (Status != STATUS_PENDING) {
DispDataRequestComplete(Irp, Status, BytesReceived); DispDataRequestComplete(Irp, Status, BytesReceived);
} else } else
IoMarkIrpPending(Irp); IoMarkIrpPending(Irp);
TcpipRecursiveMutexLeave( &TCPLock );
TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status)); TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
return Status; return Status;
@ -912,13 +914,13 @@ NTSTATUS DispTdiReceiveDatagram(
} }
done: done:
TcpipRecursiveMutexLeave( &TCPLock );
if (Status != STATUS_PENDING) { if (Status != STATUS_PENDING) {
DispDataRequestComplete(Irp, Status, BytesReceived); DispDataRequestComplete(Irp, Status, BytesReceived);
} else } else
IoMarkIrpPending(Irp); IoMarkIrpPending(Irp);
TcpipRecursiveMutexLeave( &TCPLock );
TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status)); TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
return Status; return Status;
@ -988,13 +990,13 @@ NTSTATUS DispTdiSend(
} }
done: done:
TcpipRecursiveMutexLeave( &TCPLock );
if (Status != STATUS_PENDING) { if (Status != STATUS_PENDING) {
DispDataRequestComplete(Irp, Status, BytesSent); DispDataRequestComplete(Irp, Status, BytesSent);
} else } else
IoMarkIrpPending(Irp); IoMarkIrpPending(Irp);
TcpipRecursiveMutexLeave( &TCPLock );
TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status)); TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
return Status; return Status;
@ -1070,13 +1072,13 @@ NTSTATUS DispTdiSendDatagram(
} }
done: done:
TcpipRecursiveMutexLeave( &TCPLock );
if (Status != STATUS_PENDING) { if (Status != STATUS_PENDING) {
DispDataRequestComplete(Irp, Status, Irp->IoStatus.Information); DispDataRequestComplete(Irp, Status, Irp->IoStatus.Information);
} else } else
IoMarkIrpPending(Irp); IoMarkIrpPending(Irp);
TcpipRecursiveMutexLeave( &TCPLock );
TI_DbgPrint(DEBUG_IRP, ("Leaving.\n")); TI_DbgPrint(DEBUG_IRP, ("Leaving.\n"));
return Status; return Status;

View file

@ -363,7 +363,9 @@ NTSTATUS FileCloseAddress(
case IPPROTO_TCP: case IPPROTO_TCP:
TCPFreePort( AddrFile->Port ); TCPFreePort( AddrFile->Port );
if( AddrFile->Listener ) { if( AddrFile->Listener ) {
TcpipRecursiveMutexEnter(&TCPLock, TRUE);
TCPClose( AddrFile->Listener ); TCPClose( AddrFile->Listener );
TcpipRecursiveMutexLeave(&TCPLock);
exFreePool( AddrFile->Listener ); exFreePool( AddrFile->Listener );
} }
break; break;
@ -425,7 +427,9 @@ NTSTATUS FileOpenConnection(
if( !Connection ) return STATUS_NO_MEMORY; if( !Connection ) return STATUS_NO_MEMORY;
TcpipRecursiveMutexEnter(&TCPLock, TRUE);
Status = TCPSocket( Connection, AF_INET, SOCK_STREAM, IPPROTO_TCP ); Status = TCPSocket( Connection, AF_INET, SOCK_STREAM, IPPROTO_TCP );
TcpipRecursiveMutexLeave(&TCPLock);
if( !NT_SUCCESS(Status) ) { if( !NT_SUCCESS(Status) ) {
TCPFreeConnectionEndpoint( Connection ); TCPFreeConnectionEndpoint( Connection );

View file

@ -19,6 +19,8 @@ NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener,
PTA_IP_ADDRESS RequestAddressReturn; PTA_IP_ADDRESS RequestAddressReturn;
PTDI_CONNECTION_INFORMATION WhoIsConnecting; PTDI_CONNECTION_INFORMATION WhoIsConnecting;
ASSERT_LOCKED(&TCPLock);
/* Unpack TDI info -- We need the return connection information /* Unpack TDI info -- We need the return connection information
* struct to return the address so it can be filtered if needed * struct to return the address so it can be filtered if needed
* by WSAAccept -- The returned address will be passed on to * by WSAAccept -- The returned address will be passed on to

View file

@ -16,6 +16,8 @@ int TCPSocketState(void *ClientData,
OSK_UINT NewState ) { OSK_UINT NewState ) {
PCONNECTION_ENDPOINT Connection = WhichConnection; PCONNECTION_ENDPOINT Connection = WhichConnection;
ASSERT_LOCKED(&TCPLock);
TI_DbgPrint(MID_TRACE,("Flags: %c%c%c%c\n", TI_DbgPrint(MID_TRACE,("Flags: %c%c%c%c\n",
NewState & SEL_CONNECT ? 'C' : 'c', NewState & SEL_CONNECT ? 'C' : 'c',
NewState & SEL_READ ? 'R' : 'r', NewState & SEL_READ ? 'R' : 'r',
@ -42,7 +44,7 @@ int TCPSocketState(void *ClientData,
Connection->SignalState |= NewState; Connection->SignalState |= NewState;
if( !Connection->Signalled ) { if( !Connection->Signalled ) {
Connection->Signalled = TRUE; Connection->Signalled = TRUE;
InsertTailList( &SignalledConnections, &Connection->SignalList ); ExInterlockedInsertTailList( &SignalledConnectionsList, &Connection->SignalList, &SignalledConnectionsLock );
} }
return 0; return 0;
@ -52,6 +54,8 @@ void TCPPacketSendComplete( PVOID Context,
PNDIS_PACKET NdisPacket, PNDIS_PACKET NdisPacket,
NDIS_STATUS NdisStatus ) { NDIS_STATUS NdisStatus ) {
TI_DbgPrint(DEBUG_TCP,("called %x\n", NdisPacket)); TI_DbgPrint(DEBUG_TCP,("called %x\n", NdisPacket));
ASSERT_LOCKED(&TCPLock);
FreeNdisPacket(NdisPacket); FreeNdisPacket(NdisPacket);
TI_DbgPrint(DEBUG_TCP,("done\n")); TI_DbgPrint(DEBUG_TCP,("done\n"));
} }
@ -65,6 +69,8 @@ int TCPPacketSend(void *ClientData, OSK_PCHAR data, OSK_UINT len ) {
IP_ADDRESS RemoteAddress, LocalAddress; IP_ADDRESS RemoteAddress, LocalAddress;
PIPv4_HEADER Header; PIPv4_HEADER Header;
ASSERT_LOCKED(&TCPLock);
if( *data == 0x45 ) { /* IPv4 */ if( *data == 0x45 ) { /* IPv4 */
Header = (PIPv4_HEADER)data; Header = (PIPv4_HEADER)data;
LocalAddress.Type = IP_ADDRESS_V4; LocalAddress.Type = IP_ADDRESS_V4;
@ -114,6 +120,8 @@ int TCPSleep( void *ClientData, void *token, int priority, char *msg,
PSLEEPING_THREAD SleepingThread; PSLEEPING_THREAD SleepingThread;
LARGE_INTEGER Timeout; LARGE_INTEGER Timeout;
ASSERT_LOCKED(&TCPLock);
TI_DbgPrint(DEBUG_TCP, TI_DbgPrint(DEBUG_TCP,
("Called TSLEEP: tok = %x, pri = %d, wmesg = %s, tmio = %x\n", ("Called TSLEEP: tok = %x, pri = %d, wmesg = %s, tmio = %x\n",
token, priority, msg, tmio)); token, priority, msg, tmio));
@ -159,6 +167,8 @@ void TCPWakeup( void *ClientData, void *token ) {
PLIST_ENTRY Entry; PLIST_ENTRY Entry;
PSLEEPING_THREAD SleepingThread; PSLEEPING_THREAD SleepingThread;
ASSERT_LOCKED(&TCPLock);
TcpipAcquireFastMutex( &SleepingThreadsLock ); TcpipAcquireFastMutex( &SleepingThreadsLock );
Entry = SleepingThreadsList.Flink; Entry = SleepingThreadsList.Flink;
while( Entry != &SleepingThreadsList ) { while( Entry != &SleepingThreadsList ) {
@ -223,6 +233,8 @@ void *TCPMalloc( void *ClientData,
void *v; void *v;
ULONG Signature; ULONG Signature;
ASSERT_LOCKED(&TCPLock);
#if 0 != MEM_PROFILE #if 0 != MEM_PROFILE
static OSK_UINT *Sizes = NULL, *Counts = NULL, ArrayAllocated = 0; static OSK_UINT *Sizes = NULL, *Counts = NULL, ArrayAllocated = 0;
static OSK_UINT ArrayUsed = 0, AllocationCount = 0; static OSK_UINT ArrayUsed = 0, AllocationCount = 0;
@ -298,6 +310,8 @@ void TCPFree( void *ClientData,
void *data, OSK_PCHAR File, OSK_UINT Line ) { void *data, OSK_PCHAR File, OSK_UINT Line ) {
ULONG Signature; ULONG Signature;
ASSERT_LOCKED(&TCPLock);
UntrackFL( (PCHAR)File, Line, data, FOURCC('f','b','s','d') ); UntrackFL( (PCHAR)File, Line, data, FOURCC('f','b','s','d') );
data = (void *)((char *) data - sizeof(ULONG)); data = (void *)((char *) data - sizeof(ULONG));
Signature = *((ULONG *) data); Signature = *((ULONG *) data);

View file

@ -35,6 +35,8 @@ POSK_IFADDR TCPGetInterfaceData( PIP_INTERFACE IF ) {
POSK_IFADDR ifaddr = IF->TCPContext; POSK_IFADDR ifaddr = IF->TCPContext;
ASSERT(ifaddr); ASSERT(ifaddr);
ASSERT_LOCKED(&TCPLock);
RtlZeroMemory(ifaddr, sizeof(OSK_IFADDR) + 2 * sizeof( struct sockaddr_in )); RtlZeroMemory(ifaddr, sizeof(OSK_IFADDR) + 2 * sizeof( struct sockaddr_in ));
struct sockaddr_in *addr_in = (struct sockaddr_in *)&ifaddr[1]; struct sockaddr_in *addr_in = (struct sockaddr_in *)&ifaddr[1];
@ -77,6 +79,8 @@ POSK_IFADDR TCPFindInterface( void *ClientData,
struct sockaddr_in *addr_in = (struct sockaddr_in *)ReqAddr; struct sockaddr_in *addr_in = (struct sockaddr_in *)ReqAddr;
POSK_IFADDR InterfaceData; POSK_IFADDR InterfaceData;
ASSERT_LOCKED(&TCPLock);
TI_DbgPrint(DEBUG_TCPIF,("called for type %d\n", FindType)); TI_DbgPrint(DEBUG_TCPIF,("called for type %d\n", FindType));
if( !ReqAddr ) { if( !ReqAddr ) {

View file

@ -15,14 +15,14 @@
LONG TCP_IPIdentification = 0; LONG TCP_IPIdentification = 0;
static BOOLEAN TCPInitialized = FALSE; static BOOLEAN TCPInitialized = FALSE;
static NPAGED_LOOKASIDE_LIST TCPSegmentList; static NPAGED_LOOKASIDE_LIST TCPSegmentList;
LIST_ENTRY SignalledConnections; LIST_ENTRY SignalledConnectionsList;
KSPIN_LOCK SignalledConnectionsLock;
LIST_ENTRY SleepingThreadsList; LIST_ENTRY SleepingThreadsList;
FAST_MUTEX SleepingThreadsLock; FAST_MUTEX SleepingThreadsLock;
RECURSIVE_MUTEX TCPLock; RECURSIVE_MUTEX TCPLock;
PORT_SET TCPPorts; PORT_SET TCPPorts;
static VOID HandleSignalledConnection( PCONNECTION_ENDPOINT Connection, static VOID HandleSignalledConnection( PCONNECTION_ENDPOINT Connection ) {
ULONG NewState ) {
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PTCP_COMPLETION_ROUTINE Complete; PTCP_COMPLETION_ROUTINE Complete;
PTDI_BUCKET Bucket; PTDI_BUCKET Bucket;
@ -30,194 +30,12 @@ static VOID HandleSignalledConnection( PCONNECTION_ENDPOINT Connection,
PIRP Irp; PIRP Irp;
PMDL Mdl; PMDL Mdl;
ASSERT_LOCKED(&TCPLock);
TI_DbgPrint(MID_TRACE,("Handling signalled state on %x (%x)\n", TI_DbgPrint(MID_TRACE,("Handling signalled state on %x (%x)\n",
Connection, Connection->SocketContext)); Connection, Connection->SocketContext));
/* Things that can happen when we try the initial connection */ if( Connection->SignalState & SEL_FIN ) {
if( NewState & SEL_CONNECT ) {
while( (Entry = ExInterlockedRemoveHeadList( &Connection->ConnectRequest,
&Connection->Lock )) != NULL ) {
TI_DbgPrint(DEBUG_TCP, ("Connect Event\n"));
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
TI_DbgPrint(DEBUG_TCP,
("Completing Request %x\n", Bucket->Request.RequestContext));
if( (NewState & (SEL_CONNECT | SEL_FIN)) ==
(SEL_CONNECT | SEL_FIN) )
Status = STATUS_CONNECTION_REFUSED;
else
Status = STATUS_SUCCESS;
Complete( Bucket->Request.RequestContext, Status, 0 );
/* Frees the bucket allocated in TCPConnect */
exFreePool( Bucket );
}
}
if( NewState & SEL_ACCEPT ) {
/* Handle readable on a listening socket --
* TODO: Implement filtering
*/
TI_DbgPrint(DEBUG_TCP,("Accepting new connection on %x (Queue: %s)\n",
Connection,
IsListEmpty(&Connection->ListenRequest) ?
"empty" : "nonempty"));
while( (Entry = ExInterlockedRemoveHeadList( &Connection->ListenRequest,
&Connection->Lock )) != NULL ) {
PIO_STACK_LOCATION IrpSp;
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
Irp = Bucket->Request.RequestContext;
IrpSp = IoGetCurrentIrpStackLocation( Irp );
TI_DbgPrint(DEBUG_TCP,("Getting the socket\n"));
Status = TCPServiceListeningSocket
( Connection->AddressFile->Listener,
Bucket->AssociatedEndpoint,
(PTDI_REQUEST_KERNEL)&IrpSp->Parameters );
TI_DbgPrint(DEBUG_TCP,("Socket: Status: %x\n"));
if( Status == STATUS_PENDING ) {
ExInterlockedInsertHeadList( &Connection->ListenRequest, &Bucket->Entry, &Connection->Lock );
break;
} else {
Complete( Bucket->Request.RequestContext, Status, 0 );
exFreePool( Bucket );
}
}
}
/* Things that happen after we're connected */
if( NewState & SEL_READ ) {
TI_DbgPrint(DEBUG_TCP,("Readable: irp list %s\n",
IsListEmpty(&Connection->ReceiveRequest) ?
"empty" : "nonempty"));
while( (Entry = ExInterlockedRemoveHeadList( &Connection->ReceiveRequest,
&Connection->Lock )) != NULL ) {
OSK_UINT RecvLen = 0, Received = 0;
PVOID RecvBuffer = 0;
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
Irp = Bucket->Request.RequestContext;
Mdl = Irp->MdlAddress;
TI_DbgPrint(DEBUG_TCP,
("Getting the user buffer from %x\n", Mdl));
NdisQueryBuffer( Mdl, &RecvBuffer, &RecvLen );
TI_DbgPrint(DEBUG_TCP,
("Reading %d bytes to %x\n", RecvLen, RecvBuffer));
TI_DbgPrint(DEBUG_TCP, ("Connection: %x\n", Connection));
TI_DbgPrint
(DEBUG_TCP,
("Connection->SocketContext: %x\n",
Connection->SocketContext));
TI_DbgPrint(DEBUG_TCP, ("RecvBuffer: %x\n", RecvBuffer));
Status = TCPTranslateError
( OskitTCPRecv( Connection->SocketContext,
RecvBuffer,
RecvLen,
&Received,
0 ) );
TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Received));
if( Status == STATUS_SUCCESS ) {
TI_DbgPrint(DEBUG_TCP,("Received %d bytes with status %x\n",
Received, Status));
Complete( Bucket->Request.RequestContext,
STATUS_SUCCESS, Received );
exFreePool( Bucket );
} else if( Status == STATUS_PENDING ) {
ExInterlockedInsertHeadList
( &Connection->ReceiveRequest, &Bucket->Entry, &Connection->Lock );
break;
} else {
TI_DbgPrint(DEBUG_TCP,
("Completing Receive request: %x %x\n",
Bucket->Request, Status));
Complete( Bucket->Request.RequestContext, Status, 0 );
exFreePool( Bucket );
}
}
}
if( NewState & SEL_WRITE ) {
TI_DbgPrint(DEBUG_TCP,("Writeable: irp list %s\n",
IsListEmpty(&Connection->SendRequest) ?
"empty" : "nonempty"));
while( (Entry = ExInterlockedRemoveHeadList( &Connection->SendRequest,
&Connection->Lock )) != NULL ) {
OSK_UINT SendLen = 0, Sent = 0;
PVOID SendBuffer = 0;
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
Irp = Bucket->Request.RequestContext;
Mdl = Irp->MdlAddress;
TI_DbgPrint(DEBUG_TCP,
("Getting the user buffer from %x\n", Mdl));
NdisQueryBuffer( Mdl, &SendBuffer, &SendLen );
TI_DbgPrint(DEBUG_TCP,
("Writing %d bytes to %x\n", SendLen, SendBuffer));
TI_DbgPrint(DEBUG_TCP, ("Connection: %x\n", Connection));
TI_DbgPrint
(DEBUG_TCP,
("Connection->SocketContext: %x\n",
Connection->SocketContext));
Status = TCPTranslateError
( OskitTCPSend( Connection->SocketContext,
SendBuffer,
SendLen,
&Sent,
0 ) );
TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Sent));
if( Status == STATUS_SUCCESS ) {
TI_DbgPrint(DEBUG_TCP,("Sent %d bytes with status %x\n",
Sent, Status));
Complete( Bucket->Request.RequestContext,
STATUS_SUCCESS, Sent );
exFreePool( Bucket );
} else if( Status == STATUS_PENDING ) {
ExInterlockedInsertHeadList
( &Connection->SendRequest, &Bucket->Entry, &Connection->Lock );
break;
} else {
TI_DbgPrint(DEBUG_TCP,
("Completing Send request: %x %x\n",
Bucket->Request, Status));
Complete( Bucket->Request.RequestContext, Status, 0 );
exFreePool( Bucket );
}
}
}
if( NewState & SEL_FIN ) {
TI_DbgPrint(DEBUG_TCP, ("EOF From socket\n")); TI_DbgPrint(DEBUG_TCP, ("EOF From socket\n"));
while ((Entry = ExInterlockedRemoveHeadList( &Connection->ReceiveRequest, while ((Entry = ExInterlockedRemoveHeadList( &Connection->ReceiveRequest,
@ -279,8 +97,189 @@ static VOID HandleSignalledConnection( PCONNECTION_ENDPOINT Connection,
Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 ); Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
} }
Connection->SignalState = 0;
} }
/* Things that can happen when we try the initial connection */
if( Connection->SignalState & SEL_CONNECT ) {
while( (Entry = ExInterlockedRemoveHeadList( &Connection->ConnectRequest,
&Connection->Lock )) != NULL ) {
TI_DbgPrint(DEBUG_TCP, ("Connect Event\n"));
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
TI_DbgPrint(DEBUG_TCP,
("Completing Request %x\n", Bucket->Request.RequestContext));
Complete( Bucket->Request.RequestContext, STATUS_SUCCESS, 0 );
/* Frees the bucket allocated in TCPConnect */
exFreePool( Bucket );
}
}
if( Connection->SignalState & SEL_ACCEPT ) {
/* Handle readable on a listening socket --
* TODO: Implement filtering
*/
TI_DbgPrint(DEBUG_TCP,("Accepting new connection on %x (Queue: %s)\n",
Connection,
IsListEmpty(&Connection->ListenRequest) ?
"empty" : "nonempty"));
while( (Entry = ExInterlockedRemoveHeadList( &Connection->ListenRequest,
&Connection->Lock )) != NULL ) {
PIO_STACK_LOCATION IrpSp;
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
Irp = Bucket->Request.RequestContext;
IrpSp = IoGetCurrentIrpStackLocation( Irp );
TI_DbgPrint(DEBUG_TCP,("Getting the socket\n"));
Status = TCPServiceListeningSocket
( Connection->AddressFile->Listener,
Bucket->AssociatedEndpoint,
(PTDI_REQUEST_KERNEL)&IrpSp->Parameters );
TI_DbgPrint(DEBUG_TCP,("Socket: Status: %x\n"));
if( Status == STATUS_PENDING ) {
ExInterlockedInsertHeadList( &Connection->ListenRequest, &Bucket->Entry, &Connection->Lock );
break;
} else {
Complete( Bucket->Request.RequestContext, Status, 0 );
exFreePool( Bucket );
}
}
}
/* Things that happen after we're connected */
if( Connection->SignalState & SEL_READ ) {
TI_DbgPrint(DEBUG_TCP,("Readable: irp list %s\n",
IsListEmpty(&Connection->ReceiveRequest) ?
"empty" : "nonempty"));
while( (Entry = ExInterlockedRemoveHeadList( &Connection->ReceiveRequest,
&Connection->Lock )) != NULL ) {
OSK_UINT RecvLen = 0, Received = 0;
PVOID RecvBuffer = 0;
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
Irp = Bucket->Request.RequestContext;
Mdl = Irp->MdlAddress;
TI_DbgPrint(DEBUG_TCP,
("Getting the user buffer from %x\n", Mdl));
NdisQueryBuffer( Mdl, &RecvBuffer, &RecvLen );
TI_DbgPrint(DEBUG_TCP,
("Reading %d bytes to %x\n", RecvLen, RecvBuffer));
TI_DbgPrint(DEBUG_TCP, ("Connection: %x\n", Connection));
TI_DbgPrint
(DEBUG_TCP,
("Connection->SocketContext: %x\n",
Connection->SocketContext));
TI_DbgPrint(DEBUG_TCP, ("RecvBuffer: %x\n", RecvBuffer));
Status = TCPTranslateError
( OskitTCPRecv( Connection->SocketContext,
RecvBuffer,
RecvLen,
&Received,
0 ) );
TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Received));
if( Status == STATUS_SUCCESS ) {
TI_DbgPrint(DEBUG_TCP,("Received %d bytes with status %x\n",
Received, Status));
Complete( Bucket->Request.RequestContext,
STATUS_SUCCESS, Received );
exFreePool( Bucket );
} else if( Status == STATUS_PENDING ) {
ExInterlockedInsertHeadList
( &Connection->ReceiveRequest, &Bucket->Entry, &Connection->Lock );
break;
} else {
TI_DbgPrint(DEBUG_TCP,
("Completing Receive request: %x %x\n",
Bucket->Request, Status));
Complete( Bucket->Request.RequestContext, Status, 0 );
exFreePool( Bucket );
}
}
}
if( Connection->SignalState & SEL_WRITE ) {
TI_DbgPrint(DEBUG_TCP,("Writeable: irp list %s\n",
IsListEmpty(&Connection->SendRequest) ?
"empty" : "nonempty"));
while( (Entry = ExInterlockedRemoveHeadList( &Connection->SendRequest,
&Connection->Lock )) != NULL ) {
OSK_UINT SendLen = 0, Sent = 0;
PVOID SendBuffer = 0;
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
Irp = Bucket->Request.RequestContext;
Mdl = Irp->MdlAddress;
TI_DbgPrint(DEBUG_TCP,
("Getting the user buffer from %x\n", Mdl));
NdisQueryBuffer( Mdl, &SendBuffer, &SendLen );
TI_DbgPrint(DEBUG_TCP,
("Writing %d bytes to %x\n", SendLen, SendBuffer));
TI_DbgPrint(DEBUG_TCP, ("Connection: %x\n", Connection));
TI_DbgPrint
(DEBUG_TCP,
("Connection->SocketContext: %x\n",
Connection->SocketContext));
Status = TCPTranslateError
( OskitTCPSend( Connection->SocketContext,
SendBuffer,
SendLen,
&Sent,
0 ) );
TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Sent));
if( Status == STATUS_SUCCESS ) {
TI_DbgPrint(DEBUG_TCP,("Sent %d bytes with status %x\n",
Sent, Status));
Complete( Bucket->Request.RequestContext,
STATUS_SUCCESS, Sent );
exFreePool( Bucket );
} else if( Status == STATUS_PENDING ) {
ExInterlockedInsertHeadList
( &Connection->SendRequest, &Bucket->Entry, &Connection->Lock );
break;
} else {
TI_DbgPrint(DEBUG_TCP,
("Completing Send request: %x %x\n",
Bucket->Request, Status));
Complete( Bucket->Request.RequestContext, Status, 0 );
exFreePool( Bucket );
}
}
}
Connection->SignalState = 0;
Connection->Signalled = FALSE; Connection->Signalled = FALSE;
} }
@ -288,11 +287,11 @@ VOID DrainSignals() {
PCONNECTION_ENDPOINT Connection; PCONNECTION_ENDPOINT Connection;
PLIST_ENTRY ListEntry; PLIST_ENTRY ListEntry;
while( !IsListEmpty( &SignalledConnections ) ) { while( (ListEntry = ExInterlockedRemoveHeadList(&SignalledConnectionsList,
ListEntry = RemoveHeadList( &SignalledConnections ); &SignalledConnectionsLock)) != NULL) {
Connection = CONTAINING_RECORD( ListEntry, CONNECTION_ENDPOINT, Connection = CONTAINING_RECORD( ListEntry, CONNECTION_ENDPOINT,
SignalList ); SignalList );
HandleSignalledConnection( Connection, Connection->SignalState ); HandleSignalledConnection( Connection );
} }
} }
@ -328,6 +327,8 @@ NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection,
UINT Family, UINT Type, UINT Proto ) { UINT Family, UINT Type, UINT Proto ) {
NTSTATUS Status; NTSTATUS Status;
ASSERT_LOCKED(&TCPLock);
TI_DbgPrint(DEBUG_TCP,("Called: Connection %x, Family %d, Type %d, " TI_DbgPrint(DEBUG_TCP,("Called: Connection %x, Family %d, Type %d, "
"Proto %d\n", "Proto %d\n",
Connection, Family, Type, Proto)); Connection, Family, Type, Proto));
@ -480,8 +481,9 @@ NTSTATUS TCPStartup(VOID)
TcpipRecursiveMutexInit( &TCPLock ); TcpipRecursiveMutexInit( &TCPLock );
ExInitializeFastMutex( &SleepingThreadsLock ); ExInitializeFastMutex( &SleepingThreadsLock );
KeInitializeSpinLock( &SignalledConnectionsLock );
InitializeListHead( &SleepingThreadsList ); InitializeListHead( &SleepingThreadsList );
InitializeListHead( &SignalledConnections ); InitializeListHead( &SignalledConnectionsList );
Status = TCPMemStartup(); Status = TCPMemStartup();
if ( ! NT_SUCCESS(Status) ) { if ( ! NT_SUCCESS(Status) ) {
return Status; return Status;
@ -493,8 +495,10 @@ NTSTATUS TCPStartup(VOID)
return Status; return Status;
} }
TcpipRecursiveMutexEnter(&TCPLock, TRUE);
RegisterOskitTCPEventHandlers( &EventHandlers ); RegisterOskitTCPEventHandlers( &EventHandlers );
InitOskitTCP(); InitOskitTCP();
TcpipRecursiveMutexLeave(&TCPLock);
/* Register this protocol with IP layer */ /* Register this protocol with IP layer */
IPRegisterProtocol(IPPROTO_TCP, TCPReceive); IPRegisterProtocol(IPPROTO_TCP, TCPReceive);
@ -581,6 +585,8 @@ NTSTATUS TCPConnect
TI_DbgPrint(DEBUG_TCP,("TCPConnect: Called\n")); TI_DbgPrint(DEBUG_TCP,("TCPConnect: Called\n"));
ASSERT_LOCKED(&TCPLock);
Status = AddrBuildAddress Status = AddrBuildAddress
((PTRANSPORT_ADDRESS)ConnInfo->RemoteAddress, ((PTRANSPORT_ADDRESS)ConnInfo->RemoteAddress,
&RemoteAddress, &RemoteAddress,
@ -655,6 +661,8 @@ NTSTATUS TCPDisconnect
PVOID Context ) { PVOID Context ) {
NTSTATUS Status; NTSTATUS Status;
ASSERT_LOCKED(&TCPLock);
TI_DbgPrint(DEBUG_TCP,("started\n")); TI_DbgPrint(DEBUG_TCP,("started\n"));
switch( Flags & (TDI_DISCONNECT_ABORT | TDI_DISCONNECT_RELEASE) ) { switch( Flags & (TDI_DISCONNECT_ABORT | TDI_DISCONNECT_RELEASE) ) {
@ -686,6 +694,8 @@ NTSTATUS TCPClose
TI_DbgPrint(DEBUG_TCP,("TCPClose started\n")); TI_DbgPrint(DEBUG_TCP,("TCPClose started\n"));
ASSERT_LOCKED(&TCPLock);
/* Make our code remove all pending IRPs */ /* Make our code remove all pending IRPs */
Connection->State |= SEL_FIN; Connection->State |= SEL_FIN;
DrainSignals(); DrainSignals();
@ -713,6 +723,8 @@ NTSTATUS TCPReceiveData
TI_DbgPrint(DEBUG_TCP,("Called for %d bytes (on socket %x)\n", TI_DbgPrint(DEBUG_TCP,("Called for %d bytes (on socket %x)\n",
ReceiveLength, Connection->SocketContext)); ReceiveLength, Connection->SocketContext));
ASSERT_LOCKED(&TCPLock);
ASSERT_KM_POINTER(Connection->SocketContext); ASSERT_KM_POINTER(Connection->SocketContext);
/* Closing */ /* Closing */
@ -775,6 +787,8 @@ NTSTATUS TCPSendData
NTSTATUS Status; NTSTATUS Status;
PTDI_BUCKET Bucket; PTDI_BUCKET Bucket;
ASSERT_LOCKED(&TCPLock);
TI_DbgPrint(DEBUG_TCP,("Called for %d bytes (on socket %x)\n", TI_DbgPrint(DEBUG_TCP,("Called for %d bytes (on socket %x)\n",
SendLength, Connection->SocketContext)); SendLength, Connection->SocketContext));
@ -852,6 +866,8 @@ NTSTATUS TCPGetSockAddress
OSK_UI16 LocalPort, RemotePort; OSK_UI16 LocalPort, RemotePort;
PTA_IP_ADDRESS AddressIP = (PTA_IP_ADDRESS)Address; PTA_IP_ADDRESS AddressIP = (PTA_IP_ADDRESS)Address;
ASSERT_LOCKED(&TCPLock);
OskitTCPGetAddress OskitTCPGetAddress
( Connection->SocketContext, ( Connection->SocketContext,
&LocalAddress, &LocalPort, &LocalAddress, &LocalPort,