rpcrt4: Allow all HTTP read requests to be cancelled.
This commit is contained in:
parent
e34cb91399
commit
f4c5940656
|
@ -2207,9 +2207,47 @@ static RPC_STATUS rpcrt4_http_internet_connect(RpcConnection_http *httpc)
|
||||||
return RPC_S_OK;
|
return RPC_S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rpcrt4_http_async_read(HINTERNET req, RpcHttpAsyncData *async_data, HANDLE cancel_event,
|
||||||
|
void *buffer, unsigned int count)
|
||||||
|
{
|
||||||
|
char *buf = buffer;
|
||||||
|
BOOL ret;
|
||||||
|
unsigned int bytes_left = count;
|
||||||
|
RPC_STATUS status = RPC_S_OK;
|
||||||
|
|
||||||
|
async_data->inet_buffers.lpvBuffer = HeapAlloc(GetProcessHeap(), 0, count);
|
||||||
|
|
||||||
|
while (bytes_left)
|
||||||
|
{
|
||||||
|
async_data->inet_buffers.dwBufferLength = bytes_left;
|
||||||
|
prepare_async_request(async_data);
|
||||||
|
ret = InternetReadFileExW(req, &async_data->inet_buffers, IRF_ASYNC, 0);
|
||||||
|
status = wait_async_request(async_data, ret, cancel_event);
|
||||||
|
if (status != RPC_S_OK)
|
||||||
|
{
|
||||||
|
if (status == RPC_S_CALL_CANCELLED)
|
||||||
|
TRACE("call cancelled\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!async_data->inet_buffers.dwBufferLength)
|
||||||
|
break;
|
||||||
|
memcpy(buf, async_data->inet_buffers.lpvBuffer,
|
||||||
|
async_data->inet_buffers.dwBufferLength);
|
||||||
|
|
||||||
|
bytes_left -= async_data->inet_buffers.dwBufferLength;
|
||||||
|
buf += async_data->inet_buffers.dwBufferLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, async_data->inet_buffers.lpvBuffer);
|
||||||
|
async_data->inet_buffers.lpvBuffer = NULL;
|
||||||
|
|
||||||
|
TRACE("%p %p %u -> %u\n", req, buffer, count, status);
|
||||||
|
return status == RPC_S_OK ? count : -1;
|
||||||
|
}
|
||||||
|
|
||||||
static RPC_STATUS send_echo_request(HINTERNET req, RpcHttpAsyncData *async_data, HANDLE cancel_event)
|
static RPC_STATUS send_echo_request(HINTERNET req, RpcHttpAsyncData *async_data, HANDLE cancel_event)
|
||||||
{
|
{
|
||||||
DWORD bytes_read;
|
|
||||||
BYTE buf[20];
|
BYTE buf[20];
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
RPC_STATUS status;
|
RPC_STATUS status;
|
||||||
|
@ -2224,7 +2262,7 @@ static RPC_STATUS send_echo_request(HINTERNET req, RpcHttpAsyncData *async_data,
|
||||||
status = rpcrt4_http_check_response(req);
|
status = rpcrt4_http_check_response(req);
|
||||||
if (status != RPC_S_OK) return status;
|
if (status != RPC_S_OK) return status;
|
||||||
|
|
||||||
InternetReadFile(req, buf, sizeof(buf), &bytes_read);
|
rpcrt4_http_async_read(req, async_data, cancel_event, buf, sizeof(buf));
|
||||||
/* FIXME: do something with retrieved data */
|
/* FIXME: do something with retrieved data */
|
||||||
|
|
||||||
return RPC_S_OK;
|
return RPC_S_OK;
|
||||||
|
@ -2284,14 +2322,13 @@ static RPC_STATUS rpcrt4_http_prepare_in_pipe(HINTERNET in_request, RpcHttpAsync
|
||||||
return RPC_S_OK;
|
return RPC_S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RPC_STATUS rpcrt4_http_read_http_packet(HINTERNET request, RpcPktHdr *hdr, BYTE **data)
|
static RPC_STATUS rpcrt4_http_read_http_packet(HINTERNET request, RpcHttpAsyncData *async_data,
|
||||||
|
HANDLE cancel_event, RpcPktHdr *hdr, BYTE **data)
|
||||||
{
|
{
|
||||||
BOOL ret;
|
|
||||||
DWORD bytes_read;
|
|
||||||
unsigned short data_len;
|
unsigned short data_len;
|
||||||
|
unsigned int size;
|
||||||
|
|
||||||
ret = InternetReadFile(request, hdr, sizeof(hdr->common), &bytes_read);
|
if (rpcrt4_http_async_read(request, async_data, cancel_event, hdr, sizeof(hdr->common)) < 0)
|
||||||
if (!ret)
|
|
||||||
return RPC_S_SERVER_UNAVAILABLE;
|
return RPC_S_SERVER_UNAVAILABLE;
|
||||||
if (hdr->common.ptype != PKT_HTTP || hdr->common.frag_len < sizeof(hdr->http))
|
if (hdr->common.ptype != PKT_HTTP || hdr->common.frag_len < sizeof(hdr->http))
|
||||||
{
|
{
|
||||||
|
@ -2300,8 +2337,8 @@ static RPC_STATUS rpcrt4_http_read_http_packet(HINTERNET request, RpcPktHdr *hdr
|
||||||
return RPC_S_PROTOCOL_ERROR;
|
return RPC_S_PROTOCOL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = InternetReadFile(request, &hdr->common + 1, sizeof(hdr->http) - sizeof(hdr->common), &bytes_read);
|
size = sizeof(hdr->http) - sizeof(hdr->common);
|
||||||
if (!ret)
|
if (rpcrt4_http_async_read(request, async_data, cancel_event, &hdr->common + 1, size) < 0)
|
||||||
return RPC_S_SERVER_UNAVAILABLE;
|
return RPC_S_SERVER_UNAVAILABLE;
|
||||||
|
|
||||||
data_len = hdr->common.frag_len - sizeof(hdr->http);
|
data_len = hdr->common.frag_len - sizeof(hdr->http);
|
||||||
|
@ -2310,8 +2347,7 @@ static RPC_STATUS rpcrt4_http_read_http_packet(HINTERNET request, RpcPktHdr *hdr
|
||||||
*data = HeapAlloc(GetProcessHeap(), 0, data_len);
|
*data = HeapAlloc(GetProcessHeap(), 0, data_len);
|
||||||
if (!*data)
|
if (!*data)
|
||||||
return RPC_S_OUT_OF_RESOURCES;
|
return RPC_S_OUT_OF_RESOURCES;
|
||||||
ret = InternetReadFile(request, *data, data_len, &bytes_read);
|
if (rpcrt4_http_async_read(request, async_data, cancel_event, *data, data_len) < 0)
|
||||||
if (!ret)
|
|
||||||
{
|
{
|
||||||
HeapFree(GetProcessHeap(), 0, *data);
|
HeapFree(GetProcessHeap(), 0, *data);
|
||||||
return RPC_S_SERVER_UNAVAILABLE;
|
return RPC_S_SERVER_UNAVAILABLE;
|
||||||
|
@ -2341,7 +2377,6 @@ static RPC_STATUS rpcrt4_http_prepare_out_pipe(HINTERNET out_request, RpcHttpAsy
|
||||||
BYTE *data_from_server;
|
BYTE *data_from_server;
|
||||||
RpcPktHdr pkt_from_server;
|
RpcPktHdr pkt_from_server;
|
||||||
ULONG field1, field3;
|
ULONG field1, field3;
|
||||||
DWORD bytes_read;
|
|
||||||
BYTE buf[20];
|
BYTE buf[20];
|
||||||
|
|
||||||
if (!authorized)
|
if (!authorized)
|
||||||
|
@ -2351,7 +2386,7 @@ static RPC_STATUS rpcrt4_http_prepare_out_pipe(HINTERNET out_request, RpcHttpAsy
|
||||||
if (status != RPC_S_OK) return status;
|
if (status != RPC_S_OK) return status;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
InternetReadFile(out_request, buf, sizeof(buf), &bytes_read);
|
rpcrt4_http_async_read(out_request, async_data, cancel_event, buf, sizeof(buf));
|
||||||
|
|
||||||
hdr = RPCRT4_BuildHttpConnectHeader(TRUE, connection_uuid, out_pipe_uuid, NULL);
|
hdr = RPCRT4_BuildHttpConnectHeader(TRUE, connection_uuid, out_pipe_uuid, NULL);
|
||||||
if (!hdr) return RPC_S_OUT_OF_RESOURCES;
|
if (!hdr) return RPC_S_OUT_OF_RESOURCES;
|
||||||
|
@ -2373,8 +2408,8 @@ static RPC_STATUS rpcrt4_http_prepare_out_pipe(HINTERNET out_request, RpcHttpAsy
|
||||||
status = rpcrt4_http_check_response(out_request);
|
status = rpcrt4_http_check_response(out_request);
|
||||||
if (status != RPC_S_OK) return status;
|
if (status != RPC_S_OK) return status;
|
||||||
|
|
||||||
status = rpcrt4_http_read_http_packet(out_request, &pkt_from_server,
|
status = rpcrt4_http_read_http_packet(out_request, async_data, cancel_event,
|
||||||
&data_from_server);
|
&pkt_from_server, &data_from_server);
|
||||||
if (status != RPC_S_OK) return status;
|
if (status != RPC_S_OK) return status;
|
||||||
status = RPCRT4_ParseHttpPrepareHeader1(&pkt_from_server, data_from_server,
|
status = RPCRT4_ParseHttpPrepareHeader1(&pkt_from_server, data_from_server,
|
||||||
&field1);
|
&field1);
|
||||||
|
@ -2384,8 +2419,8 @@ static RPC_STATUS rpcrt4_http_prepare_out_pipe(HINTERNET out_request, RpcHttpAsy
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
status = rpcrt4_http_read_http_packet(out_request, &pkt_from_server,
|
status = rpcrt4_http_read_http_packet(out_request, async_data, cancel_event,
|
||||||
&data_from_server);
|
&pkt_from_server, &data_from_server);
|
||||||
if (status != RPC_S_OK) return status;
|
if (status != RPC_S_OK) return status;
|
||||||
if (pkt_from_server.http.flags != 0x0001) break;
|
if (pkt_from_server.http.flags != 0x0001) break;
|
||||||
|
|
||||||
|
@ -2790,7 +2825,7 @@ static RPC_STATUS insert_authorization_header(HINTERNET request, ULONG scheme, c
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drain_content(HINTERNET request)
|
static void drain_content(HINTERNET request, RpcHttpAsyncData *async_data, HANDLE cancel_event)
|
||||||
{
|
{
|
||||||
DWORD count, len = 0, size = sizeof(len);
|
DWORD count, len = 0, size = sizeof(len);
|
||||||
char buf[2048];
|
char buf[2048];
|
||||||
|
@ -2800,7 +2835,7 @@ static void drain_content(HINTERNET request)
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
count = min(sizeof(buf), len);
|
count = min(sizeof(buf), len);
|
||||||
if (!InternetReadFile(request, buf, count, &count) || !count) return;
|
if (rpcrt4_http_async_read(request, async_data, cancel_event, buf, count) <= 0) return;
|
||||||
len -= count;
|
len -= count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2827,7 +2862,7 @@ static RPC_STATUS authorize_request(RpcConnection_http *httpc, HINTERNET request
|
||||||
|
|
||||||
status = rpcrt4_http_check_response(request);
|
status = rpcrt4_http_check_response(request);
|
||||||
if (status != RPC_S_OK && status != ERROR_ACCESS_DENIED) break;
|
if (status != RPC_S_OK && status != ERROR_ACCESS_DENIED) break;
|
||||||
drain_content(request);
|
drain_content(request, httpc->async_data, httpc->cancel_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->scheme != RPC_C_HTTP_AUTHN_SCHEME_BASIC)
|
if (info->scheme != RPC_C_HTTP_AUTHN_SCHEME_BASIC)
|
||||||
|
@ -2967,7 +3002,7 @@ static RPC_STATUS rpcrt4_ncacn_http_open(RpcConnection* Connection)
|
||||||
HeapFree(GetProcessHeap(), 0, url);
|
HeapFree(GetProcessHeap(), 0, url);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
drain_content(httpc->in_request);
|
drain_content(httpc->in_request, httpc->async_data, httpc->cancel_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
httpc->out_request = HttpOpenRequestW(httpc->session, wszVerbOut, url, NULL, NULL, wszAcceptTypes,
|
httpc->out_request = HttpOpenRequestW(httpc->session, wszVerbOut, url, NULL, NULL, wszAcceptTypes,
|
||||||
|
@ -3033,39 +3068,7 @@ static int rpcrt4_ncacn_http_read(RpcConnection *Connection,
|
||||||
void *buffer, unsigned int count)
|
void *buffer, unsigned int count)
|
||||||
{
|
{
|
||||||
RpcConnection_http *httpc = (RpcConnection_http *) Connection;
|
RpcConnection_http *httpc = (RpcConnection_http *) Connection;
|
||||||
char *buf = buffer;
|
return rpcrt4_http_async_read(httpc->out_request, httpc->async_data, httpc->cancel_event, buffer, count);
|
||||||
BOOL ret;
|
|
||||||
unsigned int bytes_left = count;
|
|
||||||
RPC_STATUS status = RPC_S_OK;
|
|
||||||
|
|
||||||
httpc->async_data->inet_buffers.lpvBuffer = HeapAlloc(GetProcessHeap(), 0, count);
|
|
||||||
|
|
||||||
while (bytes_left)
|
|
||||||
{
|
|
||||||
httpc->async_data->inet_buffers.dwBufferLength = bytes_left;
|
|
||||||
prepare_async_request(httpc->async_data);
|
|
||||||
ret = InternetReadFileExW(httpc->out_request, &httpc->async_data->inet_buffers, IRF_ASYNC, 0);
|
|
||||||
status = wait_async_request(httpc->async_data, ret, httpc->cancel_event);
|
|
||||||
if(status != RPC_S_OK) {
|
|
||||||
if(status == RPC_S_CALL_CANCELLED)
|
|
||||||
TRACE("call cancelled\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!httpc->async_data->inet_buffers.dwBufferLength)
|
|
||||||
break;
|
|
||||||
memcpy(buf, httpc->async_data->inet_buffers.lpvBuffer,
|
|
||||||
httpc->async_data->inet_buffers.dwBufferLength);
|
|
||||||
|
|
||||||
bytes_left -= httpc->async_data->inet_buffers.dwBufferLength;
|
|
||||||
buf += httpc->async_data->inet_buffers.dwBufferLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, httpc->async_data->inet_buffers.lpvBuffer);
|
|
||||||
httpc->async_data->inet_buffers.lpvBuffer = NULL;
|
|
||||||
|
|
||||||
TRACE("%p %p %u -> %u\n", httpc->out_request, buffer, count, status);
|
|
||||||
return status == RPC_S_OK ? count : -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static RPC_STATUS rpcrt4_ncacn_http_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload)
|
static RPC_STATUS rpcrt4_ncacn_http_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload)
|
||||||
|
|
Loading…
Reference in New Issue