summaryrefslogtreecommitdiff
path: root/toxcore
diff options
context:
space:
mode:
authorzugz (tox) <mbays+tox@sdf.org>2018-09-09 23:21:20 +0200
committerzugz (tox) <mbays+tox@sdf.org>2018-10-20 11:03:10 +0200
commit744dc2f5da2c54ad1e4d7d6ce229bc1756d81263 (patch)
tree35f6590fe3150118bc6b1336fbb0a7db06543668 /toxcore
parentaa5c7828802b3fcaedfd8d6fe9a08ca714b9aa2b (diff)
Make saving and loading the responsibility of Tox rather than Messenger
Diffstat (limited to 'toxcore')
-rw-r--r--toxcore/DHT.c4
-rw-r--r--toxcore/Messenger.c139
-rw-r--r--toxcore/Messenger.h29
-rw-r--r--toxcore/group.c16
-rw-r--r--toxcore/group.h15
-rw-r--r--toxcore/state.c32
-rw-r--r--toxcore/state.h25
-rw-r--r--toxcore/tox.c82
8 files changed, 207 insertions, 135 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index 8208052d..4908de32 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -2831,7 +2831,7 @@ uint32_t dht_size(const DHT *dht)
2831/* Save the DHT in data where data is an array of size dht_size(). */ 2831/* Save the DHT in data where data is an array of size dht_size(). */
2832void dht_save(const DHT *dht, uint8_t *data) 2832void dht_save(const DHT *dht, uint8_t *data)
2833{ 2833{
2834 host_to_lendian32(data, DHT_STATE_COOKIE_GLOBAL); 2834 host_to_lendian_bytes32(data, DHT_STATE_COOKIE_GLOBAL);
2835 data += sizeof(uint32_t); 2835 data += sizeof(uint32_t);
2836 2836
2837 uint8_t *const old_data = data; 2837 uint8_t *const old_data = data;
@@ -2960,7 +2960,7 @@ int dht_load(DHT *dht, const uint8_t *data, uint32_t length)
2960 2960
2961 if (length > cookie_len) { 2961 if (length > cookie_len) {
2962 uint32_t data32; 2962 uint32_t data32;
2963 lendian_to_host32(&data32, data); 2963 lendian_bytes_to_host32(&data32, data);
2964 2964
2965 if (data32 == DHT_STATE_COOKIE_GLOBAL) { 2965 if (data32 == DHT_STATE_COOKIE_GLOBAL) {
2966 return state_load(dht->log, dht_load_state_callback, dht, data + cookie_len, 2966 return state_load(dht->log, dht_load_state_callback, dht, data + cookie_len,
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index e092a9f2..ae2d1d3b 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -2739,10 +2739,6 @@ void do_messenger(Messenger *m, void *userdata)
2739 2739
2740/* new messenger format for load/save, more robust and forward compatible */ 2740/* new messenger format for load/save, more robust and forward compatible */
2741 2741
2742#define MESSENGER_STATE_COOKIE_GLOBAL 0x15ed1b1f
2743
2744#define MESSENGER_STATE_COOKIE_TYPE 0x01ce
2745
2746#define SAVED_FRIEND_REQUEST_SIZE 1024 2742#define SAVED_FRIEND_REQUEST_SIZE 1024
2747#define NUM_SAVED_PATH_NODES 8 2743#define NUM_SAVED_PATH_NODES 8
2748 2744
@@ -2881,7 +2877,7 @@ static uint32_t m_state_plugins_size(const Messenger *m)
2881 * returns true on success 2877 * returns true on success
2882 * returns false on failure 2878 * returns false on failure
2883 */ 2879 */
2884bool m_register_state_plugin(Messenger *m, Messenger_State_Type type, m_state_size_cb size_callback, 2880bool m_register_state_plugin(Messenger *m, State_Type type, m_state_size_cb size_callback,
2885 m_state_load_cb load_callback, 2881 m_state_load_cb load_callback,
2886 m_state_save_cb save_callback) 2882 m_state_save_cb save_callback)
2887{ 2883{
@@ -2904,7 +2900,7 @@ bool m_register_state_plugin(Messenger *m, Messenger_State_Type type, m_state_si
2904 return true; 2900 return true;
2905} 2901}
2906 2902
2907static uint32_t m_plugin_size(const Messenger *m, Messenger_State_Type type) 2903static uint32_t m_plugin_size(const Messenger *m, State_Type type)
2908{ 2904{
2909 for (uint8_t i = 0; i < m->options.state_plugins_length; ++i) { 2905 for (uint8_t i = 0; i < m->options.state_plugins_length; ++i) {
2910 const Messenger_State_Plugin plugin = m->options.state_plugins[i]; 2906 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)
2922/* return size of the messenger data (for saving) */ 2918/* return size of the messenger data (for saving) */
2923uint32_t messenger_size(const Messenger *m) 2919uint32_t messenger_size(const Messenger *m)
2924{ 2920{
2925 const uint32_t size32 = sizeof(uint32_t); 2921 return m_state_plugins_size(m);
2926 const uint32_t sizesubhead = size32 * 2;
2927 return size32 * 2 // global cookie
2928 + m_state_plugins_size(m)
2929 + sizesubhead;
2930} 2922}
2931 2923
2932/* Save the messenger in data of size Messenger_size(). */ 2924/* Save the messenger in data of size messenger_size(). */
2933void messenger_save(const Messenger *m, uint8_t *data) 2925uint8_t *messenger_save(const Messenger *m, uint8_t *data)
2934{ 2926{
2935 memset(data, 0, messenger_size(m));
2936
2937 const uint32_t size32 = sizeof(uint32_t);
2938
2939 // write cookie
2940 memset(data, 0, size32);
2941 data += size32;
2942 host_to_lendian32(data, MESSENGER_STATE_COOKIE_GLOBAL);
2943 data += size32;
2944
2945 for (uint8_t i = 0; i < m->options.state_plugins_length; ++i) { 2927 for (uint8_t i = 0; i < m->options.state_plugins_length; ++i) {
2946 const Messenger_State_Plugin plugin = m->options.state_plugins[i]; 2928 const Messenger_State_Plugin plugin = m->options.state_plugins[i];
2947 data = plugin.save(m, data); 2929 data = plugin.save(m, data);
2948 } 2930 }
2931
2932 return data;
2949} 2933}
2950 2934
2951// nospam state plugin 2935// nospam state plugin
@@ -2956,12 +2940,12 @@ static uint32_t nospam_keys_size(const Messenger *m)
2956 2940
2957static State_Load_Status load_nospam_keys(Messenger *m, const uint8_t *data, uint32_t length) 2941static State_Load_Status load_nospam_keys(Messenger *m, const uint8_t *data, uint32_t length)
2958{ 2942{
2959 if (length != m_plugin_size(m, MESSENGER_STATE_TYPE_NOSPAMKEYS)) { 2943 if (length != m_plugin_size(m, STATE_TYPE_NOSPAMKEYS)) {
2960 return STATE_LOAD_STATUS_ERROR; 2944 return STATE_LOAD_STATUS_ERROR;
2961 } 2945 }
2962 2946
2963 uint32_t nospam; 2947 uint32_t nospam;
2964 lendian_to_host32(&nospam, data); 2948 lendian_bytes_to_host32(&nospam, data);
2965 set_nospam(m->fr, nospam); 2949 set_nospam(m->fr, nospam);
2966 load_secret_key(m->net_crypto, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE); 2950 load_secret_key(m->net_crypto, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE);
2967 2951
@@ -2974,11 +2958,11 @@ static State_Load_Status load_nospam_keys(Messenger *m, const uint8_t *data, uin
2974 2958
2975static uint8_t *save_nospam_keys(const Messenger *m, uint8_t *data) 2959static uint8_t *save_nospam_keys(const Messenger *m, uint8_t *data)
2976{ 2960{
2977 const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_NOSPAMKEYS); 2961 const uint32_t len = m_plugin_size(m, STATE_TYPE_NOSPAMKEYS);
2978 assert(sizeof(get_nospam(m->fr)) == sizeof(uint32_t)); 2962 assert(sizeof(get_nospam(m->fr)) == sizeof(uint32_t));
2979 data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_NOSPAMKEYS); 2963 data = state_write_section_header(data, STATE_COOKIE_TYPE, len, STATE_TYPE_NOSPAMKEYS);
2980 uint32_t nospam = get_nospam(m->fr); 2964 uint32_t nospam = get_nospam(m->fr);
2981 host_to_lendian32(data, nospam); 2965 host_to_lendian_bytes32(data, nospam);
2982 save_keys(m->net_crypto, data + sizeof(uint32_t)); 2966 save_keys(m->net_crypto, data + sizeof(uint32_t));
2983 data += len; 2967 data += len;
2984 return data; 2968 return data;
@@ -2992,8 +2976,8 @@ static uint32_t m_dht_size(const Messenger *m)
2992 2976
2993static uint8_t *save_dht(const Messenger *m, uint8_t *data) 2977static uint8_t *save_dht(const Messenger *m, uint8_t *data)
2994{ 2978{
2995 const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_DHT); 2979 const uint32_t len = m_plugin_size(m, STATE_TYPE_DHT);
2996 data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_DHT); 2980 data = state_write_section_header(data, STATE_COOKIE_TYPE, len, STATE_TYPE_DHT);
2997 dht_save(m->dht, data); 2981 dht_save(m->dht, data);
2998 data += len; 2982 data += len;
2999 return data; 2983 return data;
@@ -3013,8 +2997,8 @@ static uint32_t saved_friendslist_size(const Messenger *m)
3013 2997
3014static uint8_t *friends_list_save(const Messenger *m, uint8_t *data) 2998static uint8_t *friends_list_save(const Messenger *m, uint8_t *data)
3015{ 2999{
3016 const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_FRIENDS); 3000 const uint32_t len = m_plugin_size(m, STATE_TYPE_FRIENDS);
3017 data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_FRIENDS); 3001 data = state_write_section_header(data, STATE_COOKIE_TYPE, len, STATE_TYPE_FRIENDS);
3018 3002
3019 uint32_t num = 0; 3003 uint32_t num = 0;
3020 uint8_t *cur_data = data; 3004 uint8_t *cur_data = data;
@@ -3119,8 +3103,8 @@ static uint32_t name_size(const Messenger *m)
3119 3103
3120static uint8_t *save_name(const Messenger *m, uint8_t *data) 3104static uint8_t *save_name(const Messenger *m, uint8_t *data)
3121{ 3105{
3122 const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_NAME); 3106 const uint32_t len = m_plugin_size(m, STATE_TYPE_NAME);
3123 data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_NAME); 3107 data = state_write_section_header(data, STATE_COOKIE_TYPE, len, STATE_TYPE_NAME);
3124 memcpy(data, m->name, len); 3108 memcpy(data, m->name, len);
3125 data += len; 3109 data += len;
3126 return data; 3110 return data;
@@ -3143,8 +3127,8 @@ static uint32_t status_message_size(const Messenger *m)
3143 3127
3144static uint8_t *save_status_message(const Messenger *m, uint8_t *data) 3128static uint8_t *save_status_message(const Messenger *m, uint8_t *data)
3145{ 3129{
3146 const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_STATUSMESSAGE); 3130 const uint32_t len = m_plugin_size(m, STATE_TYPE_STATUSMESSAGE);
3147 data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_STATUSMESSAGE); 3131 data = state_write_section_header(data, STATE_COOKIE_TYPE, len, STATE_TYPE_STATUSMESSAGE);
3148 memcpy(data, m->statusmessage, len); 3132 memcpy(data, m->statusmessage, len);
3149 data += len; 3133 data += len;
3150 return data; 3134 return data;
@@ -3167,8 +3151,8 @@ static uint32_t status_size(const Messenger *m)
3167 3151
3168static uint8_t *save_status(const Messenger *m, uint8_t *data) 3152static uint8_t *save_status(const Messenger *m, uint8_t *data)
3169{ 3153{
3170 const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_STATUS); 3154 const uint32_t len = m_plugin_size(m, STATE_TYPE_STATUS);
3171 data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_STATUS); 3155 data = state_write_section_header(data, STATE_COOKIE_TYPE, len, STATE_TYPE_STATUS);
3172 *data = m->userstatus; 3156 *data = m->userstatus;
3173 data += len; 3157 data += len;
3174 return data; 3158 return data;
@@ -3193,7 +3177,7 @@ static uint8_t *save_tcp_relays(const Messenger *m, uint8_t *data)
3193{ 3177{
3194 Node_format relays[NUM_SAVED_TCP_RELAYS]; 3178 Node_format relays[NUM_SAVED_TCP_RELAYS];
3195 uint8_t *temp_data = data; 3179 uint8_t *temp_data = data;
3196 data = state_write_section_header(temp_data, MESSENGER_STATE_COOKIE_TYPE, 0, MESSENGER_STATE_TYPE_TCP_RELAY); 3180 data = state_write_section_header(temp_data, STATE_COOKIE_TYPE, 0, STATE_TYPE_TCP_RELAY);
3197 uint32_t num = copy_connected_tcp_relays(m->net_crypto, relays, NUM_SAVED_TCP_RELAYS); 3181 uint32_t num = copy_connected_tcp_relays(m->net_crypto, relays, NUM_SAVED_TCP_RELAYS);
3198 3182
3199 if (m->num_loaded_relays > 0) { 3183 if (m->num_loaded_relays > 0) {
@@ -3205,7 +3189,7 @@ static uint8_t *save_tcp_relays(const Messenger *m, uint8_t *data)
3205 3189
3206 if (l > 0) { 3190 if (l > 0) {
3207 const uint32_t len = l; 3191 const uint32_t len = l;
3208 data = state_write_section_header(temp_data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_TCP_RELAY); 3192 data = state_write_section_header(temp_data, STATE_COOKIE_TYPE, len, STATE_TYPE_TCP_RELAY);
3209 data += len; 3193 data += len;
3210 } 3194 }
3211 3195
@@ -3232,14 +3216,14 @@ static uint8_t *save_path_nodes(const Messenger *m, uint8_t *data)
3232{ 3216{
3233 Node_format nodes[NUM_SAVED_PATH_NODES]; 3217 Node_format nodes[NUM_SAVED_PATH_NODES];
3234 uint8_t *temp_data = data; 3218 uint8_t *temp_data = data;
3235 data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, 0, MESSENGER_STATE_TYPE_PATH_NODE); 3219 data = state_write_section_header(data, STATE_COOKIE_TYPE, 0, STATE_TYPE_PATH_NODE);
3236 memset(nodes, 0, sizeof(nodes)); 3220 memset(nodes, 0, sizeof(nodes));
3237 const unsigned int num = onion_backup_nodes(m->onion_c, nodes, NUM_SAVED_PATH_NODES); 3221 const unsigned int num = onion_backup_nodes(m->onion_c, nodes, NUM_SAVED_PATH_NODES);
3238 const int l = pack_nodes(data, NUM_SAVED_PATH_NODES * packed_node_size(net_family_tcp_ipv6), nodes, num); 3222 const int l = pack_nodes(data, NUM_SAVED_PATH_NODES * packed_node_size(net_family_tcp_ipv6), nodes, num);
3239 3223
3240 if (l > 0) { 3224 if (l > 0) {
3241 const uint32_t len = l; 3225 const uint32_t len = l;
3242 data = state_write_section_header(temp_data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_PATH_NODE); 3226 data = state_write_section_header(temp_data, STATE_COOKIE_TYPE, len, STATE_TYPE_PATH_NODE);
3243 data += len; 3227 data += len;
3244 } 3228 }
3245 3229
@@ -3261,77 +3245,32 @@ static State_Load_Status load_path_nodes(Messenger *m, const uint8_t *data, uint
3261 return STATE_LOAD_STATUS_CONTINUE; 3245 return STATE_LOAD_STATUS_CONTINUE;
3262} 3246}
3263 3247
3264// end state plugin
3265static uint32_t end_size(const Messenger *m)
3266{
3267 return 0;
3268}
3269
3270static uint8_t *save_end(const Messenger *m, uint8_t *data)
3271{
3272 return state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, 0, MESSENGER_STATE_TYPE_END);
3273}
3274
3275static State_Load_Status load_end(Messenger *m, const uint8_t *data, uint32_t length)
3276{
3277 if (length != 0) {
3278 return STATE_LOAD_STATUS_ERROR;
3279 }
3280
3281 return STATE_LOAD_STATUS_END;
3282}
3283
3284static void m_register_default_plugins(Messenger *m) 3248static void m_register_default_plugins(Messenger *m)
3285{ 3249{
3286 m_register_state_plugin(m, MESSENGER_STATE_TYPE_NOSPAMKEYS, nospam_keys_size, load_nospam_keys, save_nospam_keys); 3250 m_register_state_plugin(m, STATE_TYPE_NOSPAMKEYS, nospam_keys_size, load_nospam_keys, save_nospam_keys);
3287 m_register_state_plugin(m, MESSENGER_STATE_TYPE_DHT, m_dht_size, m_dht_load, save_dht); 3251 m_register_state_plugin(m, STATE_TYPE_DHT, m_dht_size, m_dht_load, save_dht);
3288 m_register_state_plugin(m, MESSENGER_STATE_TYPE_FRIENDS, saved_friendslist_size, friends_list_load, friends_list_save); 3252 m_register_state_plugin(m, STATE_TYPE_FRIENDS, saved_friendslist_size, friends_list_load, friends_list_save);
3289 m_register_state_plugin(m, MESSENGER_STATE_TYPE_NAME, name_size, load_name, save_name); 3253 m_register_state_plugin(m, STATE_TYPE_NAME, name_size, load_name, save_name);
3290 m_register_state_plugin(m, MESSENGER_STATE_TYPE_STATUSMESSAGE, status_message_size, load_status_message, 3254 m_register_state_plugin(m, STATE_TYPE_STATUSMESSAGE, status_message_size, load_status_message,
3291 save_status_message); 3255 save_status_message);
3292 m_register_state_plugin(m, MESSENGER_STATE_TYPE_STATUS, status_size, load_status, save_status); 3256 m_register_state_plugin(m, STATE_TYPE_STATUS, status_size, load_status, save_status);
3293 m_register_state_plugin(m, MESSENGER_STATE_TYPE_TCP_RELAY, tcp_relay_size, load_tcp_relays, save_tcp_relays); 3257 m_register_state_plugin(m, STATE_TYPE_TCP_RELAY, tcp_relay_size, load_tcp_relays, save_tcp_relays);
3294 m_register_state_plugin(m, MESSENGER_STATE_TYPE_PATH_NODE, path_node_size, load_path_nodes, save_path_nodes); 3258 m_register_state_plugin(m, STATE_TYPE_PATH_NODE, path_node_size, load_path_nodes, save_path_nodes);
3295 m_register_state_plugin(m, MESSENGER_STATE_TYPE_END, end_size, load_end, save_end);
3296} 3259}
3297 3260
3298static State_Load_Status messenger_load_state_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type) 3261bool messenger_load_state_section(Messenger *m, const uint8_t *data, uint32_t length, uint16_t type,
3262 State_Load_Status *status)
3299{ 3263{
3300 Messenger *m = (Messenger *)outer;
3301
3302 for (uint8_t i = 0; i < m->options.state_plugins_length; ++i) { 3264 for (uint8_t i = 0; i < m->options.state_plugins_length; ++i) {
3303 const Messenger_State_Plugin *const plugin = &m->options.state_plugins[i]; 3265 const Messenger_State_Plugin *const plugin = &m->options.state_plugins[i];
3304 3266
3305 if (plugin->type == type) { 3267 if (plugin->type == type) {
3306 return plugin->load(m, data, length); 3268 *status = plugin->load(m, data, length);
3269 return true;
3307 } 3270 }
3308 } 3271 }
3309 3272
3310 LOGGER_ERROR(m->log, "Load state: contains unrecognized part (len %u, type %u)\n", 3273 return false;
3311 length, type);
3312
3313 return STATE_LOAD_STATUS_CONTINUE;
3314}
3315
3316/* Load the messenger from data of size length. */
3317int messenger_load(Messenger *m, const uint8_t *data, uint32_t length)
3318{
3319 uint32_t data32[2];
3320 uint32_t cookie_len = sizeof(data32);
3321
3322 if (length < cookie_len) {
3323 return -1;
3324 }
3325
3326 memcpy(data32, data, sizeof(uint32_t));
3327 lendian_to_host32(data32 + 1, data + sizeof(uint32_t));
3328
3329 if (!data32[0] && (data32[1] == MESSENGER_STATE_COOKIE_GLOBAL)) {
3330 return state_load(m->log, messenger_load_state_callback, m, data + cookie_len,
3331 length - cookie_len, MESSENGER_STATE_COOKIE_TYPE);
3332 }
3333
3334 return -1;
3335} 3274}
3336 3275
3337/* Return the number of friends in the instance m. 3276/* Return the number of friends in the instance m.
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index 0d80bd0d..1651315e 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -62,20 +62,8 @@ typedef uint8_t *m_state_save_cb(const Messenger *m, uint8_t *data);
62// Returns if there were any erros during loading 62// Returns if there were any erros during loading
63typedef State_Load_Status m_state_load_cb(Messenger *m, const uint8_t *data, uint32_t length); 63typedef State_Load_Status m_state_load_cb(Messenger *m, const uint8_t *data, uint32_t length);
64 64
65typedef enum Messenger_State_Type {
66 MESSENGER_STATE_TYPE_NOSPAMKEYS = 1,
67 MESSENGER_STATE_TYPE_DHT = 2,
68 MESSENGER_STATE_TYPE_FRIENDS = 3,
69 MESSENGER_STATE_TYPE_NAME = 4,
70 MESSENGER_STATE_TYPE_STATUSMESSAGE = 5,
71 MESSENGER_STATE_TYPE_STATUS = 6,
72 MESSENGER_STATE_TYPE_TCP_RELAY = 10,
73 MESSENGER_STATE_TYPE_PATH_NODE = 11,
74 MESSENGER_STATE_TYPE_END = 255,
75} Messenger_State_Type;
76
77typedef struct Messenger_State_Plugin { 65typedef struct Messenger_State_Plugin {
78 Messenger_State_Type type; 66 State_Type type;
79 m_state_size_cb *size; 67 m_state_size_cb *size;
80 m_state_save_cb *save; 68 m_state_save_cb *save;
81 m_state_load_cb *load; 69 m_state_load_cb *load;
@@ -797,17 +785,22 @@ uint32_t messenger_run_interval(const Messenger *m);
797 * returns true on success 785 * returns true on success
798 * returns false on error 786 * returns false on error
799 */ 787 */
800bool m_register_state_plugin(Messenger *m, Messenger_State_Type type, m_state_size_cb size_callback, 788bool m_register_state_plugin(Messenger *m, State_Type type, m_state_size_cb size_callback,
801 m_state_load_cb load_callback, m_state_save_cb save_callback); 789 m_state_load_cb load_callback, m_state_save_cb save_callback);
802 790
803/* return size of the messenger data (for saving). */ 791/* return size of the messenger data (for saving). */
804uint32_t messenger_size(const Messenger *m); 792uint32_t messenger_size(const Messenger *m);
805 793
806/* Save the messenger in data (must be allocated memory of size Messenger_size()) */ 794/* Save the messenger in data (must be allocated memory of size at least Messenger_size()) */
807void messenger_save(const Messenger *m, uint8_t *data); 795uint8_t *messenger_save(const Messenger *m, uint8_t *data);
808 796
809/* Load the messenger from data of size length. */ 797/* Load a state section.
810int messenger_load(Messenger *m, const uint8_t *data, uint32_t length); 798 *
799 * @param status Result of loading section is stored here if the section is handled.
800 * @return true iff section handled.
801 */
802bool messenger_load_state_section(Messenger *m, const uint8_t *data, uint32_t length, uint16_t type,
803 State_Load_Status *status);
811 804
812/* Return the number of friends in the instance m. 805/* Return the number of friends in the instance m.
813 * You should use this to determine how much memory to allocate 806 * You should use this to determine how much memory to allocate
diff --git a/toxcore/group.c b/toxcore/group.c
index 5feb483b..ee9548a1 100644
--- a/toxcore/group.c
+++ b/toxcore/group.c
@@ -2875,6 +2875,22 @@ void send_name_all_groups(Group_Chats *g_c)
2875 } 2875 }
2876} 2876}
2877 2877
2878uint32_t conferences_size(const Group_Chats *g_c)
2879{
2880 return 0;
2881}
2882
2883uint8_t *conferences_save(const Group_Chats *g_c, uint8_t *data)
2884{
2885 return data;
2886}
2887
2888bool conferences_load_state_section(Group_Chats *g_c, const uint8_t *data, uint32_t length, uint16_t type,
2889 State_Load_Status *status)
2890{
2891 return false;
2892}
2893
2878/* Create new groupchat instance. */ 2894/* Create new groupchat instance. */
2879Group_Chats *new_groupchats(Mono_Time *mono_time, Messenger *m) 2895Group_Chats *new_groupchats(Mono_Time *mono_time, Messenger *m)
2880{ 2896{
diff --git a/toxcore/group.h b/toxcore/group.h
index 7acd4637..8673abdb 100644
--- a/toxcore/group.h
+++ b/toxcore/group.h
@@ -448,6 +448,21 @@ int callback_groupchat_peer_delete(Group_Chats *g_c, uint32_t groupnumber, peer_
448 */ 448 */
449int callback_groupchat_delete(Group_Chats *g_c, uint32_t groupnumber, group_on_delete_cb *function); 449int callback_groupchat_delete(Group_Chats *g_c, uint32_t groupnumber, group_on_delete_cb *function);
450 450
451/* Return size of the conferences data (for saving). */
452uint32_t conferences_size(const Group_Chats *g_c);
453
454/* Save the conferences in data (must be allocated memory of size at least conferences_size()) */
455uint8_t *conferences_save(const Group_Chats *g_c, uint8_t *data);
456
457/**
458 * Load a section.
459 *
460 * @param status Result of loading section is stored here if the section is handled.
461 * @return true iff section handled.
462 */
463bool conferences_load_state_section(Group_Chats *g_c, const uint8_t *data, uint32_t length, uint16_t type,
464 State_Load_Status *status);
465
451/* Create new groupchat instance. */ 466/* Create new groupchat instance. */
452Group_Chats *new_groupchats(Mono_Time *mono_time, Messenger *m); 467Group_Chats *new_groupchats(Mono_Time *mono_time, Messenger *m);
453 468
diff --git a/toxcore/state.c b/toxcore/state.c
index 29b4af88..919c2e8c 100644
--- a/toxcore/state.c
+++ b/toxcore/state.c
@@ -16,10 +16,10 @@ int state_load(const Logger *log, state_load_cb *state_load_callback, void *oute
16 16
17 while (length >= size_head) { 17 while (length >= size_head) {
18 uint32_t length_sub; 18 uint32_t length_sub;
19 lendian_to_host32(&length_sub, data); 19 lendian_bytes_to_host32(&length_sub, data);
20 20
21 uint32_t cookie_type; 21 uint32_t cookie_type;
22 lendian_to_host32(&cookie_type, data + sizeof(uint32_t)); 22 lendian_bytes_to_host32(&cookie_type, data + sizeof(uint32_t));
23 23
24 data += size_head; 24 data += size_head;
25 length -= size_head; 25 length -= size_head;
@@ -63,9 +63,9 @@ int state_load(const Logger *log, state_load_cb *state_load_callback, void *oute
63 63
64uint8_t *state_write_section_header(uint8_t *data, uint16_t cookie_type, uint32_t len, uint32_t section_type) 64uint8_t *state_write_section_header(uint8_t *data, uint16_t cookie_type, uint32_t len, uint32_t section_type)
65{ 65{
66 host_to_lendian32(data, len); 66 host_to_lendian_bytes32(data, len);
67 data += sizeof(uint32_t); 67 data += sizeof(uint32_t);
68 host_to_lendian32(data, (host_tolendian16(cookie_type) << 16) | host_tolendian16(section_type)); 68 host_to_lendian_bytes32(data, (host_to_lendian16(cookie_type) << 16) | host_to_lendian16(section_type));
69 data += sizeof(uint32_t); 69 data += sizeof(uint32_t);
70 return data; 70 return data;
71} 71}
@@ -79,12 +79,12 @@ uint16_t lendian_to_host16(uint16_t lendian)
79#endif 79#endif
80} 80}
81 81
82uint16_t host_tolendian16(uint16_t host) 82uint16_t host_to_lendian16(uint16_t host)
83{ 83{
84 return lendian_to_host16(host); 84 return lendian_to_host16(host);
85} 85}
86 86
87void host_to_lendian32(uint8_t *dest, uint32_t num) 87void host_to_lendian_bytes32(uint8_t *dest, uint32_t num)
88{ 88{
89#ifdef WORDS_BIGENDIAN 89#ifdef WORDS_BIGENDIAN
90 num = ((num << 8) & 0xFF00FF00) | ((num >> 8) & 0xFF00FF); 90 num = ((num << 8) & 0xFF00FF00) | ((num >> 8) & 0xFF00FF);
@@ -93,7 +93,7 @@ void host_to_lendian32(uint8_t *dest, uint32_t num)
93 memcpy(dest, &num, sizeof(uint32_t)); 93 memcpy(dest, &num, sizeof(uint32_t));
94} 94}
95 95
96void lendian_to_host32(uint32_t *dest, const uint8_t *lendian) 96void lendian_bytes_to_host32(uint32_t *dest, const uint8_t *lendian)
97{ 97{
98 uint32_t d; 98 uint32_t d;
99 memcpy(&d, lendian, sizeof(uint32_t)); 99 memcpy(&d, lendian, sizeof(uint32_t));
@@ -103,3 +103,21 @@ void lendian_to_host32(uint32_t *dest, const uint8_t *lendian)
103#endif 103#endif
104 *dest = d; 104 *dest = d;
105} 105}
106
107void host_to_lendian_bytes16(uint8_t *dest, uint16_t num)
108{
109#ifdef WORDS_BIGENDIAN
110 num = (num << 8) | (num >> 8);
111#endif
112 memcpy(dest, &num, sizeof(uint16_t));
113}
114
115void lendian_bytes_to_host16(uint16_t *dest, const uint8_t *lendian)
116{
117 uint16_t d;
118 memcpy(&d, lendian, sizeof(uint16_t));
119#ifdef WORDS_BIGENDIAN
120 d = (d << 8) | (d >> 8);
121#endif
122 *dest = d;
123}
diff --git a/toxcore/state.h b/toxcore/state.h
index 2d1f62c3..872b1e9d 100644
--- a/toxcore/state.h
+++ b/toxcore/state.h
@@ -18,6 +18,22 @@
18extern "C" { 18extern "C" {
19#endif 19#endif
20 20
21#define STATE_COOKIE_GLOBAL 0x15ed1b1f
22
23#define STATE_COOKIE_TYPE 0x01ce
24
25typedef enum State_Type {
26 STATE_TYPE_NOSPAMKEYS = 1,
27 STATE_TYPE_DHT = 2,
28 STATE_TYPE_FRIENDS = 3,
29 STATE_TYPE_NAME = 4,
30 STATE_TYPE_STATUSMESSAGE = 5,
31 STATE_TYPE_STATUS = 6,
32 STATE_TYPE_TCP_RELAY = 10,
33 STATE_TYPE_PATH_NODE = 11,
34 STATE_TYPE_END = 255,
35} State_Type;
36
21// Returned by the state_load_cb to instruct the loader on what to do next. 37// Returned by the state_load_cb to instruct the loader on what to do next.
22typedef enum State_Load_Status { 38typedef enum State_Load_Status {
23 // Continue loading state data sections. 39 // Continue loading state data sections.
@@ -39,10 +55,13 @@ uint8_t *state_write_section_header(uint8_t *data, uint16_t cookie_type, uint32_
39// Utilities for state data serialisation. 55// Utilities for state data serialisation.
40 56
41uint16_t lendian_to_host16(uint16_t lendian); 57uint16_t lendian_to_host16(uint16_t lendian);
42uint16_t host_tolendian16(uint16_t host); 58uint16_t host_to_lendian16(uint16_t host);
59
60void host_to_lendian_bytes32(uint8_t *dest, uint32_t num);
61void lendian_bytes_to_host32(uint32_t *dest, const uint8_t *lendian);
43 62
44void host_to_lendian32(uint8_t *dest, uint32_t num); 63void host_to_lendian_bytes16(uint8_t *dest, uint16_t num);
45void lendian_to_host32(uint32_t *dest, const uint8_t *lendian); 64void lendian_bytes_to_host16(uint16_t *dest, const uint8_t *lendian);
46 65
47#ifdef __cplusplus 66#ifdef __cplusplus
48} // extern "C" 67} // extern "C"
diff --git a/toxcore/tox.c b/toxcore/tox.c
index e679a168..629cc1c5 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -328,6 +328,51 @@ bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch)
328 return TOX_VERSION_IS_API_COMPATIBLE(major, minor, patch); 328 return TOX_VERSION_IS_API_COMPATIBLE(major, minor, patch);
329} 329}
330 330
331static State_Load_Status state_load_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type)
332{
333 Tox *tox = (Tox *)outer;
334 State_Load_Status status = STATE_LOAD_STATUS_CONTINUE;
335
336 if (messenger_load_state_section(tox->m, data, length, type, &status)
337 || conferences_load_state_section(tox->m->conferences_object, data, length, type, &status)) {
338 return status;
339 }
340
341 if (type == STATE_TYPE_END) {
342 if (length != 0) {
343 return STATE_LOAD_STATUS_ERROR;
344 }
345
346 return STATE_LOAD_STATUS_END;
347 }
348
349 LOGGER_ERROR(tox->m->log, "Load state: contains unrecognized part (len %u, type %u)\n",
350 length, type);
351
352 return STATE_LOAD_STATUS_CONTINUE;
353}
354
355/* Load tox from data of size length. */
356static int tox_load(Tox *tox, const uint8_t *data, uint32_t length)
357{
358 uint32_t data32[2];
359 uint32_t cookie_len = sizeof(data32);
360
361 if (length < cookie_len) {
362 return -1;
363 }
364
365 memcpy(data32, data, sizeof(uint32_t));
366 lendian_bytes_to_host32(data32 + 1, data + sizeof(uint32_t));
367
368 if (data32[0] != 0 || data32[1] != STATE_COOKIE_GLOBAL) {
369 return -1;
370 }
371
372 return state_load(tox->m->log, state_load_callback, tox, data + cookie_len,
373 length - cookie_len, STATE_COOKIE_TYPE);
374}
375
331 376
332Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error) 377Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
333{ 378{
@@ -488,7 +533,7 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
488 } 533 }
489 534
490 if (load_savedata_tox 535 if (load_savedata_tox
491 && messenger_load(m, tox_options_get_savedata_data(opts), tox_options_get_savedata_length(opts)) == -1) { 536 && tox_load(tox, tox_options_get_savedata_data(opts), tox_options_get_savedata_length(opts)) == -1) {
492 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT); 537 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
493 } else if (load_savedata_sk) { 538 } else if (load_savedata_sk) {
494 load_secret_key(m->net_crypto, tox_options_get_savedata_data(opts)); 539 load_secret_key(m->net_crypto, tox_options_get_savedata_data(opts));
@@ -537,18 +582,45 @@ void tox_kill(Tox *tox)
537 free(tox); 582 free(tox);
538} 583}
539 584
585static uint32_t end_size(void)
586{
587 return 2 * sizeof(uint32_t);
588}
589
590static void end_save(uint8_t *data)
591{
592 state_write_section_header(data, STATE_COOKIE_TYPE, 0, STATE_TYPE_END);
593}
594
540size_t tox_get_savedata_size(const Tox *tox) 595size_t tox_get_savedata_size(const Tox *tox)
541{ 596{
542 const Messenger *m = tox->m; 597 const Messenger *m = tox->m;
543 return messenger_size(m); 598 return 2 * sizeof(uint32_t)
599 + messenger_size(m)
600 + conferences_size(m->conferences_object)
601 + end_size();
544} 602}
545 603
546void tox_get_savedata(const Tox *tox, uint8_t *savedata) 604void tox_get_savedata(const Tox *tox, uint8_t *savedata)
547{ 605{
548 if (savedata) { 606 if (savedata == nullptr) {
549 const Messenger *m = tox->m; 607 return;
550 messenger_save(m, savedata);
551 } 608 }
609
610 memset(savedata, 0, tox_get_savedata_size(tox));
611
612 const uint32_t size32 = sizeof(uint32_t);
613
614 // write cookie
615 memset(savedata, 0, size32);
616 savedata += size32;
617 host_to_lendian_bytes32(savedata, STATE_COOKIE_GLOBAL);
618 savedata += size32;
619
620 const Messenger *m = tox->m;
621 savedata = messenger_save(m, savedata);
622 savedata = conferences_save(m->conferences_object, savedata);
623 end_save(savedata);
552} 624}
553 625
554bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key, Tox_Err_Bootstrap *error) 626bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key, Tox_Err_Bootstrap *error)