2004-09-29 05:10:48 +00:00
|
|
|
/*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS TCP/IP protocol driver
|
|
|
|
* FILE: transport/tcp/event.c
|
2010-09-21 06:11:24 +00:00
|
|
|
* PURPOSE: Transmission Control Protocol
|
|
|
|
* PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
|
2004-09-29 05:10:48 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
|
2010-09-21 06:11:24 +00:00
|
|
|
#include "lwip/err.h"
|
|
|
|
#include "lwip/sys.h"
|
|
|
|
#include "lwip/pbuf.h"
|
|
|
|
#include "lwip/tcp.h"
|
|
|
|
#include "lwip/api.h"
|
2004-09-29 05:10:48 +00:00
|
|
|
|
2010-09-21 06:11:24 +00:00
|
|
|
#include "rosip.h"
|
2004-11-21 20:54:52 +00:00
|
|
|
|
2011-08-08 21:28:50 +00:00
|
|
|
extern NPAGED_LOOKASIDE_LIST TdiBucketLookasideList;
|
|
|
|
|
2011-06-17 12:04:20 +00:00
|
|
|
static
|
2010-09-21 06:11:24 +00:00
|
|
|
VOID
|
2011-06-17 12:04:20 +00:00
|
|
|
BucketCompletionWorker(PVOID Context)
|
2010-09-21 06:11:24 +00:00
|
|
|
{
|
2011-06-22 15:32:46 +00:00
|
|
|
PTDI_BUCKET Bucket = (PTDI_BUCKET)Context;
|
2010-09-21 06:11:24 +00:00
|
|
|
PTCP_COMPLETION_ROUTINE Complete;
|
2011-06-17 12:04:20 +00:00
|
|
|
|
2011-06-22 15:32:46 +00:00
|
|
|
Complete = (PTCP_COMPLETION_ROUTINE)Bucket->Request.RequestNotifyObject;
|
2011-06-17 12:04:20 +00:00
|
|
|
|
|
|
|
Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information);
|
|
|
|
|
|
|
|
DereferenceObject(Bucket->AssociatedEndpoint);
|
2011-06-23 07:57:59 +00:00
|
|
|
|
2011-08-08 21:28:50 +00:00
|
|
|
ExFreeToNPagedLookasideList(&TdiBucketLookasideList, Bucket);
|
2004-09-29 05:10:48 +00:00
|
|
|
}
|
|
|
|
|
2011-06-17 12:04:20 +00:00
|
|
|
VOID
|
2011-08-01 20:10:55 +00:00
|
|
|
CompleteBucket(PCONNECTION_ENDPOINT Connection, PTDI_BUCKET Bucket, const BOOLEAN Synchronous)
|
2011-06-17 12:04:20 +00:00
|
|
|
{
|
|
|
|
ReferenceObject(Connection);
|
|
|
|
Bucket->AssociatedEndpoint = Connection;
|
|
|
|
if (Synchronous)
|
|
|
|
{
|
|
|
|
BucketCompletionWorker(Bucket);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ChewCreate(BucketCompletionWorker, Bucket);
|
|
|
|
}
|
2004-09-29 05:10:48 +00:00
|
|
|
}
|
|
|
|
|
2011-06-17 12:04:20 +00:00
|
|
|
VOID
|
2011-08-07 19:13:23 +00:00
|
|
|
FlushReceiveQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked)
|
2011-06-17 12:04:20 +00:00
|
|
|
{
|
2010-09-21 06:11:24 +00:00
|
|
|
PTDI_BUCKET Bucket;
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
|
|
|
|
ReferenceObject(Connection);
|
2011-08-07 19:13:23 +00:00
|
|
|
|
|
|
|
if (interlocked)
|
2011-06-11 13:24:33 +00:00
|
|
|
{
|
2011-08-07 19:13:23 +00:00
|
|
|
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ReceiveRequest, &Connection->Lock)))
|
|
|
|
{
|
|
|
|
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
2010-09-21 06:11:24 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
TI_DbgPrint(DEBUG_TCP,
|
|
|
|
("Completing Receive request: %x %x\n",
|
|
|
|
Bucket->Request, Status));
|
2010-09-21 06:11:24 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
Bucket->Status = Status;
|
|
|
|
Bucket->Information = 0;
|
2010-09-21 06:11:24 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
CompleteBucket(Connection, Bucket, FALSE);
|
|
|
|
}
|
2004-09-29 05:10:48 +00:00
|
|
|
}
|
2011-08-07 19:13:23 +00:00
|
|
|
else
|
2011-07-10 00:38:29 +00:00
|
|
|
{
|
2011-08-07 19:13:23 +00:00
|
|
|
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);
|
|
|
|
}
|
2011-07-10 00:38:29 +00:00
|
|
|
}
|
2011-08-07 19:13:23 +00:00
|
|
|
|
|
|
|
DereferenceObject(Connection);
|
|
|
|
}
|
2004-09-29 05:10:48 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
VOID
|
|
|
|
FlushSendQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked)
|
|
|
|
{
|
|
|
|
PTDI_BUCKET Bucket;
|
|
|
|
PLIST_ENTRY Entry;
|
2010-09-21 06:11:24 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
ReferenceObject(Connection);
|
2004-09-29 05:10:48 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
if (interlocked)
|
2011-05-24 18:05:51 +00:00
|
|
|
{
|
2011-08-07 19:13:23 +00:00
|
|
|
while ((Entry = ExInterlockedRemoveHeadList(&Connection->SendRequest, &Connection->Lock)))
|
|
|
|
{
|
|
|
|
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
2010-09-21 06:11:24 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
TI_DbgPrint(DEBUG_TCP,
|
|
|
|
("Completing Send request: %x %x\n",
|
|
|
|
Bucket->Request, Status));
|
2010-09-21 06:11:24 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
Bucket->Status = Status;
|
|
|
|
Bucket->Information = 0;
|
|
|
|
|
|
|
|
CompleteBucket(Connection, Bucket, FALSE);
|
|
|
|
}
|
2004-09-29 05:10:48 +00:00
|
|
|
}
|
2011-08-07 19:13:23 +00:00
|
|
|
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);
|
|
|
|
}
|
2004-12-04 23:29:56 +00:00
|
|
|
}
|
2004-09-29 05:10:48 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
DereferenceObject(Connection);
|
|
|
|
}
|
2005-05-08 02:16:32 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
VOID
|
|
|
|
FlushShutdownQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked)
|
|
|
|
{
|
|
|
|
PTDI_BUCKET Bucket;
|
|
|
|
PLIST_ENTRY Entry;
|
2010-09-21 06:11:24 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
ReferenceObject(Connection);
|
2004-09-29 05:10:48 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
if (interlocked)
|
2011-05-24 18:05:51 +00:00
|
|
|
{
|
2011-08-07 19:13:23 +00:00
|
|
|
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ShutdownRequest, &Connection->Lock)))
|
|
|
|
{
|
|
|
|
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
2010-09-21 06:11:24 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2004-11-07 20:37:21 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
DereferenceObject(Connection);
|
|
|
|
}
|
2004-09-29 05:10:48 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
VOID
|
|
|
|
FlushConnectQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
|
|
|
|
{
|
|
|
|
PTDI_BUCKET Bucket;
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
|
|
|
|
ReferenceObject(Connection);
|
2004-09-29 05:10:48 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ConnectRequest, &Connection->Lock)))
|
2008-12-21 01:29:35 +00:00
|
|
|
{
|
2011-08-07 19:13:23 +00:00
|
|
|
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
Bucket->Status = Status;
|
|
|
|
Bucket->Information = 0;
|
|
|
|
|
2011-07-10 00:38:29 +00:00
|
|
|
CompleteBucket(Connection, Bucket, FALSE);
|
2008-12-21 01:29:35 +00:00
|
|
|
}
|
2005-05-08 02:16:32 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
DereferenceObject(Connection);
|
2004-09-29 05:10:48 +00:00
|
|
|
}
|
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
VOID
|
|
|
|
FlushListenQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
|
|
|
|
{
|
|
|
|
PTDI_BUCKET Bucket;
|
|
|
|
PLIST_ENTRY Entry;
|
2010-09-21 06:11:24 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
ReferenceObject(Connection);
|
2006-01-02 20:26:03 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ListenRequest, &Connection->Lock)))
|
2011-05-24 18:05:51 +00:00
|
|
|
{
|
2010-09-21 06:11:24 +00:00
|
|
|
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
|
|
|
|
|
|
|
Bucket->Status = Status;
|
|
|
|
Bucket->Information = 0;
|
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
DereferenceObject(Bucket->AssociatedEndpoint);
|
2011-07-10 00:38:29 +00:00
|
|
|
CompleteBucket(Connection, Bucket, FALSE);
|
2008-12-21 01:29:35 +00:00
|
|
|
}
|
2006-01-02 20:26:03 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
DereferenceObject(Connection);
|
|
|
|
}
|
2006-01-02 20:26:03 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
VOID
|
|
|
|
FlushAllQueues(PCONNECTION_ENDPOINT Connection, NTSTATUS Status)
|
|
|
|
{
|
|
|
|
ReferenceObject(Connection);
|
|
|
|
|
|
|
|
// flush receive queue
|
|
|
|
FlushReceiveQueue(Connection, Status, TRUE);
|
2006-01-02 20:26:03 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
/* 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);
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
DereferenceObject(Connection);
|
2006-01-02 20:26:03 +00:00
|
|
|
}
|
|
|
|
|
2010-09-21 06:11:24 +00:00
|
|
|
VOID
|
2011-08-01 20:10:55 +00:00
|
|
|
TCPFinEventHandler(void *arg, const err_t err)
|
2006-01-02 20:26:03 +00:00
|
|
|
{
|
2012-12-23 09:53:36 +00:00
|
|
|
PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg, LastConnection;
|
|
|
|
const NTSTATUS Status = TCPTranslateError(err);
|
|
|
|
KIRQL OldIrql;
|
|
|
|
|
2013-08-12 04:08:20 +00:00
|
|
|
ASSERT(Connection->SocketContext == NULL);
|
2012-12-23 09:53:36 +00:00
|
|
|
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);
|
2006-01-02 20:26:03 +00:00
|
|
|
}
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
VOID
|
2011-08-01 20:10:55 +00:00
|
|
|
TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb)
|
2010-09-21 06:11:24 +00:00
|
|
|
{
|
2011-07-21 20:58:54 +00:00
|
|
|
PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg;
|
2010-09-21 06:11:24 +00:00
|
|
|
PTDI_BUCKET Bucket;
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
PIRP Irp;
|
|
|
|
NTSTATUS Status;
|
|
|
|
KIRQL OldIrql;
|
2011-08-02 19:20:40 +00:00
|
|
|
|
2010-09-21 06:11:24 +00:00
|
|
|
ReferenceObject(Connection);
|
|
|
|
|
2011-05-24 18:05:51 +00:00
|
|
|
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ListenRequest, &Connection->Lock)))
|
|
|
|
{
|
2010-09-21 06:11:24 +00:00
|
|
|
PIO_STACK_LOCATION IrpSp;
|
|
|
|
|
|
|
|
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
|
|
|
|
|
|
|
Irp = Bucket->Request.RequestContext;
|
|
|
|
IrpSp = IoGetCurrentIrpStackLocation( Irp );
|
|
|
|
|
2011-05-24 18:05:51 +00:00
|
|
|
TI_DbgPrint(DEBUG_TCP,("[IP, TCPAcceptEventHandler] Getting the socket\n"));
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
Status = TCPCheckPeerForAccept(newpcb,
|
|
|
|
(PTDI_REQUEST_KERNEL)&IrpSp->Parameters);
|
|
|
|
|
2011-05-24 18:05:51 +00:00
|
|
|
TI_DbgPrint(DEBUG_TCP,("Socket: Status: %x\n", Status));
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
Bucket->Status = Status;
|
|
|
|
Bucket->Information = 0;
|
2011-08-02 19:20:40 +00:00
|
|
|
|
2010-09-21 06:11:24 +00:00
|
|
|
if (Status == STATUS_SUCCESS)
|
|
|
|
{
|
|
|
|
LockObject(Bucket->AssociatedEndpoint, &OldIrql);
|
2011-06-17 13:39:28 +00:00
|
|
|
|
2011-07-21 20:58:54 +00:00
|
|
|
/* sanity assert...this should never be in anything else but a CLOSED state */
|
2011-08-01 20:10:55 +00:00
|
|
|
ASSERT( ((PTCP_PCB)Bucket->AssociatedEndpoint->SocketContext)->state == CLOSED );
|
2011-07-21 20:58:54 +00:00
|
|
|
|
|
|
|
/* free socket context created in FileOpenConnection, as we're using a new one */
|
2011-08-07 19:13:23 +00:00
|
|
|
LibTCPClose(Bucket->AssociatedEndpoint, TRUE, FALSE);
|
2011-07-21 20:58:54 +00:00
|
|
|
|
2011-06-17 13:39:28 +00:00
|
|
|
/* free previously created socket context (we don't use it, we use newpcb) */
|
2010-09-21 06:11:24 +00:00
|
|
|
Bucket->AssociatedEndpoint->SocketContext = newpcb;
|
|
|
|
|
2011-07-21 20:58:54 +00:00
|
|
|
LibTCPAccept(newpcb, (PTCP_PCB)Connection->SocketContext, Bucket->AssociatedEndpoint);
|
2011-05-16 13:00:34 +00:00
|
|
|
|
2010-09-21 06:11:24 +00:00
|
|
|
UnlockObject(Bucket->AssociatedEndpoint, OldIrql);
|
2009-06-27 07:38:02 +00:00
|
|
|
}
|
2010-09-21 06:11:24 +00:00
|
|
|
|
2011-06-20 17:19:37 +00:00
|
|
|
DereferenceObject(Bucket->AssociatedEndpoint);
|
2010-09-21 06:11:24 +00:00
|
|
|
|
2011-06-17 12:04:20 +00:00
|
|
|
CompleteBucket(Connection, Bucket, FALSE);
|
2016-08-10 10:28:28 +00:00
|
|
|
|
|
|
|
if (Status == STATUS_SUCCESS)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2006-01-02 20:26:03 +00:00
|
|
|
}
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
DereferenceObject(Connection);
|
|
|
|
}
|
2006-01-02 20:26:03 +00:00
|
|
|
|
2010-09-21 06:11:24 +00:00
|
|
|
VOID
|
2015-09-05 20:50:51 +00:00
|
|
|
TCPSendEventHandler(void *arg, const u16_t space)
|
2010-09-21 06:11:24 +00:00
|
|
|
{
|
2011-08-01 20:10:55 +00:00
|
|
|
PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg;
|
2010-09-21 06:11:24 +00:00
|
|
|
PTDI_BUCKET Bucket;
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
PIRP Irp;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PMDL Mdl;
|
2012-08-27 23:58:40 +00:00
|
|
|
ULONG BytesSent;
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
ReferenceObject(Connection);
|
|
|
|
|
2011-05-24 18:05:51 +00:00
|
|
|
while ((Entry = ExInterlockedRemoveHeadList(&Connection->SendRequest, &Connection->Lock)))
|
|
|
|
{
|
2010-09-21 06:11:24 +00:00
|
|
|
UINT SendLen = 0;
|
|
|
|
PVOID SendBuffer = 0;
|
|
|
|
|
|
|
|
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
|
|
|
|
|
|
|
Irp = Bucket->Request.RequestContext;
|
|
|
|
Mdl = Irp->MdlAddress;
|
|
|
|
|
2009-06-27 07:38:02 +00:00
|
|
|
TI_DbgPrint(DEBUG_TCP,
|
2010-09-21 06:11:24 +00:00
|
|
|
("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));
|
|
|
|
|
2011-07-21 20:58:54 +00:00
|
|
|
Status = TCPTranslateError(LibTCPSend(Connection,
|
2010-09-21 06:11:24 +00:00
|
|
|
SendBuffer,
|
2012-08-27 23:58:40 +00:00
|
|
|
SendLen, &BytesSent, TRUE));
|
2010-09-21 06:11:24 +00:00
|
|
|
|
2012-08-27 23:58:40 +00:00
|
|
|
TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", BytesSent));
|
2010-09-21 06:11:24 +00:00
|
|
|
|
2011-05-24 18:05:51 +00:00
|
|
|
if( Status == STATUS_PENDING )
|
|
|
|
{
|
2010-09-21 06:11:24 +00:00
|
|
|
ExInterlockedInsertHeadList(&Connection->SendRequest,
|
|
|
|
&Bucket->Entry,
|
|
|
|
&Connection->Lock);
|
|
|
|
break;
|
2011-05-24 18:05:51 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-09-21 06:11:24 +00:00
|
|
|
TI_DbgPrint(DEBUG_TCP,
|
|
|
|
("Completing Send request: %x %x\n",
|
|
|
|
Bucket->Request, Status));
|
|
|
|
|
|
|
|
Bucket->Status = Status;
|
2012-08-27 23:58:40 +00:00
|
|
|
Bucket->Information = (Bucket->Status == STATUS_SUCCESS) ? BytesSent : 0;
|
2011-08-02 19:20:40 +00:00
|
|
|
|
2011-06-17 12:04:20 +00:00
|
|
|
CompleteBucket(Connection, Bucket, FALSE);
|
2010-09-21 06:11:24 +00:00
|
|
|
}
|
2006-01-02 20:26:03 +00:00
|
|
|
}
|
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
// 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);
|
2006-01-02 20:26:03 +00:00
|
|
|
|
2011-08-07 19:13:23 +00:00
|
|
|
if (KeCancelTimer(&Connection->DisconnectTimer))
|
|
|
|
{
|
|
|
|
DereferenceObject(Connection);
|
|
|
|
}
|
|
|
|
}
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
DereferenceObject(Connection);
|
2006-01-02 20:26:03 +00:00
|
|
|
}
|
|
|
|
|
[LWIP]
- Rewrite receive code to make it much simpler, handle some corner cases that weren't treated correctly, and fix the data corruption bug
- Downloaded successfully (no data corruption): OpenOffice 2.4, OpenOffice 3.3, BitTorrent 7.2.1, Firefox 5, Firefox 3.6, Firefox 3, Firefox 2, Abyss Web Server, Opera 9.64, and Opera 11.01
svn path=/trunk/; revision=53189
2011-08-11 21:52:41 +00:00
|
|
|
VOID
|
|
|
|
TCPRecvEventHandler(void *arg)
|
2010-09-21 06:11:24 +00:00
|
|
|
{
|
2011-07-25 18:45:59 +00:00
|
|
|
PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg;
|
2010-09-21 06:11:24 +00:00
|
|
|
PTDI_BUCKET Bucket;
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
PIRP Irp;
|
|
|
|
PMDL Mdl;
|
[LWIP]
- Rewrite receive code to make it much simpler, handle some corner cases that weren't treated correctly, and fix the data corruption bug
- Downloaded successfully (no data corruption): OpenOffice 2.4, OpenOffice 3.3, BitTorrent 7.2.1, Firefox 5, Firefox 3.6, Firefox 3, Firefox 2, Abyss Web Server, Opera 9.64, and Opera 11.01
svn path=/trunk/; revision=53189
2011-08-11 21:52:41 +00:00
|
|
|
UINT Received;
|
2010-09-21 06:11:24 +00:00
|
|
|
UINT RecvLen;
|
|
|
|
PUCHAR RecvBuffer;
|
[LWIP]
- Rewrite receive code to make it much simpler, handle some corner cases that weren't treated correctly, and fix the data corruption bug
- Downloaded successfully (no data corruption): OpenOffice 2.4, OpenOffice 3.3, BitTorrent 7.2.1, Firefox 5, Firefox 3.6, Firefox 3, Firefox 2, Abyss Web Server, Opera 9.64, and Opera 11.01
svn path=/trunk/; revision=53189
2011-08-11 21:52:41 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
|
2010-09-21 06:11:24 +00:00
|
|
|
ReferenceObject(Connection);
|
[LWIP]
- Rewrite receive code to make it much simpler, handle some corner cases that weren't treated correctly, and fix the data corruption bug
- Downloaded successfully (no data corruption): OpenOffice 2.4, OpenOffice 3.3, BitTorrent 7.2.1, Firefox 5, Firefox 3.6, Firefox 3, Firefox 2, Abyss Web Server, Opera 9.64, and Opera 11.01
svn path=/trunk/; revision=53189
2011-08-11 21:52:41 +00:00
|
|
|
|
|
|
|
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ReceiveRequest, &Connection->Lock)))
|
2011-05-24 18:05:51 +00:00
|
|
|
{
|
2010-09-21 06:11:24 +00:00
|
|
|
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
|
|
|
|
|
|
|
Irp = Bucket->Request.RequestContext;
|
|
|
|
Mdl = Irp->MdlAddress;
|
[LWIP]
- Rewrite receive code to make it much simpler, handle some corner cases that weren't treated correctly, and fix the data corruption bug
- Downloaded successfully (no data corruption): OpenOffice 2.4, OpenOffice 3.3, BitTorrent 7.2.1, Firefox 5, Firefox 3.6, Firefox 3, Firefox 2, Abyss Web Server, Opera 9.64, and Opera 11.01
svn path=/trunk/; revision=53189
2011-08-11 21:52:41 +00:00
|
|
|
|
2010-09-21 06:11:24 +00:00
|
|
|
NdisQueryBuffer( Mdl, &RecvBuffer, &RecvLen );
|
[LWIP]
- Rewrite receive code to make it much simpler, handle some corner cases that weren't treated correctly, and fix the data corruption bug
- Downloaded successfully (no data corruption): OpenOffice 2.4, OpenOffice 3.3, BitTorrent 7.2.1, Firefox 5, Firefox 3.6, Firefox 3, Firefox 2, Abyss Web Server, Opera 9.64, and Opera 11.01
svn path=/trunk/; revision=53189
2011-08-11 21:52:41 +00:00
|
|
|
|
|
|
|
Status = LibTCPGetDataFromConnectionQueue(Connection, RecvBuffer, RecvLen, &Received);
|
|
|
|
if (Status == STATUS_PENDING)
|
2010-09-21 06:11:24 +00:00
|
|
|
{
|
[LWIP]
- Rewrite receive code to make it much simpler, handle some corner cases that weren't treated correctly, and fix the data corruption bug
- Downloaded successfully (no data corruption): OpenOffice 2.4, OpenOffice 3.3, BitTorrent 7.2.1, Firefox 5, Firefox 3.6, Firefox 3, Firefox 2, Abyss Web Server, Opera 9.64, and Opera 11.01
svn path=/trunk/; revision=53189
2011-08-11 21:52:41 +00:00
|
|
|
ExInterlockedInsertHeadList(&Connection->ReceiveRequest,
|
|
|
|
&Bucket->Entry,
|
|
|
|
&Connection->Lock);
|
|
|
|
break;
|
2010-09-21 06:11:24 +00:00
|
|
|
}
|
[LWIP]
- Rewrite receive code to make it much simpler, handle some corner cases that weren't treated correctly, and fix the data corruption bug
- Downloaded successfully (no data corruption): OpenOffice 2.4, OpenOffice 3.3, BitTorrent 7.2.1, Firefox 5, Firefox 3.6, Firefox 3, Firefox 2, Abyss Web Server, Opera 9.64, and Opera 11.01
svn path=/trunk/; revision=53189
2011-08-11 21:52:41 +00:00
|
|
|
|
|
|
|
Bucket->Status = Status;
|
2010-09-21 06:11:24 +00:00
|
|
|
Bucket->Information = Received;
|
[LWIP]
- Rewrite receive code to make it much simpler, handle some corner cases that weren't treated correctly, and fix the data corruption bug
- Downloaded successfully (no data corruption): OpenOffice 2.4, OpenOffice 3.3, BitTorrent 7.2.1, Firefox 5, Firefox 3.6, Firefox 3, Firefox 2, Abyss Web Server, Opera 9.64, and Opera 11.01
svn path=/trunk/; revision=53189
2011-08-11 21:52:41 +00:00
|
|
|
|
2011-06-17 12:04:20 +00:00
|
|
|
CompleteBucket(Connection, Bucket, FALSE);
|
2006-01-02 20:26:03 +00:00
|
|
|
}
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
DereferenceObject(Connection);
|
2006-01-02 20:26:03 +00:00
|
|
|
}
|
|
|
|
|
2010-09-21 06:11:24 +00:00
|
|
|
VOID
|
2015-09-05 20:50:51 +00:00
|
|
|
TCPConnectEventHandler(void *arg, const err_t err)
|
2006-01-02 20:26:03 +00:00
|
|
|
{
|
2011-07-21 20:58:54 +00:00
|
|
|
PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg;
|
2010-09-21 06:11:24 +00:00
|
|
|
PTDI_BUCKET Bucket;
|
|
|
|
PLIST_ENTRY Entry;
|
2011-08-02 19:20:40 +00:00
|
|
|
|
2010-09-21 06:11:24 +00:00
|
|
|
ReferenceObject(Connection);
|
|
|
|
|
2011-05-16 13:00:34 +00:00
|
|
|
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ConnectRequest, &Connection->Lock)))
|
|
|
|
{
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
|
|
|
|
|
|
|
Bucket->Status = TCPTranslateError(err);
|
|
|
|
Bucket->Information = 0;
|
2011-08-02 19:20:40 +00:00
|
|
|
|
2011-06-17 12:04:20 +00:00
|
|
|
CompleteBucket(Connection, Bucket, FALSE);
|
2010-09-21 06:11:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DereferenceObject(Connection);
|
2006-01-02 20:26:03 +00:00
|
|
|
}
|