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
|
|
|
|
2010-09-21 06:11:24 +00:00
|
|
|
VOID
|
|
|
|
FlushAllQueues(PCONNECTION_ENDPOINT Connection, NTSTATUS Status)
|
|
|
|
{
|
|
|
|
PTCP_COMPLETION_ROUTINE Complete;
|
|
|
|
PTDI_BUCKET Bucket;
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
|
|
|
|
ReferenceObject(Connection);
|
|
|
|
|
|
|
|
DbgPrint("Flushing recv/all with status: 0x%x\n", Status);
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
Complete = Bucket->Request.RequestNotifyObject;
|
|
|
|
|
|
|
|
Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information);
|
|
|
|
|
|
|
|
ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG);
|
2004-09-29 05:10:48 +00:00
|
|
|
}
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
if (Status == STATUS_SUCCESS) Status = STATUS_FILE_CLOSED;
|
|
|
|
|
|
|
|
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ListenRequest, &Connection->Lock))) {
|
|
|
|
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
|
|
|
|
|
|
|
Bucket->Status = Status;
|
|
|
|
Bucket->Information = 0;
|
|
|
|
|
|
|
|
Complete = Bucket->Request.RequestNotifyObject;
|
|
|
|
|
|
|
|
Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information);
|
|
|
|
|
|
|
|
ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG);
|
2004-12-04 23:29:56 +00:00
|
|
|
}
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
Complete = Bucket->Request.RequestNotifyObject;
|
|
|
|
|
|
|
|
Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information);
|
|
|
|
|
|
|
|
ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG);
|
2004-09-29 05:10:48 +00:00
|
|
|
}
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ConnectRequest, &Connection->Lock))) {
|
|
|
|
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
|
|
|
|
|
|
|
Bucket->Status = Status;
|
|
|
|
Bucket->Information = 0;
|
|
|
|
|
|
|
|
Complete = Bucket->Request.RequestNotifyObject;
|
|
|
|
|
|
|
|
Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information);
|
|
|
|
|
|
|
|
ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG);
|
2008-12-21 01:29:35 +00:00
|
|
|
}
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
DereferenceObject(Connection);
|
2004-09-29 05:10:48 +00:00
|
|
|
}
|
|
|
|
|
2010-09-21 06:11:24 +00:00
|
|
|
VOID
|
|
|
|
TCPFinEventHandler(void *arg, err_t err)
|
2006-01-02 20:26:03 +00:00
|
|
|
{
|
2010-09-21 06:11:24 +00:00
|
|
|
PCONNECTION_ENDPOINT Connection = arg;
|
|
|
|
|
|
|
|
FlushAllQueues(Connection, TCPTranslateError(err));
|
|
|
|
|
|
|
|
/* We're already closed so we don't want to call lwip_close */
|
|
|
|
Connection->SocketContext = NULL;
|
2006-01-02 20:26:03 +00:00
|
|
|
}
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
VOID
|
|
|
|
TCPAcceptEventHandler(void *arg, struct tcp_pcb *newpcb)
|
|
|
|
{
|
|
|
|
PCONNECTION_ENDPOINT Connection = arg;
|
|
|
|
PTCP_COMPLETION_ROUTINE Complete;
|
|
|
|
PTDI_BUCKET Bucket;
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
PIRP Irp;
|
|
|
|
NTSTATUS Status;
|
|
|
|
KIRQL OldIrql;
|
|
|
|
|
2011-05-16 13:00:34 +00:00
|
|
|
DbgPrint("TCPAcceptEventHandler] Called\n");
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
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 );
|
|
|
|
|
2011-05-16 13:00:34 +00:00
|
|
|
TI_DbgPrint(DEBUG_TCP,("[TCPAcceptEventHandler] Getting the socket\n"));
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
Status = TCPCheckPeerForAccept(newpcb,
|
|
|
|
(PTDI_REQUEST_KERNEL)&IrpSp->Parameters);
|
|
|
|
|
|
|
|
TI_DbgPrint(DEBUG_TCP,("Socket: Status: %x\n"));
|
|
|
|
|
|
|
|
Bucket->Status = Status;
|
|
|
|
Bucket->Information = 0;
|
|
|
|
|
2011-05-16 13:00:34 +00:00
|
|
|
DbgPrint("[TCPAcceptEventHandler] Associated with: 0x%x\n", Bucket->AssociatedEndpoint->SocketContext);
|
2010-09-21 06:11:24 +00:00
|
|
|
|
2011-05-16 13:00:34 +00:00
|
|
|
DbgPrint("[TCPAcceptEventHandler] Completing accept event %x\n", Status);
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
Complete = Bucket->Request.RequestNotifyObject;
|
|
|
|
|
|
|
|
if (Status == STATUS_SUCCESS)
|
|
|
|
{
|
2011-05-16 13:00:34 +00:00
|
|
|
newpcb->state = LISTEN;
|
2010-09-21 06:11:24 +00:00
|
|
|
LockObject(Bucket->AssociatedEndpoint, &OldIrql);
|
|
|
|
Bucket->AssociatedEndpoint->SocketContext = newpcb;
|
2011-05-16 13:00:34 +00:00
|
|
|
DbgPrint("[TCPAcceptEventHandler] LibTCPAccept coming up\n");
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
LibTCPAccept(newpcb, Bucket->AssociatedEndpoint);
|
2011-05-16 13:00:34 +00:00
|
|
|
|
|
|
|
DbgPrint("[TCPAcceptEventHandler] Trying to unlock Bucket->AssociatedEndpoint\n");
|
2010-09-21 06:11:24 +00:00
|
|
|
UnlockObject(Bucket->AssociatedEndpoint, OldIrql);
|
2011-05-16 13:00:34 +00:00
|
|
|
newpcb->state = ESTABLISHED;
|
2009-06-27 07:38:02 +00:00
|
|
|
}
|
2010-09-21 06:11:24 +00:00
|
|
|
|
2011-05-16 13:00:34 +00:00
|
|
|
DbgPrint("[TCPAcceptEventHandler] Done!\n");
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information);
|
|
|
|
|
|
|
|
ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG);
|
2009-06-27 07:38:02 +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
|
|
|
|
TCPSendEventHandler(void *arg, u16_t space)
|
|
|
|
{
|
|
|
|
PCONNECTION_ENDPOINT Connection = arg;
|
|
|
|
PTCP_COMPLETION_ROUTINE Complete;
|
|
|
|
PTDI_BUCKET Bucket;
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
PIRP Irp;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PMDL Mdl;
|
|
|
|
|
2011-05-16 13:00:34 +00:00
|
|
|
DbgPrint("[TCPSendEventHandler] Called\n");
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
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));
|
|
|
|
|
|
|
|
Status = TCPTranslateError(LibTCPSend(Connection->SocketContext,
|
|
|
|
SendBuffer,
|
|
|
|
SendLen));
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
DbgPrint("Completing send req %x\n", Status);
|
|
|
|
|
|
|
|
Complete = Bucket->Request.RequestNotifyObject;
|
|
|
|
|
|
|
|
Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information);
|
|
|
|
|
|
|
|
ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG);
|
|
|
|
}
|
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
|
|
|
u32_t
|
|
|
|
TCPRecvEventHandler(void *arg, struct pbuf *p)
|
|
|
|
{
|
|
|
|
PCONNECTION_ENDPOINT Connection = arg;
|
|
|
|
PTCP_COMPLETION_ROUTINE Complete;
|
|
|
|
PTDI_BUCKET Bucket;
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
PIRP Irp;
|
|
|
|
PMDL Mdl;
|
|
|
|
UINT Received = 0;
|
|
|
|
UINT RecvLen;
|
|
|
|
PUCHAR RecvBuffer;
|
|
|
|
|
|
|
|
ASSERT(p);
|
|
|
|
|
|
|
|
ReferenceObject(Connection);
|
|
|
|
|
2011-05-16 13:00:34 +00:00
|
|
|
DbgPrint("[TCPRecvEventHandler] Called\n");
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
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,
|
|
|
|
("Getting the user buffer from %x\n", Mdl));
|
|
|
|
|
|
|
|
NdisQueryBuffer( Mdl, &RecvBuffer, &RecvLen );
|
|
|
|
|
|
|
|
TI_DbgPrint(DEBUG_TCP,
|
|
|
|
("Reading %d bytes to %x\n", RecvLen, RecvBuffer));
|
|
|
|
|
|
|
|
TI_DbgPrint(DEBUG_TCP, ("Connection: %x\n", Connection));
|
|
|
|
TI_DbgPrint
|
|
|
|
(DEBUG_TCP,
|
|
|
|
("Connection->SocketContext: %x\n",
|
|
|
|
Connection->SocketContext));
|
|
|
|
TI_DbgPrint(DEBUG_TCP, ("RecvBuffer: %x\n", RecvBuffer));
|
|
|
|
|
|
|
|
RecvLen = MIN(p->tot_len, RecvLen);
|
|
|
|
|
|
|
|
for (Received = 0; Received < RecvLen; Received += p->len, p = p->next)
|
|
|
|
{
|
|
|
|
DbgPrint("0x%x: Copying %d bytes to 0x%x from 0x%x\n", p, p->len, ((PUCHAR)RecvBuffer) + Received, p->payload);
|
|
|
|
RtlCopyMemory(RecvBuffer + Received, p->payload, p->len);
|
|
|
|
}
|
|
|
|
|
|
|
|
TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Received));
|
|
|
|
|
|
|
|
Bucket->Status = STATUS_SUCCESS;
|
|
|
|
Bucket->Information = Received;
|
|
|
|
|
|
|
|
Complete = Bucket->Request.RequestNotifyObject;
|
|
|
|
|
|
|
|
Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information);
|
|
|
|
|
|
|
|
ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG);
|
2006-01-02 20:26:03 +00:00
|
|
|
}
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
DereferenceObject(Connection);
|
|
|
|
|
|
|
|
return Received;
|
2006-01-02 20:26:03 +00:00
|
|
|
}
|
|
|
|
|
2010-09-21 06:11:24 +00:00
|
|
|
VOID
|
|
|
|
TCPConnectEventHandler(void *arg, err_t err)
|
2006-01-02 20:26:03 +00:00
|
|
|
{
|
2010-09-21 06:11:24 +00:00
|
|
|
PCONNECTION_ENDPOINT Connection = arg;
|
|
|
|
PTCP_COMPLETION_ROUTINE Complete;
|
|
|
|
PTDI_BUCKET Bucket;
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
|
2011-05-16 13:00:34 +00:00
|
|
|
DbgPrint("[TCPConnectEventHandler] Called\n");
|
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-05-16 13:00:34 +00:00
|
|
|
DbgPrint("[TCPConnectEventHandler] Completing connection request! (0x%x)\n", err);
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
Complete = Bucket->Request.RequestNotifyObject;
|
|
|
|
|
|
|
|
Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information);
|
|
|
|
|
|
|
|
ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG);
|
|
|
|
}
|
2011-05-16 13:00:34 +00:00
|
|
|
|
|
|
|
DbgPrint("[TCPConnectEventHandler] Done\n");
|
2010-09-21 06:11:24 +00:00
|
|
|
|
|
|
|
DereferenceObject(Connection);
|
|
|
|
}
|