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/t…
==============================================================================
--- 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/t…
==============================================================================
--- 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/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] 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/rostc…
==============================================================================
--- 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);