mirror of
https://github.com/reactos/reactos.git
synced 2024-12-31 19:42:51 +00:00
[AFD]
- Hold on to the disconnect IRP until all pending sending IRPs are sent to the transport driver if a controlled disconnect was requested svn path=/trunk/; revision=52415
This commit is contained in:
parent
379fa83099
commit
d7a7a20e8b
3 changed files with 131 additions and 54 deletions
|
@ -440,6 +440,7 @@ AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
|||
ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]));
|
||||
ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]));
|
||||
ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_PREACCEPT]));
|
||||
ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_DISCONNECT]))
|
||||
|
||||
while (!IsListEmpty(&FCB->PendingConnections))
|
||||
{
|
||||
|
@ -531,14 +532,108 @@ AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
DoDisconnect(PAFD_FCB FCB, PIRP CurrentIrp)
|
||||
{
|
||||
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);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static NTSTATUS NTAPI
|
||||
AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
||||
PIO_STACK_LOCATION IrpSp) {
|
||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
PAFD_FCB FCB = FileObject->FsContext;
|
||||
PAFD_DISCONNECT_INFO DisReq;
|
||||
IO_STATUS_BLOCK Iosb;
|
||||
PTDI_CONNECTION_INFORMATION ConnectionReturnInfo;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
USHORT Flags = 0;
|
||||
|
||||
|
@ -559,56 +654,23 @@ AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
|||
if( !FCB->ConnectInfo )
|
||||
return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER,
|
||||
Irp, 0 );
|
||||
|
||||
ASSERT(FCB->RemoteAddress);
|
||||
|
||||
Status = TdiBuildNullConnectionInfo
|
||||
( &ConnectionReturnInfo, FCB->RemoteAddress->Address[0].AddressType );
|
||||
|
||||
if( !NT_SUCCESS(Status) )
|
||||
return UnlockAndMaybeComplete( FCB, Status,
|
||||
Irp, 0 );
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) || (Flags & TDI_DISCONNECT_ABORT))
|
||||
{
|
||||
/* Go ahead an execute the disconnect because we're ready for it */
|
||||
Status = DoDisconnect(FCB, Irp);
|
||||
|
||||
/* DoDisconnect takes care of the IRP */
|
||||
SocketStateUnlock(FCB);
|
||||
|
||||
return Status;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have a graceful disconnect waiting on pending sends to complete */
|
||||
return LeaveIrpUntilLater(FCB, Irp, FUNCTION_DISCONNECT);
|
||||
}
|
||||
|
||||
ExFreePool( ConnectionReturnInfo );
|
||||
|
||||
if (Flags & TDI_DISCONNECT_RELEASE)
|
||||
FCB->PollState |= AFD_EVENT_DISCONNECT;
|
||||
else
|
||||
FCB->PollState |= AFD_EVENT_ABORT;
|
||||
FCB->PollStatus[FD_CLOSE_BIT] = STATUS_SUCCESS;
|
||||
PollReeval( FCB->DeviceExt, FCB->FileObject );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -924,6 +986,10 @@ AfdCancelHandler(PDEVICE_OBJECT DeviceObject,
|
|||
DbgPrint("WARNING!!! IRP cancellation race could lead to a process hang! (IOCTL_AFD_SELECT)\n");
|
||||
return;
|
||||
|
||||
case IOCTL_AFD_DISCONNECT:
|
||||
Function = FUNCTION_DISCONNECT;
|
||||
break;
|
||||
|
||||
default:
|
||||
ASSERT(FALSE);
|
||||
UnlockAndMaybeComplete(FCB, STATUS_CANCELLED, Irp, 0);
|
||||
|
|
|
@ -59,8 +59,11 @@ static NTSTATUS NTAPI SendComplete
|
|||
(void)IoSetCancelRoutine(NextIrp, NULL);
|
||||
IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
|
||||
}
|
||||
SocketStateUnlock( FCB );
|
||||
return STATUS_FILE_CLOSED;
|
||||
|
||||
RetryDisconnectCompletion(FCB);
|
||||
|
||||
SocketStateUnlock( FCB );
|
||||
return STATUS_FILE_CLOSED;
|
||||
}
|
||||
|
||||
if( !NT_SUCCESS(Status) ) {
|
||||
|
@ -85,6 +88,8 @@ static NTSTATUS NTAPI SendComplete
|
|||
(void)IoSetCancelRoutine(NextIrp, NULL);
|
||||
IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
|
||||
}
|
||||
|
||||
RetryDisconnectCompletion(FCB);
|
||||
|
||||
SocketStateUnlock( FCB );
|
||||
|
||||
|
@ -164,6 +169,8 @@ static NTSTATUS NTAPI SendComplete
|
|||
&FCB->SendIrp.Iosb,
|
||||
SendComplete,
|
||||
FCB );
|
||||
|
||||
RetryDisconnectCompletion(FCB);
|
||||
} else {
|
||||
FCB->PollState |= AFD_EVENT_SEND;
|
||||
FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
|
||||
|
@ -410,6 +417,8 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
|||
Status, TotalBytesCopied));
|
||||
}
|
||||
|
||||
RetryDisconnectCompletion(FCB);
|
||||
|
||||
return UnlockAndMaybeComplete
|
||||
( FCB, Status, Irp, TotalBytesCopied );
|
||||
}
|
||||
|
|
|
@ -99,8 +99,9 @@ typedef struct IPADDR_ENTRY {
|
|||
#define FUNCTION_SEND 2
|
||||
#define FUNCTION_PREACCEPT 3
|
||||
#define FUNCTION_ACCEPT 4
|
||||
#define FUNCTION_CLOSE 5
|
||||
#define MAX_FUNCTIONS 6
|
||||
#define FUNCTION_DISCONNECT 5
|
||||
#define FUNCTION_CLOSE 6
|
||||
#define MAX_FUNCTIONS 7
|
||||
|
||||
#define IN_FLIGHT_REQUESTS 4
|
||||
|
||||
|
@ -309,6 +310,7 @@ NTSTATUS LeaveIrpUntilLater( PAFD_FCB FCB, PIRP Irp, UINT Function );
|
|||
VOID DestroySocket( PAFD_FCB FCB );
|
||||
VOID NTAPI AfdCancelHandler(PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp);
|
||||
VOID RetryDisconnectCompletion(PAFD_FCB FCB);
|
||||
|
||||
/* read.c */
|
||||
|
||||
|
|
Loading…
Reference in a new issue