mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 10:43:05 +00:00
Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.
This commit is contained in:
parent
b94e2d8ca0
commit
c2c66aff7d
24198 changed files with 0 additions and 37285 deletions
499
sdk/lib/drivers/ip/transport/tcp/event.c
Normal file
499
sdk/lib/drivers/ip/transport/tcp/event.c
Normal file
|
@ -0,0 +1,499 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS TCP/IP protocol driver
|
||||
* FILE: transport/tcp/event.c
|
||||
* PURPOSE: Transmission Control Protocol
|
||||
* PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/api.h"
|
||||
|
||||
#include "rosip.h"
|
||||
|
||||
extern NPAGED_LOOKASIDE_LIST TdiBucketLookasideList;
|
||||
|
||||
static
|
||||
VOID
|
||||
BucketCompletionWorker(PVOID Context)
|
||||
{
|
||||
PTDI_BUCKET Bucket = (PTDI_BUCKET)Context;
|
||||
PTCP_COMPLETION_ROUTINE Complete;
|
||||
|
||||
Complete = (PTCP_COMPLETION_ROUTINE)Bucket->Request.RequestNotifyObject;
|
||||
|
||||
Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information);
|
||||
|
||||
DereferenceObject(Bucket->AssociatedEndpoint);
|
||||
|
||||
ExFreeToNPagedLookasideList(&TdiBucketLookasideList, Bucket);
|
||||
}
|
||||
|
||||
VOID
|
||||
CompleteBucket(PCONNECTION_ENDPOINT Connection, PTDI_BUCKET Bucket, const BOOLEAN Synchronous)
|
||||
{
|
||||
ReferenceObject(Connection);
|
||||
Bucket->AssociatedEndpoint = Connection;
|
||||
if (Synchronous)
|
||||
{
|
||||
BucketCompletionWorker(Bucket);
|
||||
}
|
||||
else
|
||||
{
|
||||
ChewCreate(BucketCompletionWorker, Bucket);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
FlushReceiveQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked)
|
||||
{
|
||||
PTDI_BUCKET Bucket;
|
||||
PLIST_ENTRY Entry;
|
||||
|
||||
ReferenceObject(Connection);
|
||||
|
||||
if (interlocked)
|
||||
{
|
||||
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ReceiveRequest, &Connection->Lock)))
|
||||
{
|
||||
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
||||
|
||||
TI_DbgPrint(DEBUG_TCP,
|
||||
("Completing Receive request: %x %x\n",
|
||||
Bucket->Request, Status));
|
||||
|
||||
Bucket->Status = Status;
|
||||
Bucket->Information = 0;
|
||||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!IsListEmpty(&Connection->ReceiveRequest))
|
||||
{
|
||||
Entry = RemoveHeadList(&Connection->ReceiveRequest);
|
||||
|
||||
Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
|
||||
|
||||
Bucket->Information = 0;
|
||||
Bucket->Status = Status;
|
||||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
|
||||
VOID
|
||||
FlushSendQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked)
|
||||
{
|
||||
PTDI_BUCKET Bucket;
|
||||
PLIST_ENTRY Entry;
|
||||
|
||||
ReferenceObject(Connection);
|
||||
|
||||
if (interlocked)
|
||||
{
|
||||
while ((Entry = ExInterlockedRemoveHeadList(&Connection->SendRequest, &Connection->Lock)))
|
||||
{
|
||||
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
||||
|
||||
TI_DbgPrint(DEBUG_TCP,
|
||||
("Completing Send request: %x %x\n",
|
||||
Bucket->Request, Status));
|
||||
|
||||
Bucket->Status = Status;
|
||||
Bucket->Information = 0;
|
||||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!IsListEmpty(&Connection->SendRequest))
|
||||
{
|
||||
Entry = RemoveHeadList(&Connection->SendRequest);
|
||||
|
||||
Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
|
||||
|
||||
Bucket->Information = 0;
|
||||
Bucket->Status = Status;
|
||||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
|
||||
VOID
|
||||
FlushShutdownQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked)
|
||||
{
|
||||
PTDI_BUCKET Bucket;
|
||||
PLIST_ENTRY Entry;
|
||||
|
||||
ReferenceObject(Connection);
|
||||
|
||||
if (interlocked)
|
||||
{
|
||||
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ShutdownRequest, &Connection->Lock)))
|
||||
{
|
||||
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
||||
|
||||
Bucket->Status = Status;
|
||||
Bucket->Information = 0;
|
||||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!IsListEmpty(&Connection->ShutdownRequest))
|
||||
{
|
||||
Entry = RemoveHeadList(&Connection->ShutdownRequest);
|
||||
|
||||
Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
|
||||
|
||||
Bucket->Information = 0;
|
||||
Bucket->Status = Status;
|
||||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
|
||||
VOID
|
||||
FlushConnectQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
|
||||
{
|
||||
PTDI_BUCKET Bucket;
|
||||
PLIST_ENTRY Entry;
|
||||
|
||||
ReferenceObject(Connection);
|
||||
|
||||
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ConnectRequest, &Connection->Lock)))
|
||||
{
|
||||
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
||||
|
||||
Bucket->Status = Status;
|
||||
Bucket->Information = 0;
|
||||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
|
||||
VOID
|
||||
FlushListenQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
|
||||
{
|
||||
PTDI_BUCKET Bucket;
|
||||
PLIST_ENTRY Entry;
|
||||
|
||||
ReferenceObject(Connection);
|
||||
|
||||
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ListenRequest, &Connection->Lock)))
|
||||
{
|
||||
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
||||
|
||||
Bucket->Status = Status;
|
||||
Bucket->Information = 0;
|
||||
|
||||
DereferenceObject(Bucket->AssociatedEndpoint);
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
|
||||
VOID
|
||||
FlushAllQueues(PCONNECTION_ENDPOINT Connection, NTSTATUS Status)
|
||||
{
|
||||
ReferenceObject(Connection);
|
||||
|
||||
// flush receive queue
|
||||
FlushReceiveQueue(Connection, Status, TRUE);
|
||||
|
||||
/* We completed the reads successfully but we need to return failure now */
|
||||
if (Status == STATUS_SUCCESS)
|
||||
{
|
||||
Status = STATUS_FILE_CLOSED;
|
||||
}
|
||||
|
||||
// flush listen queue
|
||||
FlushListenQueue(Connection, Status);
|
||||
|
||||
// flush send queue
|
||||
FlushSendQueue(Connection, Status, TRUE);
|
||||
|
||||
// flush connect queue
|
||||
FlushConnectQueue(Connection, Status);
|
||||
|
||||
// flush shutdown queue
|
||||
FlushShutdownQueue(Connection, Status, TRUE);
|
||||
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
|
||||
VOID
|
||||
TCPFinEventHandler(void *arg, const err_t err)
|
||||
{
|
||||
PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg, LastConnection;
|
||||
const NTSTATUS Status = TCPTranslateError(err);
|
||||
KIRQL OldIrql;
|
||||
|
||||
ASSERT(Connection->SocketContext == NULL);
|
||||
ASSERT(Connection->AddressFile);
|
||||
ASSERT(err != ERR_OK);
|
||||
|
||||
/* Complete all outstanding requests now */
|
||||
FlushAllQueues(Connection, Status);
|
||||
|
||||
LockObject(Connection, &OldIrql);
|
||||
|
||||
LockObjectAtDpcLevel(Connection->AddressFile);
|
||||
|
||||
/* Unlink this connection from the address file */
|
||||
if (Connection->AddressFile->Connection == Connection)
|
||||
{
|
||||
Connection->AddressFile->Connection = Connection->Next;
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
else if (Connection->AddressFile->Listener == Connection)
|
||||
{
|
||||
Connection->AddressFile->Listener = NULL;
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
else
|
||||
{
|
||||
LastConnection = Connection->AddressFile->Connection;
|
||||
while (LastConnection->Next != Connection && LastConnection->Next != NULL)
|
||||
LastConnection = LastConnection->Next;
|
||||
if (LastConnection->Next == Connection)
|
||||
{
|
||||
LastConnection->Next = Connection->Next;
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
}
|
||||
|
||||
UnlockObjectFromDpcLevel(Connection->AddressFile);
|
||||
|
||||
/* Remove the address file from this connection */
|
||||
DereferenceObject(Connection->AddressFile);
|
||||
Connection->AddressFile = NULL;
|
||||
|
||||
UnlockObject(Connection, OldIrql);
|
||||
}
|
||||
|
||||
VOID
|
||||
TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb)
|
||||
{
|
||||
PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg;
|
||||
PTDI_BUCKET Bucket;
|
||||
PLIST_ENTRY Entry;
|
||||
PIRP Irp;
|
||||
NTSTATUS Status;
|
||||
KIRQL OldIrql;
|
||||
|
||||
ReferenceObject(Connection);
|
||||
|
||||
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ListenRequest, &Connection->Lock)))
|
||||
{
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
|
||||
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
||||
|
||||
Irp = Bucket->Request.RequestContext;
|
||||
IrpSp = IoGetCurrentIrpStackLocation( Irp );
|
||||
|
||||
TI_DbgPrint(DEBUG_TCP,("[IP, TCPAcceptEventHandler] Getting the socket\n"));
|
||||
|
||||
Status = TCPCheckPeerForAccept(newpcb,
|
||||
(PTDI_REQUEST_KERNEL)&IrpSp->Parameters);
|
||||
|
||||
TI_DbgPrint(DEBUG_TCP,("Socket: Status: %x\n", Status));
|
||||
|
||||
Bucket->Status = Status;
|
||||
Bucket->Information = 0;
|
||||
|
||||
if (Status == STATUS_SUCCESS)
|
||||
{
|
||||
LockObject(Bucket->AssociatedEndpoint, &OldIrql);
|
||||
|
||||
/* sanity assert...this should never be in anything else but a CLOSED state */
|
||||
ASSERT( ((PTCP_PCB)Bucket->AssociatedEndpoint->SocketContext)->state == CLOSED );
|
||||
|
||||
/* free socket context created in FileOpenConnection, as we're using a new one */
|
||||
LibTCPClose(Bucket->AssociatedEndpoint, TRUE, FALSE);
|
||||
|
||||
/* free previously created socket context (we don't use it, we use newpcb) */
|
||||
Bucket->AssociatedEndpoint->SocketContext = newpcb;
|
||||
|
||||
LibTCPAccept(newpcb, (PTCP_PCB)Connection->SocketContext, Bucket->AssociatedEndpoint);
|
||||
|
||||
UnlockObject(Bucket->AssociatedEndpoint, OldIrql);
|
||||
}
|
||||
|
||||
DereferenceObject(Bucket->AssociatedEndpoint);
|
||||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
|
||||
if (Status == STATUS_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
|
||||
VOID
|
||||
TCPSendEventHandler(void *arg, const u16_t space)
|
||||
{
|
||||
PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg;
|
||||
PTDI_BUCKET Bucket;
|
||||
PLIST_ENTRY Entry;
|
||||
PIRP Irp;
|
||||
NTSTATUS Status;
|
||||
PMDL Mdl;
|
||||
ULONG BytesSent;
|
||||
|
||||
ReferenceObject(Connection);
|
||||
|
||||
while ((Entry = ExInterlockedRemoveHeadList(&Connection->SendRequest, &Connection->Lock)))
|
||||
{
|
||||
UINT SendLen = 0;
|
||||
PVOID SendBuffer = 0;
|
||||
|
||||
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
||||
|
||||
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(LibTCPSend(Connection,
|
||||
SendBuffer,
|
||||
SendLen, &BytesSent, TRUE));
|
||||
|
||||
TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", BytesSent));
|
||||
|
||||
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));
|
||||
|
||||
Bucket->Status = Status;
|
||||
Bucket->Information = (Bucket->Status == STATUS_SUCCESS) ? BytesSent : 0;
|
||||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
// If we completed all outstanding send requests then finish all pending shutdown requests,
|
||||
// cancel the timer and dereference the connection
|
||||
if (IsListEmpty(&Connection->SendRequest))
|
||||
{
|
||||
FlushShutdownQueue(Connection, STATUS_SUCCESS, FALSE);
|
||||
|
||||
if (KeCancelTimer(&Connection->DisconnectTimer))
|
||||
{
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
}
|
||||
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
|
||||
VOID
|
||||
TCPRecvEventHandler(void *arg)
|
||||
{
|
||||
PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg;
|
||||
PTDI_BUCKET Bucket;
|
||||
PLIST_ENTRY Entry;
|
||||
PIRP Irp;
|
||||
PMDL Mdl;
|
||||
UINT Received;
|
||||
UINT RecvLen;
|
||||
PUCHAR RecvBuffer;
|
||||
NTSTATUS Status;
|
||||
|
||||
ReferenceObject(Connection);
|
||||
|
||||
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ReceiveRequest, &Connection->Lock)))
|
||||
{
|
||||
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
||||
|
||||
Irp = Bucket->Request.RequestContext;
|
||||
Mdl = Irp->MdlAddress;
|
||||
|
||||
NdisQueryBuffer( Mdl, &RecvBuffer, &RecvLen );
|
||||
|
||||
Status = LibTCPGetDataFromConnectionQueue(Connection, RecvBuffer, RecvLen, &Received);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
ExInterlockedInsertHeadList(&Connection->ReceiveRequest,
|
||||
&Bucket->Entry,
|
||||
&Connection->Lock);
|
||||
break;
|
||||
}
|
||||
|
||||
Bucket->Status = Status;
|
||||
Bucket->Information = Received;
|
||||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
|
||||
VOID
|
||||
TCPConnectEventHandler(void *arg, const err_t err)
|
||||
{
|
||||
PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg;
|
||||
PTDI_BUCKET Bucket;
|
||||
PLIST_ENTRY Entry;
|
||||
|
||||
ReferenceObject(Connection);
|
||||
|
||||
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ConnectRequest, &Connection->Lock)))
|
||||
{
|
||||
|
||||
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
||||
|
||||
Bucket->Status = TCPTranslateError(err);
|
||||
Bucket->Information = 0;
|
||||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
|
||||
DereferenceObject(Connection);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue