diff options
author | iphydf <iphydf@users.noreply.github.com> | 2018-07-09 13:25:55 +0000 |
---|---|---|
committer | endoffile78 <endoffile78@yahoo.com> | 2018-09-07 12:22:10 -0500 |
commit | 08cc4184a167759e7dd7dcd334003d6257241a45 (patch) | |
tree | b4d8fa66f25eb75a40f80f9e62c4abb4418a3cdf /toxcore/Messenger.c | |
parent | 1cd183691735126aa3c916c3e2417e2edd104d1d (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.c | 537 |
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 | ||
42 | static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data, | 42 | static 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); |
44 | static 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 |
46 | static uint8_t friend_not_valid(const Messenger *m, int32_t friendnumber) | 47 | static 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 | ||
2797 | static uint32_t saved_friendslist_size(const Messenger *m) | ||
2798 | { | ||
2799 | return count_friendlist(m) * friend_size(); | ||
2800 | } | ||
2801 | |||
2802 | static uint8_t *friend_save(const struct Saved_Friend *temp, uint8_t *data) | 2793 | static 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 | ||
2836 | static uint32_t friends_list_save(const Messenger *m, uint8_t *data) | 2827 | |
2828 | static 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 | |||
2863 | static 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 | */ | ||
2884 | bool 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 | |||
2907 | static 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) */ | ||
2923 | uint32_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(). */ | ||
2933 | void 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 | ||
2952 | static uint32_t nospam_keys_size(const Messenger *m) | ||
2953 | { | ||
2954 | return sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE; | ||
2955 | } | ||
2956 | |||
2957 | static 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 | |||
2975 | static 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 | ||
2988 | static uint32_t m_dht_size(const Messenger *m) | ||
2989 | { | ||
2990 | return dht_size(m->dht); | ||
2991 | } | ||
2992 | |||
2993 | static 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 | |||
3002 | static 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 | ||
3009 | static uint32_t saved_friendslist_size(const Messenger *m) | ||
3010 | { | ||
3011 | return count_friendlist(m) * friend_size(); | ||
3012 | } | ||
3013 | |||
3014 | static 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 | |||
2884 | static 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 | ||
2918 | static int friends_list_load(Messenger *m, const uint8_t *data, uint32_t length) | 3066 | static 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 |
2966 | uint32_t messenger_size(const Messenger *m) | 3114 | static 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 | ||
2981 | static uint8_t *messenger_save_subheader(uint8_t *data, uint32_t len, uint16_t type) | 3119 | static 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(). */ | 3128 | static State_Load_Status load_name(Messenger *m, const uint8_t *data, uint32_t length) |
2991 | void 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; | 3138 | static 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)); | 3143 | static 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); | 3152 | static 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; | 3162 | static 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; | 3167 | static 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); | 3176 | static 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 | ||
3186 | static uint32_t tcp_relay_size(const Messenger *m) | ||
3187 | { | ||
3188 | return NUM_SAVED_TCP_RELAYS * packed_node_size(net_family_tcp_ipv6); | ||
3189 | } | ||
3190 | |||
3191 | static 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) { | 3208 | static 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 | ||
3072 | static State_Load_Status messenger_load_state_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type) | 3218 | // path node state plugin |
3219 | static 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; | 3224 | static 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: | 3242 | static 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 | } | 3258 | static uint32_t end_size(const Messenger *m) |
3259 | { | ||
3260 | return 0; | ||
3261 | } | ||
3130 | 3262 | ||
3131 | case MESSENGER_STATE_TYPE_PATH_NODE: { | 3263 | static 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) { | 3268 | static 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) { | 3277 | static 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; | 3291 | static 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 | ||