mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Make saving and loading the responsibility of Tox rather than Messenger
This commit is contained in:
parent
aa5c782880
commit
744dc2f5da
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
|
|
@ -62,20 +62,8 @@ typedef uint8_t *m_state_save_cb(const Messenger *m, uint8_t *data);
|
|||
// Returns if there were any erros during loading
|
||||
typedef State_Load_Status m_state_load_cb(Messenger *m, const uint8_t *data, uint32_t length);
|
||||
|
||||
typedef enum Messenger_State_Type {
|
||||
MESSENGER_STATE_TYPE_NOSPAMKEYS = 1,
|
||||
MESSENGER_STATE_TYPE_DHT = 2,
|
||||
MESSENGER_STATE_TYPE_FRIENDS = 3,
|
||||
MESSENGER_STATE_TYPE_NAME = 4,
|
||||
MESSENGER_STATE_TYPE_STATUSMESSAGE = 5,
|
||||
MESSENGER_STATE_TYPE_STATUS = 6,
|
||||
MESSENGER_STATE_TYPE_TCP_RELAY = 10,
|
||||
MESSENGER_STATE_TYPE_PATH_NODE = 11,
|
||||
MESSENGER_STATE_TYPE_END = 255,
|
||||
} Messenger_State_Type;
|
||||
|
||||
typedef struct Messenger_State_Plugin {
|
||||
Messenger_State_Type type;
|
||||
State_Type type;
|
||||
m_state_size_cb *size;
|
||||
m_state_save_cb *save;
|
||||
m_state_load_cb *load;
|
||||
|
@ -797,17 +785,22 @@ uint32_t messenger_run_interval(const Messenger *m);
|
|||
* returns true on success
|
||||
* returns false on error
|
||||
*/
|
||||
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);
|
||||
|
||||
/* return size of the messenger data (for saving). */
|
||||
uint32_t messenger_size(const Messenger *m);
|
||||
|
||||
/* Save the messenger in data (must be allocated memory of size Messenger_size()) */
|
||||
void messenger_save(const Messenger *m, uint8_t *data);
|
||||
/* Save the messenger in data (must be allocated memory of size at least Messenger_size()) */
|
||||
uint8_t *messenger_save(const Messenger *m, uint8_t *data);
|
||||
|
||||
/* Load the messenger from data of size length. */
|
||||
int messenger_load(Messenger *m, const uint8_t *data, uint32_t length);
|
||||
/* Load a state section.
|
||||
*
|
||||
* @param status Result of loading section is stored here if the section is handled.
|
||||
* @return true iff section handled.
|
||||
*/
|
||||
bool messenger_load_state_section(Messenger *m, const uint8_t *data, uint32_t length, uint16_t type,
|
||||
State_Load_Status *status);
|
||||
|
||||
/* Return the number of friends in the instance m.
|
||||
* You should use this to determine how much memory to allocate
|
||||
|
|
|
@ -2875,6 +2875,22 @@ void send_name_all_groups(Group_Chats *g_c)
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t conferences_size(const Group_Chats *g_c)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *conferences_save(const Group_Chats *g_c, uint8_t *data)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
bool conferences_load_state_section(Group_Chats *g_c, const uint8_t *data, uint32_t length, uint16_t type,
|
||||
State_Load_Status *status)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Create new groupchat instance. */
|
||||
Group_Chats *new_groupchats(Mono_Time *mono_time, Messenger *m)
|
||||
{
|
||||
|
|
|
@ -448,6 +448,21 @@ int callback_groupchat_peer_delete(Group_Chats *g_c, uint32_t groupnumber, peer_
|
|||
*/
|
||||
int callback_groupchat_delete(Group_Chats *g_c, uint32_t groupnumber, group_on_delete_cb *function);
|
||||
|
||||
/* Return size of the conferences data (for saving). */
|
||||
uint32_t conferences_size(const Group_Chats *g_c);
|
||||
|
||||
/* Save the conferences in data (must be allocated memory of size at least conferences_size()) */
|
||||
uint8_t *conferences_save(const Group_Chats *g_c, uint8_t *data);
|
||||
|
||||
/**
|
||||
* Load a section.
|
||||
*
|
||||
* @param status Result of loading section is stored here if the section is handled.
|
||||
* @return true iff section handled.
|
||||
*/
|
||||
bool conferences_load_state_section(Group_Chats *g_c, const uint8_t *data, uint32_t length, uint16_t type,
|
||||
State_Load_Status *status);
|
||||
|
||||
/* Create new groupchat instance. */
|
||||
Group_Chats *new_groupchats(Mono_Time *mono_time, Messenger *m);
|
||||
|
||||
|
|
|
@ -16,10 +16,10 @@ int state_load(const Logger *log, state_load_cb *state_load_callback, void *oute
|
|||
|
||||
while (length >= size_head) {
|
||||
uint32_t length_sub;
|
||||
lendian_to_host32(&length_sub, data);
|
||||
lendian_bytes_to_host32(&length_sub, data);
|
||||
|
||||
uint32_t cookie_type;
|
||||
lendian_to_host32(&cookie_type, data + sizeof(uint32_t));
|
||||
lendian_bytes_to_host32(&cookie_type, data + sizeof(uint32_t));
|
||||
|
||||
data += size_head;
|
||||
length -= size_head;
|
||||
|
@ -63,9 +63,9 @@ int state_load(const Logger *log, state_load_cb *state_load_callback, void *oute
|
|||
|
||||
uint8_t *state_write_section_header(uint8_t *data, uint16_t cookie_type, uint32_t len, uint32_t section_type)
|
||||
{
|
||||
host_to_lendian32(data, len);
|
||||
host_to_lendian_bytes32(data, len);
|
||||
data += sizeof(uint32_t);
|
||||
host_to_lendian32(data, (host_tolendian16(cookie_type) << 16) | host_tolendian16(section_type));
|
||||
host_to_lendian_bytes32(data, (host_to_lendian16(cookie_type) << 16) | host_to_lendian16(section_type));
|
||||
data += sizeof(uint32_t);
|
||||
return data;
|
||||
}
|
||||
|
@ -79,12 +79,12 @@ uint16_t lendian_to_host16(uint16_t lendian)
|
|||
#endif
|
||||
}
|
||||
|
||||
uint16_t host_tolendian16(uint16_t host)
|
||||
uint16_t host_to_lendian16(uint16_t host)
|
||||
{
|
||||
return lendian_to_host16(host);
|
||||
}
|
||||
|
||||
void host_to_lendian32(uint8_t *dest, uint32_t num)
|
||||
void host_to_lendian_bytes32(uint8_t *dest, uint32_t num)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
num = ((num << 8) & 0xFF00FF00) | ((num >> 8) & 0xFF00FF);
|
||||
|
@ -93,7 +93,7 @@ void host_to_lendian32(uint8_t *dest, uint32_t num)
|
|||
memcpy(dest, &num, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
void lendian_to_host32(uint32_t *dest, const uint8_t *lendian)
|
||||
void lendian_bytes_to_host32(uint32_t *dest, const uint8_t *lendian)
|
||||
{
|
||||
uint32_t d;
|
||||
memcpy(&d, lendian, sizeof(uint32_t));
|
||||
|
@ -103,3 +103,21 @@ void lendian_to_host32(uint32_t *dest, const uint8_t *lendian)
|
|||
#endif
|
||||
*dest = d;
|
||||
}
|
||||
|
||||
void host_to_lendian_bytes16(uint8_t *dest, uint16_t num)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
num = (num << 8) | (num >> 8);
|
||||
#endif
|
||||
memcpy(dest, &num, sizeof(uint16_t));
|
||||
}
|
||||
|
||||
void lendian_bytes_to_host16(uint16_t *dest, const uint8_t *lendian)
|
||||
{
|
||||
uint16_t d;
|
||||
memcpy(&d, lendian, sizeof(uint16_t));
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
d = (d << 8) | (d >> 8);
|
||||
#endif
|
||||
*dest = d;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,22 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define STATE_COOKIE_GLOBAL 0x15ed1b1f
|
||||
|
||||
#define STATE_COOKIE_TYPE 0x01ce
|
||||
|
||||
typedef enum State_Type {
|
||||
STATE_TYPE_NOSPAMKEYS = 1,
|
||||
STATE_TYPE_DHT = 2,
|
||||
STATE_TYPE_FRIENDS = 3,
|
||||
STATE_TYPE_NAME = 4,
|
||||
STATE_TYPE_STATUSMESSAGE = 5,
|
||||
STATE_TYPE_STATUS = 6,
|
||||
STATE_TYPE_TCP_RELAY = 10,
|
||||
STATE_TYPE_PATH_NODE = 11,
|
||||
STATE_TYPE_END = 255,
|
||||
} State_Type;
|
||||
|
||||
// Returned by the state_load_cb to instruct the loader on what to do next.
|
||||
typedef enum State_Load_Status {
|
||||
// Continue loading state data sections.
|
||||
|
@ -39,10 +55,13 @@ uint8_t *state_write_section_header(uint8_t *data, uint16_t cookie_type, uint32_
|
|||
// Utilities for state data serialisation.
|
||||
|
||||
uint16_t lendian_to_host16(uint16_t lendian);
|
||||
uint16_t host_tolendian16(uint16_t host);
|
||||
uint16_t host_to_lendian16(uint16_t host);
|
||||
|
||||
void host_to_lendian32(uint8_t *dest, uint32_t num);
|
||||
void lendian_to_host32(uint32_t *dest, const uint8_t *lendian);
|
||||
void host_to_lendian_bytes32(uint8_t *dest, uint32_t num);
|
||||
void lendian_bytes_to_host32(uint32_t *dest, const uint8_t *lendian);
|
||||
|
||||
void host_to_lendian_bytes16(uint8_t *dest, uint16_t num);
|
||||
void lendian_bytes_to_host16(uint16_t *dest, const uint8_t *lendian);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
@ -328,6 +328,51 @@ bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch)
|
|||
return TOX_VERSION_IS_API_COMPATIBLE(major, minor, patch);
|
||||
}
|
||||
|
||||
static State_Load_Status state_load_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type)
|
||||
{
|
||||
Tox *tox = (Tox *)outer;
|
||||
State_Load_Status status = STATE_LOAD_STATUS_CONTINUE;
|
||||
|
||||
if (messenger_load_state_section(tox->m, data, length, type, &status)
|
||||
|| conferences_load_state_section(tox->m->conferences_object, data, length, type, &status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (type == STATE_TYPE_END) {
|
||||
if (length != 0) {
|
||||
return STATE_LOAD_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return STATE_LOAD_STATUS_END;
|
||||
}
|
||||
|
||||
LOGGER_ERROR(tox->m->log, "Load state: contains unrecognized part (len %u, type %u)\n",
|
||||
length, type);
|
||||
|
||||
return STATE_LOAD_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
/* Load tox from data of size length. */
|
||||
static int tox_load(Tox *tox, 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_bytes_to_host32(data32 + 1, data + sizeof(uint32_t));
|
||||
|
||||
if (data32[0] != 0 || data32[1] != STATE_COOKIE_GLOBAL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return state_load(tox->m->log, state_load_callback, tox, data + cookie_len,
|
||||
length - cookie_len, STATE_COOKIE_TYPE);
|
||||
}
|
||||
|
||||
|
||||
Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
|
||||
{
|
||||
|
@ -488,7 +533,7 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
|
|||
}
|
||||
|
||||
if (load_savedata_tox
|
||||
&& messenger_load(m, tox_options_get_savedata_data(opts), tox_options_get_savedata_length(opts)) == -1) {
|
||||
&& tox_load(tox, tox_options_get_savedata_data(opts), tox_options_get_savedata_length(opts)) == -1) {
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
|
||||
} else if (load_savedata_sk) {
|
||||
load_secret_key(m->net_crypto, tox_options_get_savedata_data(opts));
|
||||
|
@ -537,18 +582,45 @@ void tox_kill(Tox *tox)
|
|||
free(tox);
|
||||
}
|
||||
|
||||
static uint32_t end_size(void)
|
||||
{
|
||||
return 2 * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
static void end_save(uint8_t *data)
|
||||
{
|
||||
state_write_section_header(data, STATE_COOKIE_TYPE, 0, STATE_TYPE_END);
|
||||
}
|
||||
|
||||
size_t tox_get_savedata_size(const Tox *tox)
|
||||
{
|
||||
const Messenger *m = tox->m;
|
||||
return messenger_size(m);
|
||||
return 2 * sizeof(uint32_t)
|
||||
+ messenger_size(m)
|
||||
+ conferences_size(m->conferences_object)
|
||||
+ end_size();
|
||||
}
|
||||
|
||||
void tox_get_savedata(const Tox *tox, uint8_t *savedata)
|
||||
{
|
||||
if (savedata) {
|
||||
const Messenger *m = tox->m;
|
||||
messenger_save(m, savedata);
|
||||
if (savedata == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(savedata, 0, tox_get_savedata_size(tox));
|
||||
|
||||
const uint32_t size32 = sizeof(uint32_t);
|
||||
|
||||
// write cookie
|
||||
memset(savedata, 0, size32);
|
||||
savedata += size32;
|
||||
host_to_lendian_bytes32(savedata, STATE_COOKIE_GLOBAL);
|
||||
savedata += size32;
|
||||
|
||||
const Messenger *m = tox->m;
|
||||
savedata = messenger_save(m, savedata);
|
||||
savedata = conferences_save(m->conferences_object, savedata);
|
||||
end_save(savedata);
|
||||
}
|
||||
|
||||
bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key, Tox_Err_Bootstrap *error)
|
||||
|
|
Loading…
Reference in New Issue
Block a user