Skip to content

Commit 3f71894

Browse files
authored
Merge pull request #11 from jagerman/multipart
Add support for large, multi-part config messages
2 parents 5fb3995 + ca53f1b commit 3f71894

37 files changed

+1659
-482
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,6 @@
1919
[submodule "external/protobuf"]
2020
path = external/protobuf
2121
url = https://github.com/protocolbuffers/protobuf.git
22+
[submodule "external/oxen-logging"]
23+
path = external/oxen-logging
24+
url = https://github.com/oxen-io/oxen-logging.git

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ if(CCACHE_PROGRAM)
1717
endif()
1818

1919
project(libsession-util
20-
VERSION 1.3.1
20+
VERSION 1.4.0
2121
DESCRIPTION "Session client utility library"
2222
LANGUAGES ${LANGS})
2323

external/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ if(APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL AppleClang AND NOT CMAKE_CXX_COMPILE
126126
oxen_logging_add_source_dir("${CMAKE_CURRENT_SOURCE_DIR}/oxen-libquic/external/oxen-logging/include/oxen")
127127
endif()
128128

129-
130129
if(CMAKE_C_COMPILER_LAUNCHER)
131130
set(deps_cc "${CMAKE_C_COMPILER_LAUNCHER} ${deps_cc}")
132131
endif()

external/oxen-logging

Submodule oxen-logging added at 6ae91a2

include/session/config.hpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,20 @@
1515

1616
namespace session::config {
1717

18-
// FIXME: for multi-message we encode to longer and then split it up
19-
inline constexpr int MAX_MESSAGE_SIZE = 76800; // 76.8kB = Storage server's limit
18+
// The maximum size of a single message in storage server. For larger configs we have to split a
19+
// config message into a multipart message.
20+
inline constexpr int MAX_MESSAGE_SIZE = 76'800; // 76.8kB = Storage server's limit
21+
22+
// Maximum size of a post-compression outgoing multipart config message (before chopping into
23+
// multiple parts, and so not counting the small encryption and encoding overhead of each piece)
24+
// that we will allow. This is not a strict network limit, but rather is simply to prevent bugs
25+
// that have some sort of accidental runaway size. This limit does not apply to *incoming*
26+
// multipart messages so that if a future version changes the limit it will not break compatibility
27+
// with existing clients.
28+
//
29+
// Also note that we encode part index and length as 1 byte each, so this must be small enough to
30+
// not exceed 255 parts (but that would be insane anyway).
31+
inline constexpr int MAX_MULTIPART_SIZE = 5'000'000;
2032

2133
// Application data data types:
2234
using scalar = std::variant<int64_t, std::string>;
@@ -337,11 +349,12 @@ class MutableConfigMessage : public ConfigMessage {
337349
/// pruning.
338350
bool prune();
339351

340-
/// Calculates the hash of the current message. Can optionally be given the already-serialized
341-
/// value, if available; if empty/omitted, `serialize()` will be called to compute it.
352+
/// Calculates the hash of the current message.
342353
const hash_t& hash() override;
343354

344355
protected:
356+
/// Internal version of hash() that takes the already-serialized value, to avoid needing a call
357+
/// to `serialize()` when such a call has already been done for other reasons.
345358
const hash_t& hash(std::span<const unsigned char> serialized);
346359
void increment_impl();
347360
};

include/session/config/base.h

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,12 @@ LIBSESSION_EXPORT bool config_needs_push(const config_object* conf);
123123
typedef struct config_push_data {
124124
// The config seqno (to be provided later in `config_confirm_pushed`).
125125
seqno_t seqno;
126-
// The config message to push (binary data, not null-terminated).
127-
unsigned char* config;
128-
// The length of `config`
129-
size_t config_len;
126+
// Array of config message(s) to push (each is binary data, not null-terminated).
127+
unsigned char** config;
128+
// Array of lengths of the messages in `config`
129+
size_t* config_lens;
130+
// Length of config and config_len arrays.
131+
size_t n_configs;
130132
// Array of obsolete message hashes to delete; each element is a null-terminated C string
131133
char** obsolete;
132134
// length of `obsolete`
@@ -161,24 +163,28 @@ LIBSESSION_EXPORT config_push_data* config_push(config_object* conf);
161163
/// API: base/config_confirm_pushed
162164
///
163165
/// Reports that data obtained from `config_push` has been successfully stored on the server with
164-
/// message hash `msg_hash`. The seqno value is the one returned by the config_push call that
165-
/// yielded the config data.
166+
/// message hash(es) `msg_hashes` containing `hashes_len` hashes. The seqno value is the one
167+
/// returned by the config_push call that yielded the config data. The order of hashes in the
168+
/// msg_hashes array is unimportant.
166169
///
167170
/// Declaration:
168171
/// ```cpp
169172
/// VOID config_confirm_pushed(
170173
/// [in, out] config_object* conf,
171-
/// [out] seqno_t seqno,
172-
/// [out] const char* msg_hash
174+
/// [in] seqno_t seqno,
175+
/// [in] const char* const* msg_hashes
176+
/// [in] size_t hashes_len
173177
/// );
174178
/// ```
175179
///
176180
/// Inputs:
177181
/// - `conf` -- [in] Pointer to config_object object
178-
/// - `seqno` -- [out] Value returned by config_push call
179-
/// - `msg_hash` -- [out] Value returned by config_push call
182+
/// - `seqno` -- [in] Value returned by config_push call
183+
/// - `msg_hashes` -- [in] array of message hashes (null terminated C strings) returned by the
184+
/// storage server when stored.
185+
/// - `hashes_len` -- [in] length of the `msg_hashes` array
180186
LIBSESSION_EXPORT void config_confirm_pushed(
181-
config_object* conf, seqno_t seqno, const char* msg_hash);
187+
config_object* conf, seqno_t seqno, const char* const* msg_hashes, size_t hashes_len);
182188

183189
/// API: base/config_dump
184190
///
@@ -229,17 +235,46 @@ LIBSESSION_EXPORT bool config_dump(config_object* conf, unsigned char** out, siz
229235
/// - `bool` -- True if config has changed since last call to `dump()`
230236
LIBSESSION_EXPORT bool config_needs_dump(const config_object* conf);
231237

232-
/// API: base/config_current_hashes
238+
/// API: base/config_curr_hashes
233239
///
234-
/// Obtains the current active hashes. Note that this will be empty if the current hash is unknown
235-
/// or not yet determined (for example, because the current state is dirty or because the most
236-
/// recent push is still pending and we don't know the hash yet).
240+
/// Obtains the hashes of the current config state. Note that this will be empty if the current
241+
/// hash is unknown or not yet determined (for example, because the current state is dirty or
242+
/// because the most recent push is still pending and we don't know the hash yet).
243+
///
244+
/// See also config_active_hashes(), which you often want to use instead of this.
245+
///
246+
/// The returned pointer belongs to the caller and must be freed via `free()` when done with it.
247+
///
248+
/// Declaration:
249+
/// ```cpp
250+
/// CONFIG_STRING_LIST* config_curr_hashes(
251+
/// [in] const config_object* conf
252+
/// );
253+
///
254+
/// ```
255+
///
256+
/// Inputs:
257+
/// - `conf` -- [in] Pointer to config_object object
258+
///
259+
/// Outputs:
260+
/// - `config_string_list*` -- pointer to the list of hashes; the pointer belongs to the caller
261+
LIBSESSION_EXPORT config_string_list* config_curr_hashes(const config_object* conf)
262+
LIBSESSION_WARN_UNUSED;
263+
264+
/// API: base/config_active_hashes
265+
///
266+
/// Obtains the hashes of currently active config messages. This includes both the hashes of the
267+
/// current config (as returned by config_curr_hashes), but also any partially-arrived multipart
268+
/// config messages for which we are still waiting for remaining parts to complete the config.
269+
///
270+
/// The returned array of hashes have no particular ordering (and may differ from one call to the
271+
/// next even without any change to the values considered as a set).
237272
///
238273
/// The returned pointer belongs to the caller and must be freed via `free()` when done with it.
239274
///
240275
/// Declaration:
241276
/// ```cpp
242-
/// CONFIG_STRING_LIST* config_current_hashes(
277+
/// CONFIG_STRING_LIST* config_active_hashes(
243278
/// [in] const config_object* conf
244279
/// );
245280
///
@@ -250,7 +285,7 @@ LIBSESSION_EXPORT bool config_needs_dump(const config_object* conf);
250285
///
251286
/// Outputs:
252287
/// - `config_string_list*` -- pointer to the list of hashes; the pointer belongs to the caller
253-
LIBSESSION_EXPORT config_string_list* config_current_hashes(const config_object* conf)
288+
LIBSESSION_EXPORT config_string_list* config_active_hashes(const config_object* conf)
254289
LIBSESSION_WARN_UNUSED;
255290

256291
/// API: base/config_old_hashes

0 commit comments

Comments
 (0)