* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: transport/tcp/event.c
- * PURPOSE: Transmission Control Protocol -- Events from oskittcp
- * PROGRAMMERS: Art Yerkes
- * REVISIONS:
- * CSH 01/08-2000 Created
+ * PURPOSE: Transmission Control Protocol
+ * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
*/
#include "precomp.h"
-int TCPSocketState(void *ClientData,
- void *WhichSocket,
- void *WhichConnection,
- OSK_UINT NewState ) {
- PCONNECTION_ENDPOINT Connection = WhichConnection;
-
- TI_DbgPrint(DEBUG_TCP,("Connection: %x Flags: %c%c%c%c%c\n",
- Connection,
- NewState & SEL_CONNECT ? 'C' : 'c',
- NewState & SEL_READ ? 'R' : 'r',
- NewState & SEL_FIN ? 'F' : 'f',
- NewState & SEL_ACCEPT ? 'A' : 'a',
- NewState & SEL_WRITE ? 'W' : 'w'));
-
- /* If this socket is missing its socket context, that means that it
- * has been created as a new connection in sonewconn but not accepted
- * yet. We can safely ignore event notifications on these sockets.
- * Once they are accepted, they will get a socket context and we will
- * be able to process them.
- */
- if (!Connection)
- return 0;
-
- TI_DbgPrint(DEBUG_TCP,("Called: NewState %x (Conn %x) (Change %x)\n",
- NewState, Connection,
- Connection->SignalState ^ NewState,
- NewState));
-
- Connection->SignalState = NewState;
-
- HandleSignalledConnection(Connection);
-
- return 0;
+#include "lwip/err.h"
+#include "lwip/sys.h"
+#include "lwip/pbuf.h"
+#include "lwip/tcp.h"
+#include "lwip/api.h"
+
+#include "rosip.h"
+
+static const char * const tcp_state_str[] = {
+ "CLOSED",
+ "LISTEN",
+ "SYN_SENT",
+ "SYN_RCVD",
+ "ESTABLISHED",
+ "FIN_WAIT_1",
+ "FIN_WAIT_2",
+ "CLOSE_WAIT",
+ "CLOSING",
+ "LAST_ACK",
+ "TIME_WAIT"
+};
+
+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);
+
+ ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG);
}
-void TCPPacketSendComplete( PVOID Context,
- PNDIS_PACKET NdisPacket,
- NDIS_STATUS NdisStatus ) {
- TI_DbgPrint(DEBUG_TCP,("called %x\n", NdisPacket));
- FreeNdisPacket(NdisPacket);
- TI_DbgPrint(DEBUG_TCP,("done\n"));
+VOID
+CompleteBucket(PCONNECTION_ENDPOINT Connection, PTDI_BUCKET Bucket, const BOOLEAN Synchronous)
+{
+ ReferenceObject(Connection);
+ Bucket->AssociatedEndpoint = Connection;
+ if (Synchronous)
+ {
+ BucketCompletionWorker(Bucket);
+ }
+ else
+ {
+ ChewCreate(BucketCompletionWorker, Bucket);
+ }
}
-#define STRINGIFY(x) #x
+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);
+}
-int TCPPacketSend(void *ClientData, OSK_PCHAR data, OSK_UINT len ) {
- NDIS_STATUS NdisStatus;
- PNEIGHBOR_CACHE_ENTRY NCE;
- IP_PACKET Packet = { 0 };
- IP_ADDRESS RemoteAddress, LocalAddress;
- PIPv4_HEADER Header;
+VOID
+FlushSendQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked)
+{
+ PTDI_BUCKET Bucket;
+ PLIST_ENTRY Entry;
+
+ ReferenceObject(Connection);
- if( *data == 0x45 ) { /* IPv4 */
- Header = (PIPv4_HEADER)data;
- LocalAddress.Type = IP_ADDRESS_V4;
- LocalAddress.Address.IPv4Address = Header->SrcAddr;
- RemoteAddress.Type = IP_ADDRESS_V4;
- RemoteAddress.Address.IPv4Address = Header->DstAddr;
- } else {
- TI_DbgPrint(MIN_TRACE,("Outgoing packet is not IPv4\n"));
- OskitDumpBuffer( data, len );
- return OSK_EINVAL;
+ 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);
+ }
}
-
- if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) {
- TI_DbgPrint(MIN_TRACE,("Unable to get route to %s\n", A2S(&RemoteAddress)));
- return OSK_EADDRNOTAVAIL;
+ 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);
+ }
}
- NdisStatus = AllocatePacketWithBuffer( &Packet.NdisPacket, NULL, len );
+ DereferenceObject(Connection);
+}
- if (NdisStatus != NDIS_STATUS_SUCCESS) {
- TI_DbgPrint(DEBUG_TCP, ("Error from NDIS: %08x\n", NdisStatus));
- return OSK_ENOBUFS;
- }
+VOID
+FlushShutdownQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked)
+{
+ PTDI_BUCKET Bucket;
+ PLIST_ENTRY Entry;
+
+ ReferenceObject(Connection);
- GetDataPtr( Packet.NdisPacket, 0,
- (PCHAR *)&Packet.Header, &Packet.ContigSize );
+ 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);
+ }
+ }
- RtlCopyMemory( Packet.Header, data, len );
+ DereferenceObject(Connection);
+}
- Packet.HeaderSize = sizeof(IPv4_HEADER);
- Packet.TotalSize = len;
- Packet.SrcAddr = LocalAddress;
- Packet.DstAddr = RemoteAddress;
+VOID
+FlushConnectQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
+{
+ PTDI_BUCKET Bucket;
+ PLIST_ENTRY Entry;
+
+ ReferenceObject(Connection);
- if (!NT_SUCCESS(IPSendDatagram( &Packet, NCE, TCPPacketSendComplete, NULL )))
+ while ((Entry = ExInterlockedRemoveHeadList(&Connection->ConnectRequest, &Connection->Lock)))
{
- FreeNdisPacket(Packet.NdisPacket);
- return OSK_EINVAL;
+ Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
+
+ Bucket->Status = Status;
+ Bucket->Information = 0;
+
+ CompleteBucket(Connection, Bucket, FALSE);
}
- return 0;
+ DereferenceObject(Connection);
}
-/* Memory management routines
- *
- * By far the most requests for memory are either for 128 or 2049 byte blocks,
- * so we want to satisfy those from lookaside lists. Unfortunately, the
- * TCPFree() function doesn't pass the size of the block to be freed, so we
- * need to keep track of it ourselves. We do it by prepending each block with
- * 4 bytes, indicating if this is a 'L'arge (2049), 'S'mall (128) or 'O'ther
- * block.
- */
+VOID
+FlushListenQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
+{
+ PTDI_BUCKET Bucket;
+ PLIST_ENTRY Entry;
+
+ ReferenceObject(Connection);
-/* Set to some non-zero value to get a profile of memory allocation sizes */
-#define MEM_PROFILE 0
+ 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);
+ }
-#define SMALL_SIZE 128
-#define LARGE_SIZE 2049
+ DereferenceObject(Connection);
+}
-#define SIGNATURE_LARGE 'LLLL'
-#define SIGNATURE_SMALL 'SSSS'
-#define SIGNATURE_OTHER 'OOOO'
-static NPAGED_LOOKASIDE_LIST LargeLookasideList;
-static NPAGED_LOOKASIDE_LIST SmallLookasideList;
+VOID
+FlushAllQueues(PCONNECTION_ENDPOINT Connection, NTSTATUS Status)
+{
+ ReferenceObject(Connection);
+
+ // flush receive queue
+ FlushReceiveQueue(Connection, Status, TRUE);
-NTSTATUS
-TCPMemStartup( void )
-{
- ExInitializeNPagedLookasideList( &LargeLookasideList,
- NULL,
- NULL,
- 0,
- LARGE_SIZE + sizeof( ULONG ),
- OSK_LARGE_TAG,
- 0 );
- ExInitializeNPagedLookasideList( &SmallLookasideList,
- NULL,
- NULL,
- 0,
- SMALL_SIZE + sizeof( ULONG ),
- OSK_SMALL_TAG,
- 0 );
-
- return STATUS_SUCCESS;
+ /* 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 *TCPMalloc( void *ClientData,
- OSK_UINT Bytes, OSK_PCHAR File, OSK_UINT Line ) {
- void *v;
- ULONG Signature;
-
-#if 0 != MEM_PROFILE
- static OSK_UINT *Sizes = NULL, *Counts = NULL, ArrayAllocated = 0;
- static OSK_UINT ArrayUsed = 0, AllocationCount = 0;
- OSK_UINT i, NewSize, *NewArray;
- int Found;
-
- Found = 0;
- for ( i = 0; i < ArrayUsed && ! Found; i++ ) {
- Found = ( Sizes[i] == Bytes );
- if ( Found ) {
- Counts[i]++;
- }
- }
- if ( ! Found ) {
- if ( ArrayAllocated <= ArrayUsed ) {
- NewSize = ( 0 == ArrayAllocated ? 16 : 2 * ArrayAllocated );
- NewArray = exAllocatePool( NonPagedPool, 2 * NewSize * sizeof( OSK_UINT ) );
- if ( NULL != NewArray ) {
- if ( 0 != ArrayAllocated ) {
- memcpy( NewArray, Sizes,
- ArrayAllocated * sizeof( OSK_UINT ) );
- exFreePool( Sizes );
- memcpy( NewArray + NewSize, Counts,
- ArrayAllocated * sizeof( OSK_UINT ) );
- exFreePool( Counts );
+VOID
+TCPFinEventHandler(void *arg, const err_t err)
+{
+ PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg, LastConnection;
+ const NTSTATUS Status = TCPTranslateError(err);
+ KIRQL OldIrql;
+
+ ASSERT(Connection->AddressFile);
+
+ /* Check if this was a partial socket closure */
+ if (err == ERR_OK && Connection->SocketContext)
+ {
+ /* Just flush the receive queue and get out of here */
+ FlushReceiveQueue(Connection, STATUS_SUCCESS, TRUE);
+ }
+ else
+ {
+ /* First off all, remove the PCB pointer */
+ Connection->SocketContext = NULL;
+
+ /* 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);
}
- Sizes = NewArray;
- Counts = NewArray + NewSize;
- ArrayAllocated = NewSize;
- } else if ( 0 != ArrayAllocated ) {
- exFreePool( Sizes );
- exFreePool( Counts );
- ArrayAllocated = 0;
+ 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);
}
- if ( ArrayUsed < ArrayAllocated ) {
- Sizes[ArrayUsed] = Bytes;
- Counts[ArrayUsed] = 1;
- ArrayUsed++;
- }
+}
+
+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);
}
+
+ DereferenceObject(Connection);
+}
- if ( 0 == (++AllocationCount % MEM_PROFILE) ) {
- TI_DbgPrint(DEBUG_TCP, ("Memory allocation size profile:\n"));
- for ( i = 0; i < ArrayUsed; i++ ) {
+VOID
+TCPSendEventHandler(void *arg, u16_t space)
+{
+ PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg;
+ PTDI_BUCKET Bucket;
+ PLIST_ENTRY Entry;
+ PIRP Irp;
+ NTSTATUS Status;
+ PMDL Mdl;
+
+ 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,
- ("Size %4u Count %5u\n", Sizes[i], Counts[i]));
- }
- TI_DbgPrint(DEBUG_TCP, ("End of memory allocation size profile\n"));
+ ("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, TRUE));
+
+ TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", SendLen));
+
+ 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) ? SendLen : 0;
+
+ CompleteBucket(Connection, Bucket, FALSE);
+ }
}
-#endif /* MEM_PROFILE */
- if ( SMALL_SIZE == Bytes ) {
- v = ExAllocateFromNPagedLookasideList( &SmallLookasideList );
- Signature = SIGNATURE_SMALL;
- } else if ( LARGE_SIZE == Bytes ) {
- v = ExAllocateFromNPagedLookasideList( &LargeLookasideList );
- Signature = SIGNATURE_LARGE;
- } else {
- v = ExAllocatePoolWithTag( NonPagedPool, Bytes + sizeof(ULONG),
- OSK_OTHER_TAG );
- Signature = SIGNATURE_OTHER;
- }
- if( v ) {
- *((ULONG *) v) = Signature;
- v = (void *)((char *) v + sizeof(ULONG));
- }
+ // 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);
- return v;
+ if (KeCancelTimer(&Connection->DisconnectTimer))
+ {
+ DereferenceObject(Connection);
+ }
+ }
+
+ DereferenceObject(Connection);
}
-void TCPFree( void *ClientData,
- void *data, OSK_PCHAR File, OSK_UINT Line ) {
- ULONG Signature;
-
- data = (void *)((char *) data - sizeof(ULONG));
- Signature = *((ULONG *) data);
- if ( SIGNATURE_SMALL == Signature ) {
- ExFreeToNPagedLookasideList( &SmallLookasideList, data );
- } else if ( SIGNATURE_LARGE == Signature ) {
- ExFreeToNPagedLookasideList( &LargeLookasideList, data );
- } else if ( SIGNATURE_OTHER == Signature ) {
- ExFreePoolWithTag( data, OSK_OTHER_TAG );
- } else {
- ASSERT( FALSE );
+u32_t
+TCPRecvEventHandler(void *arg, struct pbuf *p)
+{
+ PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg;
+ PTDI_BUCKET Bucket;
+ PLIST_ENTRY Entry;
+ PIRP Irp;
+ PMDL Mdl;
+ UINT Received = 0;
+ UINT RecvLen;
+ PUCHAR RecvBuffer;
+
+ ASSERT(p);
+
+ ReferenceObject(Connection);
+
+ if ((Entry = ExInterlockedRemoveHeadList(&Connection->ReceiveRequest, &Connection->Lock)))
+ {
+ Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
+
+ Irp = Bucket->Request.RequestContext;
+ Mdl = Irp->MdlAddress;
+
+ TI_DbgPrint(DEBUG_TCP,
+ ("[IP, TCPRecvEventHandler] Getting the user buffer from %x\n", Mdl));
+
+ NdisQueryBuffer( Mdl, &RecvBuffer, &RecvLen );
+
+ TI_DbgPrint(DEBUG_TCP,
+ ("[IP, TCPRecvEventHandler] Reading %d bytes to %x\n", RecvLen, RecvBuffer));
+
+ TI_DbgPrint(DEBUG_TCP, ("Connection: %x\n", Connection));
+ TI_DbgPrint(DEBUG_TCP, ("[IP, TCPRecvEventHandler] Connection->SocketContext: %x\n", Connection->SocketContext));
+ TI_DbgPrint(DEBUG_TCP, ("[IP, TCPRecvEventHandler] RecvBuffer: %x\n", RecvBuffer));
+
+ RecvLen = MIN(p->tot_len, RecvLen);
+
+ for (Received = 0; Received < RecvLen; Received += p->len, p = p->next)
+ {
+ RtlCopyMemory(RecvBuffer + Received, p->payload, p->len);
+ }
+
+ TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Received));
+
+ Bucket->Status = STATUS_SUCCESS;
+ Bucket->Information = Received;
+
+ CompleteBucket(Connection, Bucket, FALSE);
}
+
+ DereferenceObject(Connection);
+
+ return Received;
}
-void
-TCPMemShutdown( void )
+VOID
+TCPConnectEventHandler(void *arg, err_t err)
{
- ExDeleteNPagedLookasideList( &SmallLookasideList );
- ExDeleteNPagedLookasideList( &LargeLookasideList );
+ 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);
}