mirror of
https://github.com/reactos/reactos.git
synced 2025-05-29 14:08:22 +00:00
[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 svn path=/trunk/; revision=57186
This commit is contained in:
parent
c71cca6db6
commit
f65fc45ba2
4 changed files with 40 additions and 20 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue