Author: cgutman Date: Fri Jul 1 14:31:37 2011 New Revision: 52497
URL: http://svn.reactos.org/svn/reactos?rev=52497&view=rev Log: [AFD] - Rewrite disconnect to work asynchronously
Modified: trunk/reactos/drivers/network/afd/afd/connect.c trunk/reactos/drivers/network/afd/afd/listen.c trunk/reactos/drivers/network/afd/afd/main.c trunk/reactos/drivers/network/afd/afd/tdi.c trunk/reactos/drivers/network/afd/include/afd.h trunk/reactos/drivers/network/afd/include/tdi_proto.h
Modified: trunk/reactos/drivers/network/afd/afd/connect.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/afd/afd/con... ============================================================================== --- trunk/reactos/drivers/network/afd/afd/connect.c [iso-8859-1] (original) +++ trunk/reactos/drivers/network/afd/afd/connect.c [iso-8859-1] Fri Jul 1 14:31:37 2011 @@ -332,19 +332,19 @@ return Status; }
- FCB->FilledConnectData = MIN(FCB->ConnectInfo->UserDataLength, FCB->ConnectDataSize); + FCB->FilledConnectData = MIN(FCB->ConnectReturnInfo->UserDataLength, FCB->ConnectDataSize); if (FCB->FilledConnectData) { RtlCopyMemory(FCB->ConnectData, - FCB->ConnectInfo->UserData, + FCB->ConnectReturnInfo->UserData, FCB->FilledConnectData); }
- FCB->FilledConnectOptions = MIN(FCB->ConnectInfo->OptionsLength, FCB->ConnectOptionsSize); + FCB->FilledConnectOptions = MIN(FCB->ConnectReturnInfo->OptionsLength, FCB->ConnectOptionsSize); if (FCB->FilledConnectOptions) { RtlCopyMemory(FCB->ConnectOptions, - FCB->ConnectInfo->Options, + FCB->ConnectReturnInfo->Options, FCB->FilledConnectOptions); }
@@ -380,7 +380,6 @@ PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; PAFD_CONNECT_INFO ConnectReq; - PTDI_CONNECTION_INFORMATION TargetAddress; AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); @@ -450,21 +449,25 @@ if( !NT_SUCCESS(Status) ) break;
+ if (FCB->ConnectReturnInfo) ExFreePool(FCB->ConnectReturnInfo); Status = TdiBuildConnectionInfo - ( &FCB->ConnectInfo, + ( &FCB->ConnectReturnInfo, &ConnectReq->RemoteAddress );
if( NT_SUCCESS(Status) ) - Status = TdiBuildConnectionInfo(&TargetAddress, + { + if (FCB->ConnectCallInfo) ExFreePool(FCB->ConnectCallInfo); + Status = TdiBuildConnectionInfo(&FCB->ConnectCallInfo, &ConnectReq->RemoteAddress); + } else break;
if( NT_SUCCESS(Status) ) { - TargetAddress->UserData = FCB->ConnectData; - TargetAddress->UserDataLength = FCB->ConnectDataSize; - TargetAddress->Options = FCB->ConnectOptions; - TargetAddress->OptionsLength = FCB->ConnectOptionsSize; + FCB->ConnectCallInfo->UserData = FCB->ConnectData; + FCB->ConnectCallInfo->UserDataLength = FCB->ConnectDataSize; + FCB->ConnectCallInfo->Options = FCB->ConnectOptions; + FCB->ConnectCallInfo->OptionsLength = FCB->ConnectOptionsSize;
FCB->State = SOCKET_STATE_CONNECTING;
@@ -474,8 +477,8 @@ { Status = TdiConnect( &FCB->ConnectIrp.InFlightRequest, FCB->Connection.Object, - TargetAddress, - FCB->ConnectInfo, + FCB->ConnectCallInfo, + FCB->ConnectReturnInfo, &FCB->ConnectIrp.Iosb, StreamSocketConnectComplete, FCB ); @@ -483,8 +486,6 @@
if (Status != STATUS_PENDING) FCB->State = SOCKET_STATE_BOUND; - - ExFreePool(TargetAddress);
SocketStateUnlock(FCB);
Modified: trunk/reactos/drivers/network/afd/afd/listen.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/afd/afd/lis... ============================================================================== --- trunk/reactos/drivers/network/afd/afd/listen.c [iso-8859-1] (original) +++ trunk/reactos/drivers/network/afd/afd/listen.c [iso-8859-1] Fri Jul 1 14:31:37 2011 @@ -37,7 +37,10 @@ Status = MakeSocketIntoConnection( FCB );
if (NT_SUCCESS(Status)) - Status = TdiBuildConnectionInfo(&FCB->ConnectInfo, FCB->RemoteAddress); + Status = TdiBuildConnectionInfo(&FCB->ConnectCallInfo, FCB->RemoteAddress); + + if (NT_SUCCESS(Status)) + Status = TdiBuildConnectionInfo(&FCB->ConnectReturnInfo, FCB->RemoteAddress);
return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); }
Modified: trunk/reactos/drivers/network/afd/afd/main.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/afd/afd/mai... ============================================================================== --- trunk/reactos/drivers/network/afd/afd/main.c [iso-8859-1] (original) +++ trunk/reactos/drivers/network/afd/afd/main.c [iso-8859-1] Fri Jul 1 14:31:37 2011 @@ -472,8 +472,11 @@ if( FCB->AddressFrom ) ExFreePool( FCB->AddressFrom );
- if( FCB->ConnectInfo ) - ExFreePool( FCB->ConnectInfo ); + if( FCB->ConnectCallInfo ) + ExFreePool( FCB->ConnectCallInfo ); + + if( FCB->ConnectReturnInfo ) + ExFreePool( FCB->ConnectReturnInfo );
if( FCB->ConnectData ) ExFreePool( FCB->ConnectData ); @@ -534,76 +537,101 @@
static NTSTATUS -DoDisconnect(PAFD_FCB FCB, PIRP CurrentIrp) +NTAPI +DisconnectComplete(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context) +{ + PAFD_FCB FCB = Context; + PIRP CurrentIrp; + PLIST_ENTRY CurrentEntry; + + if( !SocketAcquireStateLock( FCB ) ) + return STATUS_FILE_CLOSED; + + ASSERT(FCB->DisconnectIrp.InFlightRequest == Irp); + FCB->DisconnectIrp.InFlightRequest = NULL; + + ASSERT(FCB->DisconnectPending); + //ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) || (FCB->DisconnectFlags & TDI_DISCONNECT_ABORT)); + + if (NT_SUCCESS(Irp->IoStatus.Status) && (FCB->DisconnectFlags & TDI_DISCONNECT_RELEASE)) + { + FCB->FilledDisconnectData = MIN(FCB->DisconnectDataSize, FCB->ConnectReturnInfo->UserDataLength); + if (FCB->FilledDisconnectData) + { + RtlCopyMemory(FCB->DisconnectData, + FCB->ConnectReturnInfo->UserData, + FCB->FilledDisconnectData); + } + + FCB->FilledDisconnectOptions = MIN(FCB->DisconnectOptionsSize, FCB->ConnectReturnInfo->OptionsLength); + if (FCB->FilledDisconnectOptions) + { + RtlCopyMemory(FCB->DisconnectOptions, + FCB->ConnectReturnInfo->Options, + FCB->FilledDisconnectOptions); + } + } + + FCB->DisconnectPending = FALSE; + + while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_DISCONNECT])) + { + CurrentEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_DISCONNECT]); + CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry); + CurrentIrp->IoStatus.Status = Irp->IoStatus.Status; + CurrentIrp->IoStatus.Information = 0; + UnlockRequest(CurrentIrp, IoGetCurrentIrpStackLocation(CurrentIrp)); + (void)IoSetCancelRoutine(CurrentIrp, NULL); + IoCompleteRequest(CurrentIrp, IO_NETWORK_INCREMENT ); + } + + if (FCB->DisconnectFlags & TDI_DISCONNECT_RELEASE) + FCB->PollState |= AFD_EVENT_DISCONNECT; + else + FCB->PollState |= AFD_EVENT_ABORT; + FCB->PollStatus[FD_CLOSE_BIT] = Irp->IoStatus.Status; + PollReeval(FCB->DeviceExt, FCB->FileObject); + + SocketStateUnlock(FCB); + + return Irp->IoStatus.Status; +} + +static +NTSTATUS +DoDisconnect(PAFD_FCB FCB) { PAFD_DISCONNECT_INFO DisReq; IO_STATUS_BLOCK Iosb; - PTDI_CONNECTION_INFORMATION ConnectionReturnInfo; - PIO_STACK_LOCATION CurrentIrpSp; - USHORT Flags = 0; NTSTATUS Status;
- CurrentIrpSp = IoGetCurrentIrpStackLocation(CurrentIrp); - DisReq = GetLockedData(CurrentIrp, CurrentIrpSp); - - if( DisReq->DisconnectType & AFD_DISCONNECT_SEND ) - Flags |= TDI_DISCONNECT_RELEASE; - if( DisReq->DisconnectType & AFD_DISCONNECT_RECV || - DisReq->DisconnectType & AFD_DISCONNECT_ABORT ) - Flags |= TDI_DISCONNECT_ABORT; - - Status = TdiBuildNullConnectionInfo(&ConnectionReturnInfo, - FCB->RemoteAddress->Address[0].AddressType); - if (NT_SUCCESS(Status)) - { - FCB->ConnectInfo->UserData = FCB->DisconnectData; - FCB->ConnectInfo->UserDataLength = FCB->DisconnectDataSize; - FCB->ConnectInfo->Options = FCB->DisconnectOptions; - FCB->ConnectInfo->OptionsLength = FCB->DisconnectOptionsSize; - - Status = TdiDisconnect(FCB->Connection.Object, - &DisReq->Timeout, - Flags, - &Iosb, - NULL, - NULL, - FCB->ConnectInfo, - ConnectionReturnInfo); - - if (NT_SUCCESS(Status)) { - FCB->FilledDisconnectData = MIN(FCB->DisconnectDataSize, ConnectionReturnInfo->UserDataLength); - if (FCB->FilledDisconnectData) - { - RtlCopyMemory(FCB->DisconnectData, - ConnectionReturnInfo->UserData, - FCB->FilledDisconnectData); - } - - FCB->FilledDisconnectOptions = MIN(FCB->DisconnectOptionsSize, ConnectionReturnInfo->OptionsLength); - if (FCB->FilledDisconnectOptions) - { - RtlCopyMemory(FCB->DisconnectOptions, - ConnectionReturnInfo->Options, - FCB->FilledDisconnectOptions); - } - } - - ExFreePool( ConnectionReturnInfo ); - - if (Flags & TDI_DISCONNECT_RELEASE) - FCB->PollState |= AFD_EVENT_DISCONNECT; - else - FCB->PollState |= AFD_EVENT_ABORT; - FCB->PollStatus[FD_CLOSE_BIT] = Status; - PollReeval( FCB->DeviceExt, FCB->FileObject ); - } - - CurrentIrp->IoStatus.Status = Status; - CurrentIrp->IoStatus.Information = 0; - UnlockRequest(CurrentIrp, CurrentIrpSp); - (void)IoSetCancelRoutine(CurrentIrp, NULL); - - IoCompleteRequest(CurrentIrp, IO_NETWORK_INCREMENT); + ASSERT(FCB->DisconnectPending); + + if (FCB->DisconnectIrp.InFlightRequest) + { + return STATUS_PENDING; + } + + FCB->ConnectCallInfo->UserData = FCB->DisconnectData; + FCB->ConnectCallInfo->UserDataLength = FCB->DisconnectDataSize; + FCB->ConnectCallInfo->Options = FCB->DisconnectOptions; + FCB->ConnectCallInfo->OptionsLength = FCB->DisconnectOptionsSize; + + Status = TdiDisconnect(&FCB->DisconnectIrp.InFlightRequest, + FCB->Connection.Object, + &DisReq->Timeout, + FCB->DisconnectFlags, + &Iosb, + DisconnectComplete, + FCB, + FCB->ConnectCallInfo, + FCB->ConnectReturnInfo); + if (Status != STATUS_PENDING) + { + FCB->DisconnectPending = FALSE; + }
return Status; } @@ -611,20 +639,12 @@ VOID RetryDisconnectCompletion(PAFD_FCB FCB) { - if (IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND])) - { - PIRP CurrentIrp; - PLIST_ENTRY CurrentEntry; - - ASSERT(FCB->RemoteAddress); - - while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_DISCONNECT])) - { - CurrentEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_DISCONNECT]); - CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry); - - DoDisconnect(FCB, CurrentIrp); - } + ASSERT(FCB->RemoteAddress); + + if (IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) && FCB->DisconnectPending) + { + /* Sends are done; fire off a TDI_DISCONNECT request */ + DoDisconnect(FCB); } }
@@ -636,6 +656,8 @@ PAFD_DISCONNECT_INFO DisReq; NTSTATUS Status = STATUS_SUCCESS; USHORT Flags = 0; + PLIST_ENTRY CurrentEntry; + PIRP CurrentIrp;
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
@@ -651,26 +673,54 @@
if (!(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS)) { - if( !FCB->ConnectInfo ) + if( !FCB->ConnectCallInfo ) return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, 0 ); + + if (FCB->DisconnectPending) + { + if (FCB->DisconnectIrp.InFlightRequest) + { + IoCancelIrp(FCB->DisconnectIrp.InFlightRequest); + ASSERT(!FCB->DisconnectIrp.InFlightRequest); + } + else + { + while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_DISCONNECT])) + { + CurrentEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_DISCONNECT]); + CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry); + CurrentIrp->IoStatus.Status = STATUS_CANCELLED; + CurrentIrp->IoStatus.Information = 0; + UnlockRequest(CurrentIrp, IoGetCurrentIrpStackLocation(CurrentIrp)); + (void)IoSetCancelRoutine(CurrentIrp, NULL); + IoCompleteRequest(CurrentIrp, IO_NETWORK_INCREMENT ); + } + } + }
- if (IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) || (Flags & TDI_DISCONNECT_ABORT)) + FCB->DisconnectFlags = Flags; + FCB->DisconnectPending = TRUE; + + Status = QueueUserModeIrp(FCB, Irp, FUNCTION_DISCONNECT); + if (Status == STATUS_PENDING) { - /* Go ahead an execute the disconnect because we're ready for it */ - Status = DoDisconnect(FCB, Irp); + if (IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) || (FCB->DisconnectFlags & TDI_DISCONNECT_ABORT)) + { + /* Go ahead an execute the disconnect because we're ready for it */ + Status = DoDisconnect(FCB); + }
- /* DoDisconnect takes care of the IRP */ + if (Status != STATUS_PENDING) + RemoveEntryList(&Irp->Tail.Overlay.ListEntry); + } + + if (Status == STATUS_PENDING) + { SocketStateUnlock(FCB); - + return Status; } - else - { - /* We have a graceful disconnect waiting on pending sends to complete */ - return LeaveIrpUntilLater(FCB, Irp, FUNCTION_DISCONNECT); - } - } else {
Modified: trunk/reactos/drivers/network/afd/afd/tdi.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/afd/afd/tdi... ============================================================================== --- trunk/reactos/drivers/network/afd/afd/tdi.c [iso-8859-1] (original) +++ trunk/reactos/drivers/network/afd/afd/tdi.c [iso-8859-1] Fri Jul 1 14:31:37 2011 @@ -1228,6 +1228,7 @@ }
NTSTATUS TdiDisconnect( + PIRP *Irp, PFILE_OBJECT TransportObject, PLARGE_INTEGER Time, USHORT Flags, @@ -1237,10 +1238,6 @@ PTDI_CONNECTION_INFORMATION RequestConnectionInfo, PTDI_CONNECTION_INFORMATION ReturnConnectionInfo) { PDEVICE_OBJECT DeviceObject; - KEVENT Event; - PIRP Irp; - - KeInitializeEvent(&Event, NotificationEvent, FALSE);
if (!TransportObject) { AFD_DbgPrint(MIN_TRACE, ("Bad transport object.\n")); @@ -1255,20 +1252,20 @@ return STATUS_INVALID_PARAMETER; }
- Irp = TdiBuildInternalDeviceControlIrp + *Irp = TdiBuildInternalDeviceControlIrp ( TDI_DISCONNECT, /* Sub function */ DeviceObject, /* Device object */ TransportObject, /* File object */ - &Event, /* Event */ + NULL, /* Event */ Iosb ); /* Status */
- if (!Irp) { + if (!*Irp) { AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); return STATUS_INSUFFICIENT_RESOURCES; }
TdiBuildDisconnect - (Irp, /* I/O Request Packet */ + (*Irp, /* I/O Request Packet */ DeviceObject, /* Device object */ TransportObject, /* File object */ CompletionRoutine, /* Completion routine */ @@ -1278,7 +1275,9 @@ RequestConnectionInfo, /* Indication of who to disconnect */ ReturnConnectionInfo); /* Indication of who disconnected */
- return TdiCall(Irp, DeviceObject, &Event, Iosb); + TdiCall(*Irp, DeviceObject, NULL, Iosb); + + return STATUS_PENDING; }
/* EOF */
Modified: trunk/reactos/drivers/network/afd/include/afd.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/afd/include... ============================================================================== --- trunk/reactos/drivers/network/afd/include/afd.h [iso-8859-1] (original) +++ trunk/reactos/drivers/network/afd/include/afd.h [iso-8859-1] Fri Jul 1 14:31:37 2011 @@ -182,10 +182,12 @@ PAFD_DEVICE_EXTENSION DeviceExt; BOOLEAN DelayedAccept; UINT ConnSeq; + USHORT DisconnectFlags; + BOOLEAN DisconnectPending; PTRANSPORT_ADDRESS LocalAddress, RemoteAddress; - PTDI_CONNECTION_INFORMATION AddressFrom, ConnectInfo; + PTDI_CONNECTION_INFORMATION AddressFrom, ConnectCallInfo, ConnectReturnInfo; AFD_TDI_OBJECT AddressFile, Connection; - AFD_IN_FLIGHT_REQUEST ConnectIrp, ListenIrp, ReceiveIrp, SendIrp; + AFD_IN_FLIGHT_REQUEST ConnectIrp, ListenIrp, ReceiveIrp, SendIrp, DisconnectIrp; AFD_DATA_WINDOW Send, Recv; KMUTEX Mutex; PKEVENT EventSelect;
Modified: trunk/reactos/drivers/network/afd/include/tdi_proto.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/afd/include... ============================================================================== --- trunk/reactos/drivers/network/afd/include/tdi_proto.h [iso-8859-1] (original) +++ trunk/reactos/drivers/network/afd/include/tdi_proto.h [iso-8859-1] Fri Jul 1 14:31:37 2011 @@ -16,7 +16,8 @@ PFILE_OBJECT FileObject);
NTSTATUS TdiDisconnect -( PFILE_OBJECT TransportObject, +( PIRP *Irp, + PFILE_OBJECT TransportObject, PLARGE_INTEGER Time, USHORT Flags, PIO_STATUS_BLOCK Iosb,