summaryrefslogtreecommitdiff
path: root/toxcore/Messenger.c
diff options
context:
space:
mode:
authoriphydf <iphydf@users.noreply.github.com>2018-07-09 13:25:55 +0000
committerendoffile78 <endoffile78@yahoo.com>2018-09-07 12:22:10 -0500
commit08cc4184a167759e7dd7dcd334003d6257241a45 (patch)
treeb4d8fa66f25eb75a40f80f9e62c4abb4418a3cdf /toxcore/Messenger.c
parent1cd183691735126aa3c916c3e2417e2edd104d1d (diff)
Add messenger state plugin system.
This is for modules like groups to hook into to have their own state management in the `tox_savedata` format.
Diffstat (limited to 'toxcore/Messenger.c')
-rw-r--r--toxcore/Messenger.c537
1 files changed, 341 insertions, 196 deletions
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index cd1cdf2f..fa019936 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -41,6 +41,7 @@
41 41
42static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data, 42static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data,
43 uint32_t length, uint8_t congestion_control); 43 uint32_t length, uint8_t congestion_control);
44static void m_register_default_plugins(Messenger *m);
44 45
45// friend_not_valid determines if the friendnumber passed is valid in the Messenger object 46// friend_not_valid determines if the friendnumber passed is valid in the Messenger object
46static uint8_t friend_not_valid(const Messenger *m, int32_t friendnumber) 47static uint8_t friend_not_valid(const Messenger *m, int32_t friendnumber)
@@ -2083,6 +2084,8 @@ Messenger *new_messenger(Mono_Time *mono_time, Messenger_Options *options, unsig
2083 2084
2084 m->lastdump = 0; 2085 m->lastdump = 0;
2085 2086
2087 m_register_default_plugins(m);
2088
2086 if (error) { 2089 if (error) {
2087 *error = MESSENGER_ERROR_NONE; 2090 *error = MESSENGER_ERROR_NONE;
2088 } 2091 }
@@ -2118,6 +2121,8 @@ void kill_messenger(Messenger *m)
2118 logger_kill(m->log); 2121 logger_kill(m->log);
2119 free(m->friendlist); 2122 free(m->friendlist);
2120 friendreq_kill(m->fr); 2123 friendreq_kill(m->fr);
2124
2125 free(m->options.state_plugins);
2121 free(m); 2126 free(m);
2122} 2127}
2123 2128
@@ -2737,15 +2742,6 @@ void do_messenger(Messenger *m, void *userdata)
2737#define MESSENGER_STATE_COOKIE_GLOBAL 0x15ed1b1f 2742#define MESSENGER_STATE_COOKIE_GLOBAL 0x15ed1b1f
2738 2743
2739#define MESSENGER_STATE_COOKIE_TYPE 0x01ce 2744#define MESSENGER_STATE_COOKIE_TYPE 0x01ce
2740#define MESSENGER_STATE_TYPE_NOSPAMKEYS 1
2741#define MESSENGER_STATE_TYPE_DHT 2
2742#define MESSENGER_STATE_TYPE_FRIENDS 3
2743#define MESSENGER_STATE_TYPE_NAME 4
2744#define MESSENGER_STATE_TYPE_STATUSMESSAGE 5
2745#define MESSENGER_STATE_TYPE_STATUS 6
2746#define MESSENGER_STATE_TYPE_TCP_RELAY 10
2747#define MESSENGER_STATE_TYPE_PATH_NODE 11
2748#define MESSENGER_STATE_TYPE_END 255
2749 2745
2750#define SAVED_FRIEND_REQUEST_SIZE 1024 2746#define SAVED_FRIEND_REQUEST_SIZE 1024
2751#define NUM_SAVED_PATH_NODES 8 2747#define NUM_SAVED_PATH_NODES 8
@@ -2794,11 +2790,6 @@ static uint32_t friend_size(void)
2794 return data; 2790 return data;
2795} 2791}
2796 2792
2797static uint32_t saved_friendslist_size(const Messenger *m)
2798{
2799 return count_friendlist(m) * friend_size();
2800}
2801
2802static uint8_t *friend_save(const struct Saved_Friend *temp, uint8_t *data) 2793static uint8_t *friend_save(const struct Saved_Friend *temp, uint8_t *data)
2803{ 2794{
2804#define VALUE_MEMBER(name) do { \ 2795#define VALUE_MEMBER(name) do { \
@@ -2833,13 +2824,202 @@ static uint8_t *friend_save(const struct Saved_Friend *temp, uint8_t *data)
2833 return data; 2824 return data;
2834} 2825}
2835 2826
2836static uint32_t friends_list_save(const Messenger *m, uint8_t *data) 2827
2828static const uint8_t *friend_load(struct Saved_Friend *temp, const uint8_t *data)
2837{ 2829{
2838 uint32_t i; 2830#define VALUE_MEMBER(name) do { \
2831 memcpy(&temp->name, data, sizeof(temp->name)); \
2832 data += sizeof(temp->name); \
2833} while (0)
2834
2835#define ARRAY_MEMBER(name) do { \
2836 memcpy(temp->name, data, sizeof(temp->name)); \
2837 data += sizeof(temp->name); \
2838} while (0)
2839
2840 // Exactly the same in friend_load, friend_save, and friend_size
2841 VALUE_MEMBER(status);
2842 ARRAY_MEMBER(real_pk);
2843 ARRAY_MEMBER(info);
2844 ++data; // padding
2845 VALUE_MEMBER(info_size);
2846 ARRAY_MEMBER(name);
2847 VALUE_MEMBER(name_length);
2848 ARRAY_MEMBER(statusmessage);
2849 ++data; // padding
2850 VALUE_MEMBER(statusmessage_length);
2851 VALUE_MEMBER(userstatus);
2852 data += 3; // padding
2853 VALUE_MEMBER(friendrequest_nospam);
2854 VALUE_MEMBER(last_seen_time);
2855
2856#undef VALUE_MEMBER
2857#undef ARRAY_MEMBER
2858
2859 return data;
2860}
2861
2862
2863static uint32_t m_state_plugins_size(const Messenger *m)
2864{
2865 const uint32_t size32 = sizeof(uint32_t);
2866 const uint32_t sizesubhead = size32 * 2;
2867
2868 uint32_t size = 0;
2869
2870 for (const Messenger_State_Plugin *plugin = m->options.state_plugins;
2871 plugin != m->options.state_plugins + m->options.state_plugins_length;
2872 ++plugin) {
2873 size += sizesubhead + plugin->size(m);
2874 }
2875
2876 return size;
2877}
2878
2879/*
2880 * Registers a state plugin with the messenger
2881 * returns true on success
2882 * returns false on failure
2883 */
2884bool m_register_state_plugin(Messenger *m, Messenger_State_Type type, m_state_size_cb size_callback,
2885 m_state_load_cb load_callback,
2886 m_state_save_cb save_callback)
2887{
2888 Messenger_State_Plugin *temp = (Messenger_State_Plugin *)realloc(m->options.state_plugins,
2889 sizeof(Messenger_State_Plugin) * (m->options.state_plugins_length + 1));
2890
2891 if (!temp) {
2892 return false;
2893 }
2894
2895 m->options.state_plugins = temp;
2896 ++m->options.state_plugins_length;
2897
2898 const uint8_t index = m->options.state_plugins_length - 1;
2899 m->options.state_plugins[index].type = type;
2900 m->options.state_plugins[index].size = size_callback;
2901 m->options.state_plugins[index].load = load_callback;
2902 m->options.state_plugins[index].save = save_callback;
2903
2904 return true;
2905}
2906
2907static uint32_t m_plugin_size(const Messenger *m, Messenger_State_Type type)
2908{
2909 for (uint8_t i = 0; i < m->options.state_plugins_length; ++i) {
2910 const Messenger_State_Plugin plugin = m->options.state_plugins[i];
2911
2912 if (plugin.type == type) {
2913 return plugin.size(m);
2914 }
2915 }
2916
2917 LOGGER_ERROR(m->log, "Unknown type encountered: %u", type);
2918
2919 return UINT32_MAX;
2920}
2921
2922/* return size of the messenger data (for saving) */
2923uint32_t messenger_size(const Messenger *m)
2924{
2925 const uint32_t size32 = sizeof(uint32_t);
2926 const uint32_t sizesubhead = size32 * 2;
2927 return size32 * 2 // global cookie
2928 + m_state_plugins_size(m)
2929 + sizesubhead;
2930}
2931
2932/* Save the messenger in data of size Messenger_size(). */
2933void messenger_save(const Messenger *m, uint8_t *data)
2934{
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) {
2946 const Messenger_State_Plugin plugin = m->options.state_plugins[i];
2947 data = plugin.save(m, data);
2948 }
2949}
2950
2951// nospam state plugin
2952static uint32_t nospam_keys_size(const Messenger *m)
2953{
2954 return sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE;
2955}
2956
2957static State_Load_Status load_nospam_keys(Messenger *m, const uint8_t *data, uint32_t length)
2958{
2959 if (length != m_plugin_size(m, MESSENGER_STATE_TYPE_NOSPAMKEYS)) {
2960 return STATE_LOAD_STATUS_ERROR;
2961 }
2962
2963 uint32_t nospam;
2964 lendian_to_host32(&nospam, data);
2965 set_nospam(m->fr, nospam);
2966 load_secret_key(m->net_crypto, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE);
2967
2968 if (public_key_cmp(data + sizeof(uint32_t), nc_get_self_public_key(m->net_crypto)) != 0) {
2969 return STATE_LOAD_STATUS_ERROR;
2970 }
2971
2972 return STATE_LOAD_STATUS_CONTINUE;
2973}
2974
2975static uint8_t *save_nospam_keys(const Messenger *m, uint8_t *data)
2976{
2977 const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_NOSPAMKEYS);
2978 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);
2980 uint32_t nospam = get_nospam(m->fr);
2981 host_to_lendian32(data, nospam);
2982 save_keys(m->net_crypto, data + sizeof(uint32_t));
2983 data += len;
2984 return data;
2985}
2986
2987// DHT state plugin
2988static uint32_t m_dht_size(const Messenger *m)
2989{
2990 return dht_size(m->dht);
2991}
2992
2993static uint8_t *save_dht(const Messenger *m, uint8_t *data)
2994{
2995 const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_DHT);
2996 data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_DHT);
2997 dht_save(m->dht, data);
2998 data += len;
2999 return data;
3000}
3001
3002static State_Load_Status m_dht_load(Messenger *m, const uint8_t *data, uint32_t length)
3003{
3004 dht_load(m->dht, data, length); // TODO(endoffile78): Should we throw an error if dht_load fails?
3005 return STATE_LOAD_STATUS_CONTINUE;
3006}
3007
3008// friendlist state plugin
3009static uint32_t saved_friendslist_size(const Messenger *m)
3010{
3011 return count_friendlist(m) * friend_size();
3012}
3013
3014static uint8_t *friends_list_save(const Messenger *m, uint8_t *data)
3015{
3016 const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_FRIENDS);
3017 data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_FRIENDS);
3018
2839 uint32_t num = 0; 3019 uint32_t num = 0;
2840 uint8_t *cur_data = data; 3020 uint8_t *cur_data = data;
2841 3021
2842 for (i = 0; i < m->numfriends; ++i) { 3022 for (uint32_t i = 0; i < m->numfriends; ++i) {
2843 if (m->friendlist[i].status > 0) { 3023 if (m->friendlist[i].status > 0) {
2844 struct Saved_Friend temp = { 0 }; 3024 struct Saved_Friend temp = { 0 };
2845 temp.status = m->friendlist[i].status; 3025 temp.status = m->friendlist[i].status;
@@ -2878,47 +3058,15 @@ static uint32_t friends_list_save(const Messenger *m, uint8_t *data)
2878 } 3058 }
2879 3059
2880 assert(cur_data - data == num * friend_size()); 3060 assert(cur_data - data == num * friend_size());
2881 return cur_data - data; 3061 data += len;
2882}
2883
2884static const uint8_t *friend_load(struct Saved_Friend *temp, const uint8_t *data)
2885{
2886#define VALUE_MEMBER(name) do { \
2887 memcpy(&temp->name, data, sizeof(temp->name)); \
2888 data += sizeof(temp->name); \
2889} while (0)
2890
2891#define ARRAY_MEMBER(name) do { \
2892 memcpy(temp->name, data, sizeof(temp->name)); \
2893 data += sizeof(temp->name); \
2894} while (0)
2895
2896 // Exactly the same in friend_load, friend_save, and friend_size
2897 VALUE_MEMBER(status);
2898 ARRAY_MEMBER(real_pk);
2899 ARRAY_MEMBER(info);
2900 ++data; // padding
2901 VALUE_MEMBER(info_size);
2902 ARRAY_MEMBER(name);
2903 VALUE_MEMBER(name_length);
2904 ARRAY_MEMBER(statusmessage);
2905 ++data; // padding
2906 VALUE_MEMBER(statusmessage_length);
2907 VALUE_MEMBER(userstatus);
2908 data += 3; // padding
2909 VALUE_MEMBER(friendrequest_nospam);
2910 VALUE_MEMBER(last_seen_time);
2911
2912#undef VALUE_MEMBER
2913#undef ARRAY_MEMBER
2914 3062
2915 return data; 3063 return data;
2916} 3064}
2917 3065
2918static int friends_list_load(Messenger *m, const uint8_t *data, uint32_t length) 3066static State_Load_Status friends_list_load(Messenger *m, const uint8_t *data, uint32_t length)
2919{ 3067{
2920 if (length % friend_size() != 0) { 3068 if (length % friend_size() != 0) {
2921 return -1; 3069 return STATE_LOAD_STATUS_ERROR; // TODO(endoffile78): error or continue?
2922 } 3070 }
2923 3071
2924 uint32_t num = length / friend_size(); 3072 uint32_t num = length / friend_size();
@@ -2959,205 +3107,202 @@ static int friends_list_load(Messenger *m, const uint8_t *data, uint32_t length)
2959 } 3107 }
2960 } 3108 }
2961 3109
2962 return num; 3110 return STATE_LOAD_STATUS_CONTINUE;
2963} 3111}
2964 3112
2965/* return size of the messenger data (for saving) */ 3113// name state plugin
2966uint32_t messenger_size(const Messenger *m) 3114static uint32_t name_size(const Messenger *m)
2967{ 3115{
2968 uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2; 3116 return m->name_length;
2969 return size32 * 2 // global cookie
2970 + sizesubhead + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE
2971 + sizesubhead + dht_size(m->dht) // DHT
2972 + sizesubhead + saved_friendslist_size(m) // Friendlist itself.
2973 + sizesubhead + m->name_length // Own nickname.
2974 + sizesubhead + m->statusmessage_length // status message
2975 + sizesubhead + 1 // status
2976 + sizesubhead + NUM_SAVED_TCP_RELAYS * packed_node_size(net_family_tcp_ipv6) // TCP relays
2977 + sizesubhead + NUM_SAVED_PATH_NODES * packed_node_size(net_family_tcp_ipv6) // saved path nodes
2978 + sizesubhead;
2979} 3117}
2980 3118
2981static uint8_t *messenger_save_subheader(uint8_t *data, uint32_t len, uint16_t type) 3119static uint8_t *save_name(const Messenger *m, uint8_t *data)
2982{ 3120{
2983 host_to_lendian32(data, len); 3121 const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_NAME);
2984 data += sizeof(uint32_t); 3122 data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_NAME);
2985 host_to_lendian32(data, (host_tolendian16(MESSENGER_STATE_COOKIE_TYPE) << 16) | host_tolendian16(type)); 3123 memcpy(data, m->name, len);
2986 data += sizeof(uint32_t); 3124 data += len;
2987 return data; 3125 return data;
2988} 3126}
2989 3127
2990/* Save the messenger in data of size Messenger_size(). */ 3128static State_Load_Status load_name(Messenger *m, const uint8_t *data, uint32_t length)
2991void messenger_save(const Messenger *m, uint8_t *data)
2992{ 3129{
2993 memset(data, 0, messenger_size(m)); 3130 if (length > 0 && length <= MAX_NAME_LENGTH) {
3131 setname(m, data, length);
3132 }
2994 3133
2995 uint32_t len; 3134 return STATE_LOAD_STATUS_CONTINUE;
2996 uint16_t type; 3135}
2997 uint32_t size32 = sizeof(uint32_t);
2998 3136
2999 memset(data, 0, size32); 3137// status message state plugin
3000 data += size32; 3138static uint32_t status_message_size(const Messenger *m)
3001 host_to_lendian32(data, MESSENGER_STATE_COOKIE_GLOBAL); 3139{
3002 data += size32; 3140 return m->statusmessage_length;
3141}
3003 3142
3004 assert(sizeof(get_nospam(m->fr)) == sizeof(uint32_t)); 3143static uint8_t *save_status_message(const Messenger *m, uint8_t *data)
3005 len = size32 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE; 3144{
3006 type = MESSENGER_STATE_TYPE_NOSPAMKEYS; 3145 const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_STATUSMESSAGE);
3007 data = messenger_save_subheader(data, len, type); 3146 data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_STATUSMESSAGE);
3008 *(uint32_t *)data = get_nospam(m->fr); 3147 memcpy(data, m->statusmessage, len);
3009 save_keys(m->net_crypto, data + size32);
3010 data += len; 3148 data += len;
3149 return data;
3150}
3011 3151
3012 len = saved_friendslist_size(m); 3152static State_Load_Status load_status_message(Messenger *m, const uint8_t *data, uint32_t length)
3013 type = MESSENGER_STATE_TYPE_FRIENDS; 3153{
3014 data = messenger_save_subheader(data, len, type); 3154 if (length > 0 && length <= MAX_STATUSMESSAGE_LENGTH) {
3015 friends_list_save(m, data); 3155 m_set_statusmessage(m, data, length);
3016 data += len; 3156 }
3017 3157
3018 len = m->name_length; 3158 return STATE_LOAD_STATUS_CONTINUE;
3019 type = MESSENGER_STATE_TYPE_NAME; 3159}
3020 data = messenger_save_subheader(data, len, type);
3021 memcpy(data, m->name, len);
3022 data += len;
3023 3160
3024 len = m->statusmessage_length; 3161// status state plugin
3025 type = MESSENGER_STATE_TYPE_STATUSMESSAGE; 3162static uint32_t status_size(const Messenger *m)
3026 data = messenger_save_subheader(data, len, type); 3163{
3027 memcpy(data, m->statusmessage, len); 3164 return 1;
3028 data += len; 3165}
3029 3166
3030 len = 1; 3167static uint8_t *save_status(const Messenger *m, uint8_t *data)
3031 type = MESSENGER_STATE_TYPE_STATUS; 3168{
3032 data = messenger_save_subheader(data, len, type); 3169 const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_STATUS);
3170 data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_STATUS);
3033 *data = m->userstatus; 3171 *data = m->userstatus;
3034 data += len; 3172 data += len;
3173 return data;
3174}
3035 3175
3036 len = dht_size(m->dht); 3176static State_Load_Status load_status(Messenger *m, const uint8_t *data, uint32_t length)
3037 type = MESSENGER_STATE_TYPE_DHT; 3177{
3038 data = messenger_save_subheader(data, len, type); 3178 if (length == 1) {
3039 dht_save(m->dht, data); 3179 m_set_userstatus(m, *data);
3040 data += len; 3180 }
3041 3181
3182 return STATE_LOAD_STATUS_CONTINUE;
3183}
3184
3185// TCP Relay state plugin
3186static uint32_t tcp_relay_size(const Messenger *m)
3187{
3188 return NUM_SAVED_TCP_RELAYS * packed_node_size(net_family_tcp_ipv6);
3189}
3190
3191static uint8_t *save_tcp_relays(const Messenger *m, uint8_t *data)
3192{
3042 Node_format relays[NUM_SAVED_TCP_RELAYS]; 3193 Node_format relays[NUM_SAVED_TCP_RELAYS];
3043 type = MESSENGER_STATE_TYPE_TCP_RELAY;
3044 uint8_t *temp_data = data; 3194 uint8_t *temp_data = data;
3045 data = messenger_save_subheader(temp_data, 0, type); 3195 data = state_write_section_header(temp_data, MESSENGER_STATE_COOKIE_TYPE, 0, MESSENGER_STATE_TYPE_TCP_RELAY);
3046 unsigned int num = copy_connected_tcp_relays(m->net_crypto, relays, NUM_SAVED_TCP_RELAYS); 3196 unsigned int num = copy_connected_tcp_relays(m->net_crypto, relays, NUM_SAVED_TCP_RELAYS);
3047 int l = pack_nodes(data, NUM_SAVED_TCP_RELAYS * packed_node_size(net_family_tcp_ipv6), relays, num); 3197 int l = pack_nodes(data, NUM_SAVED_TCP_RELAYS * packed_node_size(net_family_tcp_ipv6), relays, num);
3048 3198
3049 if (l > 0) { 3199 if (l > 0) {
3050 len = l; 3200 const uint32_t len = l;
3051 data = messenger_save_subheader(temp_data, len, type); 3201 data = state_write_section_header(temp_data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_TCP_RELAY);
3052 data += len; 3202 data += len;
3053 } 3203 }
3054 3204
3055 Node_format nodes[NUM_SAVED_PATH_NODES]; 3205 return data;
3056 type = MESSENGER_STATE_TYPE_PATH_NODE; 3206}
3057 temp_data = data;
3058 data = messenger_save_subheader(data, 0, type);
3059 memset(nodes, 0, sizeof(nodes));
3060 num = onion_backup_nodes(m->onion_c, nodes, NUM_SAVED_PATH_NODES);
3061 l = pack_nodes(data, NUM_SAVED_PATH_NODES * packed_node_size(net_family_tcp_ipv6), nodes, num);
3062 3207
3063 if (l > 0) { 3208static State_Load_Status load_tcp_replays(Messenger *m, const uint8_t *data, uint32_t length)
3064 len = l; 3209{
3065 data = messenger_save_subheader(temp_data, len, type); 3210 if (length != 0) {
3066 data += len; 3211 unpack_nodes(m->loaded_relays, NUM_SAVED_TCP_RELAYS, nullptr, data, length, 1);
3212 m->has_added_relays = 0;
3067 } 3213 }
3068 3214
3069 messenger_save_subheader(data, 0, MESSENGER_STATE_TYPE_END); 3215 return STATE_LOAD_STATUS_CONTINUE;
3070} 3216}
3071 3217
3072static State_Load_Status messenger_load_state_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type) 3218// path node state plugin
3219static uint32_t path_node_size(const Messenger *m)
3073{ 3220{
3074 Messenger *m = (Messenger *)outer; 3221 return NUM_SAVED_PATH_NODES * packed_node_size(net_family_tcp_ipv6);
3075 3222}
3076 switch (type) {
3077 case MESSENGER_STATE_TYPE_NOSPAMKEYS:
3078 if (length == CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE + sizeof(uint32_t)) {
3079 set_nospam(m->fr, *(const uint32_t *)data);
3080 load_secret_key(m->net_crypto, (&data[sizeof(uint32_t)]) + CRYPTO_PUBLIC_KEY_SIZE);
3081
3082 if (public_key_cmp((&data[sizeof(uint32_t)]), nc_get_self_public_key(m->net_crypto)) != 0) {
3083 return STATE_LOAD_STATUS_ERROR;
3084 }
3085 } else {
3086 return STATE_LOAD_STATUS_ERROR; /* critical */
3087 }
3088
3089 break;
3090
3091 case MESSENGER_STATE_TYPE_DHT:
3092 dht_load(m->dht, data, length);
3093 break;
3094
3095 case MESSENGER_STATE_TYPE_FRIENDS:
3096 friends_list_load(m, data, length);
3097 break;
3098
3099 case MESSENGER_STATE_TYPE_NAME:
3100 if ((length > 0) && (length <= MAX_NAME_LENGTH)) {
3101 setname(m, data, length);
3102 }
3103 3223
3104 break; 3224static uint8_t *save_path_nodes(const Messenger *m, uint8_t *data)
3225{
3226 Node_format nodes[NUM_SAVED_PATH_NODES];
3227 uint8_t *temp_data = data;
3228 data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, 0, MESSENGER_STATE_TYPE_PATH_NODE);
3229 memset(nodes, 0, sizeof(nodes));
3230 const unsigned int num = onion_backup_nodes(m->onion_c, nodes, NUM_SAVED_PATH_NODES);
3231 const int l = pack_nodes(data, NUM_SAVED_PATH_NODES * packed_node_size(net_family_tcp_ipv6), nodes, num);
3105 3232
3106 case MESSENGER_STATE_TYPE_STATUSMESSAGE: 3233 if (l > 0) {
3107 if ((length > 0) && (length <= MAX_STATUSMESSAGE_LENGTH)) { 3234 const uint32_t len = l;
3108 m_set_statusmessage(m, data, length); 3235 data = state_write_section_header(temp_data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_PATH_NODE);
3109 } 3236 data += len;
3237 }
3110 3238
3111 break; 3239 return data;
3240}
3112 3241
3113 case MESSENGER_STATE_TYPE_STATUS: 3242static State_Load_Status load_path_nodes(Messenger *m, const uint8_t *data, uint32_t length)
3114 if (length == 1) { 3243{
3115 m_set_userstatus(m, *data); 3244 Node_format nodes[NUM_SAVED_PATH_NODES];
3116 }
3117 3245
3118 break; 3246 if (length != 0) {
3247 const int num = unpack_nodes(nodes, NUM_SAVED_PATH_NODES, nullptr, data, length, 0);
3119 3248
3120 case MESSENGER_STATE_TYPE_TCP_RELAY: { 3249 for (int i = 0; i < num; ++i) {
3121 if (length == 0) { 3250 onion_add_bs_path_node(m->onion_c, nodes[i].ip_port, nodes[i].public_key);
3122 break; 3251 }
3123 } 3252 }
3124 3253
3125 unpack_nodes(m->loaded_relays, NUM_SAVED_TCP_RELAYS, nullptr, data, length, 1); 3254 return STATE_LOAD_STATUS_CONTINUE;
3126 m->has_added_relays = 0; 3255}
3127 3256
3128 break; 3257// end state plugin
3129 } 3258static uint32_t end_size(const Messenger *m)
3259{
3260 return 0;
3261}
3130 3262
3131 case MESSENGER_STATE_TYPE_PATH_NODE: { 3263static uint8_t *save_end(const Messenger *m, uint8_t *data)
3132 Node_format nodes[NUM_SAVED_PATH_NODES]; 3264{
3265 return state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, 0, MESSENGER_STATE_TYPE_END);
3266}
3133 3267
3134 if (length == 0) { 3268static State_Load_Status load_end(Messenger *m, const uint8_t *data, uint32_t length)
3135 break; 3269{
3136 } 3270 if (length != 0) {
3271 return STATE_LOAD_STATUS_ERROR;
3272 }
3137 3273
3138 int i, num = unpack_nodes(nodes, NUM_SAVED_PATH_NODES, nullptr, data, length, 0); 3274 return STATE_LOAD_STATUS_END;
3275}
3139 3276
3140 for (i = 0; i < num; ++i) { 3277static void m_register_default_plugins(Messenger *m)
3141 onion_add_bs_path_node(m->onion_c, nodes[i].ip_port, nodes[i].public_key); 3278{
3142 } 3279 m_register_state_plugin(m, MESSENGER_STATE_TYPE_NOSPAMKEYS, nospam_keys_size, load_nospam_keys, save_nospam_keys);
3280 m_register_state_plugin(m, MESSENGER_STATE_TYPE_DHT, m_dht_size, m_dht_load, save_dht);
3281 m_register_state_plugin(m, MESSENGER_STATE_TYPE_FRIENDS, saved_friendslist_size, friends_list_load, friends_list_save);
3282 m_register_state_plugin(m, MESSENGER_STATE_TYPE_NAME, name_size, load_name, save_name);
3283 m_register_state_plugin(m, MESSENGER_STATE_TYPE_STATUSMESSAGE, status_message_size, load_status_message,
3284 save_status_message);
3285 m_register_state_plugin(m, MESSENGER_STATE_TYPE_STATUS, status_size, load_status, save_status);
3286 m_register_state_plugin(m, MESSENGER_STATE_TYPE_TCP_RELAY, tcp_relay_size, load_tcp_replays, save_tcp_relays);
3287 m_register_state_plugin(m, MESSENGER_STATE_TYPE_PATH_NODE, path_node_size, load_path_nodes, save_path_nodes);
3288 m_register_state_plugin(m, MESSENGER_STATE_TYPE_END, end_size, load_end, save_end);
3289}
3143 3290
3144 break; 3291static State_Load_Status messenger_load_state_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type)
3145 } 3292{
3293 Messenger *m = (Messenger *)outer;
3146 3294
3147 case MESSENGER_STATE_TYPE_END: { 3295 for (uint8_t i = 0; i < m->options.state_plugins_length; ++i) {
3148 if (length != 0) { 3296 const Messenger_State_Plugin *const plugin = &m->options.state_plugins[i];
3149 return STATE_LOAD_STATUS_ERROR;
3150 }
3151 3297
3152 return STATE_LOAD_STATUS_END; 3298 if (plugin->type == type) {
3299 return plugin->load(m, data, length);
3153 } 3300 }
3154
3155 default:
3156 LOGGER_ERROR(m->log, "Load state: contains unrecognized part (len %u, type %u)\n",
3157 length, type);
3158 break;
3159 } 3301 }
3160 3302
3303 LOGGER_ERROR(m->log, "Load state: contains unrecognized part (len %u, type %u)\n",
3304 length, type);
3305
3161 return STATE_LOAD_STATUS_CONTINUE; 3306 return STATE_LOAD_STATUS_CONTINUE;
3162} 3307}
3163 3308