webservices: Reuse the message read buffer.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
99e24f0004
commit
79be5ad469
|
@ -98,6 +98,9 @@ struct channel
|
|||
HINTERNET http_session;
|
||||
HINTERNET http_connect;
|
||||
HINTERNET http_request;
|
||||
char *read_buf;
|
||||
ULONG read_buflen;
|
||||
ULONG read_size;
|
||||
ULONG prop_count;
|
||||
struct prop prop[sizeof(channel_props)/sizeof(channel_props[0])];
|
||||
};
|
||||
|
@ -134,6 +137,8 @@ static void reset_channel( struct channel *channel )
|
|||
channel->http_connect = NULL;
|
||||
WinHttpCloseHandle( channel->http_session );
|
||||
channel->http_session = NULL;
|
||||
|
||||
channel->read_size = 0;
|
||||
}
|
||||
|
||||
static void free_channel( struct channel *channel )
|
||||
|
@ -143,6 +148,8 @@ static void free_channel( struct channel *channel )
|
|||
WsFreeWriter( channel->writer );
|
||||
WsFreeReader( channel->reader );
|
||||
|
||||
heap_free( channel->read_buf );
|
||||
|
||||
channel->cs.DebugInfo->Spare[0] = 0;
|
||||
DeleteCriticalSection( &channel->cs );
|
||||
heap_free( channel );
|
||||
|
@ -629,57 +636,72 @@ done:
|
|||
return hr;
|
||||
}
|
||||
|
||||
#define INITIAL_READ_BUFFER_SIZE 4096
|
||||
static HRESULT receive_message( struct channel *channel, ULONG max_len, char **ret, ULONG *ret_len )
|
||||
static HRESULT resize_read_buffer( struct channel *channel, ULONG size )
|
||||
{
|
||||
DWORD len, bytes_read, offset = 0, size = INITIAL_READ_BUFFER_SIZE;
|
||||
char *buf;
|
||||
if (!channel->read_buf)
|
||||
{
|
||||
if (!(channel->read_buf = heap_alloc( size ))) return E_OUTOFMEMORY;
|
||||
channel->read_buflen = size;
|
||||
return S_OK;
|
||||
}
|
||||
if (channel->read_buflen < size)
|
||||
{
|
||||
char *tmp;
|
||||
ULONG new_size = max( size, channel->read_buflen * 2 );
|
||||
if (!(tmp = heap_realloc( channel->read_buf, new_size ))) return E_OUTOFMEMORY;
|
||||
channel->read_buf = tmp;
|
||||
channel->read_buflen = new_size;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#define INITIAL_READ_BUFFER_SIZE 4096
|
||||
static HRESULT receive_message( struct channel *channel )
|
||||
{
|
||||
DWORD len, max_len, bytes_read, offset = 0, size = INITIAL_READ_BUFFER_SIZE;
|
||||
HRESULT hr;
|
||||
|
||||
prop_get( channel->prop, channel->prop_count, WS_CHANNEL_PROPERTY_MAX_BUFFERED_MESSAGE_SIZE,
|
||||
&max_len, sizeof(max_len) );
|
||||
|
||||
if ((hr = resize_read_buffer( channel, size )) != S_OK) return hr;
|
||||
channel->read_size = 0;
|
||||
|
||||
if (!(buf = heap_alloc( size ))) return E_OUTOFMEMORY;
|
||||
*ret_len = 0;
|
||||
for (;;)
|
||||
{
|
||||
if (!WinHttpQueryDataAvailable( channel->http_request, &len ))
|
||||
{
|
||||
heap_free( buf );
|
||||
return HRESULT_FROM_WIN32( GetLastError() );
|
||||
}
|
||||
if (!len) break;
|
||||
if (*ret_len + len > max_len)
|
||||
if (channel->read_size + len > max_len) return WS_E_QUOTA_EXCEEDED;
|
||||
if ((hr = resize_read_buffer( channel, channel->read_size + len )) != S_OK) return hr;
|
||||
|
||||
if (!WinHttpReadData( channel->http_request, channel->read_buf + offset, len, &bytes_read ))
|
||||
{
|
||||
heap_free( buf );
|
||||
return WS_E_QUOTA_EXCEEDED;
|
||||
}
|
||||
if (*ret_len + len > size)
|
||||
{
|
||||
char *tmp;
|
||||
DWORD new_size = max( *ret_len + len, size * 2 );
|
||||
if (!(tmp = heap_realloc( buf, new_size )))
|
||||
{
|
||||
heap_free( buf );
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
buf = tmp;
|
||||
size = new_size;
|
||||
}
|
||||
if (!WinHttpReadData( channel->http_request, buf + offset, len, &bytes_read ))
|
||||
{
|
||||
heap_free( buf );
|
||||
return HRESULT_FROM_WIN32( GetLastError() );
|
||||
}
|
||||
if (!bytes_read) break;
|
||||
*ret_len += bytes_read;
|
||||
channel->read_size += bytes_read;
|
||||
offset += bytes_read;
|
||||
}
|
||||
|
||||
*ret = buf;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT channel_receive_message( WS_CHANNEL *handle, char **buf, ULONG *len )
|
||||
static HRESULT set_input( WS_XML_READER *reader, char *data, ULONG size )
|
||||
{
|
||||
WS_XML_READER_TEXT_ENCODING text = {{WS_XML_READER_ENCODING_TYPE_TEXT}, WS_CHARSET_UTF8};
|
||||
WS_XML_READER_BUFFER_INPUT buf;
|
||||
|
||||
buf.input.inputType = WS_XML_READER_INPUT_TYPE_BUFFER;
|
||||
buf.encodedData = data;
|
||||
buf.encodedDataSize = size;
|
||||
return WsSetInput( reader, &text.encoding, &buf.input, NULL, 0, NULL );
|
||||
}
|
||||
|
||||
HRESULT channel_receive_message( WS_CHANNEL *handle )
|
||||
{
|
||||
struct channel *channel = (struct channel *)handle;
|
||||
ULONG max_len;
|
||||
HRESULT hr;
|
||||
|
||||
EnterCriticalSection( &channel->cs );
|
||||
|
@ -690,22 +712,31 @@ HRESULT channel_receive_message( WS_CHANNEL *handle, char **buf, ULONG *len )
|
|||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
WsGetChannelProperty( handle, WS_CHANNEL_PROPERTY_MAX_BUFFERED_MESSAGE_SIZE, &max_len, sizeof(max_len), NULL );
|
||||
hr = receive_message( channel, max_len, buf, len );
|
||||
if ((hr = receive_message( channel )) != S_OK) goto done;
|
||||
if (!channel->reader && (hr = WsCreateReader( NULL, 0, &channel->reader, NULL )) != S_OK) goto done;
|
||||
if ((hr = set_input( channel->reader, channel->read_buf, channel->read_size )) != S_OK) goto done;
|
||||
|
||||
done:
|
||||
LeaveCriticalSection( &channel->cs );
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT set_input( WS_XML_READER *reader, char *data, ULONG size )
|
||||
HRESULT channel_get_reader( WS_CHANNEL *handle, WS_XML_READER **reader )
|
||||
{
|
||||
WS_XML_READER_TEXT_ENCODING text = {{WS_XML_READER_ENCODING_TYPE_TEXT}, WS_CHARSET_UTF8};
|
||||
WS_XML_READER_BUFFER_INPUT buf;
|
||||
struct channel *channel = (struct channel *)handle;
|
||||
|
||||
buf.input.inputType = WS_XML_READER_INPUT_TYPE_BUFFER;
|
||||
buf.encodedData = data;
|
||||
buf.encodedDataSize = size;
|
||||
return WsSetInput( reader, &text.encoding, &buf.input, NULL, 0, NULL );
|
||||
EnterCriticalSection( &channel->cs );
|
||||
|
||||
if (channel->magic != CHANNEL_MAGIC)
|
||||
{
|
||||
LeaveCriticalSection( &channel->cs );
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*reader = channel->reader;
|
||||
|
||||
LeaveCriticalSection( &channel->cs );
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT read_message( WS_MESSAGE *handle, WS_XML_READER *reader, const WS_ELEMENT_DESCRIPTION *desc,
|
||||
|
@ -725,8 +756,6 @@ HRESULT WINAPI WsReceiveMessage( WS_CHANNEL *handle, WS_MESSAGE *msg, const WS_M
|
|||
void *value, ULONG size, ULONG *index, const WS_ASYNC_CONTEXT *ctx, WS_ERROR *error )
|
||||
{
|
||||
struct channel *channel = (struct channel *)handle;
|
||||
char *buf = NULL;
|
||||
ULONG len;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE( "%p %p %p %u %08x %08x %p %p %u %p %p %p\n", handle, msg, desc, count, option, read_option, heap,
|
||||
|
@ -751,23 +780,20 @@ HRESULT WINAPI WsReceiveMessage( WS_CHANNEL *handle, WS_MESSAGE *msg, const WS_M
|
|||
|
||||
if (!channel || !msg || !desc || !count) return E_INVALIDARG;
|
||||
|
||||
if ((hr = channel_receive_message( handle, &buf, &len )) != S_OK) return hr;
|
||||
|
||||
EnterCriticalSection( &channel->cs );
|
||||
|
||||
if (channel->magic != CHANNEL_MAGIC)
|
||||
{
|
||||
heap_free( buf );
|
||||
LeaveCriticalSection( &channel->cs );
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if ((hr = receive_message( channel )) != S_OK) goto done;
|
||||
if (!channel->reader && (hr = WsCreateReader( NULL, 0, &channel->reader, NULL )) != S_OK) goto done;
|
||||
if ((hr = set_input( channel->reader, buf, len )) != S_OK) goto done;
|
||||
if ((hr = set_input( channel->reader, channel->read_buf, channel->read_size )) != S_OK) goto done;
|
||||
hr = read_message( msg, channel->reader, desc[0]->bodyElementDescription, read_option, heap, value, size );
|
||||
|
||||
done:
|
||||
heap_free( buf );
|
||||
LeaveCriticalSection( &channel->cs );
|
||||
return hr;
|
||||
}
|
||||
|
|
|
@ -433,20 +433,12 @@ static HRESULT receive_message( WS_CHANNEL *channel, WS_MESSAGE *msg, WS_MESSAGE
|
|||
WS_PARAMETER_DESCRIPTION *params, ULONG count, WS_HEAP *heap, const void **args )
|
||||
{
|
||||
WS_XML_READER *reader;
|
||||
char *buf;
|
||||
ULONG len;
|
||||
HRESULT hr;
|
||||
|
||||
if ((hr = message_set_action( msg, desc->action )) != S_OK) return hr;
|
||||
if ((hr = channel_receive_message( channel, &buf, &len )) != S_OK) return hr;
|
||||
if ((hr = WsCreateReader( NULL, 0, &reader, NULL )) != S_OK) goto done;
|
||||
if ((hr = set_input( reader, buf, len )) != S_OK) goto done;
|
||||
hr = read_message( msg, reader, heap, desc->bodyElementDescription, params, count, args );
|
||||
|
||||
done:
|
||||
WsFreeReader( reader );
|
||||
heap_free( buf);
|
||||
return hr;
|
||||
if ((hr = channel_receive_message( channel )) != S_OK) return hr;
|
||||
if ((hr = channel_get_reader( channel, &reader )) != S_OK) return hr;
|
||||
return read_message( msg, reader, heap, desc->bodyElementDescription, params, count, args );
|
||||
}
|
||||
|
||||
static HRESULT create_input_message( WS_CHANNEL *channel, const WS_CALL_PROPERTY *properties,
|
||||
|
|
|
@ -43,7 +43,6 @@ WS_TYPE map_value_type( WS_VALUE_TYPE ) DECLSPEC_HIDDEN;
|
|||
BOOL set_fpword( unsigned short, unsigned short * ) DECLSPEC_HIDDEN;
|
||||
void restore_fpword( unsigned short ) DECLSPEC_HIDDEN;
|
||||
HRESULT set_output( WS_XML_WRITER * ) DECLSPEC_HIDDEN;
|
||||
HRESULT set_input( WS_XML_READER *, char *, ULONG ) DECLSPEC_HIDDEN;
|
||||
ULONG get_type_size( WS_TYPE, const WS_STRUCT_DESCRIPTION * ) DECLSPEC_HIDDEN;
|
||||
|
||||
#define INVALID_PARAMETER_INDEX 0xffff
|
||||
|
@ -119,7 +118,8 @@ void message_do_receive_callback( WS_MESSAGE * ) DECLSPEC_HIDDEN;
|
|||
HRESULT message_insert_http_headers( WS_MESSAGE *, HINTERNET ) DECLSPEC_HIDDEN;
|
||||
|
||||
HRESULT channel_send_message( WS_CHANNEL *, WS_MESSAGE * ) DECLSPEC_HIDDEN;
|
||||
HRESULT channel_receive_message( WS_CHANNEL *, char **, ULONG * ) DECLSPEC_HIDDEN;
|
||||
HRESULT channel_receive_message( WS_CHANNEL * ) DECLSPEC_HIDDEN;
|
||||
HRESULT channel_get_reader( WS_CHANNEL *, WS_XML_READER ** ) DECLSPEC_HIDDEN;
|
||||
|
||||
#define TICKS_PER_SEC 10000000
|
||||
#define TICKS_PER_MIN (60 * (ULONGLONG)TICKS_PER_SEC)
|
||||
|
|
Loading…
Reference in New Issue