diff options
author | George Hazan <ghazan@miranda.im> | 2019-01-16 21:13:32 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2019-01-16 21:13:32 +0300 |
commit | 2ad44a4cd4f811d6c7da5c8e9e31acf6e0152c79 (patch) | |
tree | 0585db93be035ea25d807b788ccfc4c7217c7587 /protocols/Tox/libtox | |
parent | 8fc53a06b7a8163d61c06fbde88ffea904222bdd (diff) |
fixes #1767 (Update toxcore to 0.2.9)
Diffstat (limited to 'protocols/Tox/libtox')
27 files changed, 1251 insertions, 380 deletions
diff --git a/protocols/Tox/libtox/src/toxcore/DHT.c b/protocols/Tox/libtox/src/toxcore/DHT.c index 1eebb0c736..6b2715ee55 100644 --- a/protocols/Tox/libtox/src/toxcore/DHT.c +++ b/protocols/Tox/libtox/src/toxcore/DHT.c @@ -2741,10 +2741,12 @@ DHT *new_dht(const Logger *log, Mono_Time *mono_time, Networking_Core *net, bool dht->dht_harden_ping_array = ping_array_new(DHT_PING_ARRAY_SIZE, PING_TIMEOUT); for (uint32_t i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) { - uint8_t random_key_bytes[CRYPTO_PUBLIC_KEY_SIZE]; - random_bytes(random_key_bytes, sizeof(random_key_bytes)); + uint8_t random_public_key_bytes[CRYPTO_PUBLIC_KEY_SIZE]; + uint8_t random_secret_key_bytes[CRYPTO_SECRET_KEY_SIZE]; - if (dht_addfriend(dht, random_key_bytes, nullptr, nullptr, 0, nullptr) != 0) { + crypto_new_keypair(random_public_key_bytes, random_secret_key_bytes); + + if (dht_addfriend(dht, random_public_key_bytes, nullptr, nullptr, 0, nullptr) != 0) { kill_dht(dht); return nullptr; } @@ -2803,6 +2805,11 @@ uint32_t dht_size(const DHT *dht) uint32_t numv4 = 0; uint32_t numv6 = 0; + for (uint32_t i = 0; i < dht->loaded_num_nodes; ++i) { + numv4 += net_family_is_ipv4(dht->loaded_nodes_list[i].ip_port.ip.family); + numv6 += net_family_is_ipv6(dht->loaded_nodes_list[i].ip_port.ip.family); + } + for (uint32_t i = 0; i < LCLIENT_LIST; ++i) { numv4 += (dht->close_clientlist[i].assoc4.timestamp != 0); numv6 += (dht->close_clientlist[i].assoc6.timestamp != 0); @@ -2826,7 +2833,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; @@ -2838,6 +2845,11 @@ void dht_save(const DHT *dht, uint8_t *data) uint32_t num = 0; + if (dht->loaded_num_nodes > 0) { + memcpy(clients, dht->loaded_nodes_list, sizeof(Node_format) * dht->loaded_num_nodes); + num += dht->loaded_num_nodes; + } + for (uint32_t i = 0; i < LCLIENT_LIST; ++i) { if (dht->close_clientlist[i].assoc4.timestamp != 0) { memcpy(clients[num].public_key, dht->close_clientlist[i].public_key, CRYPTO_PUBLIC_KEY_SIZE); @@ -2950,7 +2962,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, diff --git a/protocols/Tox/libtox/src/toxcore/LAN_discovery.c b/protocols/Tox/libtox/src/toxcore/LAN_discovery.c index aeeea5661a..1137fc3d2f 100644 --- a/protocols/Tox/libtox/src/toxcore/LAN_discovery.c +++ b/protocols/Tox/libtox/src/toxcore/LAN_discovery.c @@ -119,7 +119,7 @@ static void fetch_broadcast_info(uint16_t port) } } -#elif defined(__linux__) || defined(__FreeBSD__) +#elif defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) #include <netinet/in.h> #include <sys/ioctl.h> @@ -131,7 +131,7 @@ static void fetch_broadcast_info(uint16_t port) #include <linux/netdevice.h> #endif -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__DragonFly__) #include <net/if.h> #endif diff --git a/protocols/Tox/libtox/src/toxcore/LAN_discovery.h b/protocols/Tox/libtox/src/toxcore/LAN_discovery.h index 8c48316d9e..1364a28078 100644 --- a/protocols/Tox/libtox/src/toxcore/LAN_discovery.h +++ b/protocols/Tox/libtox/src/toxcore/LAN_discovery.h @@ -70,4 +70,4 @@ bool ip_is_local(IP ip); */ bool ip_is_lan(IP ip); -#endif +#endif // C_TOXCORE_TOXCORE_LAN_DISCOVERY_H diff --git a/protocols/Tox/libtox/src/toxcore/Messenger.c b/protocols/Tox/libtox/src/toxcore/Messenger.c index 594fc79a07..ae2d1d3bb0 100644 --- a/protocols/Tox/libtox/src/toxcore/Messenger.c +++ b/protocols/Tox/libtox/src/toxcore/Messenger.c @@ -2593,12 +2593,12 @@ void do_messenger(Messenger *m, void *userdata) if (!m->has_added_relays) { m->has_added_relays = true; - int i; - - for (i = 0; i < NUM_SAVED_TCP_RELAYS; ++i) { + for (uint16_t i = 0; i < m->num_loaded_relays; ++i) { add_tcp_relay(m->net_crypto, m->loaded_relays[i].ip_port, m->loaded_relays[i].public_key); } + m->num_loaded_relays = 0; + if (m->tcp_server) { /* Add self tcp server. */ IP_Port local_ip_port; @@ -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; @@ -3035,6 +3019,7 @@ static uint8_t *friends_list_save(const Messenger *m, uint8_t *data) temp.info_size = net_htons(m->friendlist[i].info_size); temp.friendrequest_nospam = m->friendlist[i].friendrequest_nospam; } else { + temp.status = 3; memcpy(temp.name, m->friendlist[i].name, m->friendlist[i].name_length); temp.name_length = net_htons(m->friendlist[i].name_length); memcpy(temp.statusmessage, m->friendlist[i].statusmessage, m->friendlist[i].statusmessage_length); @@ -3118,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; @@ -3142,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; @@ -3166,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; @@ -3192,13 +3177,19 @@ 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); - unsigned int num = copy_connected_tcp_relays(m->net_crypto, relays, NUM_SAVED_TCP_RELAYS); + 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) { + memcpy(relays, m->loaded_relays, sizeof(Node_format) * m->num_loaded_relays); + num = min_u32(num + m->num_loaded_relays, NUM_SAVED_TCP_RELAYS); + } + int l = pack_nodes(data, NUM_SAVED_TCP_RELAYS * packed_node_size(net_family_tcp_ipv6), relays, num); 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; } @@ -3208,7 +3199,7 @@ static uint8_t *save_tcp_relays(const Messenger *m, uint8_t *data) static State_Load_Status load_tcp_relays(Messenger *m, const uint8_t *data, uint32_t length) { if (length != 0) { - unpack_nodes(m->loaded_relays, NUM_SAVED_TCP_RELAYS, nullptr, data, length, 1); + m->num_loaded_relays = unpack_nodes(m->loaded_relays, NUM_SAVED_TCP_RELAYS, nullptr, data, length, 1); m->has_added_relays = false; } @@ -3225,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; } @@ -3254,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. diff --git a/protocols/Tox/libtox/src/toxcore/Messenger.h b/protocols/Tox/libtox/src/toxcore/Messenger.h index ab9d72568e..a3376e237a 100644 --- a/protocols/Tox/libtox/src/toxcore/Messenger.h +++ b/protocols/Tox/libtox/src/toxcore/Messenger.h @@ -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; @@ -293,6 +281,8 @@ struct Messenger { time_t lastdump; bool has_added_relays; // If the first connection has occurred in do_messenger + + uint16_t num_loaded_relays; Node_format loaded_relays[NUM_SAVED_TCP_RELAYS]; // Relays loaded from config m_friend_message_cb *friend_message; @@ -795,17 +785,25 @@ 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 data Data to load. + * @param length Length of data. + * @param type Type of section (STATE_TYPE_*). + * @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 diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core.c b/protocols/Tox/libtox/src/toxcore/crypto_core.c index 1fd6286681..0e53100acd 100644 --- a/protocols/Tox/libtox/src/toxcore/crypto_core.c +++ b/protocols/Tox/libtox/src/toxcore/crypto_core.c @@ -30,6 +30,7 @@ #include "ccompat.h" #include "crypto_core.h" +#include <stdlib.h> #include <string.h> #ifndef VANILLA_NACL @@ -82,6 +83,20 @@ #error "CRYPTO_PUBLIC_KEY_SIZE is required to be 32 bytes for public_key_cmp to work," #endif +static uint8_t *crypto_malloc(size_t bytes) +{ + return (uint8_t *)malloc(bytes); +} + +static void crypto_free(uint8_t *ptr, size_t bytes) +{ + if (ptr != nullptr) { + crypto_memzero(ptr, bytes); + } + + free(ptr); +} + int32_t public_key_cmp(const uint8_t *pk1, const uint8_t *pk2) { return crypto_verify_32(pk1, pk2); @@ -142,8 +157,17 @@ int32_t encrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, return -1; } - VLA(uint8_t, temp_plain, length + crypto_box_ZEROBYTES); - VLA(uint8_t, temp_encrypted, length + crypto_box_MACBYTES + crypto_box_BOXZEROBYTES); + const size_t size_temp_plain = length + crypto_box_ZEROBYTES; + const size_t size_temp_encrypted = length + crypto_box_MACBYTES + crypto_box_BOXZEROBYTES; + + uint8_t *temp_plain = crypto_malloc(size_temp_plain); + uint8_t *temp_encrypted = crypto_malloc(size_temp_encrypted); + + if (temp_plain == nullptr || temp_encrypted == nullptr) { + crypto_free(temp_plain, size_temp_plain); + crypto_free(temp_encrypted, size_temp_encrypted); + return -1; + } memset(temp_plain, 0, crypto_box_ZEROBYTES); // Pad the message with 32 0 bytes. @@ -151,11 +175,17 @@ int32_t encrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, if (crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, secret_key) != 0) { + crypto_free(temp_plain, size_temp_plain); + crypto_free(temp_encrypted, size_temp_encrypted); return -1; } // Unpad the encrypted message. memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES); + + crypto_free(temp_plain, size_temp_plain); + crypto_free(temp_encrypted, size_temp_encrypted); + return length + crypto_box_MACBYTES; } @@ -166,8 +196,17 @@ int32_t decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, return -1; } - VLA(uint8_t, temp_plain, length + crypto_box_ZEROBYTES); - VLA(uint8_t, temp_encrypted, length + crypto_box_BOXZEROBYTES); + const size_t size_temp_plain = length + crypto_box_ZEROBYTES; + const size_t size_temp_encrypted = length + crypto_box_BOXZEROBYTES; + + uint8_t *temp_plain = crypto_malloc(size_temp_plain); + uint8_t *temp_encrypted = crypto_malloc(size_temp_encrypted); + + if (temp_plain == nullptr || temp_encrypted == nullptr) { + crypto_free(temp_plain, size_temp_plain); + crypto_free(temp_encrypted, size_temp_encrypted); + return -1; + } memset(temp_encrypted, 0, crypto_box_BOXZEROBYTES); // Pad the message with 16 0 bytes. @@ -175,10 +214,15 @@ int32_t decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce, secret_key) != 0) { + crypto_free(temp_plain, size_temp_plain); + crypto_free(temp_encrypted, size_temp_encrypted); return -1; } memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES); + + crypto_free(temp_plain, size_temp_plain); + crypto_free(temp_encrypted, size_temp_encrypted); return length - crypto_box_MACBYTES; } diff --git a/protocols/Tox/libtox/src/toxcore/friend_connection.c b/protocols/Tox/libtox/src/toxcore/friend_connection.c index 9c805b45ed..69533def1e 100644 --- a/protocols/Tox/libtox/src/toxcore/friend_connection.c +++ b/protocols/Tox/libtox/src/toxcore/friend_connection.c @@ -85,6 +85,9 @@ struct Friend_Connections { fr_request_cb *fr_request_callback; void *fr_request_object; + global_status_cb *global_status_callback; + void *global_status_callback_object; + uint64_t last_lan_discovery; uint16_t next_lan_port; @@ -401,9 +404,11 @@ static int handle_status(void *object, int number, uint8_t status, void *userdat } if (status_changed) { - unsigned int i; + if (fr_c->global_status_callback) { + fr_c->global_status_callback(fr_c->global_status_callback_object, number, status, userdata); + } - for (i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) { + for (unsigned i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) { if (friend_con->callbacks[i].status_callback) { friend_con->callbacks[i].status_callback( friend_con->callbacks[i].callback_object, @@ -716,6 +721,13 @@ int friend_connection_callbacks(Friend_Connections *fr_c, int friendcon_id, unsi return 0; } +/* Set global status callback for friend connections. */ +void set_global_status_callback(Friend_Connections *fr_c, global_status_cb *global_status_callback, void *object) +{ + fr_c->global_status_callback = global_status_callback; + fr_c->global_status_callback_object = object; +} + /* return the crypt_connection_id for the connection. * * return crypt_connection_id on success. diff --git a/protocols/Tox/libtox/src/toxcore/friend_connection.h b/protocols/Tox/libtox/src/toxcore/friend_connection.h index 149a4fa7ec..166c731b84 100644 --- a/protocols/Tox/libtox/src/toxcore/friend_connection.h +++ b/protocols/Tox/libtox/src/toxcore/friend_connection.h @@ -101,10 +101,15 @@ void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t * */ int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, IP_Port ip_port, const uint8_t *public_key); +typedef int global_status_cb(void *object, int id, uint8_t status, void *userdata); + typedef int fc_status_cb(void *object, int id, uint8_t status, void *userdata); typedef int fc_data_cb(void *object, int id, const uint8_t *data, uint16_t length, void *userdata); typedef int fc_lossy_data_cb(void *object, int id, const uint8_t *data, uint16_t length, void *userdata); +/* Set global status callback for friend connections. */ +void set_global_status_callback(Friend_Connections *fr_c, global_status_cb *global_status_callback, void *object); + /* Set the callbacks for the friend connection. * index is the index (0 to (MAX_FRIEND_CONNECTION_CALLBACKS - 1)) we want the callback to set in the array. * diff --git a/protocols/Tox/libtox/src/toxcore/group.c b/protocols/Tox/libtox/src/toxcore/group.c index 5feb483b74..101c11963d 100644 --- a/protocols/Tox/libtox/src/toxcore/group.c +++ b/protocols/Tox/libtox/src/toxcore/group.c @@ -27,10 +27,12 @@ #include "group.h" +#include <assert.h> #include <stdlib.h> #include <string.h> #include "mono_time.h" +#include "state.h" #include "util.h" /** @@ -40,6 +42,7 @@ typedef enum Group_Message_Id { GROUP_MESSAGE_PING_ID = 0, GROUP_MESSAGE_NEW_PEER_ID = 16, GROUP_MESSAGE_KILL_PEER_ID = 17, + GROUP_MESSAGE_FREEZE_PEER_ID = 18, GROUP_MESSAGE_NAME_ID = 48, GROUP_MESSAGE_TITLE_ID = 49, } Group_Message_Id; @@ -199,6 +202,17 @@ static int peer_in_chat(const Group_c *chat, const uint8_t *real_pk) return -1; } +static int frozen_in_chat(const Group_c *chat, const uint8_t *real_pk) +{ + for (uint32_t i = 0; i < chat->numfrozen; ++i) { + if (id_equal(chat->frozen[i].real_pk, real_pk)) { + return i; + } + } + + return -1; +} + /* * check if group with the given type and id is in group array. * @@ -237,7 +251,7 @@ int32_t conference_by_id(const Group_Chats *g_c, const uint8_t *id) * * TODO(irungentoo): make this more efficient. */ -static int get_peer_index(Group_c *g, uint16_t peer_number) +static int get_peer_index(const Group_c *g, uint16_t peer_number) { for (uint32_t i = 0; i < g->numpeers; ++i) { if (g->group[i].peer_number == peer_number) { @@ -350,7 +364,7 @@ static int add_to_closest(Group_Chats *g_c, uint32_t groupnumber, const uint8_t return 0; } -static unsigned int pk_in_closest_peers(Group_c *g, uint8_t *real_pk) +static unsigned int pk_in_closest_peers(const Group_c *g, uint8_t *real_pk) { unsigned int i; @@ -373,7 +387,7 @@ static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, uint32_t gr static void remove_conn_reason(Group_Chats *g_c, uint32_t groupnumber, uint16_t i, uint8_t reason); static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t type, - uint8_t *id); + const uint8_t *id); static int connect_to_closest(Group_Chats *g_c, uint32_t groupnumber, void *userdata) { @@ -443,7 +457,7 @@ static int connect_to_closest(Group_Chats *g_c, uint32_t groupnumber, void *user return 0; } -static int get_frozen_index(Group_c *g, uint16_t peer_number) +static int get_frozen_index(const Group_c *g, uint16_t peer_number) { for (uint32_t i = 0; i < g->numfrozen; ++i) { if (g->frozen[i].peer_number == peer_number) { @@ -454,6 +468,34 @@ static int get_frozen_index(Group_c *g, uint16_t peer_number) return -1; } +static bool delete_frozen(Group_c *g, uint32_t frozen_index) +{ + if (frozen_index >= g->numfrozen) { + return false; + } + + --g->numfrozen; + + if (g->numfrozen == 0) { + free(g->frozen); + g->frozen = nullptr; + } else { + if (g->numfrozen != frozen_index) { + g->frozen[frozen_index] = g->frozen[g->numfrozen]; + } + + Group_Peer *const frozen_temp = (Group_Peer *)realloc(g->frozen, sizeof(Group_Peer) * (g->numfrozen)); + + if (frozen_temp == nullptr) { + return false; + } + + g->frozen = frozen_temp; + } + + return true; +} + /* Update last_active timestamp on peer, and thaw the peer if it is frozen. * * return peer index if peer is in the conference. @@ -497,23 +539,8 @@ static int note_peer_active(Group_Chats *g_c, uint32_t groupnumber, uint16_t pee ++g->numpeers; - --g->numfrozen; - - if (g->numfrozen == 0) { - free(g->frozen); - g->frozen = nullptr; - } else { - if (g->numfrozen != (uint32_t)frozen_index) { - g->frozen[frozen_index] = g->frozen[g->numfrozen]; - } - - Group_Peer *frozen_temp = (Group_Peer *)realloc(g->frozen, sizeof(Group_Peer) * (g->numfrozen)); - - if (frozen_temp == nullptr) { - return -1; - } - - g->frozen = frozen_temp; + if (!delete_frozen(g, frozen_index)) { + return -1; } if (g_c->peer_list_changed_callback) { @@ -529,6 +556,29 @@ static int note_peer_active(Group_Chats *g_c, uint32_t groupnumber, uint16_t pee return g->numpeers - 1; } +static int delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void *userdata, bool keep_connection); + +static void delete_any_peer_with_pk(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_pk, void *userdata) +{ + Group_c *g = get_group_c(g_c, groupnumber); + + if (!g) { + return; + } + + const int prev_peer_index = peer_in_chat(g, real_pk); + + if (prev_peer_index >= 0) { + delpeer(g_c, groupnumber, prev_peer_index, userdata, false); + } + + const int prev_frozen_index = frozen_in_chat(g, real_pk); + + if (prev_frozen_index >= 0) { + delete_frozen(g, prev_frozen_index); + } +} + /* Add a peer to the group chat, or update an existing peer. * * fresh indicates whether we should consider this information on the peer to @@ -581,6 +631,8 @@ static int addpeer(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_p } } + delete_any_peer_with_pk(g_c, groupnumber, real_pk, userdata); + Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * (g->numpeers + 1)); if (temp == nullptr) { @@ -880,13 +932,23 @@ static void rejoin_frozen_friend(Group_Chats *g_c, int friendcon_id) } } +static int g_handle_any_status(void *object, int friendcon_id, uint8_t status, void *userdata) +{ + Group_Chats *g_c = (Group_Chats *)object; + + if (status) { + rejoin_frozen_friend(g_c, friendcon_id); + } + + return 0; +} + static int g_handle_status(void *object, int friendcon_id, uint8_t status, void *userdata) { Group_Chats *g_c = (Group_Chats *)object; if (status) { /* Went online */ set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_ONLINE, userdata); - rejoin_frozen_friend(g_c, friendcon_id); } else { /* Went offline */ set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_CONNECTION, userdata); // TODO(irungentoo): remove timedout connections? @@ -978,7 +1040,10 @@ static void remove_conn_reason(Group_Chats *g_c, uint32_t groupnumber, uint16_t if (reason == GROUPCHAT_CLOSE_REASON_INTRODUCER) { --g->num_introducer_connections; - send_peer_introduced(g_c, g->close[i].number, g->close[i].group_number); + + if (g->close[i].type == GROUPCHAT_CLOSE_ONLINE) { + send_peer_introduced(g_c, g->close[i].number, g->close[i].group_number); + } } if (g->close[i].reasons == 0) { @@ -1021,13 +1086,15 @@ int add_groupchat(Group_Chats *g_c, uint8_t type) return groupnumber; } -static int group_kill_peer_send(const Group_Chats *g_c, uint32_t groupnumber, uint16_t peer_num); -/* Delete a groupchat from the chats array. +static bool group_leave(const Group_Chats *g_c, uint32_t groupnumber, bool permanent); + +/* Delete a groupchat from the chats array, informing the group first as + * appropriate. * * return 0 on success. * return -1 if groupnumber is invalid. */ -int del_groupchat(Group_Chats *g_c, uint32_t groupnumber) +int del_groupchat(Group_Chats *g_c, uint32_t groupnumber, bool leave_permanently) { Group_c *g = get_group_c(g_c, groupnumber); @@ -1035,7 +1102,7 @@ int del_groupchat(Group_Chats *g_c, uint32_t groupnumber) return -1; } - group_kill_peer_send(g_c, groupnumber, g->peer_number); + group_leave(g_c, groupnumber, leave_permanently); for (uint32_t i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { if (g->close[i].type == GROUPCHAT_CLOSE_NONE) { @@ -1062,82 +1129,115 @@ int del_groupchat(Group_Chats *g_c, uint32_t groupnumber) return wipe_group_chat(g_c, groupnumber); } -/* Copy the public key of peernumber who is in groupnumber to pk. - * pk must be CRYPTO_PUBLIC_KEY_SIZE long. +/* Copy the public key of (frozen, if frozen is true) peernumber who is in + * groupnumber to pk. pk must be CRYPTO_PUBLIC_KEY_SIZE long. * * return 0 on success * return -1 if groupnumber is invalid. * return -2 if peernumber is invalid. */ -int group_peer_pubkey(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, uint8_t *pk) +int group_peer_pubkey(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, uint8_t *pk, bool frozen) { - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { return -1; } - if ((uint32_t)peernumber >= g->numpeers) { + const Group_Peer *list = frozen ? g->frozen : g->group; + const uint32_t num = frozen ? g->numfrozen : g->numpeers; + + if ((uint32_t)peernumber >= num) { return -2; } - memcpy(pk, g->group[peernumber].real_pk, CRYPTO_PUBLIC_KEY_SIZE); + memcpy(pk, list[peernumber].real_pk, CRYPTO_PUBLIC_KEY_SIZE); return 0; } /* - * Return the size of peernumber's name. + * Return the size of (frozen, if frozen is true) peernumber's name. * * return -1 if groupnumber is invalid. * return -2 if peernumber is invalid. */ -int group_peername_size(const Group_Chats *g_c, uint32_t groupnumber, int peernumber) +int group_peername_size(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, bool frozen) { - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { return -1; } - if ((uint32_t)peernumber >= g->numpeers) { + const Group_Peer *list = frozen ? g->frozen : g->group; + const uint32_t num = frozen ? g->numfrozen : g->numpeers; + + if ((uint32_t)peernumber >= num) { return -2; } - if (g->group[peernumber].nick_len == 0) { + if (list[peernumber].nick_len == 0) { return 0; } - return g->group[peernumber].nick_len; + return list[peernumber].nick_len; } -/* Copy the name of peernumber who is in groupnumber to name. - * name must be at least MAX_NAME_LENGTH long. +/* Copy the name of (frozen, if frozen is true) peernumber who is in + * groupnumber to name. name must be at least MAX_NAME_LENGTH long. * * return length of name if success * return -1 if groupnumber is invalid. * return -2 if peernumber is invalid. */ -int group_peername(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, uint8_t *name) +int group_peername(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, uint8_t *name, bool frozen) { - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { return -1; } - if ((uint32_t)peernumber >= g->numpeers) { + const Group_Peer *list = frozen ? g->frozen : g->group; + const uint32_t num = frozen ? g->numfrozen : g->numpeers; + + if ((uint32_t)peernumber >= num) { return -2; } - if (g->group[peernumber].nick_len == 0) { + if (list[peernumber].nick_len == 0) { return 0; } - memcpy(name, g->group[peernumber].nick, g->group[peernumber].nick_len); - return g->group[peernumber].nick_len; + memcpy(name, list[peernumber].nick, list[peernumber].nick_len); + return list[peernumber].nick_len; +} + +/* Copy last active timestamp of frozennumber who is in groupnumber to + * last_active. + * + * return 0 on success. + * return -1 if groupnumber is invalid. + * return -2 if frozennumber is invalid. + */ +int group_frozen_last_active(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, + uint64_t *last_active) +{ + const Group_c *g = get_group_c(g_c, groupnumber); + + if (!g) { + return -1; + } + + if ((uint32_t)peernumber >= g->numfrozen) { + return -2; + } + + *last_active = g->frozen[peernumber].last_active; + return 0; } -/* List all the peers in the group chat. +/* List all the (frozen, if frozen is true) peers in the group chat. * * Copies the names of the peers to the name[length][MAX_NAME_LENGTH] array. * @@ -1148,35 +1248,38 @@ int group_peername(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, * return -1 on failure. */ int group_names(const Group_Chats *g_c, uint32_t groupnumber, uint8_t names[][MAX_NAME_LENGTH], uint16_t lengths[], - uint16_t length) + uint16_t length, bool frozen) { - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { return -1; } + const uint32_t num = frozen ? g->numfrozen : g->numpeers; + unsigned int i; - for (i = 0; i < g->numpeers && i < length; ++i) { - lengths[i] = group_peername(g_c, groupnumber, i, names[i]); + for (i = 0; i < num && i < length; ++i) { + lengths[i] = group_peername(g_c, groupnumber, i, names[i], frozen); } return i; } -/* Return the number of peers in the group chat on success. +/* Return the number of (frozen, if frozen is true) peers in the group chat on + * success. * return -1 if groupnumber is invalid. */ -int group_number_peers(const Group_Chats *g_c, uint32_t groupnumber) +int group_number_peers(const Group_Chats *g_c, uint32_t groupnumber, bool frozen) { - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { return -1; } - return g->numpeers; + return frozen ? g->numfrozen : g->numpeers; } /* return 1 if the peernumber corresponds to ours. @@ -1187,7 +1290,7 @@ int group_number_peers(const Group_Chats *g_c, uint32_t groupnumber) */ int group_peernumber_is_ours(const Group_Chats *g_c, uint32_t groupnumber, int peernumber) { - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { return -1; @@ -1553,10 +1656,9 @@ static int group_new_peer_send(const Group_Chats *g_c, uint32_t groupnumber, uin } /* send a kill_peer message - * return 0 on success - * return -1 on failure + * return true on success */ -static int group_kill_peer_send(const Group_Chats *g_c, uint32_t groupnumber, uint16_t peer_num) +static bool group_kill_peer_send(const Group_Chats *g_c, uint32_t groupnumber, uint16_t peer_num) { uint8_t packet[GROUP_MESSAGE_KILL_PEER_LENGTH]; @@ -1564,10 +1666,27 @@ static int group_kill_peer_send(const Group_Chats *g_c, uint32_t groupnumber, ui memcpy(packet, &peer_num, sizeof(uint16_t)); if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_KILL_PEER_ID, packet, sizeof(packet)) > 0) { - return 0; + return true; } - return -1; + return false; +} + +/* send a freeze_peer message + * return true on success + */ +static bool group_freeze_peer_send(const Group_Chats *g_c, uint32_t groupnumber, uint16_t peer_num) +{ + uint8_t packet[GROUP_MESSAGE_KILL_PEER_LENGTH]; + + peer_num = net_htons(peer_num); + memcpy(packet, &peer_num, sizeof(uint16_t)); + + if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_FREEZE_PEER_ID, packet, sizeof(packet)) > 0) { + return true; + } + + return false; } /* send a name message @@ -1587,6 +1706,25 @@ static int group_name_send(const Group_Chats *g_c, uint32_t groupnumber, const u return -1; } +/* send message to announce leaving group + * return true on success + */ +static bool group_leave(const Group_Chats *g_c, uint32_t groupnumber, bool permanent) +{ + const Group_c *g = get_group_c(g_c, groupnumber); + + if (!g) { + return false; + } + + if (permanent) { + return group_kill_peer_send(g_c, groupnumber, g->peer_number); + } else { + return group_freeze_peer_send(g_c, groupnumber, g->peer_number); + } +} + + /* set the group's title, limited to MAX_NAME_LENGTH * return 0 on success * return -1 if groupnumber is invalid. @@ -1630,7 +1768,7 @@ int group_title_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t */ int group_title_get_size(const Group_Chats *g_c, uint32_t groupnumber) { - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { return -1; @@ -1652,7 +1790,7 @@ int group_title_get_size(const Group_Chats *g_c, uint32_t groupnumber) */ int group_title_get(const Group_Chats *g_c, uint32_t groupnumber, uint8_t *title) { - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { return -1; @@ -1675,11 +1813,11 @@ static bool get_peer_number(const Group_c *g, const uint8_t *real_pk, uint16_t * return true; } - for (uint32_t i = 0; i < g->numfrozen; ++i) { - if (id_equal(g->frozen[i].real_pk, real_pk)) { - *peer_number = g->frozen[i].peer_number; - return true; - } + const int frozen_index = frozen_in_chat(g, real_pk); + + if (frozen_index >= 0) { + *peer_number = g->frozen[frozen_index].peer_number; + return true; } return false; @@ -1790,7 +1928,7 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con * returns index on success * returns -1 on failure. */ -static int friend_in_close(Group_c *g, int friendcon_id) +static int friend_in_close(const Group_c *g, int friendcon_id) { unsigned int i; @@ -1811,7 +1949,7 @@ static int friend_in_close(Group_c *g, int friendcon_id) /* return number of connected close connections. */ -static unsigned int count_close_connected(Group_c *g) +static unsigned int count_close_connected(const Group_c *g) { unsigned int i, count = 0; @@ -1825,7 +1963,7 @@ static unsigned int count_close_connected(Group_c *g) } static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t type, - uint8_t *id) + const uint8_t *id) { uint8_t packet[1 + ONLINE_PACKET_DATA_SIZE]; group_num = net_htons(group_num); @@ -1906,7 +2044,7 @@ static int handle_packet_rejoin(Group_Chats *g_c, int friendcon_id, const uint8_ const int32_t groupnum = get_group_num(g_c, *data, data + 1); - Group_c *g = get_group_c(g_c, groupnum); + const Group_c *g = get_group_c(g_c, groupnum); if (!g) { return -1; @@ -1960,7 +2098,7 @@ static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t */ static unsigned int send_peers(Group_Chats *g_c, uint32_t groupnumber, int friendcon_id, uint16_t group_num) { - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { return 0; @@ -2083,7 +2221,7 @@ static void handle_direct_packet(Group_Chats *g_c, uint32_t groupnumber, const u switch (data[0]) { case PEER_INTRODUCED_ID: { - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { return; @@ -2095,12 +2233,16 @@ static void handle_direct_packet(Group_Chats *g_c, uint32_t groupnumber, const u break; case PEER_QUERY_ID: { - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { return; } + if (g->close[close_index].type != GROUPCHAT_CLOSE_ONLINE) { + return; + } + send_peers(g_c, groupnumber, g->close[close_index].number, g->close[close_index].group_number); } @@ -2113,7 +2255,7 @@ static void handle_direct_packet(Group_Chats *g_c, uint32_t groupnumber, const u break; case PEER_TITLE_ID: { - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { break; @@ -2136,7 +2278,7 @@ static void handle_direct_packet(Group_Chats *g_c, uint32_t groupnumber, const u static unsigned int send_message_all_close(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *data, uint16_t length, int receiver) { - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { return 0; @@ -2171,7 +2313,7 @@ static unsigned int send_lossy_all_close(const Group_Chats *g_c, uint32_t groupn uint16_t length, int receiver) { - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { return 0; @@ -2257,7 +2399,7 @@ static unsigned int send_lossy_all_close(const Group_Chats *g_c, uint32_t groupn * return -1 if groupnumber is invalid. * return -2 if message is too long. * return -3 if we are not connected to the group. - * reutrn -4 if message failed to send. + * return -4 if message failed to send. */ static int send_message_group(const Group_Chats *g_c, uint32_t groupnumber, uint8_t message_id, const uint8_t *data, uint16_t len) @@ -2272,7 +2414,7 @@ static int send_message_group(const Group_Chats *g_c, uint32_t groupnumber, uint return -2; } - if (g->status != GROUPCHAT_STATUS_CONNECTED) { + if (g->status != GROUPCHAT_STATUS_CONNECTED || count_close_connected(g) == 0) { return -3; } @@ -2418,7 +2560,7 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber, return; } - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { return; @@ -2428,9 +2570,28 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber, memcpy(&peer_number, data, sizeof(uint16_t)); peer_number = net_ntohs(peer_number); - const int index = note_peer_active(g_c, groupnumber, peer_number, userdata); + uint32_t message_number; + memcpy(&message_number, data + sizeof(uint16_t), sizeof(message_number)); + message_number = net_ntohl(message_number); + + const uint8_t message_id = data[sizeof(uint16_t) + sizeof(message_number)]; + const uint8_t *msg_data = data + sizeof(uint16_t) + sizeof(message_number) + 1; + const uint16_t msg_data_len = length - (sizeof(uint16_t) + sizeof(message_number) + 1); + + const bool ignore_frozen = message_id == GROUP_MESSAGE_FREEZE_PEER_ID; + + const int index = ignore_frozen ? get_peer_index(g, peer_number) + : note_peer_active(g_c, groupnumber, peer_number, userdata); if (index == -1) { + if (ignore_frozen) { + return; + } + + if (g->close[close_index].type != GROUPCHAT_CLOSE_ONLINE) { + return; + } + /* If we don't know the peer this packet came from, then we query the * list of peers from the relaying peer. * (They would not have relayed it if they didn't know the peer.) */ @@ -2457,14 +2618,6 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber, } } - uint32_t message_number; - memcpy(&message_number, data + sizeof(uint16_t), sizeof(message_number)); - message_number = net_ntohl(message_number); - - const uint8_t message_id = data[sizeof(uint16_t) + sizeof(message_number)]; - const uint8_t *msg_data = data + sizeof(uint16_t) + sizeof(message_number) + 1; - const uint16_t msg_data_len = length - (sizeof(uint16_t) + sizeof(message_number) + 1); - if (!check_message_info(message_number, message_id, &g->group[index])) { return; } @@ -2486,7 +2639,8 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber, } break; - case GROUP_MESSAGE_KILL_PEER_ID: { + case GROUP_MESSAGE_KILL_PEER_ID: + case GROUP_MESSAGE_FREEZE_PEER_ID: { if (msg_data_len != GROUP_MESSAGE_KILL_PEER_LENGTH) { return; } @@ -2496,7 +2650,11 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber, kill_peer_number = net_ntohs(kill_peer_number); if (peer_number == kill_peer_number) { - delpeer(g_c, groupnumber, index, userdata, false); + if (message_id == GROUP_MESSAGE_KILL_PEER_ID) { + delpeer(g_c, groupnumber, index, userdata, false); + } else { + freeze_peer(g_c, groupnumber, index, userdata); + } } else { return; // TODO(irungentoo): @@ -2582,7 +2740,7 @@ static int g_handle_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t groupnumber; memcpy(&groupnumber, data + 1, sizeof(uint16_t)); groupnumber = net_ntohs(groupnumber); - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { return -1; @@ -2622,7 +2780,7 @@ static int g_handle_packet(void *object, int friendcon_id, const uint8_t *data, * * TODO(irungentoo): test this */ -static unsigned int lossy_packet_not_received(Group_c *g, int peer_index, uint16_t message_number) +static unsigned int lossy_packet_not_received(const Group_c *g, int peer_index, uint16_t message_number) { if (peer_index == -1) { // TODO(sudden6): invalid return value @@ -2693,7 +2851,7 @@ static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uin peer_number = net_ntohs(peer_number); message_number = net_ntohs(message_number); - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { return -1; @@ -2762,7 +2920,7 @@ int group_set_object(const Group_Chats *g_c, uint32_t groupnumber, void *object) */ int group_peer_set_object(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, void *object) { - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { return -1; @@ -2783,7 +2941,7 @@ int group_peer_set_object(const Group_Chats *g_c, uint32_t groupnumber, int peer */ void *group_get_object(const Group_Chats *g_c, uint32_t groupnumber) { - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { return nullptr; @@ -2799,7 +2957,7 @@ void *group_get_object(const Group_Chats *g_c, uint32_t groupnumber) */ void *group_peer_get_object(const Group_Chats *g_c, uint32_t groupnumber, int peernumber) { - Group_c *g = get_group_c(g_c, groupnumber); + const Group_c *g = get_group_c(g_c, groupnumber); if (!g) { return nullptr; @@ -2875,6 +3033,244 @@ void send_name_all_groups(Group_Chats *g_c) } } +#define SAVED_PEER_SIZE_CONSTANT (2 * CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint16_t) + sizeof(uint64_t) + 1) + +static uint32_t saved_peer_size(const Group_Peer *peer) +{ + return SAVED_PEER_SIZE_CONSTANT + peer->nick_len; +} + +static uint8_t *save_peer(const Group_Peer *peer, uint8_t *data) +{ + memcpy(data, peer->real_pk, CRYPTO_PUBLIC_KEY_SIZE); + data += CRYPTO_PUBLIC_KEY_SIZE; + + memcpy(data, peer->temp_pk, CRYPTO_PUBLIC_KEY_SIZE); + data += CRYPTO_PUBLIC_KEY_SIZE; + + host_to_lendian_bytes16(data, peer->peer_number); + data += sizeof(uint16_t); + + host_to_lendian_bytes64(data, peer->last_active); + data += sizeof(uint64_t); + + *data = peer->nick_len; + ++data; + + memcpy(data, peer->nick, peer->nick_len); + data += peer->nick_len; + + return data; +} + +#define SAVED_CONF_SIZE_CONSTANT (1 + GROUP_ID_LENGTH + sizeof(uint32_t) \ + + sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t) + 1) + +static uint32_t saved_conf_size(const Group_c *g) +{ + uint32_t len = SAVED_CONF_SIZE_CONSTANT + g->title_len; + + for (uint32_t j = 0; j < g->numpeers + g->numfrozen; ++j) { + const Group_Peer *peer = (j < g->numpeers) ? &g->group[j] : &g->frozen[j - g->numpeers]; + + if (id_equal(peer->real_pk, g->real_pk)) { + continue; + } + + len += saved_peer_size(peer); + } + + return len; +} + +static uint8_t *save_conf(const Group_c *g, uint8_t *data) +{ + *data = g->type; + ++data; + + memcpy(data, g->id, GROUP_ID_LENGTH); + data += GROUP_ID_LENGTH; + + host_to_lendian_bytes32(data, g->message_number); + data += sizeof(uint32_t); + + host_to_lendian_bytes16(data, g->lossy_message_number); + data += sizeof(uint16_t); + + host_to_lendian_bytes16(data, g->peer_number); + data += sizeof(uint16_t); + + uint8_t *const numsaved_location = data; + data += sizeof(uint32_t); + + *data = g->title_len; + ++data; + + memcpy(data, g->title, g->title_len); + data += g->title_len; + + uint32_t numsaved = 0; + + for (uint32_t j = 0; j < g->numpeers + g->numfrozen; ++j) { + const Group_Peer *peer = (j < g->numpeers) ? &g->group[j] : &g->frozen[j - g->numpeers]; + + if (id_equal(peer->real_pk, g->real_pk)) { + continue; + } + + data = save_peer(peer, data); + ++numsaved; + } + + host_to_lendian_bytes32(numsaved_location, numsaved); + + return data; +} + +static uint32_t conferences_section_size(const Group_Chats *g_c) +{ + uint32_t len = 0; + + for (uint16_t i = 0; i < g_c->num_chats; ++i) { + const Group_c *g = get_group_c(g_c, i); + + if (!g || g->status != GROUPCHAT_STATUS_CONNECTED) { + continue; + } + + len += saved_conf_size(g); + } + + return len; +} + +uint32_t conferences_size(const Group_Chats *g_c) +{ + return 2 * sizeof(uint32_t) + conferences_section_size(g_c); +} + +uint8_t *conferences_save(const Group_Chats *g_c, uint8_t *data) +{ + const uint32_t len = conferences_section_size(g_c); + data = state_write_section_header(data, STATE_COOKIE_TYPE, len, STATE_TYPE_CONFERENCES); + + for (uint16_t i = 0; i < g_c->num_chats; ++i) { + const Group_c *g = get_group_c(g_c, i); + + if (!g || g->status != GROUPCHAT_STATUS_CONNECTED) { + continue; + } + + data = save_conf(g, data); + } + + return data; +} + +static State_Load_Status load_conferences(Group_Chats *g_c, const uint8_t *data, uint32_t length) +{ + const uint8_t *init_data = data; + + while (length >= (uint32_t)(data - init_data) + SAVED_CONF_SIZE_CONSTANT) { + const int groupnumber = create_group_chat(g_c); + + if (groupnumber == -1) { + return STATE_LOAD_STATUS_ERROR; + } + + Group_c *g = &g_c->chats[groupnumber]; + + g->type = *data; + ++data; + + memcpy(g->id, data, GROUP_ID_LENGTH); + data += GROUP_ID_LENGTH; + + lendian_bytes_to_host32(&g->message_number, data); + data += sizeof(uint32_t); + + lendian_bytes_to_host16(&g->lossy_message_number, data); + data += sizeof(uint16_t); + + lendian_bytes_to_host16(&g->peer_number, data); + data += sizeof(uint16_t); + + lendian_bytes_to_host32(&g->numfrozen, data); + data += sizeof(uint32_t); + + g->frozen = (Group_Peer *)malloc(sizeof(Group_Peer) * g->numfrozen); + + if (g->frozen == nullptr) { + return STATE_LOAD_STATUS_ERROR; + } + + g->title_len = *data; + ++data; + + if (length < (uint32_t)(data - init_data) + g->title_len) { + return STATE_LOAD_STATUS_ERROR; + } + + memcpy(g->title, data, g->title_len); + data += g->title_len; + + for (uint32_t j = 0; j < g->numfrozen; ++j) { + if (length < (uint32_t)(data - init_data) + SAVED_PEER_SIZE_CONSTANT) { + return STATE_LOAD_STATUS_ERROR; + } + + Group_Peer *peer = &g->frozen[j]; + memset(peer, 0, sizeof(Group_Peer)); + + id_copy(peer->real_pk, data); + data += CRYPTO_PUBLIC_KEY_SIZE; + id_copy(peer->temp_pk, data); + data += CRYPTO_PUBLIC_KEY_SIZE; + + lendian_bytes_to_host16(&peer->peer_number, data); + data += sizeof(uint16_t); + + lendian_bytes_to_host64(&peer->last_active, data); + data += sizeof(uint64_t); + + peer->nick_len = *data; + ++data; + + if (length < (uint32_t)(data - init_data) + peer->nick_len) { + return STATE_LOAD_STATUS_ERROR; + } + + memcpy(peer->nick, data, peer->nick_len); + data += peer->nick_len; + } + + g->status = GROUPCHAT_STATUS_CONNECTED; + memcpy(g->real_pk, nc_get_self_public_key(g_c->m->net_crypto), CRYPTO_PUBLIC_KEY_SIZE); + const int peer_index = addpeer(g_c, groupnumber, g->real_pk, dht_get_self_public_key(g_c->m->dht), g->peer_number, + nullptr, true, false); + + if (peer_index == -1) { + return STATE_LOAD_STATUS_ERROR; + } + + setnick(g_c, groupnumber, peer_index, g_c->m->name, g_c->m->name_length, nullptr, false); + } + + return STATE_LOAD_STATUS_CONTINUE; +} + +bool conferences_load_state_section(Group_Chats *g_c, const uint8_t *data, uint32_t length, uint16_t type, + State_Load_Status *status) +{ + if (type != STATE_TYPE_CONFERENCES) { + return false; + } + + *status = load_conferences(g_c, data, length); + return true; +} + + /* Create new groupchat instance. */ Group_Chats *new_groupchats(Mono_Time *mono_time, Messenger *m) { @@ -2894,6 +3290,8 @@ Group_Chats *new_groupchats(Mono_Time *mono_time, Messenger *m) m->conferences_object = temp; m_callback_conference_invite(m, &handle_friend_invite_packet); + set_global_status_callback(m->fr_c, &g_handle_any_status, temp); + return temp; } @@ -2926,7 +3324,7 @@ void do_groupchats(Group_Chats *g_c, void *userdata) void kill_groupchats(Group_Chats *g_c) { for (uint16_t i = 0; i < g_c->num_chats; ++i) { - del_groupchat(g_c, i); + del_groupchat(g_c, i, false); } m_callback_conference_invite(g_c->m, nullptr); diff --git a/protocols/Tox/libtox/src/toxcore/group.h b/protocols/Tox/libtox/src/toxcore/group.h index 7acd46371e..83015273b3 100644 --- a/protocols/Tox/libtox/src/toxcore/group.h +++ b/protocols/Tox/libtox/src/toxcore/group.h @@ -238,38 +238,51 @@ void g_callback_peer_list_changed(Group_Chats *g_c, peer_list_changed_cb *functi */ int add_groupchat(Group_Chats *g_c, uint8_t type); -/* Delete a groupchat from the chats array. +/* Delete a groupchat from the chats array, informing the group first as + * appropriate. * * return 0 on success. * return -1 if groupnumber is invalid. */ -int del_groupchat(Group_Chats *g_c, uint32_t groupnumber); +int del_groupchat(Group_Chats *g_c, uint32_t groupnumber, bool leave_permanently); -/* Copy the public key of peernumber who is in groupnumber to pk. +/* Copy the public key of (frozen, if frozen is true) peernumber who is in + * groupnumber to pk. * pk must be CRYPTO_PUBLIC_KEY_SIZE long. * * return 0 on success * return -1 if groupnumber is invalid. * return -2 if peernumber is invalid. */ -int group_peer_pubkey(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, uint8_t *pk); +int group_peer_pubkey(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, uint8_t *pk, bool frozen); /* - * Return the size of peernumber's name. + * Return the size of (frozen, if frozen is true) peernumber's name. * * return -1 if groupnumber is invalid. * return -2 if peernumber is invalid. */ -int group_peername_size(const Group_Chats *g_c, uint32_t groupnumber, int32_t peernumber); +int group_peername_size(const Group_Chats *g_c, uint32_t groupnumber, int32_t peernumber, bool frozen); -/* Copy the name of peernumber who is in groupnumber to name. +/* Copy the name of (frozen, if frozen is true) peernumber who is in + * groupnumber to name. * name must be at least MAX_NAME_LENGTH long. * * return length of name if success * return -1 if groupnumber is invalid. * return -2 if peernumber is invalid. */ -int group_peername(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, uint8_t *name); +int group_peername(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, uint8_t *name, bool frozen); + +/* Copy last active timestamp of frozen peernumber who is in groupnumber to + * last_active. + * + * return 0 on success. + * return -1 if groupnumber is invalid. + * return -2 if peernumber is invalid. + */ +int group_frozen_last_active(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, + uint64_t *last_active); /* invite friendnumber to groupnumber * @@ -330,10 +343,11 @@ int group_title_get_size(const Group_Chats *g_c, uint32_t groupnumber); */ int group_title_get(const Group_Chats *g_c, uint32_t groupnumber, uint8_t *title); -/* Return the number of peers in the group chat on success. +/* Return the number of (frozen, if frozen is true) peers in the group chat on + * success. * return -1 if groupnumber is invalid. */ -int group_number_peers(const Group_Chats *g_c, uint32_t groupnumber); +int group_number_peers(const Group_Chats *g_c, uint32_t groupnumber, bool frozen); /* return 1 if the peernumber corresponds to ours. * return 0 if the peernumber is not ours. @@ -343,7 +357,7 @@ int group_number_peers(const Group_Chats *g_c, uint32_t groupnumber); */ int group_peernumber_is_ours(const Group_Chats *g_c, uint32_t groupnumber, int peernumber); -/* List all the peers in the group chat. +/* List all the (frozen, if frozen is true) peers in the group chat. * * Copies the names of the peers to the name[length][MAX_NAME_LENGTH] array. * @@ -354,7 +368,7 @@ int group_peernumber_is_ours(const Group_Chats *g_c, uint32_t groupnumber, int p * return -1 on failure. */ int group_names(const Group_Chats *g_c, uint32_t groupnumber, uint8_t names[][MAX_NAME_LENGTH], uint16_t lengths[], - uint16_t length); + uint16_t length, bool frozen); /* Set handlers for custom lossy packets. */ void group_lossy_packet_registerhandler(Group_Chats *g_c, uint8_t byte, lossy_packet_cb *function); @@ -448,6 +462,24 @@ 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 state section. + * + * @param data Data to load + * @param length Length of data + * @param type Type of section (STATE_TYPE_*) + * @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); diff --git a/protocols/Tox/libtox/src/toxcore/logger.c b/protocols/Tox/libtox/src/toxcore/logger.c index 51c30edec4..808332198c 100644 --- a/protocols/Tox/libtox/src/toxcore/logger.c +++ b/protocols/Tox/libtox/src/toxcore/logger.c @@ -104,7 +104,8 @@ void logger_write(const Logger *log, Logger_Level level, const char *file, int l #ifdef USE_STDERR_LOGGER log = &logger_stderr; #else - assert(!"NULL logger not permitted"); + fprintf(stderr, "NULL logger not permitted.\n"); + abort(); #endif } diff --git a/protocols/Tox/libtox/src/toxcore/logger.h b/protocols/Tox/libtox/src/toxcore/logger.h index 2cae7a0efd..3abed896c2 100644 --- a/protocols/Tox/libtox/src/toxcore/logger.h +++ b/protocols/Tox/libtox/src/toxcore/logger.h @@ -91,4 +91,18 @@ void logger_write( #define LOGGER_WARNING(log, ...) LOGGER_WRITE(log, LOGGER_LEVEL_WARNING, __VA_ARGS__) #define LOGGER_ERROR(log, ...) LOGGER_WRITE(log, LOGGER_LEVEL_ERROR , __VA_ARGS__) +#define LOGGER_FATAL(log, ...) \ + do { \ + LOGGER_ERROR(log, __VA_ARGS__); \ + abort(); \ + } while(0) + +#define LOGGER_ASSERT(log, cond, ...) \ + do { \ + if (!(cond)) { \ + LOGGER_ERROR(log, "Assertion failed"); \ + LOGGER_FATAL(log, __VA_ARGS__); \ + } \ + } while(0) + #endif // C_TOXCORE_TOXCORE_LOGGER_H diff --git a/protocols/Tox/libtox/src/toxcore/mono_time.h b/protocols/Tox/libtox/src/toxcore/mono_time.h index 503548f222..aa244baeb0 100644 --- a/protocols/Tox/libtox/src/toxcore/mono_time.h +++ b/protocols/Tox/libtox/src/toxcore/mono_time.h @@ -45,11 +45,26 @@ typedef struct Mono_Time Mono_Time; Mono_Time *mono_time_new(void); void mono_time_free(Mono_Time *mono_time); +/** + * Update mono_time; subsequent calls to mono_time_get or mono_time_is_timeout + * will use the time at the call to mono_time_update. + */ void mono_time_update(Mono_Time *mono_time); + +/** + * Return unix time since epoch in seconds. + */ uint64_t mono_time_get(const Mono_Time *mono_time); + +/** + * Return true iff timestamp is at least timeout seconds in the past. + */ bool mono_time_is_timeout(const Mono_Time *mono_time, uint64_t timestamp, uint64_t timeout); -/* return current monotonic time in milliseconds (ms). */ +/** + * Return current monotonic time in milliseconds (ms). The starting point is + * unspecified. + */ uint64_t current_time_monotonic(Mono_Time *mono_time); typedef uint64_t mono_time_current_time_cb(Mono_Time *mono_time, void *user_data); diff --git a/protocols/Tox/libtox/src/toxcore/net_crypto.c b/protocols/Tox/libtox/src/toxcore/net_crypto.c index 736b9c4a25..3ace3beaea 100644 --- a/protocols/Tox/libtox/src/toxcore/net_crypto.c +++ b/protocols/Tox/libtox/src/toxcore/net_crypto.c @@ -2529,16 +2529,18 @@ static void send_crypto_packets(Net_Crypto *c) unsigned int pos = conn->last_sendqueue_counter % CONGESTION_QUEUE_ARRAY_SIZE; conn->last_sendqueue_size[pos] = num_packets_array(&conn->send_array); - ++conn->last_sendqueue_counter; long signed int sum = 0; - sum = (long signed int)conn->last_sendqueue_size[(pos) % CONGESTION_QUEUE_ARRAY_SIZE] - - (long signed int)conn->last_sendqueue_size[(pos - (CONGESTION_QUEUE_ARRAY_SIZE - 1)) % CONGESTION_QUEUE_ARRAY_SIZE]; + sum = (long signed int)conn->last_sendqueue_size[pos] - + (long signed int)conn->last_sendqueue_size[(pos + 1) % CONGESTION_QUEUE_ARRAY_SIZE]; unsigned int n_p_pos = conn->last_sendqueue_counter % CONGESTION_LAST_SENT_ARRAY_SIZE; conn->last_num_packets_sent[n_p_pos] = packets_sent; conn->last_num_packets_resent[n_p_pos] = packets_resent; + conn->last_sendqueue_counter = (conn->last_sendqueue_counter + 1) % + (CONGESTION_QUEUE_ARRAY_SIZE * CONGESTION_LAST_SENT_ARRAY_SIZE); + bool direct_connected = 0; crypto_connection_status(c, i, &direct_connected, nullptr); diff --git a/protocols/Tox/libtox/src/toxcore/network.c b/protocols/Tox/libtox/src/toxcore/network.c index 917556ac44..5e5160d893 100644 --- a/protocols/Tox/libtox/src/toxcore/network.c +++ b/protocols/Tox/libtox/src/toxcore/network.c @@ -405,16 +405,23 @@ bool set_socket_dualstack(Socket sock) static uint32_t data_0(uint16_t buflen, const uint8_t *buffer) { - // TODO(iphydf): Do this differently. Right now this is most likely a - // misaligned memory access in reality, and definitely undefined behaviour - // in terms of C standard. - const uint8_t *const start = buffer + 1; - return buflen > 4 ? net_ntohl(*(const uint32_t *)start) : 0; + uint32_t data = 0; + + if (buflen > 4) { + net_unpack_u32(buffer + 1, &data); + } + + return data; } static uint32_t data_1(uint16_t buflen, const uint8_t *buffer) { - const uint8_t *const start = buffer + 5; - return buflen > 7 ? net_ntohl(*(const uint32_t *)start) : 0; + uint32_t data = 0; + + if (buflen > 7) { + net_unpack_u32(buffer + 5, &data); + } + + return data; } static void loglogdata(const Logger *log, const char *message, const uint8_t *buffer, @@ -426,13 +433,13 @@ static void loglogdata(const Logger *log, const char *message, const uint8_t *bu int error = net_error(); const char *strerror = net_new_strerror(error); LOGGER_TRACE(log, "[%2u] %s %3u%c %s:%u (%u: %s) | %04x%04x", - buffer[0], message, (buflen < 999 ? buflen : 999), 'E', + buffer[0], message, min_u16(buflen, 999), 'E', ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port.port), error, strerror, data_0(buflen, buffer), data_1(buflen, buffer)); net_kill_strerror(strerror); } else if ((res > 0) && ((size_t)res <= buflen)) { LOGGER_TRACE(log, "[%2u] %s %3u%c %s:%u (%u: %s) | %04x%04x", - buffer[0], message, (res < 999 ? res : 999), ((size_t)res < buflen ? '<' : '='), + buffer[0], message, min_u16(res, 999), ((size_t)res < buflen ? '<' : '='), ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port.port), 0, "OK", data_0(buflen, buffer), data_1(buflen, buffer)); } else { /* empty or overwrite */ diff --git a/protocols/Tox/libtox/src/toxcore/onion_client.c b/protocols/Tox/libtox/src/toxcore/onion_client.c index 1c3b34dabf..d11a91e81d 100644 --- a/protocols/Tox/libtox/src/toxcore/onion_client.c +++ b/protocols/Tox/libtox/src/toxcore/onion_client.c @@ -232,27 +232,35 @@ static int onion_add_path_node(Onion_Client *onion_c, IP_Port ip_port, const uin */ uint16_t onion_backup_nodes(const Onion_Client *onion_c, Node_format *nodes, uint16_t max_num) { - unsigned int i; - if (!max_num) { return 0; } - unsigned int num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES; + const uint16_t num_nodes = min_u16(onion_c->path_nodes_index, MAX_PATH_NODES); + uint16_t i = 0; - if (num_nodes == 0) { - return 0; + while (i < max_num && i < num_nodes) { + nodes[i] = onion_c->path_nodes[(onion_c->path_nodes_index - (1 + i)) % num_nodes]; + ++i; } - if (num_nodes < max_num) { - max_num = num_nodes; - } + for (uint16_t j = 0; i < max_num && j < MAX_PATH_NODES && j < onion_c->path_nodes_index_bs; ++j) { + bool already_saved = false; - for (i = 0; i < max_num; ++i) { - nodes[i] = onion_c->path_nodes[(onion_c->path_nodes_index - (1 + i)) % num_nodes]; + for (uint16_t k = 0; k < num_nodes; ++k) { + if (public_key_cmp(nodes[k].public_key, onion_c->path_nodes_bs[j].public_key) == 0) { + already_saved = true; + break; + } + } + + if (!already_saved) { + nodes[i] = onion_c->path_nodes_bs[j]; + ++i; + } } - return max_num; + return i; } /* Put up to max_num random nodes in nodes. @@ -267,7 +275,7 @@ static uint16_t random_nodes_path_onion(const Onion_Client *onion_c, Node_format return 0; } - const uint32_t num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES; + const uint16_t num_nodes = min_u16(onion_c->path_nodes_index, MAX_PATH_NODES); // if (dht_non_lan_connected(onion_c->dht)) { if (dht_isconnected(onion_c->dht)) { @@ -293,8 +301,7 @@ static uint16_t random_nodes_path_onion(const Onion_Client *onion_c, Node_format nodes[i] = onion_c->path_nodes[random_u32() % num_nodes]; } } else { - unsigned int num_nodes_bs = (onion_c->path_nodes_index_bs < MAX_PATH_NODES) ? onion_c->path_nodes_index_bs : - MAX_PATH_NODES; + const uint16_t num_nodes_bs = min_u16(onion_c->path_nodes_index_bs, MAX_PATH_NODES); if (num_nodes_bs == 0) { return 0; @@ -1611,9 +1618,8 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum) } if (count != MAX_ONION_CLIENTS) { - unsigned int num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES; - - unsigned int n = num_nodes; + const uint16_t num_nodes = min_u16(onion_c->path_nodes_index, MAX_PATH_NODES); + uint16_t n = num_nodes; if (num_nodes > (MAX_ONION_CLIENTS / 2)) { n = (MAX_ONION_CLIENTS / 2); @@ -1732,14 +1738,14 @@ static void do_announce(Onion_Client *onion_c) } if (count != MAX_ONION_CLIENTS_ANNOUNCE) { - unsigned int num_nodes; + uint16_t num_nodes; Node_format *path_nodes; if (random_u08() % 2 == 0 || onion_c->path_nodes_index == 0) { - num_nodes = (onion_c->path_nodes_index_bs < MAX_PATH_NODES) ? onion_c->path_nodes_index_bs : MAX_PATH_NODES; + num_nodes = min_u16(onion_c->path_nodes_index_bs, MAX_PATH_NODES); path_nodes = onion_c->path_nodes_bs; } else { - num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES; + num_nodes = min_u16(onion_c->path_nodes_index, MAX_PATH_NODES); path_nodes = onion_c->path_nodes; } diff --git a/protocols/Tox/libtox/src/toxcore/state.c b/protocols/Tox/libtox/src/toxcore/state.c index 29b4af88a3..bca7a1512d 100644 --- a/protocols/Tox/libtox/src/toxcore/state.c +++ b/protocols/Tox/libtox/src/toxcore/state.c @@ -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,34 @@ 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_bytes64(uint8_t *dest, uint64_t num) +{ +#ifdef WORDS_BIGENDIAN + num = ((num << 8) & 0xFF00FF00FF00FF00) | ((num >> 8) & 0xFF00FF00FF00FF); + num = ((num << 16) & 0xFFFF0000FFFF0000) | ((num >> 16) & 0xFFFF0000FFFF); + num = (num << 32) | (num >> 32); +#endif + memcpy(dest, &num, sizeof(uint64_t)); +} + +void lendian_bytes_to_host64(uint64_t *dest, const uint8_t *lendian) +{ + uint64_t d; + memcpy(&d, lendian, sizeof(uint64_t)); +#ifdef WORDS_BIGENDIAN + d = ((d << 8) & 0xFF00FF00FF00FF00) | ((d >> 8) & 0xFF00FF00FF00FF); + d = ((d << 16) & 0xFFFF0000FFFF0000) | ((d >> 16) & 0xFFFF0000FFFF); + d = (d << 32) | (d >> 32); +#endif + *dest = d; +} + +void host_to_lendian_bytes32(uint8_t *dest, uint32_t num) { #ifdef WORDS_BIGENDIAN num = ((num << 8) & 0xFF00FF00) | ((num >> 8) & 0xFF00FF); @@ -93,7 +115,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 +125,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; +} diff --git a/protocols/Tox/libtox/src/toxcore/state.h b/protocols/Tox/libtox/src/toxcore/state.h index 2d1f62c36d..829036d8dd 100644 --- a/protocols/Tox/libtox/src/toxcore/state.h +++ b/protocols/Tox/libtox/src/toxcore/state.h @@ -18,6 +18,23 @@ 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_CONFERENCES = 20, + 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 +56,16 @@ 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_lendian_bytes64(uint8_t *dest, uint64_t num); +void lendian_bytes_to_host64(uint64_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_lendian32(uint8_t *dest, uint32_t num); -void lendian_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" diff --git a/protocols/Tox/libtox/src/toxcore/tox.api.h b/protocols/Tox/libtox/src/toxcore/tox.api.h index 5378847358..237254de73 100644 --- a/protocols/Tox/libtox/src/toxcore/tox.api.h +++ b/protocols/Tox/libtox/src/toxcore/tox.api.h @@ -182,7 +182,7 @@ const VERSION_MINOR = 2; * The patch or revision number. Incremented when bugfixes are applied without * changing any functionality or API or ABI. */ -const VERSION_PATCH = 8; +const VERSION_PATCH = 9; /** * A macro to check at preprocessing time whether the client code is compatible @@ -2257,32 +2257,32 @@ namespace conference { CONFERENCE_NOT_FOUND, } - - namespace peer { - + /** + * Error codes for peer info queries. + */ + error for peer_query { /** - * Error codes for peer info queries. + * The conference number passed did not designate a valid conference. */ - error for query { - /** - * The conference number passed did not designate a valid conference. - */ - CONFERENCE_NOT_FOUND, - /** - * The peer number passed did not designate a valid peer. - */ - PEER_NOT_FOUND, - /** - * The client is not connected to the conference. - */ - NO_CONNECTION, - } + CONFERENCE_NOT_FOUND, + /** + * The peer number passed did not designate a valid peer. + */ + PEER_NOT_FOUND, + /** + * The client is not connected to the conference. + */ + NO_CONNECTION, + } + + + namespace peer { /** * Return the number of peers in the conference. Return value is unspecified on failure. */ const uint32_t count(uint32_t conference_number) - with error for query; + with error for peer_query; uint8_t[size] name { @@ -2290,7 +2290,7 @@ namespace conference { * Return the length of the peer's name. Return value is unspecified on failure. */ size(uint32_t conference_number, uint32_t peer_number) - with error for query; + with error for peer_query; /** * Copy the name of peer_number who is in conference_number to name. @@ -2299,7 +2299,7 @@ namespace conference { * @return true on success. */ get(uint32_t conference_number, uint32_t peer_number) - with error for query; + with error for peer_query; } /** @@ -2310,17 +2310,63 @@ namespace conference { */ uint8_t[PUBLIC_KEY_SIZE] public_key { get(uint32_t conference_number, uint32_t peer_number) - with error for query; + with error for peer_query; } /** * Return true if passed peer_number corresponds to our own. */ const bool number_is_ours(uint32_t conference_number, uint32_t peer_number) - with error for query; + with error for peer_query; } + namespace offline_peer { + + /** + * Return the number of offline peers in the conference. Return value is unspecified on failure. + */ + const uint32_t count(uint32_t conference_number) + with error for peer_query; + + uint8_t[size] name { + + /** + * Return the length of the offline peer's name. Return value is unspecified on failure. + */ + size(uint32_t conference_number, uint32_t offline_peer_number) + with error for peer_query; + + /** + * Copy the name of offline_peer_number who is in conference_number to name. + * name must be at least $MAX_NAME_LENGTH long. + * + * @return true on success. + */ + get(uint32_t conference_number, uint32_t offline_peer_number) + with error for peer_query; + } + + /** + * Copy the public key of offline_peer_number who is in conference_number to public_key. + * public_key must be $PUBLIC_KEY_SIZE long. + * + * @return true on success. + */ + uint8_t[PUBLIC_KEY_SIZE] public_key { + get(uint32_t conference_number, uint32_t offline_peer_number) + with error for peer_query; + } + + /** + * Return a unix-time timestamp of the last time offline_peer_number was seen to be active. + */ + uint64_t last_active { + get(uint32_t conference_number, uint32_t offline_peer_number) + with error for peer_query; + } + + } /** * Invites a friend to a conference. diff --git a/protocols/Tox/libtox/src/toxcore/tox.c b/protocols/Tox/libtox/src/toxcore/tox.c index 5258e9b6e3..d59094afa3 100644 --- a/protocols/Tox/libtox/src/toxcore/tox.c +++ b/protocols/Tox/libtox/src/toxcore/tox.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) +{ + const Tox *tox = (const 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]; + const 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)); @@ -530,25 +575,52 @@ void tox_kill(Tox *tox) } Messenger *m = tox->m; - assert(m->msi_packet == nullptr && "Attempted to kill tox while toxav is still alive"); + LOGGER_ASSERT(m->log, m->msi_packet == nullptr, "Attempted to kill tox while toxav is still alive"); kill_groupchats(m->conferences_object); kill_messenger(m); mono_time_free(tox->mono_time); 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) @@ -565,7 +637,7 @@ bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *pub IP_Port *root; - int32_t count = net_getipport(host, &root, TOX_SOCK_DGRAM); + const int32_t count = net_getipport(host, &root, TOX_SOCK_DGRAM); if (count == -1) { net_freeipport(root); @@ -641,7 +713,7 @@ Tox_Connection tox_self_get_connection_status(const Tox *tox) { const Messenger *m = tox->m; - unsigned int ret = onion_connection_status(m->onion_c); + const unsigned int ret = onion_connection_status(m->onion_c); if (ret == 2) { return TOX_CONNECTION_UDP; @@ -793,7 +865,7 @@ Tox_User_Status tox_self_get_status(const Tox *tox) return (Tox_User_Status)status; } -static void set_friend_error(int32_t ret, Tox_Err_Friend_Add *error) +static void set_friend_error(const Logger *log, int32_t ret, Tox_Err_Friend_Add *error) { switch (ret) { case FAERR_TOOLONG: @@ -826,7 +898,7 @@ static void set_friend_error(int32_t ret, Tox_Err_Friend_Add *error) default: /* can't happen */ - assert(!"impossible: unknown friend-add error"); + LOGGER_FATAL(log, "impossible: unknown friend-add error"); break; } } @@ -840,14 +912,14 @@ uint32_t tox_friend_add(Tox *tox, const uint8_t *address, const uint8_t *message } Messenger *m = tox->m; - int32_t ret = m_addfriend(m, address, message, length); + const int32_t ret = m_addfriend(m, address, message, length); if (ret >= 0) { SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_OK); return ret; } - set_friend_error(ret, error); + set_friend_error(m->log, ret, error); return UINT32_MAX; } @@ -859,21 +931,21 @@ uint32_t tox_friend_add_norequest(Tox *tox, const uint8_t *public_key, Tox_Err_F } Messenger *m = tox->m; - int32_t ret = m_addfriend_norequest(m, public_key); + const int32_t ret = m_addfriend_norequest(m, public_key); if (ret >= 0) { SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_OK); return ret; } - set_friend_error(ret, error); + set_friend_error(m->log, ret, error); return UINT32_MAX; } bool tox_friend_delete(Tox *tox, uint32_t friend_number, Tox_Err_Friend_Delete *error) { Messenger *m = tox->m; - int ret = m_delfriend(m, friend_number); + const int ret = m_delfriend(m, friend_number); // TODO(irungentoo): handle if realloc fails? if (ret == -1) { @@ -893,7 +965,7 @@ uint32_t tox_friend_by_public_key(const Tox *tox, const uint8_t *public_key, Tox } const Messenger *m = tox->m; - int32_t ret = getfriend_id(m, public_key); + const int32_t ret = getfriend_id(m, public_key); if (ret == -1) { SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND); @@ -931,7 +1003,7 @@ bool tox_friend_exists(const Tox *tox, uint32_t friend_number) uint64_t tox_friend_get_last_online(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Get_Last_Online *error) { const Messenger *m = tox->m; - uint64_t timestamp = m_get_last_online(m, friend_number); + const uint64_t timestamp = m_get_last_online(m, friend_number); if (timestamp == UINT64_MAX) { SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_LAST_ONLINE_FRIEND_NOT_FOUND); @@ -960,7 +1032,7 @@ void tox_self_get_friend_list(const Tox *tox, uint32_t *friend_list) size_t tox_friend_get_name_size(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error) { const Messenger *m = tox->m; - int ret = m_get_name_size(m, friend_number); + const int ret = m_get_name_size(m, friend_number); if (ret == -1) { SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); @@ -979,7 +1051,7 @@ bool tox_friend_get_name(const Tox *tox, uint32_t friend_number, uint8_t *name, } const Messenger *m = tox->m; - int ret = getname(m, friend_number, name); + const int ret = getname(m, friend_number, name); if (ret == -1) { SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); @@ -998,7 +1070,7 @@ void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *callback) size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error) { const Messenger *m = tox->m; - int ret = m_get_statusmessage_size(m, friend_number); + const int ret = m_get_statusmessage_size(m, friend_number); if (ret == -1) { SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); @@ -1026,7 +1098,7 @@ bool tox_friend_get_status_message(const Tox *tox, uint32_t friend_number, uint8 } const int ret = m_copy_statusmessage(m, friend_number, status_message, size); - assert(ret == size && "concurrency problem: friend status message changed"); + LOGGER_ASSERT(m->log, ret == size, "concurrency problem: friend status message changed"); SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK); return ret == size; @@ -1041,7 +1113,7 @@ Tox_User_Status tox_friend_get_status(const Tox *tox, uint32_t friend_number, To { const Messenger *m = tox->m; - int ret = m_get_userstatus(m, friend_number); + const int ret = m_get_userstatus(m, friend_number); if (ret == USERSTATUS_INVALID) { SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); @@ -1061,7 +1133,7 @@ Tox_Connection tox_friend_get_connection_status(const Tox *tox, uint32_t friend_ { const Messenger *m = tox->m; - int ret = m_get_friend_connectionstatus(m, friend_number); + const int ret = m_get_friend_connectionstatus(m, friend_number); if (ret == -1) { SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); @@ -1080,7 +1152,7 @@ void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_statu bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error) { const Messenger *m = tox->m; - int ret = m_get_istyping(m, friend_number); + const int ret = m_get_istyping(m, friend_number); if (ret == -1) { SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); @@ -1109,7 +1181,7 @@ bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool typing, Tox_Err_ return 1; } -static void set_message_error(int ret, Tox_Err_Friend_Send_Message *error) +static void set_message_error(const Logger *log, int ret, Tox_Err_Friend_Send_Message *error) { switch (ret) { case 0: @@ -1133,9 +1205,12 @@ static void set_message_error(int ret, Tox_Err_Friend_Send_Message *error) break; case -5: + LOGGER_FATAL(log, "impossible: Messenger and Tox disagree on message types"); + break; + default: /* can't happen */ - assert(!"impossible: unknown send-message error"); + LOGGER_FATAL(log, "impossible: unknown send-message error: %d", ret); break; } } @@ -1155,7 +1230,7 @@ uint32_t tox_friend_send_message(Tox *tox, uint32_t friend_number, Tox_Message_T Messenger *m = tox->m; uint32_t message_id = 0; - set_message_error(m_send_message_generic(m, friend_number, type, message, length, &message_id), error); + set_message_error(m->log, m_send_message_generic(m, friend_number, type, message, length, &message_id), error); return message_id; } @@ -1188,7 +1263,7 @@ bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, To Tox_Err_File_Control *error) { Messenger *m = tox->m; - int ret = file_control(m, friend_number, file_number, control); + const int ret = file_control(m, friend_number, file_number, control); if (ret == 0) { SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_OK); @@ -1237,7 +1312,7 @@ bool tox_file_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint6 Tox_Err_File_Seek *error) { Messenger *m = tox->m; - int ret = file_seek(m, friend_number, file_number, position); + const int ret = file_seek(m, friend_number, file_number, position); if (ret == 0) { SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_OK); @@ -1289,7 +1364,7 @@ bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_ } const Messenger *m = tox->m; - int ret = file_get_id(m, friend_number, file_number, file_id); + const int ret = file_get_id(m, friend_number, file_number, file_id); if (ret == 0) { SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_OK); @@ -1322,7 +1397,7 @@ uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t } Messenger *m = tox->m; - long int file_num = new_filesender(m, friend_number, kind, file_size, file_id, filename, filename_length); + const long int file_num = new_filesender(m, friend_number, kind, file_size, file_id, filename, filename_length); if (file_num >= 0) { SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_OK); @@ -1355,7 +1430,7 @@ bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, size_t length, Tox_Err_File_Send_Chunk *error) { Messenger *m = tox->m; - int ret = file_data(m, friend_number, file_number, position, data, length); + const int ret = file_data(m, friend_number, file_number, position, data, length); if (ret == 0) { SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_OK); @@ -1444,7 +1519,7 @@ void tox_callback_conference_peer_list_changed(Tox *tox, tox_conference_peer_lis uint32_t tox_conference_new(Tox *tox, Tox_Err_Conference_New *error) { Messenger *m = tox->m; - int ret = add_groupchat(m->conferences_object, GROUPCHAT_TYPE_TEXT); + const int ret = add_groupchat(m->conferences_object, GROUPCHAT_TYPE_TEXT); if (ret == -1) { SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_NEW_INIT); @@ -1458,7 +1533,7 @@ uint32_t tox_conference_new(Tox *tox, Tox_Err_Conference_New *error) bool tox_conference_delete(Tox *tox, uint32_t conference_number, Tox_Err_Conference_Delete *error) { Messenger *m = tox->m; - int ret = del_groupchat(m->conferences_object, conference_number); + const int ret = del_groupchat(m->conferences_object, conference_number, true); if (ret == -1) { SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_DELETE_CONFERENCE_NOT_FOUND); @@ -1472,7 +1547,7 @@ bool tox_conference_delete(Tox *tox, uint32_t conference_number, Tox_Err_Confere uint32_t tox_conference_peer_count(const Tox *tox, uint32_t conference_number, Tox_Err_Conference_Peer_Query *error) { const Messenger *m = tox->m; - int ret = group_number_peers(m->conferences_object, conference_number); + const int ret = group_number_peers(m->conferences_object, conference_number, false); if (ret == -1) { SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND); @@ -1487,7 +1562,7 @@ size_t tox_conference_peer_get_name_size(const Tox *tox, uint32_t conference_num Tox_Err_Conference_Peer_Query *error) { const Messenger *m = tox->m; - int ret = group_peername_size(m->conferences_object, conference_number, peer_number); + const int ret = group_peername_size(m->conferences_object, conference_number, peer_number, false); switch (ret) { case -1: @@ -1507,7 +1582,7 @@ bool tox_conference_peer_get_name(const Tox *tox, uint32_t conference_number, ui Tox_Err_Conference_Peer_Query *error) { const Messenger *m = tox->m; - int ret = group_peername(m->conferences_object, conference_number, peer_number, name); + const int ret = group_peername(m->conferences_object, conference_number, peer_number, name, false); switch (ret) { case -1: @@ -1527,7 +1602,7 @@ bool tox_conference_peer_get_public_key(const Tox *tox, uint32_t conference_numb uint8_t *public_key, Tox_Err_Conference_Peer_Query *error) { const Messenger *m = tox->m; - int ret = group_peer_pubkey(m->conferences_object, conference_number, peer_number, public_key); + const int ret = group_peer_pubkey(m->conferences_object, conference_number, peer_number, public_key, false); switch (ret) { case -1: @@ -1547,7 +1622,7 @@ bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t conference_numb Tox_Err_Conference_Peer_Query *error) { const Messenger *m = tox->m; - int ret = group_peernumber_is_ours(m->conferences_object, conference_number, peer_number); + const int ret = group_peernumber_is_ours(m->conferences_object, conference_number, peer_number); switch (ret) { case -1: @@ -1567,11 +1642,111 @@ bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t conference_numb return ret; } +uint32_t tox_conference_offline_peer_count(const Tox *tox, uint32_t conference_number, + Tox_Err_Conference_Peer_Query *error) +{ + const Messenger *m = tox->m; + const int ret = group_number_peers(m->conferences_object, conference_number, true); + + if (ret == -1) { + SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND); + return UINT32_MAX; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK); + return ret; +} + +size_t tox_conference_offline_peer_get_name_size(const Tox *tox, uint32_t conference_number, + uint32_t offline_peer_number, + Tox_Err_Conference_Peer_Query *error) +{ + const Messenger *m = tox->m; + const int ret = group_peername_size(m->conferences_object, conference_number, offline_peer_number, true); + + switch (ret) { + case -1: + SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND); + return -1; + + case -2: + SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND); + return -1; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK); + return ret; +} + +bool tox_conference_offline_peer_get_name(const Tox *tox, uint32_t conference_number, uint32_t offline_peer_number, + uint8_t *name, + Tox_Err_Conference_Peer_Query *error) +{ + const Messenger *m = tox->m; + const int ret = group_peername(m->conferences_object, conference_number, offline_peer_number, name, true); + + switch (ret) { + case -1: + SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND); + return false; + + case -2: + SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND); + return false; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK); + return true; +} + +bool tox_conference_offline_peer_get_public_key(const Tox *tox, uint32_t conference_number, + uint32_t offline_peer_number, + uint8_t *public_key, Tox_Err_Conference_Peer_Query *error) +{ + const Messenger *m = tox->m; + const int ret = group_peer_pubkey(m->conferences_object, conference_number, offline_peer_number, public_key, true); + + switch (ret) { + case -1: + SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND); + return false; + + case -2: + SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND); + return false; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK); + return true; +} + +uint64_t tox_conference_offline_peer_get_last_active(const Tox *tox, uint32_t conference_number, + uint32_t offline_peer_number, + Tox_Err_Conference_Peer_Query *error) +{ + const Messenger *m = tox->m; + uint64_t last_active = UINT64_MAX; + const int ret = group_frozen_last_active(m->conferences_object, conference_number, offline_peer_number, &last_active); + + switch (ret) { + case -1: + SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND); + return UINT64_MAX; + + case -2: + SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND); + return UINT64_MAX; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK); + return last_active; +} + bool tox_conference_invite(Tox *tox, uint32_t friend_number, uint32_t conference_number, Tox_Err_Conference_Invite *error) { Messenger *m = tox->m; - int ret = invite_friend(m->conferences_object, friend_number, conference_number); + const int ret = invite_friend(m->conferences_object, friend_number, conference_number); switch (ret) { case -1: @@ -1595,7 +1770,7 @@ uint32_t tox_conference_join(Tox *tox, uint32_t friend_number, const uint8_t *co Tox_Err_Conference_Join *error) { Messenger *m = tox->m; - int ret = join_groupchat(m->conferences_object, friend_number, GROUPCHAT_TYPE_TEXT, cookie, length); + const int ret = join_groupchat(m->conferences_object, friend_number, GROUPCHAT_TYPE_TEXT, cookie, length); switch (ret) { case -1: @@ -1664,7 +1839,7 @@ bool tox_conference_send_message(Tox *tox, uint32_t conference_number, Tox_Messa size_t tox_conference_get_title_size(const Tox *tox, uint32_t conference_number, Tox_Err_Conference_Title *error) { const Messenger *m = tox->m; - int ret = group_title_get_size(m->conferences_object, conference_number); + const int ret = group_title_get_size(m->conferences_object, conference_number); switch (ret) { case -1: @@ -1684,7 +1859,7 @@ bool tox_conference_get_title(const Tox *tox, uint32_t conference_number, uint8_ Tox_Err_Conference_Title *error) { const Messenger *m = tox->m; - int ret = group_title_get(m->conferences_object, conference_number, title); + const int ret = group_title_get(m->conferences_object, conference_number, title); switch (ret) { case -1: @@ -1704,7 +1879,7 @@ bool tox_conference_set_title(Tox *tox, uint32_t conference_number, const uint8_ Tox_Err_Conference_Title *error) { Messenger *m = tox->m; - int ret = group_title_send(m->conferences_object, conference_number, title, length); + const int ret = group_title_send(m->conferences_object, conference_number, title, length); switch (ret) { case -1: @@ -1733,7 +1908,7 @@ size_t tox_conference_get_chatlist_size(const Tox *tox) void tox_conference_get_chatlist(const Tox *tox, uint32_t *chatlist) { const Messenger *m = tox->m; - size_t list_size = tox_conference_get_chatlist_size(tox); + const size_t list_size = tox_conference_get_chatlist_size(tox); copy_chatlist(m->conferences_object, chatlist, list_size); } @@ -1741,7 +1916,7 @@ Tox_Conference_Type tox_conference_get_type(const Tox *tox, uint32_t conference_ Tox_Err_Conference_Get_Type *error) { const Messenger *m = tox->m; - int ret = group_get_type(m->conferences_object, conference_number); + const int ret = group_get_type(m->conferences_object, conference_number); if (ret == -1) { SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_GET_TYPE_CONFERENCE_NOT_FOUND); @@ -1770,7 +1945,7 @@ uint32_t tox_conference_by_id(const Tox *tox, const uint8_t *id, Tox_Err_Confere return UINT32_MAX; } - int32_t ret = conference_by_id(tox->m->conferences_object, id); + const int32_t ret = conference_by_id(tox->m->conferences_object, id); if (ret == -1) { SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_BY_ID_NOT_FOUND); @@ -1855,7 +2030,7 @@ bool tox_friend_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_ return 0; } - int ret = m_send_custom_lossy_packet(m, friend_number, data, length); + const int ret = m_send_custom_lossy_packet(m, friend_number, data, length); set_custom_packet_error(ret, error); @@ -1886,7 +2061,7 @@ bool tox_friend_send_lossless_packet(Tox *tox, uint32_t friend_number, const uin return 0; } - int ret = send_custom_lossless_packet(m, friend_number, data, length); + const int ret = send_custom_lossless_packet(m, friend_number, data, length); set_custom_packet_error(ret, error); @@ -1913,7 +2088,7 @@ void tox_self_get_dht_id(const Tox *tox, uint8_t *dht_id) uint16_t tox_self_get_udp_port(const Tox *tox, Tox_Err_Get_Port *error) { const Messenger *m = tox->m; - uint16_t port = net_htons(net_port(m->net)); + const uint16_t port = net_htons(net_port(m->net)); if (port) { SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK); diff --git a/protocols/Tox/libtox/src/toxcore/tox.h b/protocols/Tox/libtox/src/toxcore/tox.h index ee8a01cc7d..ba67d5ad30 100644 --- a/protocols/Tox/libtox/src/toxcore/tox.h +++ b/protocols/Tox/libtox/src/toxcore/tox.h @@ -183,7 +183,7 @@ uint32_t tox_version_minor(void); * The patch or revision number. Incremented when bugfixes are applied without * changing any functionality or API or ABI. */ -#define TOX_VERSION_PATCH 8 +#define TOX_VERSION_PATCH 9 uint32_t tox_version_patch(void); @@ -2631,6 +2631,42 @@ bool tox_conference_peer_get_public_key(const Tox *tox, uint32_t conference_numb bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t conference_number, uint32_t peer_number, TOX_ERR_CONFERENCE_PEER_QUERY *error); +/** + * Return the number of offline peers in the conference. Return value is unspecified on failure. + */ +uint32_t tox_conference_offline_peer_count(const Tox *tox, uint32_t conference_number, + TOX_ERR_CONFERENCE_PEER_QUERY *error); + +/** + * Return the length of the offline peer's name. Return value is unspecified on failure. + */ +size_t tox_conference_offline_peer_get_name_size(const Tox *tox, uint32_t conference_number, + uint32_t offline_peer_number, TOX_ERR_CONFERENCE_PEER_QUERY *error); + +/** + * Copy the name of offline_peer_number who is in conference_number to name. + * name must be at least TOX_MAX_NAME_LENGTH long. + * + * @return true on success. + */ +bool tox_conference_offline_peer_get_name(const Tox *tox, uint32_t conference_number, uint32_t offline_peer_number, + uint8_t *name, TOX_ERR_CONFERENCE_PEER_QUERY *error); + +/** + * Copy the public key of offline_peer_number who is in conference_number to public_key. + * public_key must be TOX_PUBLIC_KEY_SIZE long. + * + * @return true on success. + */ +bool tox_conference_offline_peer_get_public_key(const Tox *tox, uint32_t conference_number, + uint32_t offline_peer_number, uint8_t *public_key, TOX_ERR_CONFERENCE_PEER_QUERY *error); + +/** + * Return a unix-time timestamp of the last time offline_peer_number was seen to be active. + */ +uint64_t tox_conference_offline_peer_get_last_active(const Tox *tox, uint32_t conference_number, + uint32_t offline_peer_number, TOX_ERR_CONFERENCE_PEER_QUERY *error); + typedef enum TOX_ERR_CONFERENCE_INVITE { /** diff --git a/protocols/Tox/libtox/src/toxcore/tox_api.c b/protocols/Tox/libtox/src/toxcore/tox_api.c index 871239686a..025c745623 100644 --- a/protocols/Tox/libtox/src/toxcore/tox_api.c +++ b/protocols/Tox/libtox/src/toxcore/tox_api.c @@ -19,6 +19,8 @@ CONST_FUNCTION(version_minor, VERSION_MINOR) CONST_FUNCTION(version_patch, VERSION_PATCH) CONST_FUNCTION(public_key_size, PUBLIC_KEY_SIZE) CONST_FUNCTION(secret_key_size, SECRET_KEY_SIZE) +CONST_FUNCTION(conference_uid_size, CONFERENCE_UID_SIZE) +CONST_FUNCTION(conference_id_size, CONFERENCE_ID_SIZE) CONST_FUNCTION(nospam_size, NOSPAM_SIZE) CONST_FUNCTION(address_size, ADDRESS_SIZE) CONST_FUNCTION(max_name_length, MAX_NAME_LENGTH) @@ -44,14 +46,14 @@ void tox_options_set_##ns##name(struct Tox_Options *options, type name) \ ACCESSORS(bool,, ipv6_enabled) ACCESSORS(bool,, udp_enabled) -ACCESSORS(TOX_PROXY_TYPE, proxy_, type) +ACCESSORS(Tox_Proxy_Type, proxy_, type) ACCESSORS(const char *, proxy_, host) ACCESSORS(uint16_t, proxy_, port) ACCESSORS(uint16_t,, start_port) ACCESSORS(uint16_t,, end_port) ACCESSORS(uint16_t,, tcp_port) ACCESSORS(bool,, hole_punching_enabled) -ACCESSORS(TOX_SAVEDATA_TYPE, savedata_, type) +ACCESSORS(Tox_Savedata_Type, savedata_, type) ACCESSORS(size_t, savedata_, length) ACCESSORS(tox_log_cb *, log_, callback) ACCESSORS(void *, log_, user_data) @@ -81,7 +83,7 @@ void tox_options_default(struct Tox_Options *options) } } -struct Tox_Options *tox_options_new(TOX_ERR_OPTIONS_NEW *error) +struct Tox_Options *tox_options_new(Tox_Err_Options_New *error) { struct Tox_Options *options = (struct Tox_Options *)malloc(sizeof(struct Tox_Options)); diff --git a/protocols/Tox/libtox/src/toxcore/util.c b/protocols/Tox/libtox/src/toxcore/util.c index adc0dc09dc..73e16c4585 100644 --- a/protocols/Tox/libtox/src/toxcore/util.c +++ b/protocols/Tox/libtox/src/toxcore/util.c @@ -95,21 +95,53 @@ int create_recursive_mutex(pthread_mutex_t *mutex) return 0; } +int16_t max_s16(int16_t a, int16_t b) +{ + return a > b ? a : b; +} int32_t max_s32(int32_t a, int32_t b) { return a > b ? a : b; } +int64_t max_s64(int64_t a, int64_t b) +{ + return a > b ? a : b; +} +int16_t min_s16(int16_t a, int16_t b) +{ + return a < b ? a : b; +} int32_t min_s32(int32_t a, int32_t b) { return a < b ? a : b; } +int64_t min_s64(int64_t a, int64_t b) +{ + return a < b ? a : b; +} + +uint16_t max_u16(uint16_t a, uint16_t b) +{ + return a > b ? a : b; +} +uint32_t max_u32(uint32_t a, uint32_t b) +{ + return a > b ? a : b; +} +uint64_t max_u64(uint64_t a, uint64_t b) +{ + return a > b ? a : b; +} +uint16_t min_u16(uint16_t a, uint16_t b) +{ + return a < b ? a : b; +} uint32_t min_u32(uint32_t a, uint32_t b) { return a < b ? a : b; } - uint64_t min_u64(uint64_t a, uint64_t b) { return a < b ? a : b; diff --git a/protocols/Tox/libtox/src/toxcore/util.h b/protocols/Tox/libtox/src/toxcore/util.h index 8558672473..79f5deb528 100644 --- a/protocols/Tox/libtox/src/toxcore/util.h +++ b/protocols/Tox/libtox/src/toxcore/util.h @@ -46,8 +46,23 @@ void net_to_host(uint8_t *num, uint16_t numbytes); /* Returns -1 if failed or 0 if success */ int create_recursive_mutex(pthread_mutex_t *mutex); +// Safe min/max functions with specific types. This forces the conversion to the +// desired type before the comparison expression, giving the choice of +// conversion to the caller. Use these instead of inline comparisons or MIN/MAX +// macros (effectively inline comparisons). +int16_t max_s16(int16_t a, int16_t b); int32_t max_s32(int32_t a, int32_t b); +int64_t max_s64(int64_t a, int64_t b); + +int16_t min_s16(int16_t a, int16_t b); int32_t min_s32(int32_t a, int32_t b); +int64_t min_s64(int64_t a, int64_t b); + +uint16_t max_u16(uint16_t a, uint16_t b); +uint32_t max_u32(uint32_t a, uint32_t b); +uint64_t max_u64(uint64_t a, uint64_t b); + +uint16_t min_u16(uint16_t a, uint16_t b); uint32_t min_u32(uint32_t a, uint32_t b); uint64_t min_u64(uint64_t a, uint64_t b); diff --git a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.api.h b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.api.h index 28d7a650a4..c6a395f3eb 100644 --- a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.api.h +++ b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.api.h @@ -313,5 +313,10 @@ static bool is_data_encrypted(const uint8_t *data); } #endif +typedef TOX_ERR_KEY_DERIVATION Tox_Err_Key_Derivation; +typedef TOX_ERR_ENCRYPTION Tox_Err_Encryption; +typedef TOX_ERR_DECRYPTION Tox_Err_Decryption; +typedef TOX_ERR_GET_SALT Tox_Err_Get_Salt; + #endif // C_TOXCORE_TOXENCRYPTSAVE_TOXENCRYPTSAVE_H %} diff --git a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c index 6221b0b6b9..a3e70b2f1e 100644 --- a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c +++ b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c @@ -91,7 +91,7 @@ void tox_pass_key_free(Tox_Pass_Key *pass_key) * success does not say anything about the validity of the data, only that data of * the appropriate size was copied */ -bool tox_get_salt(const uint8_t *data, uint8_t *salt, TOX_ERR_GET_SALT *error) +bool tox_get_salt(const uint8_t *data, uint8_t *salt, Tox_Err_Get_Salt *error) { if (!data || !salt) { SET_ERROR_PARAMETER(error, TOX_ERR_GET_SALT_NULL); @@ -121,7 +121,7 @@ bool tox_get_salt(const uint8_t *data, uint8_t *salt, TOX_ERR_GET_SALT *error) * returns true on success */ Tox_Pass_Key *tox_pass_key_derive(const uint8_t *passphrase, size_t pplength, - TOX_ERR_KEY_DERIVATION *error) + Tox_Err_Key_Derivation *error) { uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; random_bytes(salt, sizeof salt); @@ -132,7 +132,7 @@ Tox_Pass_Key *tox_pass_key_derive(const uint8_t *passphrase, size_t pplength, * The salt must be TOX_PASS_SALT_LENGTH bytes in length. */ Tox_Pass_Key *tox_pass_key_derive_with_salt(const uint8_t *passphrase, size_t pplength, - const uint8_t *salt, TOX_ERR_KEY_DERIVATION *error) + const uint8_t *salt, Tox_Err_Key_Derivation *error) { if (!salt || (!passphrase && pplength != 0)) { SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_NULL); @@ -181,7 +181,7 @@ Tox_Pass_Key *tox_pass_key_derive_with_salt(const uint8_t *passphrase, size_t pp * returns true on success */ bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t *data, size_t data_len, uint8_t *out, - TOX_ERR_ENCRYPTION *error) + Tox_Err_Encryption *error) { if (data_len == 0 || !data || !key || !out) { SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL); @@ -227,9 +227,9 @@ bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t *data, size_t d * returns true on success */ bool tox_pass_encrypt(const uint8_t *data, size_t data_len, const uint8_t *passphrase, size_t pplength, uint8_t *out, - TOX_ERR_ENCRYPTION *error) + Tox_Err_Encryption *error) { - TOX_ERR_KEY_DERIVATION _error; + Tox_Err_Key_Derivation _error; Tox_Pass_Key *key = tox_pass_key_derive(passphrase, pplength, &_error); if (!key) { @@ -255,7 +255,7 @@ bool tox_pass_encrypt(const uint8_t *data, size_t data_len, const uint8_t *passp * returns true on success */ bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t *data, size_t length, uint8_t *out, - TOX_ERR_DECRYPTION *error) + Tox_Err_Decryption *error) { if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) { SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH); @@ -301,7 +301,7 @@ bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t *data, size_t l * returns true on success */ bool tox_pass_decrypt(const uint8_t *data, size_t length, const uint8_t *passphrase, size_t pplength, uint8_t *out, - TOX_ERR_DECRYPTION *error) + Tox_Err_Decryption *error) { if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) { SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH); diff --git a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h index 400483cba8..0d608b1ced 100644 --- a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h +++ b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h @@ -375,4 +375,9 @@ bool tox_is_data_encrypted(const uint8_t *data); } #endif +typedef TOX_ERR_KEY_DERIVATION Tox_Err_Key_Derivation; +typedef TOX_ERR_ENCRYPTION Tox_Err_Encryption; +typedef TOX_ERR_DECRYPTION Tox_Err_Decryption; +typedef TOX_ERR_GET_SALT Tox_Err_Get_Salt; + #endif // C_TOXCORE_TOXENCRYPTSAVE_TOXENCRYPTSAVE_H |