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/tcp/event.c?rev=57186&r1=57185&r2=57186&view=diff
==============================================================================
--- 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/tcp/tcp.c?rev=57186&r1=57185&r2=57186&view=diff
==============================================================================
--- 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/include/rosip.h?rev=57186&r1=57185&r2=57186&view=diff
==============================================================================
--- 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.c?rev=57186&r1=57185&r2=57186&view=diff
==============================================================================
--- 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);
 


Reply via email to