Author: cgutman
Date: Sun Aug 26 22:24:49 2012
New Revision: 57169
URL:
http://svn.reactos.org/svn/reactos?rev=57169&view=rev
Log:
[LWIP]
- Fix broken handling of partial receives
Modified:
trunk/reactos/lib/drivers/lwip/src/include/rosip.h
trunk/reactos/lib/drivers/lwip/src/rostcp.c
Modified: trunk/reactos/lib/drivers/lwip/src/include/rosip.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/lwip/src/inclu…
==============================================================================
--- trunk/reactos/lib/drivers/lwip/src/include/rosip.h [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/lwip/src/include/rosip.h [iso-8859-1] Sun Aug 26 22:24:49
2012
@@ -15,6 +15,7 @@
typedef struct _QUEUE_ENTRY
{
struct pbuf *p;
+ ULONG Offset;
LIST_ENTRY ListEntry;
} QUEUE_ENTRY, *PQUEUE_ENTRY;
Modified: trunk/reactos/lib/drivers/lwip/src/rostcp.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/lwip/src/rostc…
==============================================================================
--- trunk/reactos/lib/drivers/lwip/src/rostcp.c [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/lwip/src/rostcp.c [iso-8859-1] Sun Aug 26 22:24:49 2012
@@ -60,6 +60,7 @@
qp = (PQUEUE_ENTRY)ExAllocateFromNPagedLookasideList(&QueueEntryLookasideList);
qp->p = p;
+ qp->Offset = 0;
ExInterlockedInsertTailList(&Connection->PacketQueue, &qp->ListEntry,
&Connection->Lock);
}
@@ -82,9 +83,10 @@
{
PQUEUE_ENTRY qp;
struct pbuf* p;
- NTSTATUS Status = STATUS_PENDING;
- UINT ReadLength, ExistingDataLength;
+ NTSTATUS Status;
+ UINT ReadLength, PayloadLength;
KIRQL OldIrql;
+ PUCHAR Payload;
(*Received) = 0;
@@ -95,49 +97,53 @@
while ((qp = LibTCPDequeuePacket(Connection)) != NULL)
{
p = qp->p;
- ExistingDataLength = (*Received);
+
+ /* Calculate the payload first */
+ Payload = p->payload;
+ Payload += qp->Offset;
+ PayloadLength = p->len;
+ PayloadLength -= qp->Offset;
+
+ /* Check if we're reading the whole buffer */
+ ReadLength = MIN(PayloadLength, RecvLen);
+ if (ReadLength != PayloadLength)
+ {
+ /* Save this one for later */
+ qp->Offset += ReadLength;
+ InsertHeadList(&Connection->PacketQueue, &qp->ListEntry);
+ qp = NULL;
+ }
+
+ UnlockObject(Connection, OldIrql);
+
+ /* Return to a lower IRQL because the receive buffer may be pageable memory
*/
+ RtlCopyMemory(RecvBuffer,
+ Payload,
+ ReadLength);
+
+ LockObject(Connection, &OldIrql);
+
+ /* Update trackers */
+ RecvLen -= ReadLength;
+ RecvBuffer += ReadLength;
+ (*Received) += ReadLength;
+
+ if (qp != NULL)
+ {
+ /* Use this special pbuf free callback function because we're outside
tcpip thread */
+ pbuf_free_callback(qp->p);
+
+ ExFreeToNPagedLookasideList(&QueueEntryLookasideList, qp);
+ }
+ else
+ {
+ /* If we get here, it means we've filled the buffer */
+ ASSERT(RecvLen == 0);
+ }
Status = STATUS_SUCCESS;
- ReadLength = MIN(p->tot_len, RecvLen);
- if (ReadLength != p->tot_len)
- {
- if (ExistingDataLength)
- {
- /* The packet was too big but we used some data already so give it
another shot later */
- InsertHeadList(&Connection->PacketQueue,
&qp->ListEntry);
- break;
- }
- else
- {
- /* The packet is just too big to fit fully in our buffer, even when
empty so
- * return an informative status but still copy all the data we can
fit.
- */
- Status = STATUS_BUFFER_OVERFLOW;
- }
- }
-
- UnlockObject(Connection, OldIrql);
-
- /* Return to a lower IRQL because the receive buffer may be pageable memory
*/
- for (; (*Received) < ReadLength + ExistingDataLength; (*Received) +=
p->len, p = p->next)
- {
- RtlCopyMemory(RecvBuffer + (*Received), p->payload, p->len);
- }
-
- LockObject(Connection, &OldIrql);
-
- RecvLen -= ReadLength;
-
- /* Use this special pbuf free callback function because we're outside
tcpip thread */
- pbuf_free_callback(qp->p);
-
- ExFreeToNPagedLookasideList(&QueueEntryLookasideList, qp);
-
if (!RecvLen)
- break;
-
- if (Status != STATUS_SUCCESS)
break;
}
}
@@ -196,6 +202,8 @@
InternalRecvEventHandler(void *arg, PTCP_PCB pcb, struct pbuf *p, const err_t err)
{
PCONNECTION_ENDPOINT Connection = arg;
+ struct pbuf *pb;
+ ULONG RecvLen;
/* Make sure the socket didn't get closed */
if (!arg)
@@ -208,9 +216,19 @@
if (p)
{
- LibTCPEnqueuePacket(Connection, p);
-
- tcp_recved(pcb, p->tot_len);
+ pb = p;
+ RecvLen = 0;
+ while (pb != NULL)
+ {
+ /* Enqueue this buffer */
+ LibTCPEnqueuePacket(Connection, pb);
+ RecvLen += pb->len;
+
+ /* Advance and unchain the buffer */
+ pb = pbuf_dechain(pb);;
+ }
+
+ tcp_recved(pcb, RecvLen);
TCPRecvEventHandler(arg);
}