Skip to content

Commit

Permalink
Make saving and loading the responsibility of Tox rather than Messenger
Browse files Browse the repository at this point in the history
  • Loading branch information
zugz committed Oct 20, 2018
1 parent aa5c782 commit 744dc2f
Show file tree
Hide file tree
Showing 10 changed files with 208 additions and 194 deletions.
43 changes: 0 additions & 43 deletions auto_tests/messenger_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,54 +265,11 @@ START_TEST(test_dht_state_saveloadsave)
}
END_TEST

START_TEST(test_messenger_state_saveloadsave)
{
/* validate that:
* a) saving stays within the confined space
* b) a save()d state can be load()ed back successfully
* c) a second save() is of equal size
* d) the second save() is of equal content */
const size_t extra = 64;
const size_t size = messenger_size(m);
VLA(uint8_t, buffer, size + 2 * extra);
memset(buffer, 0xCD, extra);
memset(buffer + extra + size, 0xCD, extra);
messenger_save(m, buffer + extra);

for (size_t i = 0; i < extra; i++) {
ck_assert_msg(buffer[i] == 0xCD, "Buffer underwritten from messenger_save() @%u", (unsigned)i);
ck_assert_msg(buffer[extra + size + i] == 0xCD, "Buffer overwritten from messenger_save() @%u", (unsigned)i);
}

const int res = messenger_load(m, buffer + extra, size);

if (res == -1) {
ck_assert_msg(res == 0, "Failed to load back stored buffer: res == -1");
} else {
const size_t offset = res >> 4;
const uint8_t *ptr = buffer + extra + offset;
ck_assert_msg(res == 0, "Failed to load back stored buffer: 0x%02x%02x%02x%02x%02x%02x%02x%02x @%u/%u, code %d",
ptr[-2], ptr[-1], ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5],
(unsigned)offset, (unsigned)size, res & 0x0F);
}

const size_t size2 = messenger_size(m);
ck_assert_msg(size == size2, "Messenger \"grew\" in size from a store/load cycle: %u -> %u",
(unsigned)size, (unsigned)size2);

VLA(uint8_t, buffer2, size2);
messenger_save(m, buffer2);

ck_assert_msg(!memcmp(buffer + extra, buffer2, size), "Messenger state changed by store/load/store cycle");
}
END_TEST

static Suite *messenger_suite(void)
{
Suite *s = suite_create("Messenger");

DEFTESTCASE(dht_state_saveloadsave);
DEFTESTCASE(messenger_state_saveloadsave);

DEFTESTCASE(getself_name);
DEFTESTCASE(m_get_userstatus_size);
Expand Down
17 changes: 1 addition & 16 deletions testing/Messenger_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,8 @@ int main(int argc, char *argv[])
}

/* with optional --ipvx, now it can be 1-4 arguments... */
if ((argc != argvoffset + 2) && (argc != argvoffset + 4)) {
if (argc != argvoffset + 4) {
printf("Usage: %s [--ipv4|--ipv6] ip port public_key (of the DHT bootstrap node)\n", argv[0]);
printf("or\n");
printf(" %s [--ipv4|--ipv6] Save.bak (to read Save.bak as state file)\n", argv[0]);
exit(0);
}

Expand Down Expand Up @@ -134,19 +132,6 @@ int main(int argc, char *argv[])
printf("Failed to convert \"%s\" into an IP address. Exiting...\n", argv[argvoffset + 1]);
exit(1);
}
} else {
FILE *file = fopen(argv[argvoffset + 1], "rb");

if (file == nullptr) {
printf("Failed to open \"%s\" - does it exist?\n", argv[argvoffset + 1]);
return 1;
}

int read;
uint8_t buffer[128000];
read = fread(buffer, 1, 128000, file);
printf("Messenger loaded: %i\n", messenger_load(m, buffer, read));
fclose(file);
}

m_callback_friendrequest(m, print_request);
Expand Down
4 changes: 2 additions & 2 deletions toxcore/DHT.c
Original file line number Diff line number Diff line change
Expand Up @@ -2831,7 +2831,7 @@ uint32_t dht_size(const DHT *dht)
/* Save the DHT in data where data is an array of size dht_size(). */
void dht_save(const DHT *dht, uint8_t *data)
{
host_to_lendian32(data, DHT_STATE_COOKIE_GLOBAL);
host_to_lendian_bytes32(data, DHT_STATE_COOKIE_GLOBAL);
data += sizeof(uint32_t);

uint8_t *const old_data = data;
Expand Down Expand Up @@ -2960,7 +2960,7 @@ int dht_load(DHT *dht, const uint8_t *data, uint32_t length)

if (length > cookie_len) {
uint32_t data32;
lendian_to_host32(&data32, data);
lendian_bytes_to_host32(&data32, data);

if (data32 == DHT_STATE_COOKIE_GLOBAL) {
return state_load(dht->log, dht_load_state_callback, dht, data + cookie_len,
Expand Down
139 changes: 39 additions & 100 deletions toxcore/Messenger.c
Original file line number Diff line number Diff line change
Expand Up @@ -2739,10 +2739,6 @@ void do_messenger(Messenger *m, void *userdata)

/* new messenger format for load/save, more robust and forward compatible */

#define MESSENGER_STATE_COOKIE_GLOBAL 0x15ed1b1f

#define MESSENGER_STATE_COOKIE_TYPE 0x01ce

#define SAVED_FRIEND_REQUEST_SIZE 1024
#define NUM_SAVED_PATH_NODES 8

Expand Down Expand Up @@ -2881,7 +2877,7 @@ static uint32_t m_state_plugins_size(const Messenger *m)
* returns true on success
* returns false on failure
*/
bool m_register_state_plugin(Messenger *m, Messenger_State_Type type, m_state_size_cb size_callback,
bool m_register_state_plugin(Messenger *m, State_Type type, m_state_size_cb size_callback,
m_state_load_cb load_callback,
m_state_save_cb save_callback)
{
Expand All @@ -2904,7 +2900,7 @@ bool m_register_state_plugin(Messenger *m, Messenger_State_Type type, m_state_si
return true;
}

static uint32_t m_plugin_size(const Messenger *m, Messenger_State_Type type)
static uint32_t m_plugin_size(const Messenger *m, State_Type type)
{
for (uint8_t i = 0; i < m->options.state_plugins_length; ++i) {
const Messenger_State_Plugin plugin = m->options.state_plugins[i];
Expand All @@ -2922,30 +2918,18 @@ static uint32_t m_plugin_size(const Messenger *m, Messenger_State_Type type)
/* return size of the messenger data (for saving) */
uint32_t messenger_size(const Messenger *m)
{
const uint32_t size32 = sizeof(uint32_t);
const uint32_t sizesubhead = size32 * 2;
return size32 * 2 // global cookie
+ m_state_plugins_size(m)
+ sizesubhead;
return m_state_plugins_size(m);
}

/* Save the messenger in data of size Messenger_size(). */
void messenger_save(const Messenger *m, uint8_t *data)
/* Save the messenger in data of size messenger_size(). */
uint8_t *messenger_save(const Messenger *m, uint8_t *data)
{
memset(data, 0, messenger_size(m));

const uint32_t size32 = sizeof(uint32_t);

// write cookie
memset(data, 0, size32);
data += size32;
host_to_lendian32(data, MESSENGER_STATE_COOKIE_GLOBAL);
data += size32;

for (uint8_t i = 0; i < m->options.state_plugins_length; ++i) {
const Messenger_State_Plugin plugin = m->options.state_plugins[i];
data = plugin.save(m, data);
}

return data;
}

// nospam state plugin
Expand All @@ -2956,12 +2940,12 @@ static uint32_t nospam_keys_size(const Messenger *m)

static State_Load_Status load_nospam_keys(Messenger *m, const uint8_t *data, uint32_t length)
{
if (length != m_plugin_size(m, MESSENGER_STATE_TYPE_NOSPAMKEYS)) {
if (length != m_plugin_size(m, STATE_TYPE_NOSPAMKEYS)) {
return STATE_LOAD_STATUS_ERROR;
}

uint32_t nospam;
lendian_to_host32(&nospam, data);
lendian_bytes_to_host32(&nospam, data);
set_nospam(m->fr, nospam);
load_secret_key(m->net_crypto, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE);

Expand All @@ -2974,11 +2958,11 @@ static State_Load_Status load_nospam_keys(Messenger *m, const uint8_t *data, uin

static uint8_t *save_nospam_keys(const Messenger *m, uint8_t *data)
{
const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_NOSPAMKEYS);
const uint32_t len = m_plugin_size(m, STATE_TYPE_NOSPAMKEYS);
assert(sizeof(get_nospam(m->fr)) == sizeof(uint32_t));
data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_NOSPAMKEYS);
data = state_write_section_header(data, STATE_COOKIE_TYPE, len, STATE_TYPE_NOSPAMKEYS);
uint32_t nospam = get_nospam(m->fr);
host_to_lendian32(data, nospam);
host_to_lendian_bytes32(data, nospam);
save_keys(m->net_crypto, data + sizeof(uint32_t));
data += len;
return data;
Expand All @@ -2992,8 +2976,8 @@ static uint32_t m_dht_size(const Messenger *m)

static uint8_t *save_dht(const Messenger *m, uint8_t *data)
{
const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_DHT);
data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_DHT);
const uint32_t len = m_plugin_size(m, STATE_TYPE_DHT);
data = state_write_section_header(data, STATE_COOKIE_TYPE, len, STATE_TYPE_DHT);
dht_save(m->dht, data);
data += len;
return data;
Expand All @@ -3013,8 +2997,8 @@ static uint32_t saved_friendslist_size(const Messenger *m)

static uint8_t *friends_list_save(const Messenger *m, uint8_t *data)
{
const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_FRIENDS);
data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_FRIENDS);
const uint32_t len = m_plugin_size(m, STATE_TYPE_FRIENDS);
data = state_write_section_header(data, STATE_COOKIE_TYPE, len, STATE_TYPE_FRIENDS);

uint32_t num = 0;
uint8_t *cur_data = data;
Expand Down Expand Up @@ -3119,8 +3103,8 @@ static uint32_t name_size(const Messenger *m)

static uint8_t *save_name(const Messenger *m, uint8_t *data)
{
const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_NAME);
data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_NAME);
const uint32_t len = m_plugin_size(m, STATE_TYPE_NAME);
data = state_write_section_header(data, STATE_COOKIE_TYPE, len, STATE_TYPE_NAME);
memcpy(data, m->name, len);
data += len;
return data;
Expand All @@ -3143,8 +3127,8 @@ static uint32_t status_message_size(const Messenger *m)

static uint8_t *save_status_message(const Messenger *m, uint8_t *data)
{
const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_STATUSMESSAGE);
data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_STATUSMESSAGE);
const uint32_t len = m_plugin_size(m, STATE_TYPE_STATUSMESSAGE);
data = state_write_section_header(data, STATE_COOKIE_TYPE, len, STATE_TYPE_STATUSMESSAGE);
memcpy(data, m->statusmessage, len);
data += len;
return data;
Expand All @@ -3167,8 +3151,8 @@ static uint32_t status_size(const Messenger *m)

static uint8_t *save_status(const Messenger *m, uint8_t *data)
{
const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_STATUS);
data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_STATUS);
const uint32_t len = m_plugin_size(m, STATE_TYPE_STATUS);
data = state_write_section_header(data, STATE_COOKIE_TYPE, len, STATE_TYPE_STATUS);
*data = m->userstatus;
data += len;
return data;
Expand All @@ -3193,7 +3177,7 @@ static uint8_t *save_tcp_relays(const Messenger *m, uint8_t *data)
{
Node_format relays[NUM_SAVED_TCP_RELAYS];
uint8_t *temp_data = data;
data = state_write_section_header(temp_data, MESSENGER_STATE_COOKIE_TYPE, 0, MESSENGER_STATE_TYPE_TCP_RELAY);
data = state_write_section_header(temp_data, STATE_COOKIE_TYPE, 0, STATE_TYPE_TCP_RELAY);
uint32_t num = copy_connected_tcp_relays(m->net_crypto, relays, NUM_SAVED_TCP_RELAYS);

if (m->num_loaded_relays > 0) {
Expand All @@ -3205,7 +3189,7 @@ static uint8_t *save_tcp_relays(const Messenger *m, uint8_t *data)

if (l > 0) {
const uint32_t len = l;
data = state_write_section_header(temp_data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_TCP_RELAY);
data = state_write_section_header(temp_data, STATE_COOKIE_TYPE, len, STATE_TYPE_TCP_RELAY);
data += len;
}

Expand All @@ -3232,14 +3216,14 @@ static uint8_t *save_path_nodes(const Messenger *m, uint8_t *data)
{
Node_format nodes[NUM_SAVED_PATH_NODES];
uint8_t *temp_data = data;
data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, 0, MESSENGER_STATE_TYPE_PATH_NODE);
data = state_write_section_header(data, STATE_COOKIE_TYPE, 0, STATE_TYPE_PATH_NODE);
memset(nodes, 0, sizeof(nodes));
const unsigned int num = onion_backup_nodes(m->onion_c, nodes, NUM_SAVED_PATH_NODES);
const int l = pack_nodes(data, NUM_SAVED_PATH_NODES * packed_node_size(net_family_tcp_ipv6), nodes, num);

if (l > 0) {
const uint32_t len = l;
data = state_write_section_header(temp_data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_PATH_NODE);
data = state_write_section_header(temp_data, STATE_COOKIE_TYPE, len, STATE_TYPE_PATH_NODE);
data += len;
}

Expand All @@ -3261,77 +3245,32 @@ static State_Load_Status load_path_nodes(Messenger *m, const uint8_t *data, uint
return STATE_LOAD_STATUS_CONTINUE;
}

// end state plugin
static uint32_t end_size(const Messenger *m)
{
return 0;
}

static uint8_t *save_end(const Messenger *m, uint8_t *data)
{
return state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, 0, MESSENGER_STATE_TYPE_END);
}

static State_Load_Status load_end(Messenger *m, const uint8_t *data, uint32_t length)
{
if (length != 0) {
return STATE_LOAD_STATUS_ERROR;
}

return STATE_LOAD_STATUS_END;
}

static void m_register_default_plugins(Messenger *m)
{
m_register_state_plugin(m, MESSENGER_STATE_TYPE_NOSPAMKEYS, nospam_keys_size, load_nospam_keys, save_nospam_keys);
m_register_state_plugin(m, MESSENGER_STATE_TYPE_DHT, m_dht_size, m_dht_load, save_dht);
m_register_state_plugin(m, MESSENGER_STATE_TYPE_FRIENDS, saved_friendslist_size, friends_list_load, friends_list_save);
m_register_state_plugin(m, MESSENGER_STATE_TYPE_NAME, name_size, load_name, save_name);
m_register_state_plugin(m, MESSENGER_STATE_TYPE_STATUSMESSAGE, status_message_size, load_status_message,
m_register_state_plugin(m, STATE_TYPE_NOSPAMKEYS, nospam_keys_size, load_nospam_keys, save_nospam_keys);
m_register_state_plugin(m, STATE_TYPE_DHT, m_dht_size, m_dht_load, save_dht);
m_register_state_plugin(m, STATE_TYPE_FRIENDS, saved_friendslist_size, friends_list_load, friends_list_save);
m_register_state_plugin(m, STATE_TYPE_NAME, name_size, load_name, save_name);
m_register_state_plugin(m, STATE_TYPE_STATUSMESSAGE, status_message_size, load_status_message,
save_status_message);
m_register_state_plugin(m, MESSENGER_STATE_TYPE_STATUS, status_size, load_status, save_status);
m_register_state_plugin(m, MESSENGER_STATE_TYPE_TCP_RELAY, tcp_relay_size, load_tcp_relays, save_tcp_relays);
m_register_state_plugin(m, MESSENGER_STATE_TYPE_PATH_NODE, path_node_size, load_path_nodes, save_path_nodes);
m_register_state_plugin(m, MESSENGER_STATE_TYPE_END, end_size, load_end, save_end);
m_register_state_plugin(m, STATE_TYPE_STATUS, status_size, load_status, save_status);
m_register_state_plugin(m, STATE_TYPE_TCP_RELAY, tcp_relay_size, load_tcp_relays, save_tcp_relays);
m_register_state_plugin(m, STATE_TYPE_PATH_NODE, path_node_size, load_path_nodes, save_path_nodes);
}

static State_Load_Status messenger_load_state_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type)
bool messenger_load_state_section(Messenger *m, const uint8_t *data, uint32_t length, uint16_t type,
State_Load_Status *status)
{
Messenger *m = (Messenger *)outer;

for (uint8_t i = 0; i < m->options.state_plugins_length; ++i) {
const Messenger_State_Plugin *const plugin = &m->options.state_plugins[i];

if (plugin->type == type) {
return plugin->load(m, data, length);
*status = plugin->load(m, data, length);
return true;
}
}

LOGGER_ERROR(m->log, "Load state: contains unrecognized part (len %u, type %u)\n",
length, type);

return STATE_LOAD_STATUS_CONTINUE;
}

/* Load the messenger from data of size length. */
int messenger_load(Messenger *m, const uint8_t *data, uint32_t length)
{
uint32_t data32[2];
uint32_t cookie_len = sizeof(data32);

if (length < cookie_len) {
return -1;
}

memcpy(data32, data, sizeof(uint32_t));
lendian_to_host32(data32 + 1, data + sizeof(uint32_t));

if (!data32[0] && (data32[1] == MESSENGER_STATE_COOKIE_GLOBAL)) {
return state_load(m->log, messenger_load_state_callback, m, data + cookie_len,
length - cookie_len, MESSENGER_STATE_COOKIE_TYPE);
}

return -1;
return false;
}

/* Return the number of friends in the instance m.
Expand Down
Loading

0 comments on commit 744dc2f

Please sign in to comment.