webservices: Send incremental string table updates with messages in the same session.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Hans Leidekker 2018-06-20 15:04:48 +02:00 committed by Alexandre Julliard
parent d120f7f841
commit 3c3ab8911e
4 changed files with 56 additions and 15 deletions

View File

@ -1009,22 +1009,26 @@ static inline ULONG size_length( ULONG size )
return 5;
}
static ULONG string_table_size( const WS_XML_DICTIONARY *dict )
static ULONG string_table_size( const struct dictionary *dict )
{
ULONG i, size = 0;
for (i = 0; i < dict->stringCount; i++)
size += size_length( dict->strings[i].length ) + dict->strings[i].length;
for (i = 0; i < dict->dict.stringCount; i++)
{
if (dict->sequence[i] == dict->current_sequence)
size += size_length( dict->dict.strings[i].length ) + dict->dict.strings[i].length;
}
return size;
}
static HRESULT send_string_table( SOCKET socket, const WS_XML_DICTIONARY *dict )
static HRESULT send_string_table( SOCKET socket, const struct dictionary *dict )
{
ULONG i;
HRESULT hr;
for (i = 0; i < dict->stringCount; i++)
for (i = 0; i < dict->dict.stringCount; i++)
{
if ((hr = send_size( socket, dict->strings[i].length )) != S_OK) return hr;
if ((hr = send_bytes( socket, dict->strings[i].bytes, dict->strings[i].length )) != S_OK) return hr;
if (dict->sequence[i] != dict->current_sequence) continue;
if ((hr = send_size( socket, dict->dict.strings[i].length )) != S_OK) return hr;
if ((hr = send_bytes( socket, dict->dict.strings[i].bytes, dict->dict.strings[i].length )) != S_OK) return hr;
}
return S_OK;
}
@ -1154,13 +1158,13 @@ static HRESULT receive_preamble_ack( struct channel *channel )
static HRESULT send_sized_envelope( struct channel *channel, BYTE *data, ULONG len )
{
ULONG table_size = string_table_size( &channel->dict_send.dict );
ULONG table_size = string_table_size( &channel->dict_send );
HRESULT hr;
if ((hr = send_byte( channel->u.tcp.socket, FRAME_RECORD_TYPE_SIZED_ENVELOPE )) != S_OK) return hr;
if ((hr = send_size( channel->u.tcp.socket, size_length(table_size) + table_size + len )) != S_OK) return hr;
if ((hr = send_size( channel->u.tcp.socket, table_size )) != S_OK) return hr;
if ((hr = send_string_table( channel->u.tcp.socket, &channel->dict_send.dict )) != S_OK) return hr;
if ((hr = send_string_table( channel->u.tcp.socket, &channel->dict_send )) != S_OK) return hr;
return send_bytes( channel->u.tcp.socket, data, len );
}
@ -1285,11 +1289,8 @@ static HRESULT init_writer( struct channel *channel )
return WsSetOutput( channel->writer, &text.encoding, &buf.output, NULL, 0, NULL );
case WS_ENCODING_XML_BINARY_SESSION_1:
clear_dict( &channel->dict_send );
bin.staticDictionary = (WS_XML_DICTIONARY *)&dict_builtin_static.dict;
bin.dynamicStringCallback = dict_cb;
bin.dynamicStringCallbackState = &channel->dict_send;
return WsSetOutput( channel->writer, &bin.encoding, &buf.output, NULL, 0, NULL );
bin.staticDictionary = (WS_XML_DICTIONARY *)&dict_builtin_static.dict;
/* fall through */
case WS_ENCODING_XML_BINARY_1:
return WsSetOutput( channel->writer, &bin.encoding, &buf.output, NULL, 0, NULL );
@ -1307,6 +1308,8 @@ static HRESULT write_message( struct channel *channel, WS_MESSAGE *msg, const WS
if ((hr = writer_set_lookup( channel->writer, TRUE )) != S_OK) return hr;
if ((hr = WsWriteEnvelopeStart( msg, channel->writer, NULL, NULL, NULL )) != S_OK) return hr;
if ((hr = writer_set_lookup( channel->writer, FALSE )) != S_OK) return hr;
channel->dict_send.current_sequence++;
if ((hr = writer_set_dict_callback( channel->writer, dict_cb, &channel->dict_send )) != S_OK) return hr;
if ((hr = WsWriteBody( msg, desc, option, body, size, NULL )) != S_OK) return hr;
return WsWriteEnvelopeEnd( msg, NULL );
}

View File

@ -91,7 +91,7 @@ int find_string( const struct dictionary *dict, const unsigned char *data, ULONG
static HRESULT grow_dict( struct dictionary *dict, ULONG size )
{
WS_XML_STRING *tmp;
ULONG new_size, *tmp_sorted;
ULONG new_size, *tmp_sorted, *tmp_sequence;
assert( !dict->dict.isConst );
if (dict->size >= dict->dict.stringCount + size) return S_OK;
@ -107,6 +107,14 @@ static HRESULT grow_dict( struct dictionary *dict, ULONG size )
dict->dict.strings = NULL;
return E_OUTOFMEMORY;
}
if (!(dict->sequence = heap_alloc( new_size * sizeof(*dict->sequence) )))
{
heap_free( dict->dict.strings );
dict->dict.strings = NULL;
heap_free( dict->sorted );
dict->sorted = NULL;
return E_OUTOFMEMORY;
}
dict->size = new_size;
return S_OK;
}
@ -116,6 +124,8 @@ static HRESULT grow_dict( struct dictionary *dict, ULONG size )
dict->dict.strings = tmp;
if (!(tmp_sorted = heap_realloc( dict->sorted, new_size * sizeof(*tmp_sorted) ))) return E_OUTOFMEMORY;
dict->sorted = tmp_sorted;
if (!(tmp_sequence = heap_realloc( dict->sequence, new_size * sizeof(*tmp_sequence) ))) return E_OUTOFMEMORY;
dict->sequence = tmp_sequence;
dict->size = new_size;
return S_OK;
@ -131,6 +141,9 @@ void clear_dict( struct dictionary *dict )
dict->dict.stringCount = 0;
heap_free( dict->sorted );
dict->sorted = NULL;
heap_free( dict->sequence );
dict->sequence = NULL;
dict->current_sequence = 0;
dict->size = 0;
}
@ -149,6 +162,9 @@ HRESULT insert_string( struct dictionary *dict, unsigned char *data, ULONG len,
dict->dict.strings[id].dictionary = &dict->dict;
dict->dict.strings[id].id = id;
dict->dict.stringCount++;
dict->sequence[id] = dict->current_sequence;
if (ret_id) *ret_id = id;
return S_OK;
}

View File

@ -43,6 +43,8 @@ struct dictionary
WS_XML_DICTIONARY dict;
ULONG *sorted;
ULONG size;
ULONG current_sequence;
ULONG *sequence;
};
struct dictionary dict_builtin DECLSPEC_HIDDEN;
const struct dictionary dict_builtin_static DECLSPEC_HIDDEN;
@ -51,6 +53,7 @@ int find_string( const struct dictionary *, const unsigned char *, ULONG, ULONG
HRESULT insert_string( struct dictionary *, unsigned char *, ULONG, int, ULONG * ) DECLSPEC_HIDDEN;
void clear_dict( struct dictionary * ) DECLSPEC_HIDDEN;
HRESULT writer_set_lookup( WS_XML_WRITER *, BOOL ) DECLSPEC_HIDDEN;
HRESULT writer_set_dict_callback( WS_XML_WRITER *, WS_DYNAMIC_STRING_CALLBACK, void * ) DECLSPEC_HIDDEN;
const char *debugstr_xmlstr( const WS_XML_STRING * ) DECLSPEC_HIDDEN;
WS_XML_STRING *alloc_xml_string( const unsigned char *, ULONG ) DECLSPEC_HIDDEN;

View File

@ -4866,3 +4866,22 @@ HRESULT writer_set_lookup( WS_XML_WRITER *handle, BOOL enable )
LeaveCriticalSection( &writer->cs );
return S_OK;
}
HRESULT writer_set_dict_callback( WS_XML_WRITER *handle, WS_DYNAMIC_STRING_CALLBACK cb, void *state )
{
struct writer *writer = (struct writer *)handle;
EnterCriticalSection( &writer->cs );
if (writer->magic != WRITER_MAGIC)
{
LeaveCriticalSection( &writer->cs );
return E_INVALIDARG;
}
writer->dict_cb = cb;
writer->dict_cb_state = state;
LeaveCriticalSection( &writer->cs );
return S_OK;
}