Author: cgutman Date: Mon Aug 27 23:58:40 2012 New Revision: 57186
URL: http://svn.reactos.org/svn/reactos?rev=57186&view=rev Log: [TCPIP] - Implement proper support for partial sends on TCP sockets - This prevents a deadlock when a very very large packet is queued to be sent
Modified: trunk/reactos/lib/drivers/ip/transport/tcp/event.c trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c trunk/reactos/lib/drivers/lwip/src/include/rosip.h trunk/reactos/lib/drivers/lwip/src/rostcp.c
Modified: trunk/reactos/lib/drivers/ip/transport/tcp/event.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/transport/tc... ============================================================================== --- trunk/reactos/lib/drivers/ip/transport/tcp/event.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/ip/transport/tcp/event.c [iso-8859-1] Mon Aug 27 23:58:40 2012 @@ -383,6 +383,7 @@ PIRP Irp; NTSTATUS Status; PMDL Mdl; + ULONG BytesSent;
ReferenceObject(Connection);
@@ -412,9 +413,9 @@
Status = TCPTranslateError(LibTCPSend(Connection, SendBuffer, - SendLen, TRUE)); - - TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", SendLen)); + SendLen, &BytesSent, TRUE)); + + TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", BytesSent));
if( Status == STATUS_PENDING ) { @@ -430,7 +431,7 @@ Bucket->Request, Status));
Bucket->Status = Status; - Bucket->Information = (Bucket->Status == STATUS_SUCCESS) ? SendLen : 0; + Bucket->Information = (Bucket->Status == STATUS_SUCCESS) ? BytesSent : 0;
CompleteBucket(Connection, Bucket, FALSE); }
Modified: trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/transport/tc... ============================================================================== --- trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c [iso-8859-1] Mon Aug 27 23:58:40 2012 @@ -544,6 +544,7 @@ Status = TCPTranslateError(LibTCPSend(Connection, BufferData, SendLength, + BytesSent, FALSE));
TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Send: %x, %d\n", Status, SendLength)); @@ -562,18 +563,9 @@
Bucket->Request.RequestNotifyObject = Complete; Bucket->Request.RequestContext = Context; - *BytesSent = 0;
InsertTailList( &Connection->SendRequest, &Bucket->Entry ); TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Queued write irp\n")); - } - else if (Status == STATUS_SUCCESS) - { - *BytesSent = SendLength; - } - else - { - *BytesSent = 0; }
UnlockObject(Connection, OldIrql);
Modified: trunk/reactos/lib/drivers/lwip/src/include/rosip.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/lwip/src/includ... ============================================================================== --- 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] Mon Aug 27 23:58:40 2012 @@ -72,6 +72,7 @@ } Listen; struct { err_t Error; + u32_t Information; } Send; struct { err_t Error; @@ -98,7 +99,7 @@ PTCP_PCB LibTCPSocket(void *arg); err_t LibTCPBind(PCONNECTION_ENDPOINT Connection, struct ip_addr *const ipaddr, const u16_t port); PTCP_PCB LibTCPListen(PCONNECTION_ENDPOINT Connection, const u8_t backlog); -err_t LibTCPSend(PCONNECTION_ENDPOINT Connection, void *const dataptr, const u16_t len, const int safe); +err_t LibTCPSend(PCONNECTION_ENDPOINT Connection, void *const dataptr, const u16_t len, u32_t *sent, const int safe); err_t LibTCPConnect(PCONNECTION_ENDPOINT Connection, struct ip_addr *const ipaddr, const u16_t port); err_t LibTCPShutdown(PCONNECTION_ENDPOINT Connection, const int shut_rx, const int shut_tx); err_t LibTCPClose(PCONNECTION_ENDPOINT Connection, const int safe, const int callback);
Modified: trunk/reactos/lib/drivers/lwip/src/rostcp.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/lwip/src/rostcp... ============================================================================== --- trunk/reactos/lib/drivers/lwip/src/rostcp.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/lwip/src/rostcp.c [iso-8859-1] Mon Aug 27 23:58:40 2012 @@ -443,6 +443,9 @@ LibTCPSendCallback(void *arg) { struct lwip_callback_msg *msg = arg; + PTCP_PCB pcb = msg->Input.Send.Connection->SocketContext; + ULONG SendLength; + UCHAR SendFlags;
ASSERT(msg);
@@ -458,19 +461,37 @@ goto done; }
- msg->Output.Send.Error = tcp_write((PTCP_PCB)msg->Input.Send.Connection->SocketContext, - msg->Input.Send.Data, - msg->Input.Send.DataLength, - TCP_WRITE_FLAG_COPY); - if (msg->Output.Send.Error == ERR_MEM) + SendFlags = TCP_WRITE_FLAG_COPY; + SendLength = msg->Input.Send.DataLength; + if (tcp_sndbuf(pcb) == 0) { /* No buffer space so return pending */ msg->Output.Send.Error = ERR_INPROGRESS; - } - else if (msg->Output.Send.Error == ERR_OK) + goto done; + } + else if (tcp_sndbuf(pcb) < SendLength) + { + /* We've got some room so let's send what we can */ + SendLength = tcp_sndbuf(pcb); + + /* Don't set the push flag */ + SendFlags |= TCP_WRITE_FLAG_MORE; + } + + msg->Output.Send.Error = tcp_write(pcb, + msg->Input.Send.Data, + SendLength, + SendFlags); + if (msg->Output.Send.Error == ERR_OK) { /* Queued successfully so try to send it */ tcp_output((PTCP_PCB)msg->Input.Send.Connection->SocketContext); + msg->Output.Send.Information = SendLength; + } + else if (msg->Output.Send.Error == ERR_MEM) + { + /* The queue is too long */ + msg->Output.Send.Error = ERR_INPROGRESS; }
done: @@ -478,7 +499,7 @@ }
err_t -LibTCPSend(PCONNECTION_ENDPOINT Connection, void *const dataptr, const u16_t len, const int safe) +LibTCPSend(PCONNECTION_ENDPOINT Connection, void *const dataptr, const u16_t len, u32_t *sent, const int safe) { err_t ret; struct lwip_callback_msg *msg; @@ -500,6 +521,11 @@ ret = msg->Output.Send.Error; else ret = ERR_CLSD; + + if (ret == ERR_OK) + *sent = msg->Output.Send.Information; + else + *sent = 0;
ExFreeToNPagedLookasideList(&MessageLookasideList, msg);