mirror of
https://github.com/reactos/reactos.git
synced 2025-05-31 15:08:14 +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;
|
PIRP Irp;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PMDL Mdl;
|
PMDL Mdl;
|
||||||
|
ULONG BytesSent;
|
||||||
|
|
||||||
ReferenceObject(Connection);
|
ReferenceObject(Connection);
|
||||||
|
|
||||||
|
@ -412,9 +413,9 @@ TCPSendEventHandler(void *arg, u16_t space)
|
||||||
|
|
||||||
Status = TCPTranslateError(LibTCPSend(Connection,
|
Status = TCPTranslateError(LibTCPSend(Connection,
|
||||||
SendBuffer,
|
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 )
|
if( Status == STATUS_PENDING )
|
||||||
{
|
{
|
||||||
|
@ -430,7 +431,7 @@ TCPSendEventHandler(void *arg, u16_t space)
|
||||||
Bucket->Request, Status));
|
Bucket->Request, Status));
|
||||||
|
|
||||||
Bucket->Status = Status;
|
Bucket->Status = Status;
|
||||||
Bucket->Information = (Bucket->Status == STATUS_SUCCESS) ? SendLen : 0;
|
Bucket->Information = (Bucket->Status == STATUS_SUCCESS) ? BytesSent : 0;
|
||||||
|
|
||||||
CompleteBucket(Connection, Bucket, FALSE);
|
CompleteBucket(Connection, Bucket, FALSE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -544,6 +544,7 @@ NTSTATUS TCPSendData
|
||||||
Status = TCPTranslateError(LibTCPSend(Connection,
|
Status = TCPTranslateError(LibTCPSend(Connection,
|
||||||
BufferData,
|
BufferData,
|
||||||
SendLength,
|
SendLength,
|
||||||
|
BytesSent,
|
||||||
FALSE));
|
FALSE));
|
||||||
|
|
||||||
TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Send: %x, %d\n", Status, SendLength));
|
TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Send: %x, %d\n", Status, SendLength));
|
||||||
|
@ -562,19 +563,10 @@ NTSTATUS TCPSendData
|
||||||
|
|
||||||
Bucket->Request.RequestNotifyObject = Complete;
|
Bucket->Request.RequestNotifyObject = Complete;
|
||||||
Bucket->Request.RequestContext = Context;
|
Bucket->Request.RequestContext = Context;
|
||||||
*BytesSent = 0;
|
|
||||||
|
|
||||||
InsertTailList( &Connection->SendRequest, &Bucket->Entry );
|
InsertTailList( &Connection->SendRequest, &Bucket->Entry );
|
||||||
TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Queued write irp\n"));
|
TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Queued write irp\n"));
|
||||||
}
|
}
|
||||||
else if (Status == STATUS_SUCCESS)
|
|
||||||
{
|
|
||||||
*BytesSent = SendLength;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*BytesSent = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
UnlockObject(Connection, OldIrql);
|
UnlockObject(Connection, OldIrql);
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@ struct lwip_callback_msg
|
||||||
} Listen;
|
} Listen;
|
||||||
struct {
|
struct {
|
||||||
err_t Error;
|
err_t Error;
|
||||||
|
u32_t Information;
|
||||||
} Send;
|
} Send;
|
||||||
struct {
|
struct {
|
||||||
err_t Error;
|
err_t Error;
|
||||||
|
@ -98,7 +99,7 @@ extern void TCPRecvEventHandler(void *arg);
|
||||||
PTCP_PCB LibTCPSocket(void *arg);
|
PTCP_PCB LibTCPSocket(void *arg);
|
||||||
err_t LibTCPBind(PCONNECTION_ENDPOINT Connection, struct ip_addr *const ipaddr, const u16_t port);
|
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);
|
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 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 LibTCPShutdown(PCONNECTION_ENDPOINT Connection, const int shut_rx, const int shut_tx);
|
||||||
err_t LibTCPClose(PCONNECTION_ENDPOINT Connection, const int safe, const int callback);
|
err_t LibTCPClose(PCONNECTION_ENDPOINT Connection, const int safe, const int callback);
|
||||||
|
|
|
@ -443,6 +443,9 @@ void
|
||||||
LibTCPSendCallback(void *arg)
|
LibTCPSendCallback(void *arg)
|
||||||
{
|
{
|
||||||
struct lwip_callback_msg *msg = arg;
|
struct lwip_callback_msg *msg = arg;
|
||||||
|
PTCP_PCB pcb = msg->Input.Send.Connection->SocketContext;
|
||||||
|
ULONG SendLength;
|
||||||
|
UCHAR SendFlags;
|
||||||
|
|
||||||
ASSERT(msg);
|
ASSERT(msg);
|
||||||
|
|
||||||
|
@ -458,19 +461,37 @@ LibTCPSendCallback(void *arg)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg->Output.Send.Error = tcp_write((PTCP_PCB)msg->Input.Send.Connection->SocketContext,
|
SendFlags = TCP_WRITE_FLAG_COPY;
|
||||||
msg->Input.Send.Data,
|
SendLength = msg->Input.Send.DataLength;
|
||||||
msg->Input.Send.DataLength,
|
if (tcp_sndbuf(pcb) == 0)
|
||||||
TCP_WRITE_FLAG_COPY);
|
|
||||||
if (msg->Output.Send.Error == ERR_MEM)
|
|
||||||
{
|
{
|
||||||
/* No buffer space so return pending */
|
/* No buffer space so return pending */
|
||||||
msg->Output.Send.Error = ERR_INPROGRESS;
|
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 */
|
/* Queued successfully so try to send it */
|
||||||
tcp_output((PTCP_PCB)msg->Input.Send.Connection->SocketContext);
|
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:
|
done:
|
||||||
|
@ -478,7 +499,7 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
err_t
|
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;
|
err_t ret;
|
||||||
struct lwip_callback_msg *msg;
|
struct lwip_callback_msg *msg;
|
||||||
|
@ -501,6 +522,11 @@ LibTCPSend(PCONNECTION_ENDPOINT Connection, void *const dataptr, const u16_t len
|
||||||
else
|
else
|
||||||
ret = ERR_CLSD;
|
ret = ERR_CLSD;
|
||||||
|
|
||||||
|
if (ret == ERR_OK)
|
||||||
|
*sent = msg->Output.Send.Information;
|
||||||
|
else
|
||||||
|
*sent = 0;
|
||||||
|
|
||||||
ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
|
ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in a new issue