Let oskit tell us when sending should be blocked 'cause its stuffed upto its nose with data waiting to be sent. Bug 1232. Modified: trunk/reactos/drivers/lib/ip/transport/tcp/event.c Modified: trunk/reactos/drivers/lib/ip/transport/tcp/tcp.c Modified: trunk/reactos/drivers/lib/oskittcp/oskittcp/interface.c Modified: trunk/reactos/drivers/lib/oskittcp/oskittcp/sleep.c Modified: trunk/reactos/drivers/net/afd/afd/write.c Modified: trunk/reactos/drivers/net/tcpip/include/tcp.h Modified: trunk/reactos/drivers/net/tcpip/include/titypes.h Modified: trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c _____
Modified: trunk/reactos/drivers/lib/ip/transport/tcp/event.c --- trunk/reactos/drivers/lib/ip/transport/tcp/event.c 2006-01-04 20:45:58 UTC (rev 20561) +++ trunk/reactos/drivers/lib/ip/transport/tcp/event.c 2006-01-04 22:40:48 UTC (rev 20562) @@ -121,6 +121,11 @@
KeInitializeEvent( &SleepingThread->Event, NotificationEvent, FALSE ); SleepingThread->SleepToken = token;
+ /* We're going to sleep and need to release the lock, otherwise + it's impossible to re-enter oskittcp to deliver the event that's + going to wake us */ + TcpipRecursiveMutexLeave( &TCPLock ); + TcpipAcquireFastMutex( &SleepingThreadsLock ); InsertTailList( &SleepingThreadsList, &SleepingThread->Entry ); TcpipReleaseFastMutex( &SleepingThreadsLock ); @@ -136,6 +141,8 @@ RemoveEntryList( &SleepingThread->Entry ); TcpipReleaseFastMutex( &SleepingThreadsLock );
+ TcpipRecursiveMutexEnter( &TCPLock, TRUE ); + PoolFreeBuffer( SleepingThread ); } TI_DbgPrint(DEBUG_TCP,("Waiting finished: %x\n", token)); _____
Modified: trunk/reactos/drivers/lib/ip/transport/tcp/tcp.c --- trunk/reactos/drivers/lib/ip/transport/tcp/tcp.c 2006-01-04 20:45:58 UTC (rev 20561) +++ trunk/reactos/drivers/lib/ip/transport/tcp/tcp.c 2006-01-04 22:40:48 UTC (rev 20562) @@ -153,7 +153,64 @@
} } } + if( NewState & SEL_WRITE ) { + TI_DbgPrint(DEBUG_TCP,("Writeable: irp list %s\n", + IsListEmpty(&Connection->ReceiveRequest) ? + "empty" : "nonempty"));
+ while( !IsListEmpty( &Connection->SendRequest ) ) { + OSK_UINT SendLen = 0, Sent = 0; + OSK_PCHAR SendBuffer = 0; + + Entry = RemoveHeadList( &Connection->SendRequest ); + Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); + Complete = Bucket->Request.RequestNotifyObject; + + 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 + ( OskitTCPSend( Connection->SocketContext, + SendBuffer, + SendLen, + &Sent, + 0 ) ); + + TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Sent)); + + if( Status == STATUS_SUCCESS ) { + TI_DbgPrint(DEBUG_TCP,("Sent %d bytes with status %x\n", + Sent, Status)); + + Complete( Bucket->Request.RequestContext, + STATUS_SUCCESS, Sent ); + } else if( Status == STATUS_PENDING ) { + InsertHeadList + ( &Connection->SendRequest, &Bucket->Entry ); + break; + } else { + TI_DbgPrint(DEBUG_TCP, + ("Completing Send request: %x %x\n", + Bucket->Request, Status)); + Complete( Bucket->Request.RequestContext, Status, 0 ); + } + } + } + if( NewState & SEL_FIN ) { PLIST_ENTRY ListsToErase[4]; NTSTATUS IrpStatus[4]; @@ -209,6 +266,7 @@ InitializeListHead(&Connection->ConnectRequest); InitializeListHead(&Connection->ListenRequest); InitializeListHead(&Connection->ReceiveRequest); + InitializeListHead(&Connection->SendRequest);
/* Save client context pointer */ Connection->ClientContext = ClientContext; @@ -656,11 +714,18 @@ NTSTATUS TCPSendData ( PCONNECTION_ENDPOINT Connection, PCHAR BufferData, - ULONG PacketSize, - PULONG DataUsed, - ULONG Flags) { + ULONG SendLength, + PULONG BytesSent, + ULONG Flags, + PTCP_COMPLETION_ROUTINE Complete, + PVOID Context ) { + UINT Sent = 0; NTSTATUS Status; + PTDI_BUCKET Bucket;
+ TI_DbgPrint(DEBUG_TCP,("Called for %d bytes (on socket %x)\n", + SendLength, Connection->SocketContext)); + ASSERT_KM_POINTER(Connection->SocketContext);
TcpipRecursiveMutexEnter( &TCPLock, TRUE ); @@ -669,12 +734,38 @@ TI_DbgPrint(DEBUG_TCP,("Connection->SocketContext = %x\n", Connection->SocketContext));
- Status = OskitTCPSend( Connection->SocketContext, - (OSK_PCHAR)BufferData, PacketSize, - (PUINT)DataUsed, 0 ); + Status = TCPTranslateError + ( OskitTCPSend( Connection->SocketContext, + (OSK_PCHAR)BufferData, SendLength, + &Sent, 0 ) );
+ TI_DbgPrint(DEBUG_TCP,("OskitTCPSend: %x, %d\n", Status, Sent)); + + /* Keep this request around ... there was no data yet */ + if( Status == STATUS_PENDING ) { + /* Freed in TCPSocketState */ + Bucket = ExAllocatePool( NonPagedPool, sizeof(*Bucket) ); + if( !Bucket ) { + TI_DbgPrint(DEBUG_TCP,("Failed to allocate bucket\n")); + TcpipRecursiveMutexLeave( &TCPLock ); + return STATUS_NO_MEMORY; + } + + Bucket->Request.RequestNotifyObject = Complete; + Bucket->Request.RequestContext = Context; + *BytesSent = 0; + + InsertHeadList( &Connection->SendRequest, &Bucket->Entry ); + TI_DbgPrint(DEBUG_TCP,("Queued write irp\n")); + } else { + TI_DbgPrint(DEBUG_TCP,("Got status %x, bytes %d\n", Status, Sent)); + *BytesSent = Sent; + } + TcpipRecursiveMutexLeave( &TCPLock );
+ TI_DbgPrint(DEBUG_TCP,("Status %x\n", Status)); + return Status; }
@@ -729,14 +820,14 @@ PTDI_BUCKET Bucket; UINT i = 0;
- ListHead[0] = &Endpoint->ReceiveRequest; - ListHead[1] = &Endpoint->ConnectRequest; - ListHead[2] = &Endpoint->ListenRequest; - ListHead[3] = 0; + ListHead[0] = &Endpoint->SendRequest; + ListHead[1] = &Endpoint->ReceiveRequest; + ListHead[2] = &Endpoint->ConnectRequest; + ListHead[3] = &Endpoint->ListenRequest;
TcpipAcquireSpinLock( &Endpoint->Lock, &OldIrql );
- for( i = 0; ListHead[i]; i++ ) { + for( i = 0; i < sizeof( ListHead ) / sizeof( ListHead[0] ); i++ ) { for( Entry = ListHead[i]->Flink; Entry != ListHead[i]; Entry = Entry->Flink ) { _____
Modified: trunk/reactos/drivers/lib/oskittcp/oskittcp/interface.c --- trunk/reactos/drivers/lib/oskittcp/oskittcp/interface.c 2006-01-04 20:45:58 UTC (rev 20561) +++ trunk/reactos/drivers/lib/oskittcp/oskittcp/interface.c 2006-01-04 22:40:48 UTC (rev 20562) @@ -256,12 +256,26 @@
int OskitTCPSend( void *socket, OSK_PCHAR Data, OSK_UINT Len, OSK_UINT *OutLen, OSK_UINT flags ) { - struct mbuf* m = m_devget( Data, Len, 0, NULL, NULL ); - int error = 0; - if ( !m ) - return ENOBUFS; - error = sosend( socket, NULL, NULL, m, NULL, 0 ); - *OutLen = Len; + int error; + struct uio uio; + struct iovec iov; + + iov.iov_len = Len; + iov.iov_base = Data; + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = 0; + uio.uio_resid = Len; + uio.uio_segflg = UIO_SYSSPACE; + uio.uio_rw = UIO_WRITE; + uio.uio_procp = NULL; + + error = sosend( socket, NULL, &uio, NULL, NULL, 0 ); + if (OSK_EWOULDBLOCK == error) { + ((struct socket *) socket)->so_snd.sb_flags |= SB_WAIT; + } + *OutLen = uio.uio_offset; + return error; }
_____
Modified: trunk/reactos/drivers/lib/oskittcp/oskittcp/sleep.c --- trunk/reactos/drivers/lib/oskittcp/oskittcp/sleep.c 2006-01-04 20:45:58 UTC (rev 20561) +++ trunk/reactos/drivers/lib/oskittcp/oskittcp/sleep.c 2006-01-04 22:40:48 UTC (rev 20562) @@ -35,6 +35,10 @@
OS_DbgPrint(OSK_MID_TRACE,("Socket readable\n")); flags |= SEL_READ; } + if( 0 < sbspace(&so->so_snd) ) { + OS_DbgPrint(OSK_MID_TRACE,("Socket writeable\n")); + flags |= SEL_WRITE; + } if( so->so_state & SS_CANTRCVMORE ) { OS_DbgPrint(OSK_MID_TRACE,("Socket can't be read any longer\n")); flags |= SEL_FIN; _____
Modified: trunk/reactos/drivers/net/afd/afd/write.c --- trunk/reactos/drivers/net/afd/afd/write.c 2006-01-04 20:45:58 UTC (rev 20561) +++ trunk/reactos/drivers/net/afd/afd/write.c 2006-01-04 22:40:48 UTC (rev 20562) @@ -1,4 +1,4 @@
-/* $Id$ +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: drivers/net/afd/afd/write.c @@ -17,7 +17,6 @@ PIRP Irp, PVOID Context ) { NTSTATUS Status = Irp->IoStatus.Status; - PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); PAFD_FCB FCB = (PAFD_FCB)Context; PLIST_ENTRY NextIrpEntry; PIRP NextIrp = NULL; @@ -26,6 +25,15 @@ PAFD_MAPBUF Map; UINT TotalBytesCopied = 0, SpaceAvail, i, CopySize = 0;
+ /* + * The Irp parameter passed in is the IRP of the stream between AFD and + * TDI driver. It's not very usefull to us. We need the IRPs of the stream + * between usermode and AFD. Those are chained from + * FCB->PendingIrpList[FUNCTION_SEND] and you'll see them in the code + * below as "NextIrp" ('cause they are the next usermode IRP to be + * processed). + */ + AFD_DbgPrint(MID_TRACE,("Called, status %x, %d bytes used\n", Irp->IoStatus.Status, Irp->IoStatus.Information)); @@ -78,7 +86,7 @@ !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) && NT_SUCCESS(Status) ) { NextIrpEntry = - RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]); + RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); @@ -89,8 +97,7 @@
SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
- for( i = 0; FCB->Send.BytesUsed < FCB->Send.Content && - i < SendReq->BufferCount; i++ ) { + for( i = 0; i < SendReq->BufferCount; i++ ) { Map[i].BufferAddress = MmMapLockedPages( Map[i].Mdl, KernelMode );
@@ -101,7 +108,7 @@ Map[i].BufferAddress, CopySize );
- MmUnmapLockedPages( Map[i].Mdl, KernelMode ); + MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl );
FCB->Send.BytesUsed += CopySize; TotalBytesCopied += CopySize; @@ -116,7 +123,7 @@ SocketCalloutEnter( FCB );
Status = TdiSend( &FCB->SendIrp.InFlightRequest, - IrpSp->FileObject, + FCB->Connection.Object, 0, FCB->Send.Window, FCB->Send.BytesUsed, @@ -138,13 +145,13 @@
AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
- return UnlockAndMaybeComplete( FCB, Status, Irp, TotalBytesCopied, + return UnlockAndMaybeComplete( FCB, Status, NextIrp, TotalBytesCopied, NULL, TRUE ); } else if( NextIrp ) { AFD_DbgPrint(MID_TRACE,("Could not do any more with Irp %x\n", NextIrp)); InsertHeadList( &FCB->PendingIrpList[FUNCTION_SEND], - &Irp->Tail.Overlay.ListEntry ); + &NextIrp->Tail.Overlay.ListEntry ); }
SocketStateUnlock( FCB ); _____
Modified: trunk/reactos/drivers/net/tcpip/include/tcp.h --- trunk/reactos/drivers/net/tcpip/include/tcp.h 2006-01-04 20:45:58 UTC (rev 20561) +++ trunk/reactos/drivers/net/tcpip/include/tcp.h 2006-01-04 22:40:48 UTC (rev 20562) @@ -150,7 +150,9 @@
PCHAR Buffer, ULONG DataSize, PULONG DataUsed, - ULONG Flags); + ULONG Flags, + PTCP_COMPLETION_ROUTINE Complete, + PVOID Context);
NTSTATUS TCPClose( PCONNECTION_ENDPOINT Connection );
_____
Modified: trunk/reactos/drivers/net/tcpip/include/titypes.h --- trunk/reactos/drivers/net/tcpip/include/titypes.h 2006-01-04 20:45:58 UTC (rev 20561) +++ trunk/reactos/drivers/net/tcpip/include/titypes.h 2006-01-04 22:40:48 UTC (rev 20562) @@ -302,6 +302,7 @@
LIST_ENTRY ConnectRequest; /* Queued connect rqueusts */ LIST_ENTRY ListenRequest; /* Queued listen requests */ LIST_ENTRY ReceiveRequest; /* Queued receive requests */ + LIST_ENTRY SendRequest; /* Queued send requests */
/* Signals */ LIST_ENTRY SignalList; /* Entry in the list of sockets waiting for _____
Modified: trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c --- trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c 2006-01-04 20:45:58 UTC (rev 20561) +++ trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c 2006-01-04 22:40:48 UTC (rev 20562) @@ -898,15 +898,15 @@
*/ { PIO_STACK_LOCATION IrpSp; - PTDI_REQUEST_KERNEL_RECEIVE ReceiveInfo; + PTDI_REQUEST_KERNEL_SEND SendInfo; PTRANSPORT_CONTEXT TranContext; NTSTATUS Status; - ULONG BytesReceived; + ULONG BytesSent;
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
IrpSp = IoGetCurrentIrpStackLocation(Irp); - ReceiveInfo = (PTDI_REQUEST_KERNEL_RECEIVE)&(IrpSp->Parameters); + SendInfo = (PTDI_REQUEST_KERNEL_SEND)&(IrpSp->Parameters);
TranContext = IrpSp->FileObject->FsContext; if (TranContext == NULL) @@ -938,12 +938,14 @@ Status = TCPSendData( TranContext->Handle.ConnectionContext, Data, - ReceiveInfo->ReceiveLength, - &BytesReceived, - ReceiveInfo->ReceiveFlags); + SendInfo->SendLength, + &BytesSent, + SendInfo->SendFlags, + DispDataRequestComplete, + Irp); if (Status != STATUS_PENDING) { - DispDataRequestComplete(Irp, Status, BytesReceived); + DispDataRequestComplete(Irp, Status, BytesSent); } else IoMarkIrpPending( Irp ); }