- Implement proper support for partial sends on TCP sockets
- This prevents a deadlock when a very very large packet is queued to be sent

svn path=/trunk/; revision=57186
This commit is contained in:
Cameron Gutman 2012-08-27 23:58:40 +00:00
parent c71cca6db6
commit f65fc45ba2
4 changed files with 40 additions and 20 deletions

View file

@ -383,6 +383,7 @@ TCPSendEventHandler(void *arg, u16_t space)
PIRP Irp;
NTSTATUS Status;
PMDL Mdl;
ULONG BytesSent;
ReferenceObject(Connection);
@ -412,9 +413,9 @@ TCPSendEventHandler(void *arg, u16_t space)
Status = TCPTranslateError(LibTCPSend(Connection,
SendBuffer,
SendLen, TRUE));
SendLen, &BytesSent, TRUE));
TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", SendLen));
TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", BytesSent));
if( Status == STATUS_PENDING )
{
@ -430,7 +431,7 @@ TCPSendEventHandler(void *arg, u16_t space)
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);
}

View file

@ -544,6 +544,7 @@ NTSTATUS TCPSendData
Status = TCPTranslateError(LibTCPSend(Connection,
BufferData,
SendLength,
BytesSent,
FALSE));
TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Send: %x, %d\n", Status, SendLength));
@ -562,19 +563,10 @@ NTSTATUS TCPSendData
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);

View file

@ -72,6 +72,7 @@ struct lwip_callback_msg
} Listen;
struct {
err_t Error;
u32_t Information;
} Send;
struct {
err_t Error;
@ -98,7 +99,7 @@ extern void TCPRecvEventHandler(void *arg);
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);

View file

@ -443,6 +443,9 @@ void
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 @@ LibTCPSendCallback(void *arg)
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;
goto done;
}
else if (msg->Output.Send.Error == ERR_OK)
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 @@ done:
}
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;
@ -501,6 +522,11 @@ LibTCPSend(PCONNECTION_ENDPOINT Connection, void *const dataptr, const u16_t len
else
ret = ERR_CLSD;
if (ret == ERR_OK)
*sent = msg->Output.Send.Information;
else
*sent = 0;
ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
return ret;