PORT_SET TCPPorts;
CLIENT_DATA ClientInfo;
-static VOID
-ProcessCompletions(PCONNECTION_ENDPOINT Connection)
-{
- PLIST_ENTRY CurrentEntry;
- PTDI_BUCKET Bucket;
- PTCP_COMPLETION_ROUTINE Complete;
-
- while ((CurrentEntry = ExInterlockedRemoveHeadList(&Connection->CompletionQueue,
- &Connection->Lock)))
- {
- Bucket = CONTAINING_RECORD(CurrentEntry, TDI_BUCKET, Entry);
- Complete = Bucket->Request.RequestNotifyObject;
-
- Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information);
-
- ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG);
- }
-
- if (!Connection->SocketContext)
- TCPFreeConnectionEndpoint(Connection);
-}
-
VOID HandleSignalledConnection(PCONNECTION_ENDPOINT Connection)
{
PTDI_BUCKET Bucket;
PIRP Irp;
PMDL Mdl;
ULONG SocketError = 0;
+ KIRQL OldIrql;
+ PTCP_COMPLETION_ROUTINE Complete;
+
+ if (ClientInfo.Unlocked)
+ LockObjectAtDpcLevel(Connection);
TI_DbgPrint(MID_TRACE,("Handling signalled state on %x (%x)\n",
Connection, Connection->SocketContext));
- if( !Connection->SocketContext || Connection->SignalState & SEL_FIN ) {
+ if( Connection->SignalState & SEL_FIN ) {
TI_DbgPrint(DEBUG_TCP, ("EOF From socket\n"));
/* If OskitTCP initiated the disconnect, try to read the socket error that occurred */
Bucket->Status = SocketError;
Bucket->Information = 0;
+ DereferenceObject(Bucket->AssociatedEndpoint);
InsertTailList(&Connection->CompletionQueue, &Bucket->Entry);
}
InsertTailList(&Connection->CompletionQueue, &Bucket->Entry);
}
- Connection->SignalState = 0;
+ Connection->SignalState = SEL_FIN;
}
/* Things that can happen when we try the initial connection */
} else {
Bucket->Status = Status;
Bucket->Information = 0;
+ DereferenceObject(Bucket->AssociatedEndpoint);
InsertTailList(&Connection->CompletionQueue, &Bucket->Entry);
}
}
}
}
+
+ ReferenceObject(Connection);
+ if (ClientInfo.Unlocked)
+ {
+ UnlockObjectFromDpcLevel(Connection);
+ KeReleaseSpinLock(&ClientInfo.Lock, ClientInfo.OldIrql);
+ }
+ else
+ {
+ UnlockObject(Connection, Connection->OldIrql);
+ }
+
+ while ((Entry = ExInterlockedRemoveHeadList(&Connection->CompletionQueue,
+ &Connection->Lock)))
+ {
+ Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
+ Complete = Bucket->Request.RequestNotifyObject;
+
+ Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information);
+
+ ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG);
+ }
+
+ if (!ClientInfo.Unlocked)
+ {
+ LockObject(Connection, &OldIrql);
+ }
+ else
+ {
+ KeAcquireSpinLock(&ClientInfo.Lock, &ClientInfo.OldIrql);
+ }
+ DereferenceObject(Connection);
+
+ /* If the socket is dead, remove the reference we added for oskit */
+ if (Connection->SignalState & SEL_FIN)
+ DereferenceObject(Connection);
}
-static
-VOID DrainSignals(VOID) {
- PCONNECTION_ENDPOINT Connection;
- PLIST_ENTRY CurrentEntry;
+VOID ConnectionFree(PVOID Object) {
+ PCONNECTION_ENDPOINT Connection = Object;
KIRQL OldIrql;
- KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
- CurrentEntry = ConnectionEndpointListHead.Flink;
- while (CurrentEntry != &ConnectionEndpointListHead)
- {
- Connection = CONTAINING_RECORD( CurrentEntry, CONNECTION_ENDPOINT,
- ListEntry );
- CurrentEntry = CurrentEntry->Flink;
- KeReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
-
- KeAcquireSpinLock(&Connection->Lock, &OldIrql);
- if (Connection->SocketContext)
- {
- HandleSignalledConnection(Connection);
- KeReleaseSpinLock(&Connection->Lock, OldIrql);
+ TI_DbgPrint(DEBUG_TCP, ("Freeing TCP Endpoint\n"));
- ProcessCompletions(Connection);
- }
- else
- {
- KeReleaseSpinLock(&Connection->Lock, OldIrql);
- }
+ TcpipAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
+ RemoveEntryList(&Connection->ListEntry);
+ TcpipReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
- KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
- }
- KeReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
+ ExFreePoolWithTag( Connection, CONN_ENDPT_TAG );
}
PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext ) {
/* Save client context pointer */
Connection->ClientContext = ClientContext;
+ /* Add an extra reference for oskit */
+ Connection->RefCount = 2;
+ Connection->Free = ConnectionFree;
+
/* Add connection endpoint to global list */
ExInterlockedInsertTailList(&ConnectionEndpointListHead,
&Connection->ListEntry,
return Connection;
}
-VOID TCPFreeConnectionEndpoint( PCONNECTION_ENDPOINT Connection ) {
- KIRQL OldIrql;
-
- TI_DbgPrint(DEBUG_TCP, ("Freeing TCP Endpoint\n"));
-
- TcpipAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
- RemoveEntryList(&Connection->ListEntry);
- TcpipReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
-
- ExFreePoolWithTag( Connection, CONN_ENDPT_TAG );
-}
-
NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection,
UINT Family, UINT Type, UINT Proto ) {
NTSTATUS Status;
KIRQL OldIrql;
- KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+ LockObject(Connection, &OldIrql);
TI_DbgPrint(DEBUG_TCP,("Called: Connection %x, Family %d, Type %d, "
"Proto %d\n",
TI_DbgPrint(DEBUG_TCP,("Connection->SocketContext %x\n",
Connection->SocketContext));
- KeReleaseSpinLock(&Connection->Lock, OldIrql);
+ UnlockObject(Connection, OldIrql);
return Status;
}
KeAcquireSpinLock(&ClientInfo.Lock, &OldIrql);
ClientInfo.Unlocked = TRUE;
+ ClientInfo.OldIrql = OldIrql;
OskitTCPReceiveDatagram( IPPacket->Header,
IPPacket->TotalSize,
}
TimerOskitTCP( Next == NextFast, Next == NextSlow );
- DrainSignals();
Current = Next;
if (10 <= Current) {
AddressToConnect.sin_family = AF_INET;
AddressToBind = AddressToConnect;
- KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+ LockObject(Connection, &OldIrql);
if (!Connection->AddressFile)
{
- KeReleaseSpinLock(&Connection->Lock, OldIrql);
+ UnlockObject(Connection, OldIrql);
return STATUS_INVALID_PARAMETER;
}
{
if (!(NCE = RouteGetRouteToDestination(&RemoteAddress)))
{
- KeReleaseSpinLock(&Connection->Lock, OldIrql);
+ UnlockObject(Connection, OldIrql);
return STATUS_NETWORK_UNREACHABLE;
}
&AddressToConnect,
sizeof(AddressToConnect) ) );
- KeReleaseSpinLock(&Connection->Lock, OldIrql);
-
if (Status == STATUS_PENDING)
{
Bucket = ExAllocatePoolWithTag( NonPagedPool, sizeof(*Bucket), TDI_BUCKET_TAG );
if( !Bucket )
{
+ UnlockObject(Connection, OldIrql);
return STATUS_NO_MEMORY;
}
Bucket->Request.RequestNotifyObject = (PVOID)Complete;
Bucket->Request.RequestContext = Context;
- ExInterlockedInsertTailList( &Connection->ConnectRequest, &Bucket->Entry,
- &Connection->Lock );
+ InsertTailList( &Connection->ConnectRequest, &Bucket->Entry );
}
- } else {
- KeReleaseSpinLock(&Connection->Lock, OldIrql);
}
+ UnlockObject(Connection, OldIrql);
+
return Status;
}
TI_DbgPrint(DEBUG_TCP,("started\n"));
- KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+ LockObject(Connection, &OldIrql);
if (Flags & TDI_DISCONNECT_RELEASE)
Status = TCPTranslateError(OskitTCPDisconnect(Connection->SocketContext));
if ((Flags & TDI_DISCONNECT_ABORT) || !Flags)
Status = TCPTranslateError(OskitTCPShutdown(Connection->SocketContext, FWRITE | FREAD));
- KeReleaseSpinLock(&Connection->Lock, OldIrql);
+ UnlockObject(Connection, OldIrql);
TI_DbgPrint(DEBUG_TCP,("finished %x\n", Status));
}
NTSTATUS TCPClose
-( PCONNECTION_ENDPOINT Connection ) {
- NTSTATUS Status;
+( PCONNECTION_ENDPOINT Connection )
+{
KIRQL OldIrql;
+ NTSTATUS Status;
PVOID Socket;
- TI_DbgPrint(DEBUG_TCP,("TCPClose started\n"));
-
- KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+ /* We don't rely on SocketContext == NULL for socket
+ * closure anymore but we still need it to determine
+ * if we caused the closure
+ */
Socket = Connection->SocketContext;
Connection->SocketContext = NULL;
+
+ /* We need to close here otherwise oskit will never indicate
+ * SEL_FIN and we will never fully close the connection
+ */
+ LockObject(Connection, &OldIrql);
Status = TCPTranslateError( OskitTCPClose( Socket ) );
+ UnlockObject(Connection, OldIrql);
+
if (!NT_SUCCESS(Status))
{
Connection->SocketContext = Socket;
+ return Status;
}
- KeReleaseSpinLock(&Connection->Lock, OldIrql);
- TI_DbgPrint(DEBUG_TCP,("TCPClose finished %x\n", Status));
+ if (Connection->AddressFile)
+ DereferenceObject(Connection->AddressFile);
+
+ DereferenceObject(Connection);
return Status;
}
TI_DbgPrint(DEBUG_TCP,("TCP>|< Got an MDL %x (%x:%d)\n", Buffer, DataBuffer, DataLen));
- KeAcquireSpinLock(&Connection->Lock, &OldIrql);
-
- ASSERT_KM_POINTER(Connection->SocketContext);
+ LockObject(Connection, &OldIrql);
Status = TCPTranslateError
( OskitTCPRecv
&Received,
ReceiveFlags ) );
- KeReleaseSpinLock(&Connection->Lock, OldIrql);
-
TI_DbgPrint(DEBUG_TCP,("OskitTCPReceive: %x, %d\n", Status, Received));
/* Keep this request around ... there was no data yet */
Bucket = ExAllocatePoolWithTag( NonPagedPool, sizeof(*Bucket), TDI_BUCKET_TAG );
if( !Bucket ) {
TI_DbgPrint(DEBUG_TCP,("Failed to allocate bucket\n"));
+ UnlockObject(Connection, OldIrql);
return STATUS_NO_MEMORY;
}
Bucket->Request.RequestContext = Context;
*BytesReceived = 0;
- ExInterlockedInsertTailList( &Connection->ReceiveRequest, &Bucket->Entry,
- &Connection->Lock );
+ InsertTailList( &Connection->ReceiveRequest, &Bucket->Entry );
TI_DbgPrint(DEBUG_TCP,("Queued read irp\n"));
} else {
TI_DbgPrint(DEBUG_TCP,("Got status %x, bytes %d\n", Status, Received));
*BytesReceived = Received;
}
+ UnlockObject(Connection, OldIrql);
+
TI_DbgPrint(DEBUG_TCP,("Status %x\n", Status));
return Status;
PTDI_BUCKET Bucket;
KIRQL OldIrql;
- KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+ LockObject(Connection, &OldIrql);
TI_DbgPrint(DEBUG_TCP,("Called for %d bytes (on socket %x)\n",
SendLength, Connection->SocketContext));
- ASSERT_KM_POINTER(Connection->SocketContext);
-
TI_DbgPrint(DEBUG_TCP,("Connection = %x\n", Connection));
TI_DbgPrint(DEBUG_TCP,("Connection->SocketContext = %x\n",
Connection->SocketContext));
(OSK_PCHAR)BufferData, SendLength,
&Sent, 0 ) );
- KeReleaseSpinLock(&Connection->Lock, OldIrql);
-
TI_DbgPrint(DEBUG_TCP,("OskitTCPSend: %x, %d\n", Status, Sent));
/* Keep this request around ... there was no data yet */
/* Freed in TCPSocketState */
Bucket = ExAllocatePoolWithTag( NonPagedPool, sizeof(*Bucket), TDI_BUCKET_TAG );
if( !Bucket ) {
+ UnlockObject(Connection, OldIrql);
TI_DbgPrint(DEBUG_TCP,("Failed to allocate bucket\n"));
return STATUS_NO_MEMORY;
}
Bucket->Request.RequestContext = Context;
*BytesSent = 0;
- ExInterlockedInsertTailList( &Connection->SendRequest, &Bucket->Entry,
- &Connection->Lock );
+ InsertTailList( &Connection->SendRequest, &Bucket->Entry );
TI_DbgPrint(DEBUG_TCP,("Queued write irp\n"));
} else {
TI_DbgPrint(DEBUG_TCP,("Got status %x, bytes %d\n", Status, Sent));
*BytesSent = Sent;
}
-
+
+ UnlockObject(Connection, OldIrql);
+
TI_DbgPrint(DEBUG_TCP,("Status %x\n", Status));
return Status;
NTSTATUS Status;
KIRQL OldIrql;
- KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+ LockObject(Connection, &OldIrql);
Status = TCPTranslateError(OskitTCPGetAddress(Connection->SocketContext,
&LocalAddress, &LocalPort,
&RemoteAddress, &RemotePort));
- KeReleaseSpinLock(&Connection->Lock, OldIrql);
+ UnlockObject(Connection, OldIrql);
if (!NT_SUCCESS(Status))
return Status;
ListHead[2] = &Endpoint->ConnectRequest;
ListHead[3] = &Endpoint->ListenRequest;
- TcpipAcquireSpinLock( &Endpoint->Lock, &OldIrql );
+ LockObject(Endpoint, &OldIrql);
for( i = 0; i < 4; i++ )
{
}
}
- TcpipReleaseSpinLock( &Endpoint->Lock, OldIrql );
+ UnlockObject(Endpoint, OldIrql);
return Found;
}