[PATCH 5/5] webservices: Send incremental string table updates with messages in the same session.

Hans Leidekker hans at codeweavers.com
Wed Jun 20 08:04:48 CDT 2018


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/webservices/channel.c             | 31 +++++++++++++++++--------------
 dlls/webservices/string.c              | 18 +++++++++++++++++-
 dlls/webservices/webservices_private.h |  3 +++
 dlls/webservices/writer.c              | 19 +++++++++++++++++++
 4 files changed, 56 insertions(+), 15 deletions(-)

diff --git a/dlls/webservices/channel.c b/dlls/webservices/channel.c
index 79d431f279..5963faf00d 100644
--- a/dlls/webservices/channel.c
+++ b/dlls/webservices/channel.c
@@ -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 );
 }
diff --git a/dlls/webservices/string.c b/dlls/webservices/string.c
index 18c55e3833..0bb77df946 100644
--- a/dlls/webservices/string.c
+++ b/dlls/webservices/string.c
@@ -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;
 }
diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h
index bfc3202a64..d981527bb2 100644
--- a/dlls/webservices/webservices_private.h
+++ b/dlls/webservices/webservices_private.h
@@ -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;
diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index b3d130a52c..95d4caddb9 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -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;
+}
-- 
2.11.0




More information about the wine-devel mailing list