diff options
| author | dartraiden <wowemuh@gmail.com> | 2022-02-07 00:34:21 +0300 | 
|---|---|---|
| committer | dartraiden <wowemuh@gmail.com> | 2022-02-07 00:35:37 +0300 | 
| commit | 223306302f39455970b67a97ba62e4a542224f7a (patch) | |
| tree | 21da0622af231bea688b413d1238d15315d658ce /protocols/Tox/libtox/src | |
| parent | 41317031f257ad6a06fa743860aff212074dc416 (diff) | |
Update libtox to 0.2.15
Diffstat (limited to 'protocols/Tox/libtox/src')
74 files changed, 4615 insertions, 10026 deletions
diff --git a/protocols/Tox/libtox/src/toxcore/DHT.c b/protocols/Tox/libtox/src/toxcore/DHT.c index 267d46881e..4cc8d2002f 100644 --- a/protocols/Tox/libtox/src/toxcore/DHT.c +++ b/protocols/Tox/libtox/src/toxcore/DHT.c @@ -3,15 +3,15 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * An implementation of the DHT as seen in docs/updates/DHT.md   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -  #include "DHT.h" +#include <assert.h> +#include <stdlib.h> +#include <string.h> +  #include "LAN_discovery.h"  #include "logger.h"  #include "mono_time.h" @@ -20,22 +20,18 @@  #include "state.h"  #include "util.h" -#include <assert.h> -#include <stdlib.h> -#include <string.h> - -/* The timeout after which a node is discarded completely. */ +/** The timeout after which a node is discarded completely. */  #define KILL_NODE_TIMEOUT (BAD_NODE_TIMEOUT + PING_INTERVAL) -/* Ping interval in seconds for each random sending of a get nodes request. */ +/** Ping interval in seconds for each random sending of a get nodes request. */  #define GET_NODE_INTERVAL 20  #define MAX_PUNCHING_PORTS 48 -/* Interval in seconds between punching attempts*/ +/** Interval in seconds between punching attempts*/  #define PUNCH_INTERVAL 3 -/* Time in seconds after which punching parameters will be reset */ +/** Time in seconds after which punching parameters will be reset */  #define PUNCH_RESET_TIME 40  #define MAX_NORMAL_PUNCHING_TRIES 5 @@ -43,7 +39,7 @@  #define NAT_PING_REQUEST    0  #define NAT_PING_RESPONSE   1 -/* Number of get node requests to send to quickly find close nodes. */ +/** Number of get node requests to send to quickly find close nodes. */  #define MAX_BOOTSTRAP_TIMES 5  typedef struct DHT_Friend_Callback { @@ -103,8 +99,7 @@ struct DHT {      struct Ping   *ping;      Ping_Array    *dht_ping_array; -    Ping_Array    *dht_harden_ping_array; -    uint64_t       last_run; +    uint64_t       cur_time;      Cryptopacket_Handler cryptopackethandlers[256]; @@ -178,7 +173,23 @@ static bool assoc_timeout(uint64_t cur_time, const IPPTsPng *assoc)      return (assoc->timestamp + BAD_NODE_TIMEOUT) <= cur_time;  } -/* Compares pk1 and pk2 with pk. +/** Converts an IPv4-in-IPv6 to IPv4 and returns the new IP_Port. + * + * If the ip_port is already IPv4 this function returns a copy of the original ip_port. + */ +static IP_Port ip_port_normalize(const IP_Port *ip_port) +{ +    IP_Port res = *ip_port; + +    if (net_family_is_ipv6(res.ip.family) && ipv6_ipv4_in_v6(&res.ip.ip.v6)) { +        res.ip.family = net_family_ipv4; +        res.ip.ip.v4.uint32 = res.ip.ip.v6.uint32[3]; +    } + +    return res; +} + +/** Compares pk1 and pk2 with pk.   *   *  return 0 if both are same distance.   *  return 1 if pk1 is closer. @@ -202,7 +213,7 @@ int id_closest(const uint8_t *pk, const uint8_t *pk1, const uint8_t *pk2)      return 0;  } -/* Return index of first unequal bit number. +/** Return index of first unequal bit number.   */  static unsigned int bit_by_bit_cmp(const uint8_t *pk1, const uint8_t *pk2)  { @@ -228,11 +239,11 @@ static unsigned int bit_by_bit_cmp(const uint8_t *pk1, const uint8_t *pk2)      return i * 8 + j;  } -/* Shared key generations are costly, it is therefore smart to store commonly used - * ones so that they can re used later without being computed again. +/** Shared key generations are costly, it is therefore smart to store commonly used + * ones so that they can be re-used later without being computed again.   * - * If shared key is already in shared_keys, copy it to shared_key. - * else generate it into shared_key and copy it to shared_keys + * If a shared key is already in shared_keys, copy it to shared_key. + * Otherwise generate it into shared_key and copy it to shared_keys   */  void get_shared_key(const Mono_Time *mono_time, Shared_Keys *shared_keys, uint8_t *shared_key,                      const uint8_t *secret_key, const uint8_t *public_key) @@ -279,7 +290,7 @@ void get_shared_key(const Mono_Time *mono_time, Shared_Keys *shared_keys, uint8_      }  } -/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key +/** Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key   * for packets that we receive.   */  void dht_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *public_key) @@ -287,7 +298,7 @@ void dht_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *publi      get_shared_key(dht->mono_time, &dht->shared_keys_recv, shared_key, dht->self_secret_key, public_key);  } -/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key +/** Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key   * for packets that we send.   */  void dht_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *public_key) @@ -297,7 +308,7 @@ void dht_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *publi  #define CRYPTO_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE) -/* Create a request to peer. +/** Create a request to peer.   * send_public_key and send_secret_key are the pub/secret keys of the sender.   * recv_public_key is public key of receiver.   * packet must be an array of MAX_CRYPTO_REQUEST_SIZE big. @@ -339,7 +350,7 @@ int create_request(const uint8_t *send_public_key, const uint8_t *send_secret_ke      return len + CRYPTO_SIZE;  } -/* Puts the senders public key in the request in public_key, the data from the request +/** Puts the senders public key in the request in public_key, the data from the request   * in data if a friend or ping request was sent to us and returns the length of the data.   * packet is the request packet and length is its length.   * @@ -381,7 +392,7 @@ int handle_request(const uint8_t *self_public_key, const uint8_t *self_secret_ke  #define PACKED_NODE_SIZE_IP4 (1 + SIZE_IP4 + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE)  #define PACKED_NODE_SIZE_IP6 (1 + SIZE_IP6 + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE) -/* Return packet size of packed node with ip_family on success. +/** Return packet size of packed node with ip_family on success.   * Return -1 on failure.   */  int packed_node_size(Family ip_family) @@ -398,7 +409,9 @@ int packed_node_size(Family ip_family)  } -/* Packs an IP_Port structure into data of max size length. +/** Packs an IP_Port structure into data of max size length. + * + * Packed_length is the offset of data currently packed.   *   * Returns size of packed IP_Port data on success   * Return -1 on failure. @@ -455,7 +468,8 @@ int pack_ip_port(uint8_t *data, uint16_t length, const IP_Port *ip_port)  }  static int dht_create_packet(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], -                             const uint8_t *shared_key, const uint8_t type, uint8_t *plain, size_t plain_length, uint8_t *packet) +                             const uint8_t *shared_key, const uint8_t type, +                             const uint8_t *plain, size_t plain_length, uint8_t *packet)  {      VLA(uint8_t, encrypted, plain_length + CRYPTO_MAC_SIZE);      uint8_t nonce[CRYPTO_NONCE_SIZE]; @@ -476,7 +490,9 @@ static int dht_create_packet(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],      return 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + encrypted_length;  } -/* Unpack IP_Port structure from data of max size length into ip_port. +/** Unpack IP_Port structure from data of max size length into ip_port. + * + * len_processed is the offset of data currently unpacked.   *   * Return size of unpacked ip_port on success.   * Return -1 on failure. @@ -514,6 +530,10 @@ int unpack_ip_port(IP_Port *ip_port, const uint8_t *data, uint16_t length, bool          return -1;      } +    *ip_port = (IP_Port) { +        0 +    }; +      if (is_ipv4) {          const uint32_t size = 1 + SIZE_IP4 + sizeof(uint16_t); @@ -539,7 +559,7 @@ int unpack_ip_port(IP_Port *ip_port, const uint8_t *data, uint16_t length, bool      }  } -/* Pack number of nodes into data of maxlength length. +/** Pack number of nodes into data of maxlength length.   *   * return length of packed nodes on success.   * return -1 on failure. @@ -573,7 +593,7 @@ int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_      return packed_length;  } -/* Unpack data of length into nodes of size max_num_nodes. +/** Unpack data of length into nodes of size max_num_nodes.   * Put the length of the data processed in processed_data_len.   * tcp_enabled sets if TCP nodes are expected (true) or not (false).   * @@ -616,37 +636,44 @@ int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed      return num;  } -/* Find index in an array with public_key equal to pk. +/** Find index in an array with public_key equal to pk.   *   *  return index or UINT32_MAX if not found.   */ -#define INDEX_OF_PK(array, size, pk)               \ -  do {                                             \ -      for (uint32_t i = 0; i < size; ++i) {        \ -          if (id_equal(array[i].public_key, pk)) { \ -              return i;                            \ -          }                                        \ -      }                                            \ -                                                   \ -      return UINT32_MAX;                           \ -  } while (0) -  static uint32_t index_of_client_pk(const Client_data *array, uint32_t size, const uint8_t *pk)  { -    INDEX_OF_PK(array, size, pk); +    for (uint32_t i = 0; i < size; ++i) { +        if (id_equal(array[i].public_key, pk)) { +            return i; +        } +    } + +    return UINT32_MAX;  }  static uint32_t index_of_friend_pk(const DHT_Friend *array, uint32_t size, const uint8_t *pk)  { -    INDEX_OF_PK(array, size, pk); +    for (uint32_t i = 0; i < size; ++i) { +        if (id_equal(array[i].public_key, pk)) { +            return i; +        } +    } + +    return UINT32_MAX;  }  static uint32_t index_of_node_pk(const Node_format *array, uint32_t size, const uint8_t *pk)  { -    INDEX_OF_PK(array, size, pk); +    for (uint32_t i = 0; i < size; ++i) { +        if (id_equal(array[i].public_key, pk)) { +            return i; +        } +    } + +    return UINT32_MAX;  } -/* Find index of Client_data with ip_port equal to param ip_port. +/** Find index of Client_data with ip_port equal to param ip_port.   *   * return index or UINT32_MAX if not found.   */ @@ -662,43 +689,43 @@ static uint32_t index_of_client_ip_port(const Client_data *array, uint32_t size,      return UINT32_MAX;  } -/* Update ip_port of client if it's needed. +/** Update ip_port of client if it's needed.   */  static void update_client(const Logger *log, const Mono_Time *mono_time, int index, Client_data *client, -                          IP_Port ip_port) +                          const IP_Port *ip_port)  {      IPPTsPng *assoc;      int ip_version; -    if (net_family_is_ipv4(ip_port.ip.family)) { +    if (net_family_is_ipv4(ip_port->ip.family)) {          assoc = &client->assoc4;          ip_version = 4; -    } else if (net_family_is_ipv6(ip_port.ip.family)) { +    } else if (net_family_is_ipv6(ip_port->ip.family)) {          assoc = &client->assoc6;          ip_version = 6;      } else {          return;      } -    if (!ipport_equal(&assoc->ip_port, &ip_port)) { +    if (!ipport_equal(&assoc->ip_port, ip_port)) {          char ip_str[IP_NTOA_LEN];          LOGGER_TRACE(log, "coipil[%u]: switching ipv%d from %s:%u to %s:%u",                       index, ip_version,                       ip_ntoa(&assoc->ip_port.ip, ip_str, sizeof(ip_str)),                       net_ntohs(assoc->ip_port.port), -                     ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), -                     net_ntohs(ip_port.port)); +                     ip_ntoa(&ip_port->ip, ip_str, sizeof(ip_str)), +                     net_ntohs(ip_port->port));      } -    if (!ip_is_lan(assoc->ip_port.ip) && ip_is_lan(ip_port.ip)) { +    if (!ip_is_lan(&assoc->ip_port.ip) && ip_is_lan(&ip_port->ip)) {          return;      } -    assoc->ip_port = ip_port; +    assoc->ip_port = *ip_port;      assoc->timestamp = mono_time_get(mono_time);  } -/* Check if client with public_key is already in list of length length. +/** Check if client with public_key is already in list of length length.   * If it is then set its corresponding timestamp to current time.   * If the id is already in the list with a different ip_port, update it.   * TODO(irungentoo): Maybe optimize this. @@ -706,7 +733,7 @@ static void update_client(const Logger *log, const Mono_Time *mono_time, int ind   *  return True(1) or False(0)   */  static int client_or_ip_port_in_list(const Logger *log, const Mono_Time *mono_time, Client_data *list, uint16_t length, -                                     const uint8_t *public_key, IP_Port ip_port) +                                     const uint8_t *public_key, const IP_Port *ip_port)  {      const uint64_t temp_time = mono_time_get(mono_time);      uint32_t index = index_of_client_pk(list, length, public_key); @@ -722,7 +749,7 @@ static int client_or_ip_port_in_list(const Logger *log, const Mono_Time *mono_ti       * TODO(irungentoo): maybe we SHOULDN'T do that if that public_key is in a friend_list       * and the one who is the actual friend's public_key/address set?       * MAYBE: check the other address, if valid, don't nuke? */ -    index = index_of_client_ip_port(list, length, &ip_port); +    index = index_of_client_ip_port(list, length, ip_port);      if (index == UINT32_MAX) {          return 0; @@ -731,7 +758,7 @@ static int client_or_ip_port_in_list(const Logger *log, const Mono_Time *mono_ti      IPPTsPng *assoc;      int ip_version; -    if (net_family_is_ipv4(ip_port.ip.family)) { +    if (net_family_is_ipv4(ip_port->ip.family)) {          assoc = &list[index].assoc4;          ip_version = 4;      } else { @@ -746,11 +773,13 @@ static int client_or_ip_port_in_list(const Logger *log, const Mono_Time *mono_ti      LOGGER_DEBUG(log, "coipil[%u]: switching public_key (ipv%d)", index, ip_version);      /* kill the other address, if it was set */ -    memset(assoc, 0, sizeof(IPPTsPng)); +    *assoc = (IPPTsPng) { +        0 +    };      return 1;  } -bool add_to_list(Node_format *nodes_list, uint32_t length, const uint8_t *pk, IP_Port ip_port, +bool add_to_list(Node_format *nodes_list, uint32_t length, const uint8_t *pk, const IP_Port *ip_port,                   const uint8_t *cmp_pk)  {      for (uint32_t i = 0; i < length; ++i) { @@ -759,10 +788,10 @@ bool add_to_list(Node_format *nodes_list, uint32_t length, const uint8_t *pk, IP              memcpy(pk_bak, nodes_list[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);              const IP_Port ip_port_bak = nodes_list[i].ip_port;              memcpy(nodes_list[i].public_key, pk, CRYPTO_PUBLIC_KEY_SIZE); -            nodes_list[i].ip_port = ip_port; +            nodes_list[i].ip_port = *ip_port;              if (i != length - 1) { -                add_to_list(nodes_list, length, pk_bak, ip_port_bak, cmp_pk); +                add_to_list(nodes_list, length, pk_bak, &ip_port_bak, cmp_pk);              }              return true; @@ -772,25 +801,12 @@ bool add_to_list(Node_format *nodes_list, uint32_t length, const uint8_t *pk, IP      return false;  } -/* TODO(irungentoo): change this to 7 when done*/ -#define HARDENING_ALL_OK 2 -/* return 0 if not. - * return 1 if route request are ok - * return 2 if it responds to send node packets correctly - * return 4 if it can test other nodes correctly - * return HARDENING_ALL_OK if all ok. - */ -static uint8_t hardening_correct(const Hardening *h) -{ -    return h->routes_requests_ok + (h->send_nodes_ok << 1) + (h->testing_requests << 2); -} - -/* +/**   * helper for get_close_nodes(). argument list is a monster :D   */  static void get_close_nodes_inner(uint64_t cur_time, const uint8_t *public_key, Node_format *nodes_list,                                    Family sa_family, const Client_data *client_list, uint32_t client_list_length, -                                  uint32_t *num_nodes_ptr, bool is_LAN, uint8_t want_good) +                                  uint32_t *num_nodes_ptr, bool is_LAN)  {      if (!net_family_is_ipv4(sa_family) && !net_family_is_ipv6(sa_family) && !net_family_is_unspec(sa_family)) {          return; @@ -824,12 +840,7 @@ static void get_close_nodes_inner(uint64_t cur_time, const uint8_t *public_key,          }          /* don't send LAN ips to non LAN peers */ -        if (ip_is_lan(ipptp->ip_port.ip) && !is_LAN) { -            continue; -        } - -        if (!ip_is_lan(ipptp->ip_port.ip) && want_good && hardening_correct(&ipptp->hardening) != HARDENING_ALL_OK -                && !id_equal(public_key, client->public_key)) { +        if (ip_is_lan(&ipptp->ip_port.ip) && !is_LAN) {              continue;          } @@ -838,78 +849,58 @@ static void get_close_nodes_inner(uint64_t cur_time, const uint8_t *public_key,              nodes_list[num_nodes].ip_port = ipptp->ip_port;              ++num_nodes;          } else { -            add_to_list(nodes_list, MAX_SENT_NODES, client->public_key, ipptp->ip_port, public_key); +            add_to_list(nodes_list, MAX_SENT_NODES, client->public_key, &ipptp->ip_port, public_key);          }      }      *num_nodes_ptr = num_nodes;  } -/* Find MAX_SENT_NODES nodes closest to the public_key for the send nodes request: +/** Find MAX_SENT_NODES nodes closest to the public_key for the send nodes request:   * put them in the nodes_list and return how many were found.   *   * TODO(irungentoo): For the love of based <your favorite deity, in doubt use   * "love"> make this function cleaner and much more efficient. - * - * want_good : do we want only good nodes as checked with the hardening returned or not?   */  static int get_somewhat_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, -                                    Family sa_family, bool is_LAN, uint8_t want_good) +                                    Family sa_family, bool is_LAN)  {      uint32_t num_nodes = 0; -    get_close_nodes_inner(dht->last_run, public_key, nodes_list, sa_family, -                          dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, 0); - -    /* TODO(irungentoo): uncomment this when hardening is added to close friend clients */ -#if 0 +    get_close_nodes_inner(dht->cur_time, public_key, nodes_list, sa_family, +                          dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN);      for (uint32_t i = 0; i < dht->num_friends; ++i) { -        get_close_nodes_inner(dht->mono_time, public_key, nodes_list, sa_family, +        get_close_nodes_inner(dht->cur_time, public_key, nodes_list, sa_family,                                dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, -                              &num_nodes, is_LAN, want_good); -    } - -#endif - -    for (uint32_t i = 0; i < dht->num_friends; ++i) { -        get_close_nodes_inner(dht->last_run, public_key, nodes_list, sa_family, -                              dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, -                              &num_nodes, is_LAN, 0); +                              &num_nodes, is_LAN);      }      return num_nodes;  }  int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, Family sa_family, -                    bool is_LAN, uint8_t want_good) +                    bool is_LAN)  {      memset(nodes_list, 0, MAX_SENT_NODES * sizeof(Node_format)); -    return get_somewhat_close_nodes(dht, public_key, nodes_list, sa_family, is_LAN, want_good); +    return get_somewhat_close_nodes(dht, public_key, nodes_list, sa_family, is_LAN);  } -typedef struct DHT_Cmp_data { +typedef struct DHT_Cmp_Data {      uint64_t cur_time;      const uint8_t *base_public_key;      Client_data entry; -} DHT_Cmp_data; - -static bool incorrect_hardening(const IPPTsPng *assoc) -{ -    return hardening_correct(&assoc->hardening) != HARDENING_ALL_OK; -} +} DHT_Cmp_Data; -static int cmp_dht_entry(const void *a, const void *b) +static int dht_cmp_entry(const void *a, const void *b)  { -    DHT_Cmp_data cmp1; -    DHT_Cmp_data cmp2; -    memcpy(&cmp1, a, sizeof(DHT_Cmp_data)); -    memcpy(&cmp2, b, sizeof(DHT_Cmp_data)); -    const Client_data entry1 = cmp1.entry; -    const Client_data entry2 = cmp2.entry; -    const uint8_t *cmp_public_key = cmp1.base_public_key; +    const DHT_Cmp_Data *cmp1 = (const DHT_Cmp_Data *)a; +    const DHT_Cmp_Data *cmp2 = (const DHT_Cmp_Data *)b; +    const Client_data entry1 = cmp1->entry; +    const Client_data entry2 = cmp2->entry; +    const uint8_t *cmp_public_key = cmp1->base_public_key; -    bool t1 = assoc_timeout(cmp1.cur_time, &entry1.assoc4) && assoc_timeout(cmp1.cur_time, &entry1.assoc6); -    bool t2 = assoc_timeout(cmp2.cur_time, &entry2.assoc4) && assoc_timeout(cmp2.cur_time, &entry2.assoc6); +    const bool t1 = assoc_timeout(cmp1->cur_time, &entry1.assoc4) && assoc_timeout(cmp1->cur_time, &entry1.assoc6); +    const bool t2 = assoc_timeout(cmp2->cur_time, &entry2.assoc4) && assoc_timeout(cmp2->cur_time, &entry2.assoc6);      if (t1 && t2) {          return 0; @@ -923,17 +914,6 @@ static int cmp_dht_entry(const void *a, const void *b)          return 1;      } -    t1 = incorrect_hardening(&entry1.assoc4) && incorrect_hardening(&entry1.assoc6); -    t2 = incorrect_hardening(&entry2.assoc4) && incorrect_hardening(&entry2.assoc6); - -    if (t1 && !t2) { -        return -1; -    } - -    if (!t1 && t2) { -        return 1; -    } -      const int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key);      if (close == 1) { @@ -947,7 +927,7 @@ static int cmp_dht_entry(const void *a, const void *b)      return 0;  } -/* Is it ok to store node with public_key in client. +/** Is it ok to store node with public_key in client.   *   * return 0 if node can't be stored.   * return 1 if it can. @@ -965,7 +945,7 @@ static void sort_client_list(Client_data *list, uint64_t cur_time, unsigned int  {      // Pass comp_public_key to qsort with each Client_data entry, so the      // comparison function can use it as the base of comparison. -    VLA(DHT_Cmp_data, cmp_list, length); +    VLA(DHT_Cmp_Data, cmp_list, length);      for (uint32_t i = 0; i < length; ++i) {          cmp_list[i].cur_time = cur_time; @@ -973,7 +953,7 @@ static void sort_client_list(Client_data *list, uint64_t cur_time, unsigned int          cmp_list[i].entry = list[i];      } -    qsort(cmp_list, length, sizeof(DHT_Cmp_data), cmp_dht_entry); +    qsort(cmp_list, length, sizeof(DHT_Cmp_Data), dht_cmp_entry);      for (uint32_t i = 0; i < length; ++i) {          list[i] = cmp_list[i].entry; @@ -999,12 +979,13 @@ static void update_client_with_reset(const Mono_Time *mono_time, Client_data *cl      ip_reset(&ipptp_write->ret_ip_port.ip);      ipptp_write->ret_ip_port.port = 0;      ipptp_write->ret_timestamp = 0; +    ipptp_write->ret_ip_self = false;      /* zero out other address */      memset(ipptp_clear, 0, sizeof(*ipptp_clear));  } -/* Replace a first bad (or empty) node with this one +/** Replace a first bad (or empty) node with this one   *  or replace a possibly bad node (tests failed or not done yet)   *  that is further than any other in the list   *  from the comp_public_key @@ -1021,35 +1002,35 @@ static bool replace_all(const DHT *dht,                          Client_data    *list,                          uint16_t        length,                          const uint8_t  *public_key, -                        IP_Port         ip_port, +                        const IP_Port  *ip_port,                          const uint8_t  *comp_public_key)  { -    if (!net_family_is_ipv4(ip_port.ip.family) && !net_family_is_ipv6(ip_port.ip.family)) { +    if (!net_family_is_ipv4(ip_port->ip.family) && !net_family_is_ipv6(ip_port->ip.family)) {          return false;      } -    if (!store_node_ok(&list[1], dht->last_run, public_key, comp_public_key) && -            !store_node_ok(&list[0], dht->last_run, public_key, comp_public_key)) { +    if (!store_node_ok(&list[1], dht->cur_time, public_key, comp_public_key) && +            !store_node_ok(&list[0], dht->cur_time, public_key, comp_public_key)) {          return false;      } -    sort_client_list(list, dht->last_run, length, comp_public_key); +    sort_client_list(list, dht->cur_time, length, comp_public_key);      Client_data *const client = &list[0];      id_copy(client->public_key, public_key); -    update_client_with_reset(dht->mono_time, client, &ip_port); +    update_client_with_reset(dht->mono_time, client, ip_port);      return true;  } -/* Add node to close list. +/** Add node to close list.   *   * simulate is set to 1 if we want to check if a node can be added to the list without adding it.   *   * return -1 on failure.   * return 0 on success.   */ -static int add_to_close(DHT *dht, const uint8_t *public_key, IP_Port ip_port, bool simulate) +static int add_to_close(DHT *dht, const uint8_t *public_key, const IP_Port *ip_port, bool simulate)  {      unsigned int index = bit_by_bit_cmp(public_key, dht->self_public_key); @@ -1062,8 +1043,8 @@ static int add_to_close(DHT *dht, const uint8_t *public_key, IP_Port ip_port, bo           * index is left as >= LCLIENT_LENGTH */          Client_data *const client = &dht->close_clientlist[(index * LCLIENT_NODES) + i]; -        if (!assoc_timeout(dht->last_run, &client->assoc4) || -                !assoc_timeout(dht->last_run, &client->assoc6)) { +        if (!assoc_timeout(dht->cur_time, &client->assoc4) || +                !assoc_timeout(dht->cur_time, &client->assoc6)) {              continue;          } @@ -1072,22 +1053,22 @@ static int add_to_close(DHT *dht, const uint8_t *public_key, IP_Port ip_port, bo          }          id_copy(client->public_key, public_key); -        update_client_with_reset(dht->mono_time, client, &ip_port); +        update_client_with_reset(dht->mono_time, client, ip_port);          return 0;      }      return -1;  } -/* Return 1 if node can be added to close list, 0 if it can't. +/** Return 1 if node can be added to close list, 0 if it can't.   */ -bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port) +bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, const IP_Port *ip_port)  {      return add_to_close(dht, public_key, ip_port, 1) == 0;  }  static bool is_pk_in_client_list(const Client_data *list, unsigned int client_list_length, uint64_t cur_time, -                                 const uint8_t *public_key, IP_Port ip_port) +                                 const uint8_t *public_key, const IP_Port *ip_port)  {      const uint32_t index = index_of_client_pk(list, client_list_length, public_key); @@ -1095,14 +1076,14 @@ static bool is_pk_in_client_list(const Client_data *list, unsigned int client_li          return 0;      } -    const IPPTsPng *assoc = net_family_is_ipv4(ip_port.ip.family) +    const IPPTsPng *assoc = net_family_is_ipv4(ip_port->ip.family)                              ? &list[index].assoc4                              : &list[index].assoc6;      return !assoc_timeout(cur_time, assoc);  } -static bool is_pk_in_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port) +static bool is_pk_in_close_list(const DHT *dht, const uint8_t *public_key, const IP_Port *ip_port)  {      unsigned int index = bit_by_bit_cmp(public_key, dht->self_public_key); @@ -1110,17 +1091,17 @@ static bool is_pk_in_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_          index = LCLIENT_LENGTH - 1;      } -    return is_pk_in_client_list(dht->close_clientlist + index * LCLIENT_NODES, LCLIENT_NODES, dht->last_run, public_key, +    return is_pk_in_client_list(dht->close_clientlist + index * LCLIENT_NODES, LCLIENT_NODES, dht->cur_time, public_key,                                  ip_port);  } -/* Check if the node obtained with a get_nodes with public_key should be pinged. +/** Check if the node obtained with a get_nodes with public_key should be pinged.   * NOTE: for best results call it after addto_lists.   *   * return false if the node should not be pinged.   * return true if it should.   */ -static bool ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_key, IP_Port ip_port) +static bool ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_key, const IP_Port *ip_port)  {      bool ret = false; @@ -1136,7 +1117,7 @@ static bool ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_key, IP_P          if (ret && index == UINT32_MAX && !in_close_list) {              if (*num < MAX_CLOSE_TO_BOOTSTRAP_NODES) {                  memcpy(dht->to_bootstrap[*num].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); -                dht->to_bootstrap[*num].ip_port = ip_port; +                dht->to_bootstrap[*num].ip_port = *ip_port;                  ++*num;              } else {                  // TODO(irungentoo): ipv6 vs v4 @@ -1150,24 +1131,24 @@ static bool ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_key, IP_P          bool store_ok = false; -        if (store_node_ok(&dht_friend->client_list[1], dht->last_run, public_key, dht_friend->public_key)) { +        if (store_node_ok(&dht_friend->client_list[1], dht->cur_time, public_key, dht_friend->public_key)) {              store_ok = true;          } -        if (store_node_ok(&dht_friend->client_list[0], dht->last_run, public_key, dht_friend->public_key)) { +        if (store_node_ok(&dht_friend->client_list[0], dht->cur_time, public_key, dht_friend->public_key)) {              store_ok = true;          }          unsigned int *const friend_num = &dht_friend->num_to_bootstrap;          const uint32_t index = index_of_node_pk(dht_friend->to_bootstrap, *friend_num, public_key); -        const bool pk_in_list = is_pk_in_client_list(dht_friend->client_list, MAX_FRIEND_CLIENTS, dht->last_run, public_key, +        const bool pk_in_list = is_pk_in_client_list(dht_friend->client_list, MAX_FRIEND_CLIENTS, dht->cur_time, public_key,                                  ip_port);          if (store_ok && index == UINT32_MAX && !pk_in_list) {              if (*friend_num < MAX_SENT_NODES) {                  Node_format *const format = &dht_friend->to_bootstrap[*friend_num];                  memcpy(format->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); -                format->ip_port = ip_port; +                format->ip_port = *ip_port;                  ++*friend_num;              } else {                  add_to_list(dht_friend->to_bootstrap, MAX_SENT_NODES, public_key, ip_port, dht_friend->public_key); @@ -1180,41 +1161,37 @@ static bool ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_key, IP_P      return ret;  } -/* Attempt to add client with ip_port and public_key to the friends client list +/** Attempt to add client with ip_port and public_key to the friends client list   * and close_clientlist.   *   *  returns 1+ if the item is used in any list, 0 else   */ -uint32_t addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key) +uint32_t addto_lists(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key)  { -    uint32_t used = 0; +    IP_Port ipp_copy = ip_port_normalize(ip_port); -    /* convert IPv4-in-IPv6 to IPv4 */ -    if (net_family_is_ipv6(ip_port.ip.family) && ipv6_ipv4_in_v6(ip_port.ip.ip.v6)) { -        ip_port.ip.family = net_family_ipv4; -        ip_port.ip.ip.v4.uint32 = ip_port.ip.ip.v6.uint32[3]; -    } +    uint32_t used = 0;      /* NOTE: Current behavior if there are two clients with the same id is       * to replace the first ip by the second.       */      const bool in_close_list = client_or_ip_port_in_list(dht->log, dht->mono_time, dht->close_clientlist, LCLIENT_LIST, -                               public_key, ip_port); +                               public_key, &ipp_copy);      /* add_to_close should be called only if !in_list (don't extract to variable) */ -    if (in_close_list || add_to_close(dht, public_key, ip_port, 0)) { +    if (in_close_list || add_to_close(dht, public_key, &ipp_copy, 0)) {          ++used;      } -    DHT_Friend *friend_foundip = nullptr; +    const DHT_Friend *friend_foundip = nullptr;      for (uint32_t i = 0; i < dht->num_friends; ++i) {          const bool in_list = client_or_ip_port_in_list(dht->log, dht->mono_time, dht->friends_list[i].client_list, -                             MAX_FRIEND_CLIENTS, public_key, ip_port); +                             MAX_FRIEND_CLIENTS, public_key, &ipp_copy);          /* replace_all should be called only if !in_list (don't extract to variable) */          if (in_list -                || replace_all(dht, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, public_key, ip_port, +                || replace_all(dht, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, public_key, &ipp_copy,                                 dht->friends_list[i].public_key)) {              DHT_Friend *dht_friend = &dht->friends_list[i]; @@ -1233,15 +1210,15 @@ uint32_t addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key)      for (uint32_t i = 0; i < friend_foundip->lock_count; ++i) {          if (friend_foundip->callbacks[i].ip_callback) {              friend_foundip->callbacks[i].ip_callback(friend_foundip->callbacks[i].data, -                    friend_foundip->callbacks[i].number, ip_port); +                    friend_foundip->callbacks[i].number, &ipp_copy);          }      }      return used;  } -static bool update_client_data(const Mono_Time *mono_time, Client_data *array, size_t size, IP_Port ip_port, -                               const uint8_t *pk) +static bool update_client_data(const Mono_Time *mono_time, Client_data *array, size_t size, const IP_Port *ip_port, +                               const uint8_t *pk, bool node_is_self)  {      const uint64_t temp_time = mono_time_get(mono_time);      const uint32_t index = index_of_client_pk(array, size, pk); @@ -1253,32 +1230,30 @@ static bool update_client_data(const Mono_Time *mono_time, Client_data *array, s      Client_data *const data = &array[index];      IPPTsPng *assoc; -    if (net_family_is_ipv4(ip_port.ip.family)) { +    if (net_family_is_ipv4(ip_port->ip.family)) {          assoc = &data->assoc4; -    } else if (net_family_is_ipv6(ip_port.ip.family)) { +    } else if (net_family_is_ipv6(ip_port->ip.family)) {          assoc = &data->assoc6;      } else {          return true;      } -    assoc->ret_ip_port = ip_port; +    assoc->ret_ip_port = *ip_port;      assoc->ret_timestamp = temp_time; +    assoc->ret_ip_self = node_is_self; +      return true;  } -/* If public_key is a friend or us, update ret_ip_port +/** If public_key is a friend or us, update ret_ip_port   * nodepublic_key is the id of the node that sent us this info.   */ -static void returnedip_ports(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const uint8_t *nodepublic_key) +static void returnedip_ports(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *nodepublic_key)  { -    /* convert IPv4-in-IPv6 to IPv4 */ -    if (net_family_is_ipv6(ip_port.ip.family) && ipv6_ipv4_in_v6(ip_port.ip.ip.v6)) { -        ip_port.ip.family = net_family_ipv4; -        ip_port.ip.ip.v4.uint32 = ip_port.ip.ip.v6.uint32[3]; -    } +    IP_Port ipp_copy = ip_port_normalize(ip_port);      if (id_equal(public_key, dht->self_public_key)) { -        update_client_data(dht->mono_time, dht->close_clientlist, LCLIENT_LIST, ip_port, nodepublic_key); +        update_client_data(dht->mono_time, dht->close_clientlist, LCLIENT_LIST, &ipp_copy, nodepublic_key, true);          return;      } @@ -1286,41 +1261,36 @@ static void returnedip_ports(DHT *dht, IP_Port ip_port, const uint8_t *public_ke          if (id_equal(public_key, dht->friends_list[i].public_key)) {              Client_data *const client_list = dht->friends_list[i].client_list; -            if (update_client_data(dht->mono_time, client_list, MAX_FRIEND_CLIENTS, ip_port, nodepublic_key)) { +            if (update_client_data(dht->mono_time, client_list, MAX_FRIEND_CLIENTS, &ipp_copy, nodepublic_key, false)) {                  return;              }          }      }  } -/* Send a getnodes request. - * sendback_node is the node that it will send back the response to (set to NULL to disable this) */ -static int getnodes(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const uint8_t *client_id, -                    const Node_format *sendback_node) +bool dht_getnodes(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *client_id)  {      /* Check if packet is going to be sent to ourself. */      if (id_equal(public_key, dht->self_public_key)) { -        return -1; +        return false;      }      uint8_t plain_message[sizeof(Node_format) * 2] = {0};      Node_format receiver;      memcpy(receiver.public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); -    receiver.ip_port = ip_port; -    memcpy(plain_message, &receiver, sizeof(receiver)); +    receiver.ip_port = *ip_port; + +    if (pack_nodes(plain_message, sizeof(plain_message), &receiver, 1) == -1) { +        return false; +    }      uint64_t ping_id = 0; -    if (sendback_node != nullptr) { -        memcpy(plain_message + sizeof(receiver), sendback_node, sizeof(Node_format)); -        ping_id = ping_array_add(dht->dht_harden_ping_array, dht->mono_time, plain_message, sizeof(plain_message)); -    } else { -        ping_id = ping_array_add(dht->dht_ping_array, dht->mono_time, plain_message, sizeof(receiver)); -    } +    ping_id = ping_array_add(dht->dht_ping_array, dht->mono_time, plain_message, sizeof(receiver));      if (ping_id == 0) { -        return -1; +        return false;      }      uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + sizeof(ping_id)]; @@ -1335,15 +1305,21 @@ static int getnodes(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const      const int len = dht_create_packet(dht->self_public_key, shared_key, NET_PACKET_GET_NODES,                                        plain, sizeof(plain), data); +    crypto_memzero(shared_key, sizeof(shared_key)); +      if (len != sizeof(data)) { -        return -1; +        return false;      } -    return sendpacket(dht->net, ip_port, data, len); +    if (sendpacket(dht->net, ip_port, data, len) > 0) { +        return true; +    } + +    return false;  } -/* Send a send nodes response: message for IPv6 nodes */ -static int sendnodes_ipv6(const DHT *dht, IP_Port ip_port, const uint8_t *public_key, const uint8_t *client_id, +/** Send a send nodes response: message for IPv6 nodes */ +static int sendnodes_ipv6(const DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *client_id,                            const uint8_t *sendback_data, uint16_t length, const uint8_t *shared_encryption_key)  {      /* Check if packet is going to be sent to ourself. */ @@ -1359,7 +1335,7 @@ static int sendnodes_ipv6(const DHT *dht, IP_Port ip_port, const uint8_t *public      Node_format nodes_list[MAX_SENT_NODES];      const uint32_t num_nodes = -        get_close_nodes(dht, client_id, nodes_list, net_family_unspec, ip_is_lan(ip_port.ip), 1); +        get_close_nodes(dht, client_id, nodes_list, net_family_unspec, ip_is_lan(&ip_port->ip));      VLA(uint8_t, plain, 1 + node_format_size * MAX_SENT_NODES + length); @@ -1391,7 +1367,7 @@ static int sendnodes_ipv6(const DHT *dht, IP_Port ip_port, const uint8_t *public  #define CRYPTO_NODE_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint64_t)) -static int handle_getnodes(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) +static int handle_getnodes(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)  {      if (length != (CRYPTO_SIZE + CRYPTO_MAC_SIZE + sizeof(uint64_t))) {          return true; @@ -1416,6 +1392,7 @@ static int handle_getnodes(void *object, IP_Port source, const uint8_t *packet,                          plain);      if (len != CRYPTO_NODE_SIZE) { +        crypto_memzero(shared_key, sizeof(shared_key));          return true;      } @@ -1423,39 +1400,34 @@ static int handle_getnodes(void *object, IP_Port source, const uint8_t *packet,      ping_add(dht->ping, packet + 1, source); +    crypto_memzero(shared_key, sizeof(shared_key)); +      return false;  } -/* return false if no - * return true if yes */ -static bool sent_getnode_to_node(DHT *dht, const uint8_t *public_key, IP_Port node_ip_port, uint64_t ping_id, -                                 Node_format *sendback_node) +/** Return true if we sent a getnode packet to the peer associated with the supplied info. */ +static bool sent_getnode_to_node(DHT *dht, const uint8_t *public_key, const IP_Port *node_ip_port, uint64_t ping_id)  {      uint8_t data[sizeof(Node_format) * 2]; -    if (ping_array_check(dht->dht_ping_array, dht->mono_time, data, sizeof(data), ping_id) == sizeof(Node_format)) { -        memset(sendback_node, 0, sizeof(Node_format)); -    } else if (ping_array_check(dht->dht_harden_ping_array, dht->mono_time, data, sizeof(data), ping_id) == sizeof(data)) { -        memcpy(sendback_node, data + sizeof(Node_format), sizeof(Node_format)); -    } else { +    if (ping_array_check(dht->dht_ping_array, dht->mono_time, data, sizeof(data), ping_id) != sizeof(Node_format)) {          return false;      }      Node_format test; -    memcpy(&test, data, sizeof(Node_format)); -    if (!ipport_equal(&test.ip_port, &node_ip_port) || !id_equal(test.public_key, public_key)) { +    if (unpack_nodes(&test, 1, nullptr, data, sizeof(data), false) != 1) { +        return false; +    } + +    if (!ipport_equal(&test.ip_port, node_ip_port) || !id_equal(test.public_key, public_key)) {          return false;      }      return true;  } -/* Function is needed in following functions. */ -static int send_hardening_getnode_res(const DHT *dht, const Node_format *sendto, const uint8_t *queried_client_id, -                                      const uint8_t *nodes_data, uint16_t nodes_data_length); - -static int handle_sendnodes_core(void *object, IP_Port source, const uint8_t *packet, uint16_t length, +static int handle_sendnodes_core(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length,                                   Node_format *plain_nodes, uint16_t size_plain_nodes, uint32_t *num_nodes_out)  {      DHT *const dht = (DHT *)object; @@ -1485,6 +1457,8 @@ static int handle_sendnodes_core(void *object, IP_Port source, const uint8_t *pa                          1 + data_size + sizeof(uint64_t) + CRYPTO_MAC_SIZE,                          plain); +    crypto_memzero(shared_key, sizeof(shared_key)); +      if ((unsigned int)len != SIZEOF_VLA(plain)) {          return 1;      } @@ -1493,12 +1467,10 @@ static int handle_sendnodes_core(void *object, IP_Port source, const uint8_t *pa          return 1;      } -    Node_format sendback_node; -      uint64_t ping_id;      memcpy(&ping_id, plain + 1 + data_size, sizeof(ping_id)); -    if (!sent_getnode_to_node(dht, packet + 1, source, ping_id, &sendback_node)) { +    if (!sent_getnode_to_node(dht, packet + 1, source, ping_id)) {          return 1;      } @@ -1522,11 +1494,11 @@ static int handle_sendnodes_core(void *object, IP_Port source, const uint8_t *pa      *num_nodes_out = num_nodes; -    send_hardening_getnode_res(dht, &sendback_node, packet + 1, plain + 1, data_size);      return 0;  } -static int handle_sendnodes_ipv6(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) +static int handle_sendnodes_ipv6(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, +                                 void *userdata)  {      DHT *const dht = (DHT *)object;      Node_format plain_nodes[MAX_SENT_NODES]; @@ -1542,8 +1514,8 @@ static int handle_sendnodes_ipv6(void *object, IP_Port source, const uint8_t *pa      for (uint32_t i = 0; i < num_nodes; ++i) {          if (ipport_isset(&plain_nodes[i].ip_port)) { -            ping_node_from_getnodes_ok(dht, plain_nodes[i].public_key, plain_nodes[i].ip_port); -            returnedip_ports(dht, plain_nodes[i].ip_port, plain_nodes[i].public_key, packet + 1); +            ping_node_from_getnodes_ok(dht, plain_nodes[i].public_key, &plain_nodes[i].ip_port); +            returnedip_ports(dht, &plain_nodes[i].ip_port, plain_nodes[i].public_key, packet + 1);          }      } @@ -1553,13 +1525,25 @@ static int handle_sendnodes_ipv6(void *object, IP_Port source, const uint8_t *pa  /*----------------------------------------------------------------------------------*/  /*------------------------END of packet handling functions--------------------------*/ +static void dht_friend_lock(DHT_Friend *const dht_friend, dht_ip_cb *ip_callback, +                            void *data, int32_t number, uint16_t *lock_count) +{ +    const uint16_t lock_num = dht_friend->lock_count; +    ++dht_friend->lock_count; +    dht_friend->callbacks[lock_num].ip_callback = ip_callback; +    dht_friend->callbacks[lock_num].data = data; +    dht_friend->callbacks[lock_num].number = number; + +    if (lock_count) { +        *lock_count = lock_num + 1; +    } +} +  int dht_addfriend(DHT *dht, const uint8_t *public_key, dht_ip_cb *ip_callback,                    void *data, int32_t number, uint16_t *lock_count)  {      const uint32_t friend_num = index_of_friend_pk(dht->friends_list, dht->num_friends, public_key); -    uint16_t lock_num; -      if (friend_num != UINT32_MAX) { /* Is friend already in DHT? */          DHT_Friend *const dht_friend = &dht->friends_list[friend_num]; @@ -1567,15 +1551,7 @@ int dht_addfriend(DHT *dht, const uint8_t *public_key, dht_ip_cb *ip_callback,              return -1;          } -        lock_num = dht_friend->lock_count; -        ++dht_friend->lock_count; -        dht_friend->callbacks[lock_num].ip_callback = ip_callback; -        dht_friend->callbacks[lock_num].data = data; -        dht_friend->callbacks[lock_num].number = number; - -        if (lock_count) { -            *lock_count = lock_num + 1; -        } +        dht_friend_lock(dht_friend, ip_callback, data, number, lock_count);          return 0;      } @@ -1594,18 +1570,10 @@ int dht_addfriend(DHT *dht, const uint8_t *public_key, dht_ip_cb *ip_callback,      dht_friend->nat.nat_ping_id = random_u64();      ++dht->num_friends; -    lock_num = dht_friend->lock_count; -    ++dht_friend->lock_count; -    dht_friend->callbacks[lock_num].ip_callback = ip_callback; -    dht_friend->callbacks[lock_num].data = data; -    dht_friend->callbacks[lock_num].number = number; - -    if (lock_count) { -        *lock_count = lock_num + 1; -    } +    dht_friend_lock(dht_friend, ip_callback, data, number, lock_count);      dht_friend->num_to_bootstrap = get_close_nodes(dht, dht_friend->public_key, dht_friend->to_bootstrap, net_family_unspec, -                                   1, 0); +                                   1);      return 0;  } @@ -1632,9 +1600,7 @@ int dht_delfriend(DHT *dht, const uint8_t *public_key, uint16_t lock_count)      --dht->num_friends;      if (dht->num_friends != friend_num) { -        memcpy(&dht->friends_list[friend_num], -               &dht->friends_list[dht->num_friends], -               sizeof(DHT_Friend)); +        dht->friends_list[friend_num] = dht->friends_list[dht->num_friends];      }      if (dht->num_friends == 0) { @@ -1643,7 +1609,7 @@ int dht_delfriend(DHT *dht, const uint8_t *public_key, uint16_t lock_count)          return 0;      } -    DHT_Friend *const temp = (DHT_Friend *)realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends)); +    DHT_Friend *const temp = (DHT_Friend *)realloc(dht->friends_list, sizeof(DHT_Friend) * dht->num_friends);      if (temp == nullptr) {          return -1; @@ -1665,7 +1631,7 @@ int dht_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port)          return -1;      } -    DHT_Friend *const frnd = &dht->friends_list[friend_index]; +    const DHT_Friend *const frnd = &dht->friends_list[friend_index];      const uint32_t client_index = index_of_client_pk(frnd->client_list, MAX_FRIEND_CLIENTS, public_key);      if (client_index == -1) { @@ -1678,7 +1644,7 @@ int dht_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port)      for (const IPPTsPng * const *it = assocs; *it; ++it) {          const IPPTsPng *const assoc = *it; -        if (!assoc_timeout(dht->last_run, assoc)) { +        if (!assoc_timeout(dht->cur_time, assoc)) {              *ip_port = assoc->ip_port;              return 1;          } @@ -1687,7 +1653,7 @@ int dht_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port)      return -1;  } -/* returns number of nodes not in kill-timeout */ +/** returns number of nodes not in kill-timeout */  static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, const uint8_t *public_key,          Client_data *list, uint32_t list_count, uint32_t *bootstrap_times, bool sortable)  { @@ -1714,12 +1680,12 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co                  ++not_kill;                  if (mono_time_is_timeout(dht->mono_time, assoc->last_pinged, PING_INTERVAL)) { -                    getnodes(dht, assoc->ip_port, client->public_key, public_key, nullptr); +                    dht_getnodes(dht, &assoc->ip_port, client->public_key, public_key);                      assoc->last_pinged = temp_time;                  }                  /* If node is good. */ -                if (!assoc_timeout(dht->last_run, assoc)) { +                if (!assoc_timeout(dht->cur_time, assoc)) {                      client_list[num_nodes] = client;                      assoc_list[num_nodes] = assoc;                      ++num_nodes; @@ -1736,18 +1702,18 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co      }      if (sortable && sort_ok) { -        sort_client_list(list, dht->last_run, list_count, public_key); +        sort_client_list(list, dht->cur_time, list_count, public_key);      }      if ((num_nodes != 0) && (mono_time_is_timeout(dht->mono_time, *lastgetnode, GET_NODE_INTERVAL)                               || *bootstrap_times < MAX_BOOTSTRAP_TIMES)) { -        uint32_t rand_node = random_u32() % num_nodes; +        uint32_t rand_node = random_range_u32(num_nodes);          if ((num_nodes - 1) != rand_node) { -            rand_node += random_u32() % (num_nodes - (rand_node + 1)); +            rand_node += random_range_u32(num_nodes - (rand_node + 1));          } -        getnodes(dht, assoc_list[rand_node]->ip_port, client_list[rand_node]->public_key, public_key, nullptr); +        dht_getnodes(dht, &assoc_list[rand_node]->ip_port, client_list[rand_node]->public_key, public_key);          *lastgetnode = temp_time;          ++*bootstrap_times; @@ -1756,7 +1722,7 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co      return not_kill;  } -/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request +/** Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request   * every GET_NODE_INTERVAL seconds to a random good node for each "friend" in our "friends" list.   */  static void do_dht_friends(DHT *dht) @@ -1765,8 +1731,7 @@ static void do_dht_friends(DHT *dht)          DHT_Friend *const dht_friend = &dht->friends_list[i];          for (size_t j = 0; j < dht_friend->num_to_bootstrap; ++j) { -            getnodes(dht, dht_friend->to_bootstrap[j].ip_port, dht_friend->to_bootstrap[j].public_key, dht_friend->public_key, -                     nullptr); +            dht_getnodes(dht, &dht_friend->to_bootstrap[j].ip_port, dht_friend->to_bootstrap[j].public_key, dht_friend->public_key);          }          dht_friend->num_to_bootstrap = 0; @@ -1777,13 +1742,13 @@ static void do_dht_friends(DHT *dht)      }  } -/* Ping each client in the close nodes list every PING_INTERVAL seconds. +/** Ping each client in the close nodes list every PING_INTERVAL seconds.   * Send a get nodes request every GET_NODE_INTERVAL seconds to a random good node in the list.   */  static void do_Close(DHT *dht)  {      for (size_t i = 0; i < dht->num_to_bootstrap; ++i) { -        getnodes(dht, dht->to_bootstrap[i].ip_port, dht->to_bootstrap[i].public_key, dht->self_public_key, nullptr); +        dht_getnodes(dht, &dht->to_bootstrap[i].ip_port, dht->to_bootstrap[i].public_key, dht->self_public_key);      }      dht->num_to_bootstrap = 0; @@ -1819,15 +1784,11 @@ static void do_Close(DHT *dht)      }  } -void dht_getnodes(DHT *dht, const IP_Port *from_ipp, const uint8_t *from_id, const uint8_t *which_id) +void dht_bootstrap(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key)  { -    getnodes(dht, *from_ipp, from_id, which_id, nullptr); +    dht_getnodes(dht, ip_port, public_key, dht->self_public_key);  } -void dht_bootstrap(DHT *dht, IP_Port ip_port, const uint8_t *public_key) -{ -    getnodes(dht, ip_port, public_key, dht->self_public_key, nullptr); -}  int dht_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled,                                 uint16_t port, const uint8_t *public_key)  { @@ -1845,11 +1806,11 @@ int dht_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enable      if (addr_resolve_or_parse_ip(address, &ip_port_v64.ip, ip_extra)) {          ip_port_v64.port = port; -        dht_bootstrap(dht, ip_port_v64, public_key); +        dht_bootstrap(dht, &ip_port_v64, public_key);          if ((ip_extra != nullptr) && ip_isset(ip_extra)) {              ip_port_v4.port = port; -            dht_bootstrap(dht, ip_port_v4, public_key); +            dht_bootstrap(dht, &ip_port_v4, public_key);          }          return 1; @@ -1858,7 +1819,7 @@ int dht_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enable      return 0;  } -/* Send the given packet to node with public_key +/** Send the given packet to node with public_key.   *   *  return -1 if failure.   */ @@ -1873,7 +1834,7 @@ int route_packet(const DHT *dht, const uint8_t *public_key, const uint8_t *packe                  const IPPTsPng *const assoc = *it;                  if (ip_isset(&assoc->ip_port.ip)) { -                    return sendpacket(dht->net, assoc->ip_port, packet, length); +                    return sendpacket(dht->net, &assoc->ip_port, packet, length);                  }              } @@ -1884,7 +1845,7 @@ int route_packet(const DHT *dht, const uint8_t *public_key, const uint8_t *packe      return -1;  } -/* Puts all the different ips returned by the nodes for a friend_num into array ip_portlist. +/** Puts all the different ips returned by the nodes for a friend_num into array ip_portlist.   * ip_portlist must be at least MAX_FRIEND_CLIENTS big.   *   *  return the number of ips returned. @@ -1920,8 +1881,8 @@ static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_n          }          if (id_equal(client->public_key, dht_friend->public_key)) { -            if (!assoc_timeout(dht->last_run, &client->assoc6) -                    || !assoc_timeout(dht->last_run, &client->assoc4)) { +            if (!assoc_timeout(dht->cur_time, &client->assoc6) +                    || !assoc_timeout(dht->cur_time, &client->assoc4)) {                  return 0; /* direct connectivity */              }          } @@ -1960,12 +1921,83 @@ static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_n  } -/* Send the following packet to everyone who tells us they are connected to friend_id. +/** + * Callback invoked for each IP/port of each client of a friend. + * + * For each client, the callback is invoked twice: once for IPv4 and once for + * IPv6. If the callback returns `false` after the IPv4 invocation, it will not + * be invoked for IPv6. + * + * @param dht The main DHT instance. + * @param ip_port The currently processed IP/port. + * @param n A pointer to the number that will be returned from `foreach_ip_port`. + * @param userdata The `userdata` pointer passed to `foreach_ip_port`. + */ +typedef bool foreach_ip_port_cb(const DHT *dht, const IP_Port *ip_port, uint32_t *n, void *userdata); + +/** + * Runs a callback on every active connection for a given DHT friend. + * + * This iterates over the client list of a DHT friend and invokes a callback for + * every non-zero IP/port (IPv4 and IPv6) that's not timed out. + * + * @param dht The main DHT instance, passed to the callback. + * @param dht_friend The friend over whose connections we should iterate. + * @param callback The callback to invoke for each IP/port. + * @param userdata Extra pointer passed to the callback. + */ +static uint32_t foreach_ip_port(const DHT *dht, const DHT_Friend *dht_friend, +                                foreach_ip_port_cb *callback, void *userdata) +{ +    uint32_t n = 0; + +    /* extra legwork, because having the outside allocating the space for us +     * is *usually* good(tm) (bites us in the behind in this case though) */ +    for (uint32_t i = 0; i < MAX_FRIEND_CLIENTS; ++i) { +        const Client_data *const client = &dht_friend->client_list[i]; +        const IPPTsPng *const assocs[] = { &client->assoc4, &client->assoc6, nullptr }; + +        for (const IPPTsPng * const *it = assocs; *it != nullptr; ++it) { +            const IPPTsPng *const assoc = *it; + +            /* If ip is not zero and node is good. */ +            if (!ip_isset(&assoc->ret_ip_port.ip) +                    && !mono_time_is_timeout(dht->mono_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { +                continue; +            } + +            if (!callback(dht, &assoc->ip_port, &n, userdata)) { +                /* If the callback is happy with just one of the assocs, we +                 * don't give it the second one. */ +                break; +            } +        } +    } + +    return n; +} + +static bool send_packet_to_friend(const DHT *dht, const IP_Port *ip_port, uint32_t *n, void *userdata) +{ +    const Packet *packet = (const Packet *)userdata; +    const int retval = send_packet(dht->net, ip_port, *packet); + +    if ((uint32_t)retval == packet->length) { +        ++*n; +        /* Send one packet per friend: stop the foreach on the first success. */ +        return false; +    } + +    return true; +} + +/** + * Send the following packet to everyone who tells us they are connected to friend_id.   *   *  return ip for friend.   *  return number of nodes the packet was sent to. (Only works if more than (MAX_FRIEND_CLIENTS / 4).   */ -int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint16_t length) +uint32_t route_to_friend(const DHT *dht, const uint8_t *friend_id, const Packet *packet)  {      const uint32_t num = index_of_friend_pk(dht->friends_list, dht->num_friends, friend_id); @@ -1973,47 +2005,33 @@ int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *pack          return 0;      } -    uint32_t sent = 0;      IP_Port ip_list[MAX_FRIEND_CLIENTS];      const int ip_num = friend_iplist(dht, ip_list, num); -    if (ip_num < (MAX_FRIEND_CLIENTS / 4)) { +    if (ip_num < MAX_FRIEND_CLIENTS / 4) {          return 0; /* Reason for that? */      }      const DHT_Friend *const dht_friend = &dht->friends_list[num]; +    Packet packet_userdata = *packet;  // Copy because it needs to be non-const. -    /* extra legwork, because having the outside allocating the space for us -     * is *usually* good(tm) (bites us in the behind in this case though) */ - -    for (uint32_t i = 0; i < MAX_FRIEND_CLIENTS; ++i) { -        const Client_data *const client = &dht_friend->client_list[i]; -        const IPPTsPng *const assocs[] = { &client->assoc4, &client->assoc6, nullptr }; - -        for (const IPPTsPng * const *it = assocs; *it; ++it) { -            const IPPTsPng *const assoc = *it; - -            /* If ip is not zero and node is good. */ -            if (ip_isset(&assoc->ret_ip_port.ip) && !mono_time_is_timeout(dht->mono_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { -                const int retval = sendpacket(dht->net, assoc->ip_port, packet, length); - -                if ((unsigned int)retval == length) { -                    ++sent; -                    break; /* Send one packet per client.*/ -                } -            } -        } -    } +    return foreach_ip_port(dht, dht_friend, send_packet_to_friend, &packet_userdata); +} -    return sent; +static bool get_ip_port(const DHT *dht, const IP_Port *ip_port, uint32_t *n, void *userdata) +{ +    IP_Port *ip_list = (IP_Port *)userdata; +    ip_list[*n] = *ip_port; +    ++*n; +    return true;  } -/* Send the following packet to one random person who tells us they are connected to friend_id. +/** Send the following packet to one random person who tells us they are connected to friend_id.   *   *  return number of nodes the packet was sent to.   */ -static int routeone_tofriend(DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint16_t length) +static uint32_t routeone_to_friend(const DHT *dht, const uint8_t *friend_id, const Packet *packet)  {      const uint32_t num = index_of_friend_pk(dht->friends_list, dht->num_friends, friend_id); @@ -2024,33 +2042,17 @@ static int routeone_tofriend(DHT *dht, const uint8_t *friend_id, const uint8_t *      const DHT_Friend *const dht_friend = &dht->friends_list[num];      IP_Port ip_list[MAX_FRIEND_CLIENTS * 2]; -    int n = 0; -    /* extra legwork, because having the outside allocating the space for us -     * is *usually* good(tm) (bites us in the behind in this case though) */ - -    for (uint32_t i = 0; i < MAX_FRIEND_CLIENTS; ++i) { -        const Client_data *const client = &dht_friend->client_list[i]; -        const IPPTsPng *const assocs[] = { &client->assoc4, &client->assoc6, nullptr }; - -        for (const IPPTsPng * const *it = assocs; *it; ++it) { -            const IPPTsPng *const assoc = *it; - -            /* If ip is not zero and node is good. */ -            if (ip_isset(&assoc->ret_ip_port.ip) && !mono_time_is_timeout(dht->mono_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { -                ip_list[n] = assoc->ip_port; -                ++n; -            } -        } -    } +    const int n = foreach_ip_port(dht, dht_friend, get_ip_port, ip_list);      if (n < 1) {          return 0;      } -    const int retval = sendpacket(dht->net, ip_list[random_u32() % n], packet, length); +    const uint32_t rand_idx = random_range_u32(n); +    const int retval = send_packet(dht->net, &ip_list[rand_idx], *packet); -    if ((unsigned int)retval == length) { +    if ((unsigned int)retval == packet->length) {          return 1;      } @@ -2060,28 +2062,30 @@ static int routeone_tofriend(DHT *dht, const uint8_t *friend_id, const uint8_t *  /*----------------------------------------------------------------------------------*/  /*---------------------BEGINNING OF NAT PUNCHING FUNCTIONS--------------------------*/ -static int send_NATping(DHT *dht, const uint8_t *public_key, uint64_t ping_id, uint8_t type) +static int send_NATping(const DHT *dht, const uint8_t *public_key, uint64_t ping_id, uint8_t type)  {      uint8_t data[sizeof(uint64_t) + 1]; -    uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; - -    int num = 0; +    uint8_t packet_data[MAX_CRYPTO_REQUEST_SIZE];      data[0] = type;      memcpy(data + 1, &ping_id, sizeof(uint64_t));      /* 254 is NAT ping request packet id */      const int len = create_request( -                        dht->self_public_key, dht->self_secret_key, packet, public_key, data, +                        dht->self_public_key, dht->self_secret_key, packet_data, public_key, data,                          sizeof(uint64_t) + 1, CRYPTO_PACKET_NAT_PING);      if (len == -1) {          return -1;      } +    assert(len <= UINT16_MAX); +    uint32_t num = 0; +    const Packet packet = {packet_data, (uint16_t)len}; +      if (type == 0) { /* If packet is request use many people to route it. */ -        num = route_tofriend(dht, public_key, packet, len); +        num = route_to_friend(dht, public_key, &packet);      } else if (type == 1) { /* If packet is response use only one person to route it */ -        num = routeone_tofriend(dht, public_key, packet, len); +        num = routeone_to_friend(dht, public_key, &packet);      }      if (num == 0) { @@ -2091,8 +2095,8 @@ static int send_NATping(DHT *dht, const uint8_t *public_key, uint64_t ping_id, u      return num;  } -/* Handle a received ping request for. */ -static int handle_NATping(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet, +/** Handle a received ping request for. */ +static int handle_NATping(void *object, const IP_Port *source, const uint8_t *source_pubkey, const uint8_t *packet,                            uint16_t length, void *userdata)  {      if (length != sizeof(uint64_t) + 1) { @@ -2129,13 +2133,13 @@ static int handle_NATping(void *object, IP_Port source, const uint8_t *source_pu      return 1;  } -/* Get the most common ip in the ip_portlist. +/** Get the most common ip in the ip_portlist.   * Only return ip if it appears in list min_num or more.   * len must not be bigger than MAX_FRIEND_CLIENTS.   *   *  return ip of 0 if failure.   */ -static IP nat_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) +static IP nat_commonip(const IP_Port *ip_portlist, uint16_t len, uint16_t min_num)  {      IP zero;      ip_reset(&zero); @@ -2161,18 +2165,18 @@ static IP nat_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)      return zero;  } -/* Return all the ports for one ip in a list. +/** Return all the ports for one ip in a list.   * portlist must be at least len long,   * where len is the length of ip_portlist.   *   *  return number of ports and puts the list of ports in portlist.   */ -static uint16_t nat_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t len, IP ip) +static uint16_t nat_getports(uint16_t *portlist, const IP_Port *ip_portlist, uint16_t len, const IP *ip)  {      uint16_t num = 0;      for (uint32_t i = 0; i < len; ++i) { -        if (ip_equal(&ip_portlist[i].ip, &ip)) { +        if (ip_equal(&ip_portlist[i].ip, ip)) {              portlist[num] = net_ntohs(ip_portlist[i].port);              ++num;          } @@ -2181,7 +2185,7 @@ static uint16_t nat_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t      return num;  } -static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports, uint16_t friend_num) +static void punch_holes(DHT *dht, const IP *ip, const uint16_t *port_list, uint16_t numports, uint16_t friend_num)  {      if (!dht->hole_punching_enabled) {          return; @@ -2202,9 +2206,9 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports,      if (i == numports) { /* If all ports are the same, only try that one port. */          IP_Port pinging; -        ip_copy(&pinging.ip, &ip); +        ip_copy(&pinging.ip, ip);          pinging.port = net_htons(first_port); -        ping_send_request(dht->ping, pinging, dht->friends_list[friend_num].public_key); +        ping_send_request(dht->ping, &pinging, dht->friends_list[friend_num].public_key);      } else {          for (i = 0; i < MAX_PUNCHING_PORTS; ++i) {              /* TODO(irungentoo): Improve port guessing algorithm. */ @@ -2214,9 +2218,9 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports,              const uint32_t index = (it / 2) % numports;              const uint16_t port = port_list[index] + delta;              IP_Port pinging; -            ip_copy(&pinging.ip, &ip); +            ip_copy(&pinging.ip, ip);              pinging.port = net_htons(port); -            ping_send_request(dht->ping, pinging, dht->friends_list[friend_num].public_key); +            ping_send_request(dht->ping, &pinging, dht->friends_list[friend_num].public_key);          }          dht->friends_list[friend_num].nat.punching_index += i; @@ -2225,12 +2229,12 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports,      if (dht->friends_list[friend_num].nat.tries > MAX_NORMAL_PUNCHING_TRIES) {          const uint16_t port = 1024;          IP_Port pinging; -        ip_copy(&pinging.ip, &ip); +        ip_copy(&pinging.ip, ip);          for (i = 0; i < MAX_PUNCHING_PORTS; ++i) {              uint32_t it = i + dht->friends_list[friend_num].nat.punching_index2;              pinging.port = net_htons(port + it); -            ping_send_request(dht->ping, pinging, dht->friends_list[friend_num].public_key); +            ping_send_request(dht->ping, &pinging, dht->friends_list[friend_num].public_key);          }          dht->friends_list[friend_num].nat.punching_index2 += i - (MAX_PUNCHING_PORTS / 2); @@ -2274,8 +2278,8 @@ static void do_NAT(DHT *dht)              }              uint16_t port_list[MAX_FRIEND_CLIENTS]; -            const uint16_t numports = nat_getports(port_list, ip_list, num, ip); -            punch_holes(dht, ip, port_list, numports, i); +            const uint16_t numports = nat_getports(port_list, ip_list, num, &ip); +            punch_holes(dht, &ip, port_list, numports, i);              dht->friends_list[i].nat.punching_timestamp = temp_time;              dht->friends_list[i].nat.hole_punching = 0; @@ -2286,233 +2290,12 @@ static void do_NAT(DHT *dht)  /*----------------------------------------------------------------------------------*/  /*-----------------------END OF NAT PUNCHING FUNCTIONS------------------------------*/ -#define DHT_HARDENING 0 -#define HARDREQ_DATA_SIZE 384 // Attempt to prevent amplification/other attacks - -typedef enum Check_Type { -    CHECK_TYPE_ROUTE_REQ = 0, -    CHECK_TYPE_ROUTE_RES = 1, -    CHECK_TYPE_GETNODE_REQ = 2, -    CHECK_TYPE_GETNODE_RES = 3, -    CHECK_TYPE_TEST_REQ = 4, -    CHECK_TYPE_TEST_RES = 5, -} Check_Type; - -#if DHT_HARDENING -static int send_hardening_req(DHT *dht, Node_format *sendto, uint8_t type, uint8_t *contents, uint16_t length) -{ -    if (length > HARDREQ_DATA_SIZE - 1) { -        return -1; -    } - -    uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; -    uint8_t data[HARDREQ_DATA_SIZE] = {0}; -    data[0] = type; -    memcpy(data + 1, contents, length); -    const int len = create_request( -                        dht->self_public_key, dht->self_secret_key, packet, sendto->public_key, -                        data, sizeof(data), CRYPTO_PACKET_HARDENING); - -    if (len == -1) { -        return -1; -    } - -    return sendpacket(dht->net, sendto->ip_port, packet, len); -} - -/* Send a get node hardening request */ -static int send_hardening_getnode_req(DHT *dht, Node_format *dest, Node_format *node_totest, uint8_t *search_id) -{ -    uint8_t data[sizeof(Node_format) + CRYPTO_PUBLIC_KEY_SIZE]; -    memcpy(data, node_totest, sizeof(Node_format)); -    memcpy(data + sizeof(Node_format), search_id, CRYPTO_PUBLIC_KEY_SIZE); -    return send_hardening_req(dht, dest, CHECK_TYPE_GETNODE_REQ, data, sizeof(Node_format) + CRYPTO_PUBLIC_KEY_SIZE); -} -#endif - -/* Send a get node hardening response */ -static int send_hardening_getnode_res(const DHT *dht, const Node_format *sendto, const uint8_t *queried_client_id, -                                      const uint8_t *nodes_data, uint16_t nodes_data_length) -{ -    if (!ip_isset(&sendto->ip_port.ip)) { -        return -1; -    } - -    uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; -    VLA(uint8_t, data, 1 + CRYPTO_PUBLIC_KEY_SIZE + nodes_data_length); -    data[0] = CHECK_TYPE_GETNODE_RES; -    memcpy(data + 1, queried_client_id, CRYPTO_PUBLIC_KEY_SIZE); -    memcpy(data + 1 + CRYPTO_PUBLIC_KEY_SIZE, nodes_data, nodes_data_length); -    const int len = create_request( -                        dht->self_public_key, dht->self_secret_key, packet, sendto->public_key, -                        data, SIZEOF_VLA(data), CRYPTO_PACKET_HARDENING); - -    if (len == -1) { -        return -1; -    } - -    return sendpacket(dht->net, sendto->ip_port, packet, len); -} - -/* TODO(irungentoo): improve */ -static IPPTsPng *get_closelist_IPPTsPng(DHT *dht, const uint8_t *public_key, Family sa_family) -{ -    for (uint32_t i = 0; i < LCLIENT_LIST; ++i) { -        if (!id_equal(dht->close_clientlist[i].public_key, public_key)) { -            continue; -        } - -        if (net_family_is_ipv4(sa_family)) { -            return &dht->close_clientlist[i].assoc4; -        } - -        if (net_family_is_ipv6(sa_family)) { -            return &dht->close_clientlist[i].assoc6; -        } -    } - -    return nullptr; -} - -/* - * check how many nodes in nodes are also present in the closelist. - * TODO(irungentoo): make this function better. - */ -static uint32_t have_nodes_closelist(DHT *dht, Node_format *nodes, uint16_t num) -{ -    uint32_t counter = 0; - -    for (uint32_t i = 0; i < num; ++i) { -        if (id_equal(nodes[i].public_key, dht->self_public_key)) { -            ++counter; -            continue; -        } - -        const IPPTsPng *const temp = get_closelist_IPPTsPng(dht, nodes[i].public_key, nodes[i].ip_port.ip.family); - -        if (temp) { -            if (!assoc_timeout(dht->last_run, temp)) { -                ++counter; -            } -        } -    } - -    return counter; -} - -/* Interval in seconds between hardening checks */ -#define HARDENING_INTERVAL 120 - -/* Handle a received hardening packet */ -static int handle_hardening(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet, -                            uint16_t length, void *userdata) -{ -    DHT *const dht = (DHT *)object; - -    if (length < 2) { -        return 1; -    } - -    switch (packet[0]) { -        case CHECK_TYPE_GETNODE_REQ: { -            if (length != HARDREQ_DATA_SIZE) { -                return 1; -            } - -            Node_format node; -            Node_format tocheck_node; -            node.ip_port = source; -            memcpy(node.public_key, source_pubkey, CRYPTO_PUBLIC_KEY_SIZE); -            memcpy(&tocheck_node, packet + 1, sizeof(Node_format)); - -            if (getnodes(dht, tocheck_node.ip_port, tocheck_node.public_key, packet + 1 + sizeof(Node_format), &node) == -1) { -                return 1; -            } - -            return 0; -        } - -        case CHECK_TYPE_GETNODE_RES: { -            if (length <= CRYPTO_PUBLIC_KEY_SIZE + 1) { -                return 1; -            } - -            if (length > 1 + CRYPTO_PUBLIC_KEY_SIZE + sizeof(Node_format) * MAX_SENT_NODES) { -                return 1; -            } - -            uint16_t length_nodes = length - 1 - CRYPTO_PUBLIC_KEY_SIZE; -            Node_format nodes[MAX_SENT_NODES]; -            const int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, nullptr, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, -                                               length_nodes, 0); - -            /* TODO(irungentoo): MAX_SENT_NODES nodes should be returned at all times -             * (right now we have a small network size so it could cause problems for testing and etc..) */ -            if (num_nodes <= 0) { -                return 1; -            } - -            /* NOTE: This should work for now but should be changed to something better. */ -            if (have_nodes_closelist(dht, nodes, num_nodes) < (uint32_t)((num_nodes + 2) / 2)) { -                return 1; -            } - -            IPPTsPng *const temp = get_closelist_IPPTsPng(dht, packet + 1, nodes[0].ip_port.ip.family); - -            if (temp == nullptr) { -                return 1; -            } - -            if (mono_time_is_timeout(dht->mono_time, temp->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) { -                return 1; -            } - -            if (!id_equal(temp->hardening.send_nodes_pingedid, source_pubkey)) { -                return 1; -            } - -            /* If Nodes look good and the request checks out */ -            temp->hardening.send_nodes_ok = 1; -            return 0;/* success*/ -        } -    } - -    return 1; -} - -#if DHT_HARDENING -#define HARDEN_TIMEOUT 1200 - -/* Return a random node from all the nodes we are connected to. - * TODO(irungentoo): improve this function. - */ -static Node_format random_node(DHT *dht, Family sa_family) -{ -    uint8_t id[CRYPTO_PUBLIC_KEY_SIZE]; - -    for (uint32_t i = 0; i < CRYPTO_PUBLIC_KEY_SIZE / 4; ++i) { /* populate the id with pseudorandom bytes.*/ -        const uint32_t t = random_u32(); -        memcpy(id + i * sizeof(t), &t, sizeof(t)); -    } - -    Node_format nodes_list[MAX_SENT_NODES]; -    memset(nodes_list, 0, sizeof(nodes_list)); -    const uint32_t num_nodes = get_close_nodes(dht, id, nodes_list, sa_family, 1, 0); - -    if (num_nodes == 0) { -        return nodes_list[0]; -    } - -    return nodes_list[random_u32() % num_nodes]; -} -#endif - -/* Put up to max_num nodes in nodes from the closelist. +/** Put up to max_num nodes in nodes from the closelist.   *   * return the number of nodes.   */ -static uint16_t list_nodes(Client_data *list, size_t length, uint64_t cur_time, Node_format *nodes, -                           uint16_t max_num) +static uint16_t list_nodes(const Client_data *list, size_t length, uint64_t cur_time, +                           Node_format *nodes, uint16_t max_num)  {      if (max_num == 0) {          return 0; @@ -2549,11 +2332,11 @@ static uint16_t list_nodes(Client_data *list, size_t length, uint64_t cur_time,      return count;  } -/* Put up to max_num nodes in nodes from the random friends. +/** Put up to max_num nodes in nodes from the random friends.   *   * return the number of nodes.   */ -uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num) +uint16_t randfriends_nodes(const DHT *dht, Node_format *nodes, uint16_t max_num)  {      if (max_num == 0) {          return 0; @@ -2563,7 +2346,7 @@ uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)      const uint32_t r = random_u32();      for (size_t i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) { -        count += list_nodes(dht->friends_list[(i + r) % DHT_FAKE_FRIEND_NUMBER].client_list, MAX_FRIEND_CLIENTS, dht->last_run, +        count += list_nodes(dht->friends_list[(i + r) % DHT_FAKE_FRIEND_NUMBER].client_list, MAX_FRIEND_CLIENTS, dht->cur_time,                              nodes + count, max_num - count);          if (count >= max_num) { @@ -2574,68 +2357,15 @@ uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)      return count;  } -/* Put up to max_num nodes in nodes from the closelist. +/** Put up to max_num nodes in nodes from the closelist.   *   * return the number of nodes.   */ -uint16_t closelist_nodes(DHT *dht, Node_format *nodes, uint16_t max_num) +uint16_t closelist_nodes(const DHT *dht, Node_format *nodes, uint16_t max_num)  { -    return list_nodes(dht->close_clientlist, LCLIENT_LIST, dht->last_run, nodes, max_num); +    return list_nodes(dht->close_clientlist, LCLIENT_LIST, dht->cur_time, nodes, max_num);  } -#if DHT_HARDENING -static void do_hardening(DHT *dht) -{ -    for (uint32_t i = 0; i < LCLIENT_LIST * 2; ++i) { -        IPPTsPng *cur_iptspng; -        Family sa_family; -        const uint8_t *const public_key = dht->close_clientlist[i / 2].public_key; - -        if (i % 2 == 0) { -            cur_iptspng = &dht->close_clientlist[i / 2].assoc4; -            sa_family = net_family_ipv4; -        } else { -            cur_iptspng = &dht->close_clientlist[i / 2].assoc6; -            sa_family = net_family_ipv6; -        } - -        if (assoc_timeout(dht->mono_time, cur_iptspng)) { -            continue; -        } - -        if (cur_iptspng->hardening.send_nodes_ok == 0) { -            if (mono_time_is_timeout(dht->mono_time, cur_iptspng->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) { -                Node_format rand_node = random_node(dht, sa_family); - -                if (!ipport_isset(&rand_node.ip_port)) { -                    continue; -                } - -                if (id_equal(public_key, rand_node.public_key)) { -                    continue; -                } - -                Node_format to_test; -                to_test.ip_port = cur_iptspng->ip_port; -                memcpy(to_test.public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); - -                // TODO(irungentoo): The search id should maybe not be ours? -                if (send_hardening_getnode_req(dht, &rand_node, &to_test, dht->self_public_key) > 0) { -                    memcpy(cur_iptspng->hardening.send_nodes_pingedid, rand_node.public_key, CRYPTO_PUBLIC_KEY_SIZE); -                    cur_iptspng->hardening.send_nodes_timestamp = mono_time_get(dht->mono_time); -                } -            } -        } else { -            if (mono_time_is_timeout(dht->mono_time, cur_iptspng->hardening.send_nodes_timestamp, HARDEN_TIMEOUT)) { -                cur_iptspng->hardening.send_nodes_ok = 0; -            } -        } - -        // TODO(irungentoo): add the 2 other testers. -    } -} -#endif -  /*----------------------------------------------------------------------------------*/  void cryptopacket_registerhandler(DHT *dht, uint8_t byte, cryptopacket_handler_cb *cb, void *object) @@ -2644,7 +2374,8 @@ void cryptopacket_registerhandler(DHT *dht, uint8_t byte, cryptopacket_handler_c      dht->cryptopackethandlers[byte].object = object;  } -static int cryptopacket_handle(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) +static int cryptopacket_handle(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, +                               void *userdata)  {      DHT *const dht = (DHT *)object; @@ -2701,7 +2432,7 @@ DHT *new_dht(const Logger *log, Mono_Time *mono_time, Networking_Core *net, bool      }      dht->mono_time = mono_time; -    dht->last_run = mono_time_get(mono_time); +    dht->cur_time = mono_time_get(mono_time);      dht->log = log;      dht->net = net; @@ -2718,14 +2449,12 @@ DHT *new_dht(const Logger *log, Mono_Time *mono_time, Networking_Core *net, bool      networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht);      networking_registerhandler(dht->net, NET_PACKET_CRYPTO, &cryptopacket_handle, dht);      cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht); -    cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, &handle_hardening, dht);      crypto_new_keypair(dht->self_public_key, dht->self_secret_key);      dht->dht_ping_array = ping_array_new(DHT_PING_ARRAY_SIZE, PING_TIMEOUT); -    dht->dht_harden_ping_array = ping_array_new(DHT_PING_ARRAY_SIZE, PING_TIMEOUT); -    if (dht->dht_ping_array == nullptr || dht->dht_harden_ping_array == nullptr) { +    if (dht->dht_ping_array == nullptr) {          kill_dht(dht);          return nullptr;      } @@ -2749,11 +2478,11 @@ void do_dht(DHT *dht)  {      const uint64_t cur_time = mono_time_get(dht->mono_time); -    if (dht->last_run == cur_time) { +    if (dht->cur_time == cur_time) {          return;      } -    dht->last_run = cur_time; +    dht->cur_time = cur_time;      // Load friends/clients if first call to do_dht      if (dht->loaded_num_nodes) { @@ -2764,9 +2493,6 @@ void do_dht(DHT *dht)      do_dht_friends(dht);      do_NAT(dht);      ping_iterate(dht->ping); -#if DHT_HARDENING -    do_hardening(dht); -#endif  }  void kill_dht(DHT *dht) @@ -2774,12 +2500,13 @@ void kill_dht(DHT *dht)      networking_registerhandler(dht->net, NET_PACKET_GET_NODES, nullptr, nullptr);      networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, nullptr, nullptr);      cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, nullptr, nullptr); -    cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, nullptr, nullptr);      ping_array_kill(dht->dht_ping_array); -    ping_array_kill(dht->dht_harden_ping_array);      ping_kill(dht->ping);      free(dht->friends_list);      free(dht->loaded_nodes_list); +    crypto_memzero(&dht->shared_keys_recv, sizeof(dht->shared_keys_recv)); +    crypto_memzero(&dht->shared_keys_sent, sizeof(dht->shared_keys_sent)); +    crypto_memzero(dht->self_secret_key, sizeof(dht->self_secret_key));      free(dht);  } @@ -2792,7 +2519,7 @@ void kill_dht(DHT *dht)  #define MAX_SAVED_DHT_NODES (((DHT_FAKE_FRIEND_NUMBER * MAX_FRIEND_CLIENTS) + LCLIENT_LIST) * 2) -/* Get the size of the DHT (for saving). */ +/** Get the size of the DHT (for saving). */  uint32_t dht_size(const DHT *dht)  {      uint32_t numv4 = 0; @@ -2823,7 +2550,7 @@ uint32_t dht_size(const DHT *dht)      return size32 + sizesubhead + packed_node_size(net_family_ipv4) * numv4 + packed_node_size(net_family_ipv6) * numv6;  } -/* Save the DHT in data where data is an array of size dht_size(). */ +/** 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_lendian_bytes32(data, DHT_STATE_COOKIE_GLOBAL); @@ -2834,7 +2561,7 @@ void dht_save(const DHT *dht, uint8_t *data)      /* get right offset. we write the actual header later. */      data = state_write_section_header(data, DHT_STATE_COOKIE_TYPE, 0, 0); -    Node_format *clients = (Node_format *)malloc(MAX_SAVED_DHT_NODES * sizeof(Node_format)); +    Node_format *clients = (Node_format *)calloc(MAX_SAVED_DHT_NODES, sizeof(Node_format));      if (clients == nullptr) {          LOGGER_ERROR(dht->log, "could not allocate %u nodes", MAX_SAVED_DHT_NODES); @@ -2886,10 +2613,14 @@ void dht_save(const DHT *dht, uint8_t *data)      free(clients);  } -/* Bootstrap from this number of nodes every time dht_connect_after_load() is called */ +/** Bootstrap from this number of nodes every time dht_connect_after_load() is called */  #define SAVE_BOOTSTAP_FREQUENCY 8 -/* Start sending packets after DHT loaded_friends_list and loaded_clients_list are set */ +/** Start sending packets after DHT loaded_friends_list and loaded_clients_list are set. + * + * returns 0 if successful + * returns -1 otherwise + */  int dht_connect_after_load(DHT *dht)  {      if (dht == nullptr) { @@ -2910,7 +2641,7 @@ int dht_connect_after_load(DHT *dht)      for (uint32_t i = 0; i < dht->loaded_num_nodes && i < SAVE_BOOTSTAP_FREQUENCY; ++i) {          const unsigned int index = dht->loaded_nodes_index % dht->loaded_num_nodes; -        dht_bootstrap(dht, dht->loaded_nodes_list[index].ip_port, dht->loaded_nodes_list[index].public_key); +        dht_bootstrap(dht, &dht->loaded_nodes_list[index].ip_port, dht->loaded_nodes_list[index].public_key);          ++dht->loaded_nodes_index;      } @@ -2948,16 +2679,17 @@ static State_Load_Status dht_load_state_callback(void *outer, const uint8_t *dat              break;          } -        default: +        default: {              LOGGER_ERROR(dht->log, "Load state (DHT): contains unrecognized part (len %u, type %u)",                           length, type);              break; +        }      }      return STATE_LOAD_STATUS_CONTINUE;  } -/* Load the DHT from data of size size. +/** Load the DHT from data of size size.   *   *  return -1 if failure.   *  return 0 if success. @@ -2979,7 +2711,7 @@ int dht_load(DHT *dht, const uint8_t *data, uint32_t length)      return -1;  } -/*  return false if we are not connected to the DHT. +/**  return false if we are not connected to the DHT.   *  return true if we are.   */  bool dht_isconnected(const DHT *dht) @@ -2987,8 +2719,8 @@ bool dht_isconnected(const DHT *dht)      for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {          const Client_data *const client = &dht->close_clientlist[i]; -        if (!assoc_timeout(dht->last_run, &client->assoc4) || -                !assoc_timeout(dht->last_run, &client->assoc6)) { +        if (!assoc_timeout(dht->cur_time, &client->assoc4) || +                !assoc_timeout(dht->cur_time, &client->assoc6)) {              return true;          }      } @@ -2996,7 +2728,7 @@ bool dht_isconnected(const DHT *dht)      return false;  } -/*  return false if we are not connected or only connected to lan peers with the DHT. +/**  return false if we are not connected or only connected to lan peers with the DHT.   *  return true if we are.   */  bool dht_non_lan_connected(const DHT *dht) @@ -3004,16 +2736,66 @@ bool dht_non_lan_connected(const DHT *dht)      for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {          const Client_data *const client = &dht->close_clientlist[i]; -        if (!assoc_timeout(dht->last_run, &client->assoc4) -                && !ip_is_lan(client->assoc4.ip_port.ip)) { +        if (!assoc_timeout(dht->cur_time, &client->assoc4) +                && !ip_is_lan(&client->assoc4.ip_port.ip)) {              return true;          } -        if (!assoc_timeout(dht->last_run, &client->assoc6) -                && !ip_is_lan(client->assoc6.ip_port.ip)) { +        if (!assoc_timeout(dht->cur_time, &client->assoc6) +                && !ip_is_lan(&client->assoc6.ip_port.ip)) {              return true;          }      }      return false;  } + +/** Copies our own ip_port structure to `dest`. WAN addresses take priority over LAN addresses. + * + * This function will zero the `dest` buffer before use. + * + * Return 0 if our ip port can't be found (this usually means we're not connected to the DHT). + * Return 1 if IP is a WAN address. + * Return 2 if IP is a LAN address. + */ +unsigned int ipport_self_copy(const DHT *dht, IP_Port *dest) +{ +    ipport_reset(dest); + +    bool is_lan = false; + +    for (uint32_t i = 0; i < LCLIENT_LIST; ++i) { +        const Client_data *client = dht_get_close_client(dht, i); +        const IP_Port *ip_port4 = &client->assoc4.ret_ip_port; + +        if (client->assoc4.ret_ip_self && ipport_isset(ip_port4)) { +            ipport_copy(dest, ip_port4); +            is_lan = ip_is_lan(&dest->ip); + +            if (!is_lan) { +                break; +            } +        } + +        const IP_Port *ip_port6 = &client->assoc6.ret_ip_port; + +        if (client->assoc6.ret_ip_self && ipport_isset(ip_port6)) { +            ipport_copy(dest, ip_port6); +            is_lan = ip_is_lan(&dest->ip); + +            if (!is_lan) { +                break; +            } +        } +    } + +    if (!ipport_isset(dest)) { +        return 0; +    } + +    if (is_lan) { +        return 2; +    } + +    return 1; +} diff --git a/protocols/Tox/libtox/src/toxcore/DHT.h b/protocols/Tox/libtox/src/toxcore/DHT.h index fcc67251f6..f72ef924c9 100644 --- a/protocols/Tox/libtox/src/toxcore/DHT.h +++ b/protocols/Tox/libtox/src/toxcore/DHT.h @@ -3,63 +3,62 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * An implementation of the DHT as seen in docs/updates/DHT.md   */  #ifndef C_TOXCORE_TOXCORE_DHT_H  #define C_TOXCORE_TOXCORE_DHT_H +#include <stdbool.h> +  #include "crypto_core.h"  #include "logger.h"  #include "mono_time.h"  #include "network.h"  #include "ping_array.h" -#include <stdbool.h> -  #ifdef __cplusplus  extern "C" {  #endif -/* Maximum number of clients stored per friend. */ +/** Maximum number of clients stored per friend. */  #define MAX_FRIEND_CLIENTS 8  #define LCLIENT_NODES MAX_FRIEND_CLIENTS  #define LCLIENT_LENGTH 128 -/* A list of the clients mathematically closest to ours. */ +/** A list of the clients mathematically closest to ours. */  #define LCLIENT_LIST (LCLIENT_LENGTH * LCLIENT_NODES)  #define MAX_CLOSE_TO_BOOTSTRAP_NODES 8 -/* The max number of nodes to send with send nodes. */ +/** The max number of nodes to send with send nodes. */  #define MAX_SENT_NODES 4 -/* Ping timeout in seconds */ +/** Ping timeout in seconds */  #define PING_TIMEOUT 5 -/* size of DHT ping arrays. */ +/** size of DHT ping arrays. */  #define DHT_PING_ARRAY_SIZE 512 -/* Ping interval in seconds for each node in our lists. */ +/** Ping interval in seconds for each node in our lists. */  #define PING_INTERVAL 60 -/* The number of seconds for a non responsive node to become bad. */ +/** The number of seconds for a non responsive node to become bad. */  #define PINGS_MISSED_NODE_GOES_BAD 1  #define PING_ROUNDTRIP 2  #define BAD_NODE_TIMEOUT (PING_INTERVAL + PINGS_MISSED_NODE_GOES_BAD * (PING_INTERVAL + PING_ROUNDTRIP)) -/* The number of "fake" friends to add (for optimization purposes and so our paths for the onion part are more random) */ +/** The number of "fake" friends to add (for optimization purposes and so our paths for the onion part are more random) */  #define DHT_FAKE_FRIEND_NUMBER 2  #define MAX_CRYPTO_REQUEST_SIZE 1024  #define CRYPTO_PACKET_FRIEND_REQ    32  // Friend request crypto packet ID. -#define CRYPTO_PACKET_HARDENING     48  // Hardening crypto packet ID.  #define CRYPTO_PACKET_DHTPK         156  #define CRYPTO_PACKET_NAT_PING      254 // NAT ping crypto packet ID. -/* Create a request to peer. +/** Create a request to peer.   * send_public_key and send_secret_key are the pub/secret keys of the sender.   * recv_public_key is public key of receiver.   * packet must be an array of MAX_CRYPTO_REQUEST_SIZE big. @@ -72,10 +71,12 @@ extern "C" {  int create_request(const uint8_t *send_public_key, const uint8_t *send_secret_key, uint8_t *packet,                     const uint8_t *recv_public_key, const uint8_t *data, uint32_t length, uint8_t request_id); -/* puts the senders public key in the request in public_key, the data from the request +/** Puts the senders public key in the request in public_key, the data from the request   * in data if a friend or ping request was sent to us and returns the length of the data. - * packet is the request packet and length is its length - * return -1 if not valid request. */ + * packet is the request packet and length is its length. + * + *  return -1 if not valid request. + */  int handle_request(const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,                     uint8_t *request_id, const uint8_t *packet, uint16_t length); @@ -84,33 +85,16 @@ typedef struct IPPTs {      uint64_t    timestamp;  } IPPTs; -typedef struct Hardening { -    /* Node routes request correctly (true (1) or false/didn't check (0)) */ -    uint8_t     routes_requests_ok; -    /* Time which we last checked this.*/ -    uint64_t    routes_requests_timestamp; -    uint8_t     routes_requests_pingedid[CRYPTO_PUBLIC_KEY_SIZE]; -    /* Node sends correct send_node (true (1) or false/didn't check (0)) */ -    uint8_t     send_nodes_ok; -    /* Time which we last checked this.*/ -    uint64_t    send_nodes_timestamp; -    uint8_t     send_nodes_pingedid[CRYPTO_PUBLIC_KEY_SIZE]; -    /* Node can be used to test other nodes (true (1) or false/didn't check (0)) */ -    uint8_t     testing_requests; -    /* Time which we last checked this.*/ -    uint64_t    testing_timestamp; -    uint8_t     testing_pingedid[CRYPTO_PUBLIC_KEY_SIZE]; -} Hardening; -  typedef struct IPPTsPng {      IP_Port     ip_port;      uint64_t    timestamp;      uint64_t    last_pinged; -    Hardening hardening; -    /* Returned by this node. Either our friend or us. */ +    /* Returned by this node */      IP_Port     ret_ip_port;      uint64_t    ret_timestamp; +    /* true if this ip_port is ours */ +    bool        ret_ip_self;  } IPPTsPng;  typedef struct Client_data { @@ -146,33 +130,37 @@ typedef struct DHT_Friend DHT_Friend;  const uint8_t *dht_friend_public_key(const DHT_Friend *dht_friend);  const Client_data *dht_friend_client(const DHT_Friend *dht_friend, size_t index); -/* Return packet size of packed node with ip_family on success. +/** Return packet size of packed node with ip_family on success.   * Return -1 on failure.   */  int packed_node_size(Family ip_family); -/* Packs an IP_Port structure into data of max size length. +/** Packs an IP_Port structure into data of max size length. + * + * Packed_length is the offset of data currently packed.   *   * Returns size of packed IP_Port data on success   * Return -1 on failure.   */  int pack_ip_port(uint8_t *data, uint16_t length, const IP_Port *ip_port); -/* Unpack IP_Port structure from data of max size length into ip_port. +/** Unpack IP_Port structure from data of max size length into ip_port. + * + * len_processed is the offset of data currently unpacked.   *   * Return size of unpacked ip_port on success.   * Return -1 on failure.   */  int unpack_ip_port(IP_Port *ip_port, const uint8_t *data, uint16_t length, bool tcp_enabled); -/* Pack number of nodes into data of maxlength length. +/** Pack number of nodes into data of maxlength length.   *   * return length of packed nodes on success.   * return -1 on failure.   */  int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_t number); -/* Unpack data of length into nodes of size max_num_nodes. +/** Unpack data of length into nodes of size max_num_nodes.   * Put the length of the data processed in processed_data_len.   * tcp_enabled sets if TCP nodes are expected (true) or not (false).   * @@ -202,10 +190,9 @@ typedef struct Shared_Keys {  /*----------------------------------------------------------------------------------*/ -typedef int cryptopacket_handler_cb(void *object, IP_Port ip_port, const uint8_t *source_pubkey, +typedef int cryptopacket_handler_cb(void *object, const IP_Port *ip_port, const uint8_t *source_pubkey,                                      const uint8_t *data, uint16_t len, void *userdata); -#define DHT_DEFINED  typedef struct DHT DHT;  const uint8_t *dht_get_self_public_key(const DHT *dht); @@ -224,30 +211,36 @@ const uint8_t *dht_get_friend_public_key(const DHT *dht, uint32_t friend_num);  /*----------------------------------------------------------------------------------*/ -/* Shared key generations are costly, it is therefore smart to store commonly used - * ones so that they can re used later without being computed again. +/** Shared key generations are costly, it is therefore smart to store commonly used + * ones so that they can be re-used later without being computed again.   * - * If shared key is already in shared_keys, copy it to shared_key. - * else generate it into shared_key and copy it to shared_keys + * If a shared key is already in shared_keys, copy it to shared_key. + * Otherwise generate it into shared_key and copy it to shared_keys   */  void get_shared_key(const Mono_Time *mono_time, Shared_Keys *shared_keys, uint8_t *shared_key,                      const uint8_t *secret_key, const uint8_t *public_key); -/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key +/** Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key   * for packets that we receive.   */  void dht_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *public_key); -/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key +/** Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key   * for packets that we send.   */  void dht_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *public_key); -void dht_getnodes(DHT *dht, const IP_Port *from_ipp, const uint8_t *from_id, const uint8_t *which_id); -typedef void dht_ip_cb(void *object, int32_t number, IP_Port ip_port); +/** Sends a getnodes request to `ip_port` with the public key `public_key` for nodes + * that are close to `client_id`. + * + * Return true on success. + */ +bool dht_getnodes(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *client_id); + +typedef void dht_ip_cb(void *object, int32_t number, const IP_Port *ip_port); -/* Add a new friend to the friends list. +/** Add a new friend to the friends list.   * public_key must be CRYPTO_PUBLIC_KEY_SIZE bytes long.   *   * ip_callback is the callback of a function that will be called when the ip address @@ -262,7 +255,7 @@ typedef void dht_ip_cb(void *object, int32_t number, IP_Port ip_port);  int dht_addfriend(DHT *dht, const uint8_t *public_key, dht_ip_cb *ip_callback,                    void *data, int32_t number, uint16_t *lock_count); -/* Delete a friend from the friends list. +/** Delete a friend from the friends list.   * public_key must be CRYPTO_PUBLIC_KEY_SIZE bytes long.   *   *  return 0 if success. @@ -270,7 +263,7 @@ int dht_addfriend(DHT *dht, const uint8_t *public_key, dht_ip_cb *ip_callback,   */  int dht_delfriend(DHT *dht, const uint8_t *public_key, uint16_t lock_count); -/* Get ip of friend. +/** Get ip of friend.   *  public_key must be CRYPTO_PUBLIC_KEY_SIZE bytes long.   *  ip must be 4 bytes long.   *  port must be 2 bytes long. @@ -281,7 +274,7 @@ int dht_delfriend(DHT *dht, const uint8_t *public_key, uint16_t lock_count);   */  int dht_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port); -/* Compares pk1 and pk2 with pk. +/** Compares pk1 and pk2 with pk.   *   *  return 0 if both are same distance.   *  return 1 if pk1 is closer. @@ -289,19 +282,19 @@ int dht_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port)   */  int id_closest(const uint8_t *pk, const uint8_t *pk1, const uint8_t *pk2); -/** +/***   * Add node to the node list making sure only the nodes closest to cmp_pk are in the list.   *   * @return true iff the node was added to the list.   */ -bool add_to_list(Node_format *nodes_list, uint32_t length, const uint8_t *pk, IP_Port ip_port, +bool add_to_list(Node_format *nodes_list, uint32_t length, const uint8_t *pk, const IP_Port *ip_port,                   const uint8_t *cmp_pk); -/* Return 1 if node can be added to close list, 0 if it can't. +/** Return 1 if node can be added to close list, 0 if it can't.   */ -bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port); +bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, const IP_Port *ip_port); -/* Get the (maximum MAX_SENT_NODES) closest nodes to public_key we know +/** Get the (maximum MAX_SENT_NODES) closest nodes to public_key we know   * and put them in nodes_list (must be MAX_SENT_NODES big).   *   * sa_family = family (IPv4 or IPv6) (0 if we don't care)? @@ -312,32 +305,33 @@ bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_   *   */  int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, Family sa_family, -                    bool is_LAN, uint8_t want_good); +                    bool is_LAN); -/* Put up to max_num nodes in nodes from the random friends. +/** Put up to max_num nodes in nodes from the random friends.   *   * return the number of nodes.   */ -uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num); +uint16_t randfriends_nodes(const DHT *dht, Node_format *nodes, uint16_t max_num); -/* Put up to max_num nodes in nodes from the closelist. +/** Put up to max_num nodes in nodes from the closelist.   *   * return the number of nodes.   */ -uint16_t closelist_nodes(DHT *dht, Node_format *nodes, uint16_t max_num); +uint16_t closelist_nodes(const DHT *dht, Node_format *nodes, uint16_t max_num); -/* Run this function at least a couple times per second (It's the main loop). */ +/** Run this function at least a couple times per second (It's the main loop). */  void do_dht(DHT *dht);  /*   *  Use these two functions to bootstrap the client.   */ -/* Sends a "get nodes" request to the given node with ip, port and public_key +/** Sends a "get nodes" request to the given node with ip, port and public_key   *   to setup connections   */ -void dht_bootstrap(DHT *dht, IP_Port ip_port, const uint8_t *public_key); -/* Resolves address into an IP address. If successful, sends a "get nodes" +void dht_bootstrap(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key); + +/** Resolves address into an IP address. If successful, sends a "get nodes"   *   request to the given node with ip, port and public_key to setup connections   *   * address can be a hostname or an IP address (IPv4 or IPv6). @@ -351,7 +345,7 @@ void dht_bootstrap(DHT *dht, IP_Port ip_port, const uint8_t *public_key);  int dht_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled,                                 uint16_t port, const uint8_t *public_key); -/* Start sending packets after DHT loaded_friends_list and loaded_clients_list are set. +/** Start sending packets after DHT loaded_friends_list and loaded_clients_list are set.   *   * returns 0 if successful   * returns -1 otherwise @@ -360,54 +354,66 @@ int dht_connect_after_load(DHT *dht);  /* ROUTING FUNCTIONS */ -/* Send the given packet to node with public_key. +/** Send the given packet to node with public_key.   *   *  return -1 if failure.   */  int route_packet(const DHT *dht, const uint8_t *public_key, const uint8_t *packet, uint16_t length); -/* Send the following packet to everyone who tells us they are connected to friend_id. +/** + * Send the following packet to everyone who tells us they are connected to friend_id.   * - *  return number of nodes it sent the packet to. + *  return ip for friend. + *  return number of nodes the packet was sent to. (Only works if more than (MAX_FRIEND_CLIENTS / 4).   */ -int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint16_t length); +uint32_t route_to_friend(const DHT *dht, const uint8_t *friend_id, const Packet *packet); -/* Function to handle crypto packets. +/** Function to handle crypto packets.   */  void cryptopacket_registerhandler(DHT *dht, uint8_t byte, cryptopacket_handler_cb *cb, void *object);  /* SAVE/LOAD functions */ -/* Get the size of the DHT (for saving). */ +/** Get the size of the DHT (for saving). */  uint32_t dht_size(const DHT *dht); -/* Save the DHT in data where data is an array of size dht_size(). */ +/** Save the DHT in data where data is an array of size dht_size(). */  void dht_save(const DHT *dht, uint8_t *data); -/* Load the DHT from data of size size. +/** Load the DHT from data of size size.   *   *  return -1 if failure.   *  return 0 if success.   */  int dht_load(DHT *dht, const uint8_t *data, uint32_t length); -/* Initialize DHT. */ +/** Initialize DHT. */  DHT *new_dht(const Logger *log, Mono_Time *mono_time, Networking_Core *net, bool holepunching_enabled);  void kill_dht(DHT *dht); -/*  return false if we are not connected to the DHT. +/**  return false if we are not connected to the DHT.   *  return true if we are.   */  bool dht_isconnected(const DHT *dht); -/*  return false if we are not connected or only connected to lan peers with the DHT. +/**  return false if we are not connected or only connected to lan peers with the DHT.   *  return true if we are.   */  bool dht_non_lan_connected(const DHT *dht); -uint32_t addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key); +uint32_t addto_lists(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key); + +/** Copies our own ip_port structure to `dest`. WAN addresses take priority over LAN addresses. + * + * This function will zero the `dest` buffer before use. + * + * Return 0 if our ip port can't be found (this usually means we're not connected to the DHT). + * Return 1 if IP is a WAN address. + * Return 2 if IP is a LAN address. + */ +unsigned int ipport_self_copy(const DHT *dht, IP_Port *dest);  #ifdef __cplusplus  }  // extern "C" diff --git a/protocols/Tox/libtox/src/toxcore/LAN_discovery.api.h b/protocols/Tox/libtox/src/toxcore/LAN_discovery.api.h deleted file mode 100644 index ad3d60ed7a..0000000000 --- a/protocols/Tox/libtox/src/toxcore/LAN_discovery.api.h +++ /dev/null @@ -1,57 +0,0 @@ -%{ -/* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. - * Copyright © 2013 Tox project. - */ - -/* - * LAN discovery implementation. - */ -#ifndef C_TOXCORE_TOXCORE_LAN_DISCOVERY_H -#define C_TOXCORE_TOXCORE_LAN_DISCOVERY_H - -#include "DHT.h" -%} - -class dHT { struct this; } -class iP { struct this; } - -namespace lan_discovery { - -/** - * Interval in seconds between LAN discovery packet sending. - */ -#define LAN_DISCOVERY_INTERVAL         10 - -/** - * Send a LAN discovery pcaket to the broadcast address with port port. - */ -static int32_t send(uint16_t port, dHT::this *dht); - -/** - * Sets up packet handlers. - */ -static void init(dHT::this *dht); - -/** - * Clear packet handlers. - */ -static void kill(dHT::this *dht); - -} - -/** - * Is IP a local ip or not. - */ -static bool ip_is_local(iP::this ip); - -/** - * Checks if a given IP isn't routable. - * - * @return true if ip is a LAN ip, false if it is not. - */ -static bool ip_is_lan(iP::this ip); - -%{ -#endif // C_TOXCORE_TOXCORE_LAN_DISCOVERY_H -%} diff --git a/protocols/Tox/libtox/src/toxcore/LAN_discovery.c b/protocols/Tox/libtox/src/toxcore/LAN_discovery.c index 3f6951fcc7..6f9f77b6bb 100644 --- a/protocols/Tox/libtox/src/toxcore/LAN_discovery.c +++ b/protocols/Tox/libtox/src/toxcore/LAN_discovery.c @@ -3,17 +3,41 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * LAN discovery implementation.   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -  #include "LAN_discovery.h"  #include <string.h> +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +// The mingw32/64 Windows library warns about including winsock2.h after +// windows.h even though with the above it's a valid thing to do. So, to make +// mingw32 headers happy, we include winsock2.h first. +#include <winsock2.h> + +#include <windows.h> +#include <ws2tcpip.h> + +#include <iphlpapi.h> +#endif + +#if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) +#include <netinet/in.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <unistd.h> +#endif + +#ifdef __linux__ +#include <linux/netdevice.h> +#endif + +#if defined(__FreeBSD__) || defined(__DragonFly__) +#include <net/if.h> +#endif +  #include "util.h"  #define MAX_INTERFACES 16 @@ -29,16 +53,6 @@ static IP_Port broadcast_ip_ports[MAX_INTERFACES];  #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) -// The mingw32/64 Windows library warns about including winsock2.h after -// windows.h even though with the above it's a valid thing to do. So, to make -// mingw32 headers happy, we include winsock2.h first. -#include <winsock2.h> - -#include <windows.h> -#include <ws2tcpip.h> - -#include <iphlpapi.h> -  static void fetch_broadcast_info(uint16_t port)  {      IP_ADAPTER_INFO *pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO)); @@ -106,21 +120,7 @@ static void fetch_broadcast_info(uint16_t port)      }  } -#elif defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) - -#include <netinet/in.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <unistd.h> - -#ifdef __linux__ -#include <linux/netdevice.h> -#endif - -#if defined(__FreeBSD__) || defined(__DragonFly__) -#include <net/if.h> -#endif +#elif !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && (defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__))  static void fetch_broadcast_info(uint16_t port)  { @@ -173,7 +173,7 @@ static void fetch_broadcast_info(uint16_t port)              continue;          } -        struct sockaddr_in *sock4 = (struct sockaddr_in *)(void *)&i_faces[i].ifr_broadaddr; +        const struct sockaddr_in *sock4 = (const struct sockaddr_in *)(void *)&i_faces[i].ifr_broadaddr;          if (count >= MAX_INTERFACES) {              break; @@ -208,12 +208,13 @@ static void fetch_broadcast_info(uint16_t port)  }  #endif -/* Send packet to all IPv4 broadcast addresses + +/** Send packet to all IPv4 broadcast addresses   *   *  return 1 if sent to at least one broadcast target.   *  return 0 on failure to find any valid broadcast target.   */ -static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, const uint8_t *data, uint16_t length) +static uint32_t send_broadcasts(const Networking_Core *net, uint16_t port, const uint8_t *data, uint16_t length)  {      /* fetch only once? on every packet? every X seconds?       * old: every packet, new: once */ @@ -226,13 +227,13 @@ static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, const uint8      }      for (int i = 0; i < broadcast_count; ++i) { -        sendpacket(net, broadcast_ip_ports[i], data, length); +        sendpacket(net, &broadcast_ip_ports[i], data, length);      }      return 1;  } -/* Return the broadcast ip. */ +/** Return the broadcast ip. */  static IP broadcast_ip(Family family_socket, Family family_broadcast)  {      IP ip; @@ -259,103 +260,103 @@ static IP broadcast_ip(Family family_socket, Family family_broadcast)      return ip;  } -static bool ip4_is_local(IP4 ip4) +static bool ip4_is_local(const IP4 *ip4)  {      /* Loopback. */ -    return ip4.uint8[0] == 127; +    return ip4->uint8[0] == 127;  } -/* Is IP a local ip or not. */ -bool ip_is_local(IP ip) +/** + * Is IP a local ip or not. + */ +bool ip_is_local(const IP *ip)  { -    if (net_family_is_ipv4(ip.family)) { -        return ip4_is_local(ip.ip.v4); +    if (net_family_is_ipv4(ip->family)) { +        return ip4_is_local(&ip->ip.v4);      }      /* embedded IPv4-in-IPv6 */ -    if (ipv6_ipv4_in_v6(ip.ip.v6)) { +    if (ipv6_ipv4_in_v6(&ip->ip.v6)) {          IP4 ip4; -        ip4.uint32 = ip.ip.v6.uint32[3]; -        return ip4_is_local(ip4); +        ip4.uint32 = ip->ip.v6.uint32[3]; +        return ip4_is_local(&ip4);      }      /* localhost in IPv6 (::1) */ -    if (ip.ip.v6.uint64[0] == 0 && ip.ip.v6.uint32[2] == 0 && ip.ip.v6.uint32[3] == net_htonl(1)) { +    if (ip->ip.v6.uint64[0] == 0 && ip->ip.v6.uint32[2] == 0 && ip->ip.v6.uint32[3] == net_htonl(1)) {          return true;      }      return false;  } -static bool ip4_is_lan(IP4 ip4) +static bool ip4_is_lan(const IP4 *ip4)  {      /* 10.0.0.0 to 10.255.255.255 range. */ -    if (ip4.uint8[0] == 10) { +    if (ip4->uint8[0] == 10) {          return true;      }      /* 172.16.0.0 to 172.31.255.255 range. */ -    if (ip4.uint8[0] == 172 && ip4.uint8[1] >= 16 && ip4.uint8[1] <= 31) { +    if (ip4->uint8[0] == 172 && ip4->uint8[1] >= 16 && ip4->uint8[1] <= 31) {          return true;      }      /* 192.168.0.0 to 192.168.255.255 range. */ -    if (ip4.uint8[0] == 192 && ip4.uint8[1] == 168) { +    if (ip4->uint8[0] == 192 && ip4->uint8[1] == 168) {          return true;      }      /* 169.254.1.0 to 169.254.254.255 range. */ -    if (ip4.uint8[0] == 169 && ip4.uint8[1] == 254 && ip4.uint8[2] != 0 -            && ip4.uint8[2] != 255) { +    if (ip4->uint8[0] == 169 && ip4->uint8[1] == 254 && ip4->uint8[2] != 0 +            && ip4->uint8[2] != 255) {          return true;      }      /* RFC 6598: 100.64.0.0 to 100.127.255.255 (100.64.0.0/10)       * (shared address space to stack another layer of NAT) */ -    if ((ip4.uint8[0] == 100) && ((ip4.uint8[1] & 0xC0) == 0x40)) { +    if ((ip4->uint8[0] == 100) && ((ip4->uint8[1] & 0xC0) == 0x40)) {          return true;      }      return false;  } -bool ip_is_lan(IP ip) +bool ip_is_lan(const IP *ip)  {      if (ip_is_local(ip)) {          return true;      } -    if (net_family_is_ipv4(ip.family)) { -        return ip4_is_lan(ip.ip.v4); +    if (net_family_is_ipv4(ip->family)) { +        return ip4_is_lan(&ip->ip.v4);      } -    if (net_family_is_ipv6(ip.family)) { +    if (net_family_is_ipv6(ip->family)) {          /* autogenerated for each interface: `FE80::*` (up to `FEBF::*`)           * `FF02::1` is - according to RFC 4291 - multicast all-nodes link-local */ -        if (((ip.ip.v6.uint8[0] == 0xFF) && (ip.ip.v6.uint8[1] < 3) && (ip.ip.v6.uint8[15] == 1)) || -                ((ip.ip.v6.uint8[0] == 0xFE) && ((ip.ip.v6.uint8[1] & 0xC0) == 0x80))) { +        if (((ip->ip.v6.uint8[0] == 0xFF) && (ip->ip.v6.uint8[1] < 3) && (ip->ip.v6.uint8[15] == 1)) || +                ((ip->ip.v6.uint8[0] == 0xFE) && ((ip->ip.v6.uint8[1] & 0xC0) == 0x80))) {              return true;          }          /* embedded IPv4-in-IPv6 */ -        if (ipv6_ipv4_in_v6(ip.ip.v6)) { +        if (ipv6_ipv4_in_v6(&ip->ip.v6)) {              IP4 ip4; -            ip4.uint32 = ip.ip.v6.uint32[3]; -            return ip4_is_lan(ip4); +            ip4.uint32 = ip->ip.v6.uint32[3]; +            return ip4_is_lan(&ip4);          }      }      return false;  } -static int handle_LANdiscovery(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) +static int handle_LANdiscovery(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, +                               void *userdata)  {      DHT *dht = (DHT *)object; -    char ip_str[IP_NTOA_LEN] = { 0 }; -    ip_ntoa(&source.ip, ip_str, sizeof(ip_str)); - -    if (!ip_is_lan(source.ip)) { +    if (!ip_is_lan(&source->ip)) {          return 1;      } @@ -368,35 +369,35 @@ static int handle_LANdiscovery(void *object, IP_Port source, const uint8_t *pack  } -int lan_discovery_send(uint16_t port, DHT *dht) +bool lan_discovery_send(Networking_Core *net, const uint8_t *dht_pk, uint16_t port)  {      uint8_t data[CRYPTO_PUBLIC_KEY_SIZE + 1];      data[0] = NET_PACKET_LAN_DISCOVERY; -    id_copy(data + 1, dht_get_self_public_key(dht)); +    id_copy(data + 1, dht_pk); -    send_broadcasts(dht_get_net(dht), port, data, 1 + CRYPTO_PUBLIC_KEY_SIZE); +    send_broadcasts(net, port, data, 1 + CRYPTO_PUBLIC_KEY_SIZE); -    int res = -1; +    bool res = false;      IP_Port ip_port;      ip_port.port = port;      /* IPv6 multicast */ -    if (net_family_is_ipv6(net_family(dht_get_net(dht)))) { +    if (net_family_is_ipv6(net_family(net))) {          ip_port.ip = broadcast_ip(net_family_ipv6, net_family_ipv6);          if (ip_isset(&ip_port.ip)) { -            if (sendpacket(dht_get_net(dht), ip_port, data, 1 + CRYPTO_PUBLIC_KEY_SIZE) > 0) { -                res = 1; +            if (sendpacket(net, &ip_port, data, 1 + CRYPTO_PUBLIC_KEY_SIZE) > 0) { +                res = true;              }          }      }      /* IPv4 broadcast (has to be IPv4-in-IPv6 mapping if socket is IPv6 */ -    ip_port.ip = broadcast_ip(net_family(dht_get_net(dht)), net_family_ipv4); +    ip_port.ip = broadcast_ip(net_family(net), net_family_ipv4);      if (ip_isset(&ip_port.ip)) { -        if (sendpacket(dht_get_net(dht), ip_port, data, 1 + CRYPTO_PUBLIC_KEY_SIZE)) { -            res = 1; +        if (sendpacket(net, &ip_port, data, 1 + CRYPTO_PUBLIC_KEY_SIZE)) { +            res = true;          }      } diff --git a/protocols/Tox/libtox/src/toxcore/LAN_discovery.h b/protocols/Tox/libtox/src/toxcore/LAN_discovery.h index 6b55e3193b..cce7b5c190 100644 --- a/protocols/Tox/libtox/src/toxcore/LAN_discovery.h +++ b/protocols/Tox/libtox/src/toxcore/LAN_discovery.h @@ -3,7 +3,7 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * LAN discovery implementation.   */  #ifndef C_TOXCORE_TOXCORE_LAN_DISCOVERY_H @@ -11,16 +11,6 @@  #include "DHT.h" -#ifndef DHT_DEFINED -#define DHT_DEFINED -typedef struct DHT DHT; -#endif /* DHT_DEFINED */ - -#ifndef IP_DEFINED -#define IP_DEFINED -typedef struct IP IP; -#endif /* IP_DEFINED */ -  /**   * Interval in seconds between LAN discovery packet sending.   */ @@ -28,8 +18,10 @@ typedef struct IP IP;  /**   * Send a LAN discovery pcaket to the broadcast address with port port. + * + * @return true on success, false on failure.   */ -int32_t lan_discovery_send(uint16_t port, DHT *dht); +bool lan_discovery_send(Networking_Core *net, const uint8_t *dht_pk, uint16_t port);  /**   * Sets up packet handlers. @@ -44,13 +36,13 @@ void lan_discovery_kill(DHT *dht);  /**   * Is IP a local ip or not.   */ -bool ip_is_local(IP ip); +bool ip_is_local(const IP *ip);  /**   * Checks if a given IP isn't routable.   *   * @return true if ip is a LAN ip, false if it is not.   */ -bool ip_is_lan(IP ip); +bool ip_is_lan(const IP *ip);  #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 22c3e9e856..6413dc928e 100644 --- a/protocols/Tox/libtox/src/toxcore/Messenger.c +++ b/protocols/Tox/libtox/src/toxcore/Messenger.c @@ -3,13 +3,9 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * An implementation of a simple text chat only messenger on the tox network core.   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -  #include "Messenger.h"  #include <assert.h> @@ -24,6 +20,9 @@  #include "state.h"  #include "util.h" +static_assert(MAX_CONCURRENT_FILE_PIPES <= UINT8_MAX + 1, +              "uint8_t cannot represent all file transfer numbers"); +  static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data,                                  uint32_t length, uint8_t congestion_control);  static void m_register_default_plugins(Messenger *m); @@ -38,7 +37,7 @@ static bool friend_is_valid(const Messenger *m, int32_t friendnumber)      return (unsigned int)friendnumber < m->numfriends && m->friendlist[friendnumber].status != 0;  } -/* Set the size of the friend list to numfriends. +/** Set the size of the friend list to numfriends.   *   *  return -1 if realloc fails.   */ @@ -60,14 +59,12 @@ static int realloc_friendlist(Messenger *m, uint32_t num)      return 0;  } -/*  return the friend id associated to that public key. +/** return the friend number associated to that public key.   *  return -1 if no such friend.   */  int32_t getfriend_id(const Messenger *m, const uint8_t *real_pk)  { -    uint32_t i; - -    for (i = 0; i < m->numfriends; ++i) { +    for (uint32_t i = 0; i < m->numfriends; ++i) {          if (m->friendlist[i].status > 0) {              if (id_equal(real_pk, m->friendlist[i].real_pk)) {                  return i; @@ -78,7 +75,7 @@ int32_t getfriend_id(const Messenger *m, const uint8_t *real_pk)      return -1;  } -/* Copies the public key associated to that friend id into real_pk buffer. +/** Copies the public key associated to that friend id into real_pk buffer.   * Make sure that real_pk is of size CRYPTO_PUBLIC_KEY_SIZE.   *   *  return 0 if success. @@ -94,7 +91,7 @@ int get_real_pk(const Messenger *m, int32_t friendnumber, uint8_t *real_pk)      return 0;  } -/*  return friend connection id on success. +/**  return friend connection id on success.   *  return -1 if failure.   */  int getfriendcon_id(const Messenger *m, int32_t friendnumber) @@ -106,16 +103,15 @@ int getfriendcon_id(const Messenger *m, int32_t friendnumber)      return m->friendlist[friendnumber].friendcon_id;  } -/* +/**   *  return a uint16_t that represents the checksum of address of length len.   */  static uint16_t address_checksum(const uint8_t *address, uint32_t len)  {      uint8_t checksum[2] = {0};      uint16_t check; -    uint32_t i; -    for (i = 0; i < len; ++i) { +    for (uint32_t i = 0; i < len; ++i) {          checksum[i % 2] ^= address[i];      } @@ -123,7 +119,7 @@ static uint16_t address_checksum(const uint8_t *address, uint32_t len)      return check;  } -/* Format: `[real_pk (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]` +/** Format: `[real_pk (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]`   *   *  return FRIEND_ADDRESS_SIZE byte address to give to others.   */ @@ -180,9 +176,7 @@ static int32_t init_new_friend(Messenger *m, const uint8_t *real_pk, uint8_t sta          return FAERR_NOMEM;      } -    uint32_t i; - -    for (i = 0; i <= m->numfriends; ++i) { +    for (uint32_t i = 0; i <= m->numfriends; ++i) {          if (m->friendlist[i].status == NOFRIEND) {              m->friendlist[i].status = status;              m->friendlist[i].friendcon_id = friendcon_id; @@ -210,11 +204,16 @@ static int32_t init_new_friend(Messenger *m, const uint8_t *real_pk, uint8_t sta      return FAERR_NOMEM;  } -/* +/**   * Add a friend. + *   * Set the data that will be sent along with friend request. - * Address is the address of the friend (returned by getaddress of the friend you wish to add) it must be FRIEND_ADDRESS_SIZE bytes. - * data is the data and length is the length. + * + * @param address is the address of the friend (returned by getaddress of the friend + *   you wish to add) it must be FRIEND_ADDRESS_SIZE bytes. + *   TODO(irungentoo): add checksum. + * @param data is the data. + * @param length is the length.   *   *  return the friend number if success.   *  return FA_TOOLONG if message length is too long. @@ -348,7 +347,7 @@ static int add_receipt(Messenger *m, int32_t friendnumber, uint32_t packet_num,      new_receipts->next = nullptr;      return 0;  } -/* +/**   * return -1 on failure.   * return 0 if packet was received.   */ @@ -395,7 +394,7 @@ static int do_receipts(Messenger *m, int32_t friendnumber, void *userdata)      return 0;  } -/* Remove a friend. +/** Remove a friend.   *   *  return 0 if success.   *  return -1 if failure. @@ -421,6 +420,7 @@ int m_delfriend(Messenger *m, int32_t friendnumber)      kill_friend_connection(m->fr_c, m->friendlist[friendnumber].friendcon_id);      memset(&m->friendlist[friendnumber], 0, sizeof(Friend)); +      uint32_t i;      for (i = m->numfriends; i != 0; --i) { @@ -480,7 +480,7 @@ int m_friend_exists(const Messenger *m, int32_t friendnumber)      return 1;  } -/* Send a message of type. +/** Send a message of type to an online friend.   *   * return -1 if friend not valid.   * return -2 if too large. @@ -488,27 +488,29 @@ int m_friend_exists(const Messenger *m, int32_t friendnumber)   * return -4 if send failed (because queue is full).   * return -5 if bad type.   * return 0 if success. + * + *  the value in message_id will be passed to your read_receipt callback when the other receives the message.   */  int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, const uint8_t *message, uint32_t length,                             uint32_t *message_id)  {      if (type > MESSAGE_ACTION) { -        LOGGER_ERROR(m->log, "Message type %d is invalid", type); +        LOGGER_WARNING(m->log, "Message type %d is invalid", type);          return -5;      }      if (!friend_is_valid(m, friendnumber)) { -        LOGGER_ERROR(m->log, "Friend number %d is invalid", friendnumber); +        LOGGER_WARNING(m->log, "Friend number %d is invalid", friendnumber);          return -1;      }      if (length >= MAX_CRYPTO_DATA_SIZE) { -        LOGGER_ERROR(m->log, "Message length %u is too large", length); +        LOGGER_WARNING(m->log, "Message length %u is too large", length);          return -2;      }      if (m->friendlist[friendnumber].status != FRIEND_ONLINE) { -        LOGGER_ERROR(m->log, "Friend %d is not online", friendnumber); +        LOGGER_WARNING(m->log, "Friend %d is not online", friendnumber);          return -3;      } @@ -523,8 +525,8 @@ int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, con                                             m->friendlist[friendnumber].friendcon_id), packet, length + 1, 0);      if (packet_num == -1) { -        LOGGER_ERROR(m->log, "Failed to write crypto packet for message of length %d to friend %d", -                     length, friendnumber); +        LOGGER_WARNING(m->log, "Failed to write crypto packet for message of length %d to friend %d", +                       length, friendnumber);          return -4;      } @@ -539,7 +541,7 @@ int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, con      return 0;  } -/* Send a name packet to friendnumber. +/** Send a name packet to friendnumber.   * length is the length with the NULL terminator.   */  static int m_sendname(const Messenger *m, int32_t friendnumber, const uint8_t *name, uint16_t length) @@ -551,7 +553,10 @@ static int m_sendname(const Messenger *m, int32_t friendnumber, const uint8_t *n      return write_cryptpacket_id(m, friendnumber, PACKET_ID_NICKNAME, name, length, 0);  } -/* Set the name and name_length of a friend. +/** Set the name and name_length of a friend. + * name must be a string of maximum MAX_NAME_LENGTH length. + * length must be at least 1 byte. + * length is the length of name with the NULL terminator.   *   *  return 0 if success.   *  return -1 if failure. @@ -571,7 +576,7 @@ int setfriendname(Messenger *m, int32_t friendnumber, const uint8_t *name, uint1      return 0;  } -/* Set our nickname +/** Set our nickname.   * name must be a string of maximum MAX_NAME_LENGTH length.   * length must be at least 1 byte.   * length is the length of name with the NULL terminator. @@ -594,19 +599,21 @@ int setname(Messenger *m, const uint8_t *name, uint16_t length)      }      m->name_length = length; -    uint32_t i; -    for (i = 0; i < m->numfriends; ++i) { +    for (uint32_t i = 0; i < m->numfriends; ++i) {          m->friendlist[i].name_sent = 0;      }      return 0;  } -/* Get our nickname and put it in name. +/** + * Get your nickname. + * m - The messenger context to use.   * name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.   * - *  return the length of the name. + *  return length of the name. + *  return 0 on error.   */  uint16_t getself_name(const Messenger *m, uint8_t *name)  { @@ -619,8 +626,8 @@ uint16_t getself_name(const Messenger *m, uint8_t *name)      return m->name_length;  } -/* Get name of friendnumber and put it in name. - * name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes. +/** Get name of friendnumber and put it in name. + * name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.   *   *  return length of name if success.   *  return -1 if failure. @@ -665,9 +672,7 @@ int m_set_statusmessage(Messenger *m, const uint8_t *status, uint16_t length)      m->statusmessage_length = length; -    uint32_t i; - -    for (i = 0; i < m->numfriends; ++i) { +    for (uint32_t i = 0; i < m->numfriends; ++i) {          m->friendlist[i].statusmessage_sent = 0;      } @@ -685,17 +690,19 @@ int m_set_userstatus(Messenger *m, uint8_t status)      }      m->userstatus = (Userstatus)status; -    uint32_t i; -    for (i = 0; i < m->numfriends; ++i) { +    for (uint32_t i = 0; i < m->numfriends; ++i) {          m->friendlist[i].userstatus_sent = 0;      }      return 0;  } -/* return the size of friendnumber's user status. +/**   * Guaranteed to be at most MAX_STATUSMESSAGE_LENGTH. + * + * returns the length of friendnumber's status message, including null on success. + * returns -1 on failure.   */  int m_get_statusmessage_size(const Messenger *m, int32_t friendnumber)  { @@ -706,8 +713,12 @@ int m_get_statusmessage_size(const Messenger *m, int32_t friendnumber)      return m->friendlist[friendnumber].statusmessage_length;  } -/*  Copy the user status of friendnumber into buf, truncating if needed to maxlen - *  bytes, use m_get_statusmessage_size to find out how much you need to allocate. +/** Copy friendnumber's status message into buf, truncating if size is over maxlen. + * Get the size you need to allocate from m_get_statusmessage_size. + * The self variant will copy our own status message. + * + * returns the length of the copied data on success + * returns -1 on failure.   */  int m_copy_statusmessage(const Messenger *m, int32_t friendnumber, uint8_t *buf, uint32_t maxlen)  { @@ -724,7 +735,7 @@ int m_copy_statusmessage(const Messenger *m, int32_t friendnumber, uint8_t *buf,      return msglen;  } -/* return the size of friendnumber's user status. +/** return the size of friendnumber's user status.   * Guaranteed to be at most MAX_STATUSMESSAGE_LENGTH.   */  int m_get_self_statusmessage_size(const Messenger *m) @@ -840,13 +851,13 @@ static void set_friend_typing(const Messenger *m, int32_t friendnumber, uint8_t      m->friendlist[friendnumber].is_typing = is_typing;  } -/* Set the function that will be executed when a friend request is received. */ +/** Set the function that will be executed when a friend request is received. */  void m_callback_friendrequest(Messenger *m, m_friend_request_cb *function)  {      callback_friendrequest(m->fr, (fr_friend_request_cb *)function, m);  } -/* Set the function that will be executed when a message from a friend is received. */ +/** Set the function that will be executed when a message from a friend is received. */  void m_callback_friendmessage(Messenger *m, m_friend_message_cb *function)  {      m->friend_message = function; @@ -973,10 +984,10 @@ static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_                               m->friendlist[friendnumber].friendcon_id), packet, length + 1, congestion_control) != -1;  } -/** CONFERENCES */ +/*** CONFERENCES */ -/* Set the callback for conference invites. +/** Set the callback for conference invites.   */  void m_callback_conference_invite(Messenger *m, m_conference_invite_cb *function)  { @@ -984,7 +995,7 @@ void m_callback_conference_invite(Messenger *m, m_conference_invite_cb *function  } -/* Send a conference invite packet. +/** Send a conference invite packet.   *   *  return 1 on success   *  return 0 on failure @@ -994,31 +1005,31 @@ int send_conference_invite_packet(const Messenger *m, int32_t friendnumber, cons      return write_cryptpacket_id(m, friendnumber, PACKET_ID_INVITE_CONFERENCE, data, length, 0);  } -/** FILE SENDING */ +/*** FILE SENDING */ -/* Set the callback for file send requests. +/** Set the callback for file send requests.   */  void callback_file_sendrequest(Messenger *m, m_file_recv_cb *function)  {      m->file_sendrequest = function;  } -/* Set the callback for file control requests. +/** Set the callback for file control requests.   */  void callback_file_control(Messenger *m, m_file_recv_control_cb *function)  {      m->file_filecontrol = function;  } -/* Set the callback for file data. +/** Set the callback for file data.   */  void callback_file_data(Messenger *m, m_file_recv_chunk_cb *function)  {      m->file_filedata = function;  } -/* Set the callback for file request chunk. +/** Set the callback for file request chunk.   */  void callback_file_reqchunk(Messenger *m, m_file_chunk_request_cb *function)  { @@ -1027,7 +1038,7 @@ void callback_file_reqchunk(Messenger *m, m_file_chunk_request_cb *function)  #define MAX_FILENAME_LENGTH 255 -/* Copy the file transfer file id to file_id +/** Copy the file transfer file id to file_id   *   * return 0 on success.   * return -1 if friend not valid. @@ -1077,7 +1088,7 @@ int file_get_id(const Messenger *m, int32_t friendnumber, uint32_t filenumber, u      return 0;  } -/* Send a file send request. +/** Send a file send request.   * Maximum filename length is 255 bytes.   *  return 1 on success   *  return 0 on failure @@ -1107,7 +1118,7 @@ static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t fi      return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_SENDREQUEST, packet, SIZEOF_VLA(packet), 0);  } -/* Send a file send request. +/** Send a file send request.   * Maximum filename length is 255 bytes.   *  return file number on success   *  return -1 if friend not found. @@ -1157,13 +1168,11 @@ long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_      memcpy(ft->id, file_id, FILE_ID_LENGTH); -    ++m->friendlist[friendnumber].num_sending_files; -      return i;  }  static int send_file_control_packet(const Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber, -                                    uint8_t control_type, uint8_t *data, uint16_t data_length) +                                    uint8_t control_type, const uint8_t *data, uint16_t data_length)  {      if ((unsigned int)(1 + 3 + data_length) > MAX_CRYPTO_DATA_SIZE) {          return -1; @@ -1182,7 +1191,7 @@ static int send_file_control_packet(const Messenger *m, int32_t friendnumber, ui      return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_CONTROL, packet, SIZEOF_VLA(packet), 0);  } -/* Send a file control request. +/** Send a file control request.   *   *  return 0 on success   *  return -1 if friend not valid. @@ -1264,11 +1273,12 @@ int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber,      if (send_file_control_packet(m, friendnumber, send_receive, file_number, control, nullptr, 0)) {          if (control == FILECONTROL_KILL) { -            ft->status = FILESTATUS_NONE; - -            if (send_receive == 0) { +            if (send_receive == 0 && (ft->status == FILESTATUS_TRANSFERRING || ft->status == FILESTATUS_FINISHED)) { +                // We are actively sending that file, remove from list                  --m->friendlist[friendnumber].num_sending_files;              } + +            ft->status = FILESTATUS_NONE;          } else if (control == FILECONTROL_PAUSE) {              ft->paused |= FILE_PAUSE_US;          } else if (control == FILECONTROL_ACCEPT) { @@ -1285,7 +1295,7 @@ int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber,      return 0;  } -/* Send a seek file control request. +/** Send a seek file control request.   *   *  return 0 on success   *  return -1 if friend not valid. @@ -1348,7 +1358,7 @@ int file_seek(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uin      return 0;  } -/* return packet number on success. +/** return packet number on success.   * return -1 on failure.   */  static int64_t send_file_data_packet(const Messenger *m, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, @@ -1372,7 +1382,7 @@ static int64_t send_file_data_packet(const Messenger *m, int32_t friendnumber, u  #define MAX_FILE_DATA_SIZE (MAX_CRYPTO_DATA_SIZE - 2)  #define MIN_SLOTS_FREE (CRYPTO_MIN_QUEUE_LENGTH / 4) -/* Send file data. +/** Send file data.   *   *  return 0 on success   *  return -1 if friend not valid. @@ -1474,15 +1484,13 @@ static bool do_all_filetransfers(Messenger *m, int32_t friendnumber, void *userd              return false;          } -        if (max_speed_reached(m->net_crypto, friend_connection_crypt_connection_id( -                                  m->fr_c, friendcon->friendcon_id))) { -            LOGGER_TRACE(m->log, "Maximum connection speed reached"); -            // connection doesn't support any more data -            return false; -        } -          struct File_Transfers *const ft = &friendcon->file_sending[i]; +        if (ft->status == FILESTATUS_NONE || ft->status == FILESTATUS_NOT_ACCEPTED) { +            // Filetransfers not actively sending, nothing to do +            continue; +        } +          // If the file transfer is complete, we request a chunk of size 0.          if (ft->status == FILESTATUS_FINISHED && friend_received_packet(m, friendnumber, ft->last_packet_number) == 0) {              if (m->file_reqchunk) { @@ -1492,9 +1500,7 @@ static bool do_all_filetransfers(Messenger *m, int32_t friendnumber, void *userd              // Now it's inactive, we're no longer sending this.              ft->status = FILESTATUS_NONE;              --friendcon->num_sending_files; -        } - -        if (ft->status == FILESTATUS_TRANSFERRING && ft->paused == FILE_PAUSE_NOT) { +        } else if (ft->status == FILESTATUS_TRANSFERRING && ft->paused == FILE_PAUSE_NOT) {              if (ft->size == 0) {                  /* Send 0 data to friend if file is 0 length. */                  file_data(m, friendnumber, i, 0, nullptr, 0); @@ -1517,6 +1523,14 @@ static bool do_all_filetransfers(Messenger *m, int32_t friendnumber, void *userd              // The allocated slot is no longer free.              --*free_slots;          } + +        // Must be last to allow finishing file transfers +        if (max_speed_reached(m->net_crypto, friend_connection_crypt_connection_id( +                                  m->fr_c, friendcon->friendcon_id))) { +            LOGGER_TRACE(m->log, "Maximum connection speed reached"); +            // connection doesn't support any more data +            return false; +        }      }      return true; @@ -1561,7 +1575,7 @@ static void do_reqchunk_filecb(Messenger *m, int32_t friendnumber, void *userdat  } -/* Run this when the friend disconnects. +/** Run this when the friend disconnects.   *  Kill all current file transfers.   */  static void break_files(const Messenger *m, int32_t friendnumber) @@ -1598,7 +1612,7 @@ static struct File_Transfers *get_file_transfer(uint8_t receive_send, uint8_t fi      return ft;  } -/* return -1 on failure, 0 on success. +/** return -1 on failure, 0 on success.   */  static int handle_filecontrol(Messenger *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber,                                uint8_t control_type, const uint8_t *data, uint16_t length, void *userdata) @@ -1623,6 +1637,7 @@ static int handle_filecontrol(Messenger *m, int32_t friendnumber, uint8_t receiv          case FILECONTROL_ACCEPT: {              if (receive_send && ft->status == FILESTATUS_NOT_ACCEPTED) {                  ft->status = FILESTATUS_TRANSFERRING; +                ++m->friendlist[friendnumber].num_sending_files;              } else {                  if (ft->paused & FILE_PAUSE_OTHER) {                      ft->paused ^= FILE_PAUSE_OTHER; @@ -1661,12 +1676,12 @@ static int handle_filecontrol(Messenger *m, int32_t friendnumber, uint8_t receiv                  m->file_filecontrol(m, friendnumber, real_filenumber, control_type, userdata);              } -            ft->status = FILESTATUS_NONE; - -            if (receive_send) { +            if (receive_send && (ft->status == FILESTATUS_TRANSFERRING || ft->status == FILESTATUS_FINISHED)) {                  --m->friendlist[friendnumber].num_sending_files;              } +            ft->status = FILESTATUS_NONE; +              return 0;          } @@ -1709,7 +1724,7 @@ static int handle_filecontrol(Messenger *m, int32_t friendnumber, uint8_t receiv      }  } -/* Set the callback for msi packets. +/** Set the callback for msi packets.   */  void m_callback_msi_packet(Messenger *m, m_msi_packet_cb *function, void *userdata)  { @@ -1717,7 +1732,7 @@ void m_callback_msi_packet(Messenger *m, m_msi_packet_cb *function, void *userda      m->msi_packet_userdata = userdata;  } -/* Send an msi packet. +/** Send an msi packet.   *   *  return 1 on success   *  return 0 on failure @@ -1776,12 +1791,21 @@ int m_callback_rtp_packet(Messenger *m, int32_t friendnumber, uint8_t byte, m_lo  } -/* TODO(oxij): this name is confusing, because this function sends both av and custom lossy packets. +/** High level function to send custom lossy packets. + * + * TODO(oxij): this name is confusing, because this function sends both av and custom lossy packets.   * Meanwhile, m_handle_lossy_packet routes custom packets to custom_lossy_packet_registerhandler   * as you would expect from its name.   *   * I.e. custom_lossy_packet_registerhandler's "custom lossy packet" and this "custom lossy packet"   * are not the same set of packets. + * + * return -1 if friend invalid. + * return -2 if length wrong. + * return -3 if first byte invalid. + * return -4 if friend offline. + * return -5 if packet failed to send because of other error. + * return 0 on success.   */  int m_send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length)  { @@ -1862,7 +1886,7 @@ int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const      return 0;  } -/* Function to filter out some friend requests*/ +/** Function to filter out some friend requests*/  static int friend_already_added(const uint8_t *real_pk, void *data)  {      const Messenger *m = (const Messenger *)data; @@ -1874,7 +1898,12 @@ static int friend_already_added(const uint8_t *real_pk, void *data)      return -1;  } -/* Run this at startup. */ +/** Run this at startup. + *  return allocated instance of Messenger on success. + *  return 0 if there are problems. + * + *  if error is not NULL it will be set to one of the values in the enum above. + */  Messenger *new_messenger(Mono_Time *mono_time, Messenger_Options *options, unsigned int *error)  {      if (!options) { @@ -1923,7 +1952,7 @@ Messenger *new_messenger(Mono_Time *mono_time, Messenger_Options *options, unsig      } else {          IP ip;          ip_init(&ip, options->ipv6enabled); -        m->net = new_networking_ex(m->log, ip, options->port_range[0], options->port_range[1], &net_err); +        m->net = new_networking_ex(m->log, &ip, options->port_range[0], options->port_range[1], &net_err);      }      if (m->net == nullptr) { @@ -1959,8 +1988,8 @@ Messenger *new_messenger(Mono_Time *mono_time, Messenger_Options *options, unsig          return nullptr;      } -    m->onion = new_onion(m->mono_time, m->dht); -    m->onion_a = new_onion_announce(m->mono_time, m->dht); +    m->onion = new_onion(m->log, m->mono_time, m->dht); +    m->onion_a = new_onion_announce(m->log, m->mono_time, m->dht);      m->onion_c =  new_onion_client(m->log, m->mono_time, m->net_crypto);      m->fr_c = new_friend_connections(m->log, m->mono_time, m->onion_c, options->local_discovery_enabled); @@ -2018,15 +2047,15 @@ Messenger *new_messenger(Mono_Time *mono_time, Messenger_Options *options, unsig      return m;  } -/* Run this before closing shop. */ +/** Run this before closing shop + * Free all datastructures. + */  void kill_messenger(Messenger *m)  {      if (!m) {          return;      } -    uint32_t i; -      if (m->tcp_server) {          kill_TCP_server(m->tcp_server);      } @@ -2039,7 +2068,7 @@ void kill_messenger(Messenger *m)      kill_dht(m->dht);      kill_networking(m->net); -    for (i = 0; i < m->numfriends; ++i) { +    for (uint32_t i = 0; i < m->numfriends; ++i) {          clear_receipts(m, i);      } @@ -2051,7 +2080,7 @@ void kill_messenger(Messenger *m)      free(m);  } -/* Check for and handle a timed-out friend request. If the request has +/** Check for and handle a timed-out friend request. If the request has   * timed-out then the friend status is set back to FRIEND_ADDED.   *   i: friendlist index of the timed-out friend   *   t: time @@ -2093,7 +2122,7 @@ static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t le      Messenger *m = (Messenger *)object;      uint8_t packet_id = temp[0];      const uint8_t *data = temp + 1; -    uint32_t data_length = len - 1; +    uint16_t data_length = len - 1;      if (m->friendlist[i].status != FRIEND_ONLINE) {          if (packet_id == PACKET_ID_ONLINE && len == 1) { @@ -2204,7 +2233,7 @@ static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t le              uint8_t type = packet_id - PACKET_ID_MESSAGE;              if (m->friend_message) { -                (*m->friend_message)(m, i, type, message_terminated, message_length, userdata); +                m->friend_message(m, i, type, message_terminated, message_length, userdata);              }              break; @@ -2216,7 +2245,7 @@ static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t le              }              if (m->conference_invite) { -                (*m->conference_invite)(m, i, data, data_length, userdata); +                m->conference_invite(m, i, data, data_length, userdata);              }              break; @@ -2264,7 +2293,7 @@ static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t le              memcpy(ft->id, data + 1 + sizeof(uint32_t) + sizeof(uint64_t), FILE_ID_LENGTH);              VLA(uint8_t, filename_terminated, filename_length + 1); -            uint8_t *filename = nullptr; +            const uint8_t *filename = nullptr;              if (filename_length) {                  /* Force NULL terminate file name. */ @@ -2278,8 +2307,8 @@ static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t le              real_filenumber <<= 16;              if (m->file_sendrequest) { -                (*m->file_sendrequest)(m, i, real_filenumber, file_type, filesize, filename, filename_length, -                                       userdata); +                m->file_sendrequest(m, i, real_filenumber, file_type, filesize, filename, filename_length, +                                    userdata);              }              break; @@ -2336,7 +2365,7 @@ static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t le              uint32_t real_filenumber = filenumber;              real_filenumber += 1;              real_filenumber <<= 16; -            uint16_t file_data_length = (data_length - 1); +            uint16_t file_data_length = data_length - 1;              const uint8_t *file_data;              if (file_data_length == 0) { @@ -2351,7 +2380,7 @@ static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t le              }              if (m->file_filedata) { -                (*m->file_filedata)(m, i, real_filenumber, position, file_data, file_data_length, userdata); +                m->file_filedata(m, i, real_filenumber, position, file_data, file_data_length, userdata);              }              ft->transferred += file_data_length; @@ -2363,7 +2392,7 @@ static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t le                  /* Full file received. */                  if (m->file_filedata) { -                    (*m->file_filedata)(m, i, real_filenumber, position, file_data, file_data_length, userdata); +                    m->file_filedata(m, i, real_filenumber, position, file_data, file_data_length, userdata);                  }              } @@ -2381,7 +2410,7 @@ static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t le              }              if (m->msi_packet) { -                (*m->msi_packet)(m, i, data, data_length, m->msi_packet_userdata); +                m->msi_packet(m, i, data, data_length, m->msi_packet_userdata);              }              break; @@ -2398,10 +2427,9 @@ static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t le  static void do_friends(Messenger *m, void *userdata)  { -    uint32_t i;      uint64_t temp_time = mono_time_get(m->mono_time); -    for (i = 0; i < m->numfriends; ++i) { +    for (uint32_t i = 0; i < m->numfriends; ++i) {          if (m->friendlist[i].status == FRIEND_ADDED) {              int fr = send_friend_request_packet(m->fr_c, m->friendlist[i].friendcon_id, m->friendlist[i].friendrequest_nospam,                                                  m->friendlist[i].info, @@ -2463,7 +2491,7 @@ static void connection_status_callback(Messenger *m, void *userdata)      if (conn_status != m->last_connection_status) {          if (m->core_connection_change) { -            (*m->core_connection_change)(m, conn_status, userdata); +            m->core_connection_change(m, conn_status, userdata);          }          m->last_connection_status = conn_status; @@ -2474,7 +2502,7 @@ static void connection_status_callback(Messenger *m, void *userdata)  #define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60UL  #define IDSTRING_LEN (CRYPTO_PUBLIC_KEY_SIZE * 2 + 1) -/* id_str should be of length at least IDSTRING_LEN */ +/** id_str should be of length at least IDSTRING_LEN */  static char *id_to_string(const uint8_t *pk, char *id_str, size_t length)  {      if (length < IDSTRING_LEN) { @@ -2483,18 +2511,18 @@ static char *id_to_string(const uint8_t *pk, char *id_str, size_t length)      }      for (uint32_t i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; ++i) { -        sprintf(&id_str[i * 2], "%02X", pk[i]); +        snprintf(&id_str[i * 2], length - i * 2, "%02X", pk[i]);      }      id_str[CRYPTO_PUBLIC_KEY_SIZE * 2] = 0;      return id_str;  } -/* Minimum messenger run interval in ms +/** Minimum messenger run interval in ms   * TODO(mannol): A/V */  #define MIN_RUN_INTERVAL 50 -/* Return the time in milliseconds before do_messenger() should be called again +/** Return the time in milliseconds before do_messenger() should be called again   * for optimal performance.   *   * returns time (in ms) before the next do_messenger() needs to be run on success. @@ -2510,7 +2538,7 @@ uint32_t messenger_run_interval(const Messenger *m)      return crypto_interval;  } -/* The main loop that needs to be run at least 20 times per second. */ +/** The main loop that needs to be run at least 20 times per second. */  void do_messenger(Messenger *m, void *userdata)  {      // Add the TCP relays, but only if this is the first time calling do_messenger @@ -2518,7 +2546,7 @@ void do_messenger(Messenger *m, void *userdata)          m->has_added_relays = true;          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); +            add_tcp_relay(m->net_crypto, &m->loaded_relays[i].ip_port, m->loaded_relays[i].public_key);          }          m->num_loaded_relays = 0; @@ -2529,8 +2557,7 @@ void do_messenger(Messenger *m, void *userdata)              local_ip_port.port = m->options.tcp_server_port;              local_ip_port.ip.family = net_family_ipv4;              local_ip_port.ip.ip.v4 = get_ip4_loopback(); -            add_tcp_relay(m->net_crypto, local_ip_port, -                          tcp_server_public_key(m->tcp_server)); +            add_tcp_relay(m->net_crypto, &local_ip_port, tcp_server_public_key(m->tcp_server));          }      } @@ -2609,17 +2636,9 @@ void do_messenger(Messenger *m, void *userdata)              LOGGER_TRACE(m->log, "Friend num in DHT %u != friend num in msger %u", dht_get_num_friends(m->dht), m->numfriends);          } -        Friend *msgfptr; -        DHT_Friend *dhtfptr; -          for (uint32_t friend_idx = 0; friend_idx < num_dhtfriends; ++friend_idx) { -            if (dht2m[friend_idx] >= 0) { -                msgfptr = &m->friendlist[dht2m[friend_idx]]; -            } else { -                msgfptr = nullptr; -            } - -            dhtfptr = dht_get_friend(m->dht, friend_idx); +            const Friend *const msgfptr = dht2m[friend_idx] >= 0 ?  &m->friendlist[dht2m[friend_idx]] : nullptr; +            const DHT_Friend *const dhtfptr = dht_get_friend(m->dht, friend_idx);              if (msgfptr) {                  char id_str[IDSTRING_LEN]; @@ -2659,7 +2678,7 @@ void do_messenger(Messenger *m, void *userdata)      }  } -/* new messenger format for load/save, more robust and forward compatible */ +/** new messenger format for load/save, more robust and forward compatible */  #define SAVED_FRIEND_REQUEST_SIZE 1024  #define NUM_SAVED_PATH_NODES 8 @@ -2794,10 +2813,10 @@ static uint32_t m_state_plugins_size(const Messenger *m)      return size;  } -/* - * Registers a state plugin with the messenger +/** Registers a state plugin for saving, loadding, and getting the size of a section of the save + *   * returns true on success - * returns false on failure + * returns false on error   */  bool m_register_state_plugin(Messenger *m, State_Type type, m_state_size_cb size_callback,                               m_state_load_cb load_callback, @@ -2837,13 +2856,13 @@ static uint32_t m_plugin_size(const Messenger *m, State_Type type)      return UINT32_MAX;  } -/*  return size of the messenger data (for saving) */ +/** return size of the messenger data (for saving). */  uint32_t messenger_size(const Messenger *m)  {      return m_state_plugins_size(m);  } -/* Save the messenger in data of size messenger_size(). */ +/** 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)  {      for (uint8_t i = 0; i < m->options.state_plugins_length; ++i) { @@ -2969,21 +2988,20 @@ static uint8_t *friends_list_save(const Messenger *m, uint8_t *data)  static State_Load_Status friends_list_load(Messenger *m, const uint8_t *data, uint32_t length)  { -    if (length % friend_size() != 0) { +    const uint32_t l_friend_size = friend_size(); + +    if (length % l_friend_size != 0) {          return STATE_LOAD_STATUS_ERROR; // TODO(endoffile78): error or continue?      } -    uint32_t num = length / friend_size(); -    uint32_t i; +    uint32_t num = length / l_friend_size;      const uint8_t *cur_data = data; -    for (i = 0; i < num; ++i) { +    for (uint32_t i = 0; i < num; ++i) {          struct Saved_Friend temp = { 0 };          const uint8_t *next_data = friend_load(&temp, cur_data); -        assert(next_data - cur_data == friend_size()); -#ifdef __LP64__ -        assert(memcmp(&temp, cur_data, friend_size()) == 0); -#endif +        assert(next_data - cur_data == l_friend_size); +          cur_data = next_data;          if (temp.status >= 3) { @@ -3091,7 +3109,7 @@ static uint32_t tcp_relay_size(const Messenger *m)  static uint8_t *save_tcp_relays(const Messenger *m, uint8_t *data)  { -    Node_format relays[NUM_SAVED_TCP_RELAYS]; +    Node_format relays[NUM_SAVED_TCP_RELAYS] = {0};      uint8_t *temp_data = data;      data = state_write_section_header(temp_data, STATE_COOKIE_TYPE, 0, STATE_TYPE_TCP_RELAY); @@ -3166,7 +3184,7 @@ static State_Load_Status load_path_nodes(Messenger *m, const uint8_t *data, uint          }          for (int i = 0; i < num; ++i) { -            onion_add_bs_path_node(m->onion_c, nodes[i].ip_port, nodes[i].public_key); +            onion_add_bs_path_node(m->onion_c, &nodes[i].ip_port, nodes[i].public_key);          }      } @@ -3201,15 +3219,14 @@ bool messenger_load_state_section(Messenger *m, const uint8_t *data, uint32_t le      return false;  } -/* Return the number of friends in the instance m. +/** Return the number of friends in the instance m.   * You should use this to determine how much memory to allocate   * for copy_friendlist. */  uint32_t count_friendlist(const Messenger *m)  {      uint32_t ret = 0; -    uint32_t i; -    for (i = 0; i < m->numfriends; ++i) { +    for (uint32_t i = 0; i < m->numfriends; ++i) {          if (m->friendlist[i].status > 0) {              ++ret;          } @@ -3218,7 +3235,7 @@ uint32_t count_friendlist(const Messenger *m)      return ret;  } -/* Copy a list of valid friend IDs into the array out_list. +/** Copy a list of valid friend IDs into the array out_list.   * If out_list is NULL, returns 0.   * Otherwise, returns the number of elements copied.   * If the array was too small, the contents @@ -3233,10 +3250,9 @@ uint32_t copy_friendlist(Messenger const *m, uint32_t *out_list, uint32_t list_s          return 0;      } -    uint32_t i;      uint32_t ret = 0; -    for (i = 0; i < m->numfriends; ++i) { +    for (uint32_t i = 0; i < m->numfriends; ++i) {          if (ret >= list_size) {              break; /* Abandon ship */          } diff --git a/protocols/Tox/libtox/src/toxcore/Messenger.h b/protocols/Tox/libtox/src/toxcore/Messenger.h index 673fd425a2..477b997391 100644 --- a/protocols/Tox/libtox/src/toxcore/Messenger.h +++ b/protocols/Tox/libtox/src/toxcore/Messenger.h @@ -3,13 +3,14 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * An implementation of a simple text chat only messenger on the tox network   * core.   */  #ifndef C_TOXCORE_TOXCORE_MESSENGER_H  #define C_TOXCORE_TOXCORE_MESSENGER_H +#include "TCP_server.h"  #include "friend_connection.h"  #include "friend_requests.h"  #include "logger.h" @@ -24,10 +25,6 @@  /* This cannot be bigger than 256 */  #define MAX_CONCURRENT_FILE_PIPES 256 -#if !defined(__SPLINT__) && MAX_CONCURRENT_FILE_PIPES > UINT8_MAX + 1 -#error "uint8_t cannot represent all file transfer numbers" -#endif -  #define FRIEND_ADDRESS_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint32_t) + sizeof(uint16_t)) @@ -79,7 +76,7 @@ struct Receipts {      struct Receipts *next;  }; -/* Status definitions. */ +/** Status definitions. */  typedef enum Friend_Status {      NOFRIEND,      FRIEND_ADDED, @@ -88,7 +85,7 @@ typedef enum Friend_Status {      FRIEND_ONLINE,  } Friend_Status; -/* Errors for m_addfriend +/** Errors for m_addfriend   * FAERR - Friend Add Error   */  typedef enum Friend_Add_Error { @@ -102,7 +99,7 @@ typedef enum Friend_Add_Error {  } Friend_Add_Error; -/* Default start timeout in seconds between friend requests. */ +/** Default start timeout in seconds between friend requests. */  #define FRIENDREQUEST_TIMEOUT 5  typedef enum Connection_Status { @@ -111,7 +108,7 @@ typedef enum Connection_Status {      CONNECTION_UDP,  } Connection_Status; -/* USERSTATUS - +/** USERSTATUS -   * Represents userstatuses someone can have.   */ @@ -298,33 +295,37 @@ struct Messenger {      Messenger_Options options;  }; -/* Format: `[real_pk (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]` +/** Format: `[real_pk (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]`   *   *  return FRIEND_ADDRESS_SIZE byte address to give to others.   */  void getaddress(const Messenger *m, uint8_t *address); -/* Add a friend. +/** + * Add a friend. + *   * Set the data that will be sent along with friend request. - * address is the address of the friend (returned by getaddress of the friend + * + * @param address is the address of the friend (returned by getaddress of the friend   *   you wish to add) it must be FRIEND_ADDRESS_SIZE bytes.   *   TODO(irungentoo): add checksum. - * data is the data and length is the length. + * @param data is the data. + * @param length is the length.   *   *  return the friend number if success. - *  return -1 if message length is too long. - *  return -2 if no message (message length must be >= 1 byte). - *  return -3 if user's own key. - *  return -4 if friend request already sent or already a friend. - *  return -6 if bad checksum in address. - *  return -7 if the friend was already there but the nospam was different. + *  return FA_TOOLONG if message length is too long. + *  return FAERR_NOMESSAGE if no message (message length must be >= 1 byte). + *  return FAERR_OWNKEY if user's own key. + *  return FAERR_ALREADYSENT if friend request already sent or already a friend. + *  return FAERR_BADCHECKSUM if bad checksum in address. + *  return FAERR_SETNEWNOSPAM if the friend was already there but the nospam was different.   *  (the nospam for that friend was set to the new one). - *  return -8 if increasing the friend list size fails. + *  return FAERR_NOMEM if increasing the friend list size fails.   */  int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, uint16_t length); -/* Add a friend without sending a friendrequest. +/** Add a friend without sending a friendrequest.   *  return the friend number if success.   *  return -3 if user's own key.   *  return -4 if friend request already sent or already a friend. @@ -333,32 +334,32 @@ int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, u   */  int32_t m_addfriend_norequest(Messenger *m, const uint8_t *real_pk); -/*  return the friend number associated to that client id. +/** return the friend number associated to that public key.   *  return -1 if no such friend.   */  int32_t getfriend_id(const Messenger *m, const uint8_t *real_pk); -/* Copies the public key associated to that friend id into real_pk buffer. +/** Copies the public key associated to that friend id into real_pk buffer.   * Make sure that real_pk is of size CRYPTO_PUBLIC_KEY_SIZE.   * - *  return 0 if success - *  return -1 if failure + *  return 0 if success. + *  return -1 if failure.   */  int get_real_pk(const Messenger *m, int32_t friendnumber, uint8_t *real_pk); -/*  return friend connection id on success. +/**  return friend connection id on success.   *  return -1 if failure.   */  int getfriendcon_id(const Messenger *m, int32_t friendnumber); -/* Remove a friend. +/** Remove a friend.   * - *  return 0 if success - *  return -1 if failure + *  return 0 if success. + *  return -1 if failure.   */  int m_delfriend(Messenger *m, int32_t friendnumber); -/* Checks friend's connection status. +/** Checks friend's connection status.   *   *  return CONNECTION_UDP (2) if friend is directly connected to us (Online UDP).   *  return CONNECTION_TCP (1) if friend is connected to us (Online TCP). @@ -367,14 +368,14 @@ int m_delfriend(Messenger *m, int32_t friendnumber);   */  int m_get_friend_connectionstatus(const Messenger *m, int32_t friendnumber); -/* Checks if there exists a friend with given friendnumber. +/** Checks if there exists a friend with given friendnumber.   *   *  return 1 if friend exists.   *  return 0 if friend doesn't exist.   */  int m_friend_exists(const Messenger *m, int32_t friendnumber); -/* Send a message of type to an online friend. +/** Send a message of type to an online friend.   *   * return -1 if friend not valid.   * return -2 if too large. @@ -389,7 +390,7 @@ int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, con                             uint32_t *message_id); -/* Set the name and name_length of a friend. +/** Set the name and name_length of a friend.   * name must be a string of maximum MAX_NAME_LENGTH length.   * length must be at least 1 byte.   * length is the length of name with the NULL terminator. @@ -399,7 +400,7 @@ int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, con   */  int setfriendname(Messenger *m, int32_t friendnumber, const uint8_t *name, uint16_t length); -/* Set our nickname. +/** Set our nickname.   * name must be a string of maximum MAX_NAME_LENGTH length.   * length must be at least 1 byte.   * length is the length of name with the NULL terminator. @@ -409,7 +410,7 @@ int setfriendname(Messenger *m, int32_t friendnumber, const uint8_t *name, uint1   */  int setname(Messenger *m, const uint8_t *name, uint16_t length); -/* +/**   * Get your nickname.   * m - The messenger context to use.   * name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes. @@ -419,7 +420,7 @@ int setname(Messenger *m, const uint8_t *name, uint16_t length);   */  uint16_t getself_name(const Messenger *m, uint8_t *name); -/* Get name of friendnumber and put it in name. +/** Get name of friendnumber and put it in name.   * name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.   *   *  return length of name if success. @@ -427,13 +428,13 @@ uint16_t getself_name(const Messenger *m, uint8_t *name);   */  int getname(const Messenger *m, int32_t friendnumber, uint8_t *name); -/*  return the length of name, including null on success. +/**  return the length of name, including null on success.   *  return -1 on failure.   */  int m_get_name_size(const Messenger *m, int32_t friendnumber);  int m_get_self_name_size(const Messenger *m); -/* Set our user status. +/** Set our user status.   * You are responsible for freeing status after.   *   *  returns 0 on success. @@ -442,23 +443,26 @@ int m_get_self_name_size(const Messenger *m);  int m_set_statusmessage(Messenger *m, const uint8_t *status, uint16_t length);  int m_set_userstatus(Messenger *m, uint8_t status); -/*  return the length of friendnumber's status message, including null on success. - *  return -1 on failure. +/** + * Guaranteed to be at most MAX_STATUSMESSAGE_LENGTH. + * + * returns the length of friendnumber's status message, including null on success. + * returns -1 on failure.   */  int m_get_statusmessage_size(const Messenger *m, int32_t friendnumber);  int m_get_self_statusmessage_size(const Messenger *m); -/* Copy friendnumber's status message into buf, truncating if size is over maxlen. +/** Copy friendnumber's status message into buf, truncating if size is over maxlen.   * Get the size you need to allocate from m_get_statusmessage_size.   * The self variant will copy our own status message.   *   * returns the length of the copied data on success - * retruns -1 on failure. + * returns -1 on failure.   */  int m_copy_statusmessage(const Messenger *m, int32_t friendnumber, uint8_t *buf, uint32_t maxlen);  int m_copy_self_statusmessage(const Messenger *m, uint8_t *buf); -/*  return one of Userstatus values. +/**  return one of Userstatus values.   *  Values unknown to your application should be represented as USERSTATUS_NONE.   *  As above, the self variant will return our own Userstatus.   *  If friendnumber is invalid, this shall return USERSTATUS_INVALID. @@ -467,12 +471,12 @@ uint8_t m_get_userstatus(const Messenger *m, int32_t friendnumber);  uint8_t m_get_self_userstatus(const Messenger *m); -/* returns timestamp of last time friendnumber was seen online or 0 if never seen. +/** returns timestamp of last time friendnumber was seen online or 0 if never seen.   * if friendnumber is invalid this function will return UINT64_MAX.   */  uint64_t m_get_last_online(const Messenger *m, int32_t friendnumber); -/* Set our typing status for a friend. +/** Set our typing status for a friend.   * You are responsible for turning it on or off.   *   * returns 0 on success. @@ -480,48 +484,39 @@ uint64_t m_get_last_online(const Messenger *m, int32_t friendnumber);   */  int m_set_usertyping(Messenger *m, int32_t friendnumber, uint8_t is_typing); -/* Get the typing status of a friend. +/** Get the typing status of a friend.   *   * returns 0 if friend is not typing.   * returns 1 if friend is typing.   */  int m_get_istyping(const Messenger *m, int32_t friendnumber); -/* Set the function that will be executed when a friend request is received. - *  Function format is `function(uint8_t * public_key, uint8_t * data, size_t length)` - */ +/** Set the function that will be executed when a friend request is received. */  void m_callback_friendrequest(Messenger *m, m_friend_request_cb *function); -/* Set the function that will be executed when a message from a friend is received. - *  Function format is: `function(uint32_t friendnumber, unsigned int type, uint8_t * message, uint32_t length)` - */ +/** Set the function that will be executed when a message from a friend is received. */  void m_callback_friendmessage(Messenger *m, m_friend_message_cb *function); -/* Set the callback for name changes. - *  `Function(uint32_t friendnumber, uint8_t *newname, size_t length)` +/** Set the callback for name changes.   *  You are not responsible for freeing newname.   */  void m_callback_namechange(Messenger *m, m_friend_name_cb *function); -/* Set the callback for status message changes. - *  `Function(uint32_t friendnumber, uint8_t *newstatus, size_t length)` +/** Set the callback for status message changes.   *   *  You are not responsible for freeing newstatus   */  void m_callback_statusmessage(Messenger *m, m_friend_status_message_cb *function); -/* Set the callback for status type changes. - *  `Function(uint32_t friendnumber, Userstatus kind)` +/** Set the callback for status type changes.   */  void m_callback_userstatus(Messenger *m, m_friend_status_cb *function); -/* Set the callback for typing changes. - *  `Function(uint32_t friendnumber, uint8_t is_typing)` +/** Set the callback for typing changes.   */  void m_callback_typingchange(Messenger *m, m_friend_typing_cb *function); -/* Set the callback for read receipts. - *  `Function(uint32_t friendnumber, uint32_t receipt)` +/** Set the callback for read receipts.   *   *  If you are keeping a record of returns from m_sendmessage,   *  receipt might be one of those values, meaning the message @@ -531,8 +526,7 @@ void m_callback_typingchange(Messenger *m, m_friend_typing_cb *function);   */  void m_callback_read_receipt(Messenger *m, m_friend_read_receipt_cb *function); -/* Set the callback for connection status changes. - *  `function(uint32_t friendnumber, uint8_t status)` +/** Set the callback for connection status changes.   *   *  Status:   *    0 -- friend went offline after being previously online. @@ -544,51 +538,50 @@ void m_callback_read_receipt(Messenger *m, m_friend_read_receipt_cb *function);   */  void m_callback_connectionstatus(Messenger *m, m_friend_connection_status_cb *function); -/* Same as previous but for internal A/V core usage only */ +/** Same as previous but for internal A/V core usage only */  void m_callback_connectionstatus_internal_av(Messenger *m, m_friend_connectionstatuschange_internal_cb *function,          void *userdata); -/* Set the callback for typing changes. - *  Function(unsigned int connection_status (0 = not connected, 1 = TCP only, 2 = UDP + TCP)) +/** Set the callback for typing changes.   */  void m_callback_core_connection(Messenger *m, m_self_connection_status_cb *function); -/** CONFERENCES */ +/*** CONFERENCES */ -/* Set the callback for conference invites. +/** Set the callback for conference invites.   */  void m_callback_conference_invite(Messenger *m, m_conference_invite_cb *function); -/* Send a conference invite packet. +/** Send a conference invite packet.   *   *  return 1 on success   *  return 0 on failure   */  int send_conference_invite_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length); -/** FILE SENDING */ +/*** FILE SENDING */ -/* Set the callback for file send requests. +/** Set the callback for file send requests.   */  void callback_file_sendrequest(Messenger *m, m_file_recv_cb *function); -/* Set the callback for file control requests. +/** Set the callback for file control requests.   */  void callback_file_control(Messenger *m, m_file_recv_control_cb *function); -/* Set the callback for file data. +/** Set the callback for file data.   */  void callback_file_data(Messenger *m, m_file_recv_chunk_cb *function); -/* Set the callback for file request chunk. +/** Set the callback for file request chunk.   */  void callback_file_reqchunk(Messenger *m, m_file_chunk_request_cb *function); -/* Copy the file transfer file id to file_id +/** Copy the file transfer file id to file_id   *   * return 0 on success.   * return -1 if friend not valid. @@ -596,7 +589,7 @@ void callback_file_reqchunk(Messenger *m, m_file_chunk_request_cb *function);   */  int file_get_id(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint8_t *file_id); -/* Send a file send request. +/** Send a file send request.   * Maximum filename length is 255 bytes.   *  return file number on success   *  return -1 if friend not found. @@ -608,7 +601,7 @@ int file_get_id(const Messenger *m, int32_t friendnumber, uint32_t filenumber, u  long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_type, uint64_t filesize,                          const uint8_t *file_id, const uint8_t *filename, uint16_t filename_length); -/* Send a file control request. +/** Send a file control request.   *   *  return 0 on success   *  return -1 if friend not valid. @@ -622,7 +615,7 @@ long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_   */  int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber, unsigned int control); -/* Send a seek file control request. +/** Send a seek file control request.   *   *  return 0 on success   *  return -1 if friend not valid. @@ -635,7 +628,7 @@ int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber,   */  int file_seek(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position); -/* Send file data. +/** Send file data.   *   *  return 0 on success   *  return -1 if friend not valid. @@ -649,20 +642,20 @@ int file_seek(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uin  int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,                uint16_t length); -/** A/V related */ +/*** A/V related */ -/* Set the callback for msi packets. +/** Set the callback for msi packets.   */  void m_callback_msi_packet(Messenger *m, m_msi_packet_cb *function, void *userdata); -/* Send an msi packet. +/** Send an msi packet.   *   *  return 1 on success   *  return 0 on failure   */  int m_msi_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length); -/* Set handlers for lossy rtp packets. +/** Set handlers for lossy rtp packets.   *   * return -1 on failure.   * return 0 on success. @@ -670,14 +663,21 @@ int m_msi_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data,  int m_callback_rtp_packet(Messenger *m, int32_t friendnumber, uint8_t byte,                            m_lossy_rtp_packet_cb *function, void *object); -/** CUSTOM PACKETS */ +/*** CUSTOM PACKETS */ -/* Set handlers for custom lossy packets. +/** Set handlers for custom lossy packets.   *   */  void custom_lossy_packet_registerhandler(Messenger *m, m_friend_lossy_packet_cb *lossy_packethandler); -/* High level function to send custom lossy packets. +/** High level function to send custom lossy packets. + * + * TODO(oxij): this name is confusing, because this function sends both av and custom lossy packets. + * Meanwhile, m_handle_lossy_packet routes custom packets to custom_lossy_packet_registerhandler + * as you would expect from its name. + * + * I.e. custom_lossy_packet_registerhandler's "custom lossy packet" and this "custom lossy packet" + * are not the same set of packets.   *   * return -1 if friend invalid.   * return -2 if length wrong. @@ -689,12 +689,12 @@ void custom_lossy_packet_registerhandler(Messenger *m, m_friend_lossy_packet_cb  int m_send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length); -/* Set handlers for custom lossless packets. +/** Set handlers for custom lossless packets.   *   */  void custom_lossless_packet_registerhandler(Messenger *m, m_friend_lossless_packet_cb *lossless_packethandler); -/* High level function to send custom lossless packets. +/** High level function to send custom lossless packets.   *   * return -1 if friend invalid.   * return -2 if length wrong. @@ -705,7 +705,7 @@ void custom_lossless_packet_registerhandler(Messenger *m, m_friend_lossless_pack   */  int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length); -/** Messenger constructor/destructor/operations. */ +/*** Messenger constructor/destructor/operations. */  typedef enum Messenger_Error {      MESSENGER_ERROR_NONE, @@ -714,7 +714,7 @@ typedef enum Messenger_Error {      MESSENGER_ERROR_OTHER,  } Messenger_Error; -/* Run this at startup. +/** Run this at startup.   *  return allocated instance of Messenger on success.   *  return 0 if there are problems.   * @@ -722,15 +722,15 @@ typedef enum Messenger_Error {   */  Messenger *new_messenger(Mono_Time *mono_time, Messenger_Options *options, unsigned int *error); -/* Run this before closing shop +/** Run this before closing shop   * Free all datastructures.   */  void kill_messenger(Messenger *m); -/* The main loop that needs to be run at least 20 times per second. */ +/** The main loop that needs to be run at least 20 times per second. */  void do_messenger(Messenger *m, void *userdata); -/* Return the time in milliseconds before do_messenger() should be called again +/** Return the time in milliseconds before do_messenger() should be called again   * for optimal performance.   *   * returns time (in ms) before the next do_messenger() needs to be run on success. @@ -739,7 +739,7 @@ uint32_t messenger_run_interval(const Messenger *m);  /* SAVING AND LOADING FUNCTIONS: */ -/* Registers a state plugin for saving, loadding, and getting the size of a section of the save +/** Registers a state plugin for saving, loadding, and getting the size of a section of the save   *   * returns true on success   * returns false on error @@ -747,13 +747,13 @@ uint32_t messenger_run_interval(const Messenger *m);  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). */ +/** 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 at least Messenger_size()) */ +/** 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 a state section. +/** Load a state section.   *   * @param data Data to load.   * @param length Length of data. @@ -764,12 +764,12 @@ uint8_t *messenger_save(const Messenger *m, uint8_t *data);  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. +/** Return the number of friends in the instance m.   * You should use this to determine how much memory to allocate   * for copy_friendlist. */  uint32_t count_friendlist(const Messenger *m); -/* Copy a list of valid friend IDs into the array out_list. +/** Copy a list of valid friend IDs into the array out_list.   * If out_list is NULL, returns 0.   * Otherwise, returns the number of elements copied.   * If the array was too small, the contents diff --git a/protocols/Tox/libtox/src/toxcore/TCP_client.c b/protocols/Tox/libtox/src/toxcore/TCP_client.c index 1405d9b2c3..30aa268f1c 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_client.c +++ b/protocols/Tox/libtox/src/toxcore/TCP_client.c @@ -3,19 +3,16 @@   * Copyright © 2014 Tox project.   */ -/* +/**   * Implementation of the TCP relay client part of Tox.   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -  #include "TCP_client.h"  #include <stdio.h>  #include <stdlib.h>  #include <string.h> +#include "TCP_common.h"  #include "mono_time.h"  #include "util.h" @@ -27,26 +24,17 @@ typedef struct TCP_Client_Conn {  } TCP_Client_Conn;  struct TCP_Client_Connection { +    TCP_Connection con;      TCP_Client_Status status; -    Socket sock;      uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* our public key */      uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* public key of the server */      IP_Port ip_port; /* The ip and port of the server */      TCP_Proxy_Info proxy_info;      uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of received packets. */ -    uint8_t sent_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of sent packets. */ -    uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];      uint16_t next_packet_length;      uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE]; -    uint8_t last_packet[2 + MAX_PACKET_SIZE]; -    uint16_t last_packet_length; -    uint16_t last_packet_sent; - -    TCP_Priority_List *priority_queue_start; -    TCP_Priority_List *priority_queue_end; -      uint64_t kill_at;      uint64_t last_pinged; @@ -104,21 +92,24 @@ void tcp_con_set_custom_uint(TCP_Client_Connection *con, uint32_t value)      con->custom_uint = value;  } -/* return 1 on success +/** return 1 on success   * return 0 on failure   */ -static int connect_sock_to(Socket sock, IP_Port ip_port, TCP_Proxy_Info *proxy_info) +static int connect_sock_to(const Logger *logger, Socket sock, const IP_Port *ip_port, const TCP_Proxy_Info *proxy_info)  { +    IP_Port ipp_copy = *ip_port; +      if (proxy_info->proxy_type != TCP_PROXY_NONE) { -        ip_port = proxy_info->ip_port; +        ipp_copy = proxy_info->ip_port;      }      /* nonblocking socket, connect will never return success */ -    net_connect(sock, ip_port); +    net_connect(logger, sock, &ipp_copy); +      return 1;  } -/* return 1 on success. +/** return 1 on success.   * return 0 on failure.   */  static int proxy_http_generate_connection_request(TCP_Client_Connection *tcp_conn) @@ -134,29 +125,29 @@ static int proxy_http_generate_connection_request(TCP_Client_Connection *tcp_con      }      const uint16_t port = net_ntohs(tcp_conn->ip_port.port); -    const int written = snprintf((char *)tcp_conn->last_packet, MAX_PACKET_SIZE, "%s%s:%hu%s%s:%hu%s", one, ip, port, two, -                                 ip, port, three); +    const int written = snprintf((char *)tcp_conn->con.last_packet, MAX_PACKET_SIZE, "%s%s:%hu%s%s:%hu%s", one, ip, port, +                                 two, ip, port, three);      if (written < 0 || MAX_PACKET_SIZE < written) {          return 0;      } -    tcp_conn->last_packet_length = written; -    tcp_conn->last_packet_sent = 0; +    tcp_conn->con.last_packet_length = written; +    tcp_conn->con.last_packet_sent = 0;      return 1;  } -/* return 1 on success. +/** return 1 on success.   * return 0 if no data received.   * return -1 on failure (connection refused).   */ -static int proxy_http_read_connection_response(const Logger *logger, TCP_Client_Connection *tcp_conn) +static int proxy_http_read_connection_response(const Logger *logger, const TCP_Client_Connection *tcp_conn)  {      char success[] = "200";      uint8_t data[16]; // draining works the best if the length is a power of 2 -    int ret = read_TCP_packet(logger, tcp_conn->sock, data, sizeof(data) - 1); +    int ret = read_TCP_packet(logger, tcp_conn->con.sock, data, sizeof(data) - 1, &tcp_conn->con.ip_port);      if (ret == -1) {          return 0; @@ -164,13 +155,13 @@ static int proxy_http_read_connection_response(const Logger *logger, TCP_Client_      data[sizeof(data) - 1] = 0; -    if (strstr((char *)data, success)) { +    if (strstr((const char *)data, success)) {          // drain all data -        unsigned int data_left = net_socket_data_recv_buffer(tcp_conn->sock); +        const uint16_t data_left = net_socket_data_recv_buffer(tcp_conn->con.sock);          if (data_left) {              VLA(uint8_t, temp_data, data_left); -            read_TCP_packet(logger, tcp_conn->sock, temp_data, data_left); +            read_TCP_packet(logger, tcp_conn->con.sock, temp_data, data_left, &tcp_conn->con.ip_port);          }          return 1; @@ -179,30 +170,39 @@ static int proxy_http_read_connection_response(const Logger *logger, TCP_Client_      return -1;  } -static void proxy_socks5_generate_handshake(TCP_Client_Connection *tcp_conn) +#define TCP_SOCKS5_PROXY_HS_VERSION_SOCKS5 0x05 +#define TCP_SOCKS5_PROXY_HS_COMM_ESTABLISH_REQUEST 0x01 +#define TCP_SOCKS5_PROXY_HS_COMM_REQUEST_GRANTED 0x00 +#define TCP_SOCKS5_PROXY_HS_AUTH_METHODS_SUPPORTED 0x01 +#define TCP_SOCKS5_PROXY_HS_NO_AUTH 0x00 +#define TCP_SOCKS5_PROXY_HS_RESERVED 0x00 +#define TCP_SOCKS5_PROXY_HS_ADDR_TYPE_IPV4 0x01 +#define TCP_SOCKS5_PROXY_HS_ADDR_TYPE_IPV6 0x04 + +static void proxy_socks5_generate_greetings(TCP_Client_Connection *tcp_conn)  { -    tcp_conn->last_packet[0] = 5; /* SOCKSv5 */ -    tcp_conn->last_packet[1] = 1; /* number of authentication methods supported */ -    tcp_conn->last_packet[2] = 0; /* No authentication */ +    tcp_conn->con.last_packet[0] = TCP_SOCKS5_PROXY_HS_VERSION_SOCKS5; +    tcp_conn->con.last_packet[1] = TCP_SOCKS5_PROXY_HS_AUTH_METHODS_SUPPORTED; +    tcp_conn->con.last_packet[2] = TCP_SOCKS5_PROXY_HS_NO_AUTH; -    tcp_conn->last_packet_length = 3; -    tcp_conn->last_packet_sent = 0; +    tcp_conn->con.last_packet_length = 3; +    tcp_conn->con.last_packet_sent = 0;  } -/* return 1 on success. +/** return 1 on success.   * return 0 if no data received.   * return -1 on failure (connection refused).   */ -static int socks5_read_handshake_response(const Logger *logger, TCP_Client_Connection *tcp_conn) +static int socks5_read_handshake_response(const Logger *logger, const TCP_Client_Connection *tcp_conn)  {      uint8_t data[2]; -    int ret = read_TCP_packet(logger, tcp_conn->sock, data, sizeof(data)); +    int ret = read_TCP_packet(logger, tcp_conn->con.sock, data, sizeof(data), &tcp_conn->con.ip_port);      if (ret == -1) {          return 0;      } -    if (data[0] == 5 && data[1] == 0) { // TODO(irungentoo): magic numbers +    if (data[0] == TCP_SOCKS5_PROXY_HS_VERSION_SOCKS5 && data[1] == TCP_SOCKS5_PROXY_HS_COMM_REQUEST_GRANTED) {          return 1;      } @@ -211,56 +211,56 @@ static int socks5_read_handshake_response(const Logger *logger, TCP_Client_Conne  static void proxy_socks5_generate_connection_request(TCP_Client_Connection *tcp_conn)  { -    tcp_conn->last_packet[0] = 5; /* SOCKSv5 */ -    tcp_conn->last_packet[1] = 1; /* command code: establish a TCP/IP stream connection */ -    tcp_conn->last_packet[2] = 0; /* reserved, must be 0 */ +    tcp_conn->con.last_packet[0] = TCP_SOCKS5_PROXY_HS_VERSION_SOCKS5; +    tcp_conn->con.last_packet[1] = TCP_SOCKS5_PROXY_HS_COMM_ESTABLISH_REQUEST; +    tcp_conn->con.last_packet[2] = TCP_SOCKS5_PROXY_HS_RESERVED;      uint16_t length = 3;      if (net_family_is_ipv4(tcp_conn->ip_port.ip.family)) { -        tcp_conn->last_packet[3] = 1; /* IPv4 address */ +        tcp_conn->con.last_packet[3] = TCP_SOCKS5_PROXY_HS_ADDR_TYPE_IPV4;          ++length; -        memcpy(tcp_conn->last_packet + length, tcp_conn->ip_port.ip.ip.v4.uint8, sizeof(IP4)); +        memcpy(tcp_conn->con.last_packet + length, tcp_conn->ip_port.ip.ip.v4.uint8, sizeof(IP4));          length += sizeof(IP4);      } else { -        tcp_conn->last_packet[3] = 4; /* IPv6 address */ +        tcp_conn->con.last_packet[3] = TCP_SOCKS5_PROXY_HS_ADDR_TYPE_IPV6;          ++length; -        memcpy(tcp_conn->last_packet + length, tcp_conn->ip_port.ip.ip.v6.uint8, sizeof(IP6)); +        memcpy(tcp_conn->con.last_packet + length, tcp_conn->ip_port.ip.ip.v6.uint8, sizeof(IP6));          length += sizeof(IP6);      } -    memcpy(tcp_conn->last_packet + length, &tcp_conn->ip_port.port, sizeof(uint16_t)); +    memcpy(tcp_conn->con.last_packet + length, &tcp_conn->ip_port.port, sizeof(uint16_t));      length += sizeof(uint16_t); -    tcp_conn->last_packet_length = length; -    tcp_conn->last_packet_sent = 0; +    tcp_conn->con.last_packet_length = length; +    tcp_conn->con.last_packet_sent = 0;  } -/* return 1 on success. +/** return 1 on success.   * return 0 if no data received.   * return -1 on failure (connection refused).   */ -static int proxy_socks5_read_connection_response(const Logger *logger, TCP_Client_Connection *tcp_conn) +static int proxy_socks5_read_connection_response(const Logger *logger, const TCP_Client_Connection *tcp_conn)  {      if (net_family_is_ipv4(tcp_conn->ip_port.ip.family)) {          uint8_t data[4 + sizeof(IP4) + sizeof(uint16_t)]; -        int ret = read_TCP_packet(logger, tcp_conn->sock, data, sizeof(data)); +        int ret = read_TCP_packet(logger, tcp_conn->con.sock, data, sizeof(data), &tcp_conn->con.ip_port);          if (ret == -1) {              return 0;          } -        if (data[0] == 5 && data[1] == 0) { +        if (data[0] == TCP_SOCKS5_PROXY_HS_VERSION_SOCKS5 && data[1] == TCP_SOCKS5_PROXY_HS_COMM_REQUEST_GRANTED) {              return 1;          }      } else {          uint8_t data[4 + sizeof(IP6) + sizeof(uint16_t)]; -        int ret = read_TCP_packet(logger, tcp_conn->sock, data, sizeof(data)); +        int ret = read_TCP_packet(logger, tcp_conn->con.sock, data, sizeof(data), &tcp_conn->con.ip_port);          if (ret == -1) {              return 0;          } -        if (data[0] == 5 && data[1] == 0) { +        if (data[0] == TCP_SOCKS5_PROXY_HS_VERSION_SOCKS5 && data[1] == TCP_SOCKS5_PROXY_HS_COMM_REQUEST_GRANTED) {              return 1;          }      } @@ -268,30 +268,30 @@ static int proxy_socks5_read_connection_response(const Logger *logger, TCP_Clien      return -1;  } -/* return 0 on success. +/** return 0 on success.   * return -1 on failure.   */  static int generate_handshake(TCP_Client_Connection *tcp_conn)  {      uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE];      crypto_new_keypair(plain, tcp_conn->temp_secret_key); -    random_nonce(tcp_conn->sent_nonce); -    memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, tcp_conn->sent_nonce, CRYPTO_NONCE_SIZE); -    memcpy(tcp_conn->last_packet, tcp_conn->self_public_key, CRYPTO_PUBLIC_KEY_SIZE); -    random_nonce(tcp_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE); -    int len = encrypt_data_symmetric(tcp_conn->shared_key, tcp_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE, plain, -                                     sizeof(plain), tcp_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); +    random_nonce(tcp_conn->con.sent_nonce); +    memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, tcp_conn->con.sent_nonce, CRYPTO_NONCE_SIZE); +    memcpy(tcp_conn->con.last_packet, tcp_conn->self_public_key, CRYPTO_PUBLIC_KEY_SIZE); +    random_nonce(tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE); +    int len = encrypt_data_symmetric(tcp_conn->con.shared_key, tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE, plain, +                                     sizeof(plain), tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);      if (len != sizeof(plain) + CRYPTO_MAC_SIZE) {          return -1;      } -    tcp_conn->last_packet_length = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + sizeof(plain) + CRYPTO_MAC_SIZE; -    tcp_conn->last_packet_sent = 0; +    tcp_conn->con.last_packet_length = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + sizeof(plain) + CRYPTO_MAC_SIZE; +    tcp_conn->con.last_packet_sent = 0;      return 0;  } -/* data must be of length TCP_SERVER_HANDSHAKE_SIZE +/** data must be of length TCP_SERVER_HANDSHAKE_SIZE   *   * return 0 on success.   * return -1 on failure. @@ -299,7 +299,7 @@ static int generate_handshake(TCP_Client_Connection *tcp_conn)  static int handle_handshake(TCP_Client_Connection *tcp_conn, const uint8_t *data)  {      uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE]; -    int len = decrypt_data_symmetric(tcp_conn->shared_key, data, data + CRYPTO_NONCE_SIZE, +    int len = decrypt_data_symmetric(tcp_conn->con.shared_key, data, data + CRYPTO_NONCE_SIZE,                                       TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, plain);      if (len != sizeof(plain)) { @@ -307,178 +307,21 @@ static int handle_handshake(TCP_Client_Connection *tcp_conn, const uint8_t *data      }      memcpy(tcp_conn->recv_nonce, plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_NONCE_SIZE); -    encrypt_precompute(plain, tcp_conn->temp_secret_key, tcp_conn->shared_key); +    encrypt_precompute(plain, tcp_conn->temp_secret_key, tcp_conn->con.shared_key);      crypto_memzero(tcp_conn->temp_secret_key, CRYPTO_SECRET_KEY_SIZE);      return 0;  } -/* return 0 if pending data was sent completely - * return -1 if it wasn't - */ -static int client_send_pending_data_nonpriority(TCP_Client_Connection *con) -{ -    if (con->last_packet_length == 0) { -        return 0; -    } - -    const uint16_t left = con->last_packet_length - con->last_packet_sent; -    const int len = net_send(con->sock, con->last_packet + con->last_packet_sent, left); - -    if (len <= 0) { -        return -1; -    } - -    if (len == left) { -        con->last_packet_length = 0; -        con->last_packet_sent = 0; -        return 0; -    } - -    con->last_packet_sent += len; -    return -1; -} - -/* return 0 if pending data was sent completely - * return -1 if it wasn't - */ -static int client_send_pending_data(TCP_Client_Connection *con) -{ -    /* finish sending current non-priority packet */ -    if (client_send_pending_data_nonpriority(con) == -1) { -        return -1; -    } - -    TCP_Priority_List *p = con->priority_queue_start; - -    while (p) { -        const uint16_t left = p->size - p->sent; -        const int len = net_send(con->sock, p->data + p->sent, left); - -        if (len != left) { -            if (len > 0) { -                p->sent += len; -            } - -            break; -        } - -        TCP_Priority_List *pp = p; -        p = p->next; -        free(pp); -    } - -    con->priority_queue_start = p; - -    if (!p) { -        con->priority_queue_end = nullptr; -        return 0; -    } - -    return -1; -} - -/* return 0 on failure (only if malloc fails) - * return 1 on success - */ -static bool client_add_priority(TCP_Client_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent) -{ -    TCP_Priority_List *p = con->priority_queue_end; -    TCP_Priority_List *new_list = (TCP_Priority_List *)malloc(sizeof(TCP_Priority_List) + size); - -    if (!new_list) { -        return 0; -    } - -    new_list->next = nullptr; -    new_list->size = size; -    new_list->sent = sent; -    memcpy(new_list->data, packet, size); - -    if (p) { -        p->next = new_list; -    } else { -        con->priority_queue_start = new_list; -    } - -    con->priority_queue_end = new_list; -    return 1; -} - -/* return 1 on success. +/** return 1 on success.   * return 0 if could not send packet.   * return -1 on failure (connection must be killed).   */ -static int write_packet_TCP_client_secure_connection(TCP_Client_Connection *con, const uint8_t *data, uint16_t length, -        bool priority) -{ -    if (length + CRYPTO_MAC_SIZE > MAX_PACKET_SIZE) { -        return -1; -    } - -    bool sendpriority = 1; - -    if (client_send_pending_data(con) == -1) { -        if (priority) { -            sendpriority = 0; -        } else { -            return 0; -        } -    } - -    VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE); - -    uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE); -    memcpy(packet, &c_length, sizeof(uint16_t)); -    int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); - -    if ((unsigned int)len != (SIZEOF_VLA(packet) - sizeof(uint16_t))) { -        return -1; -    } - -    if (priority) { -        len = sendpriority ? net_send(con->sock, packet, SIZEOF_VLA(packet)) : 0; - -        if (len <= 0) { -            len = 0; -        } - -        increment_nonce(con->sent_nonce); - -        if ((unsigned int)len == SIZEOF_VLA(packet)) { -            return 1; -        } - -        return client_add_priority(con, packet, SIZEOF_VLA(packet), len); -    } - -    len = net_send(con->sock, packet, SIZEOF_VLA(packet)); - -    if (len <= 0) { -        return 0; -    } - -    increment_nonce(con->sent_nonce); - -    if ((unsigned int)len == SIZEOF_VLA(packet)) { -        return 1; -    } - -    memcpy(con->last_packet, packet, SIZEOF_VLA(packet)); -    con->last_packet_length = SIZEOF_VLA(packet); -    con->last_packet_sent = len; -    return 1; -} - -/* return 1 on success. - * return 0 if could not send packet. - * return -1 on failure (connection must be killed). - */ -int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key) +int send_routing_request(const Logger *logger, TCP_Client_Connection *con, const uint8_t *public_key)  {      uint8_t packet[1 + CRYPTO_PUBLIC_KEY_SIZE];      packet[0] = TCP_PACKET_ROUTING_REQUEST;      memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE); -    return write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1); +    return write_packet_TCP_secure_connection(logger, &con->con, packet, sizeof(packet), 1);  }  void routing_response_handler(TCP_Client_Connection *con, tcp_routing_response_cb *response_callback, void *object) @@ -493,14 +336,14 @@ void routing_status_handler(TCP_Client_Connection *con, tcp_routing_status_cb *s      con->status_callback_object = object;  } -static int tcp_send_ping_response(TCP_Client_Connection *con); -static int tcp_send_ping_request(TCP_Client_Connection *con); +static int tcp_send_ping_response(const Logger *logger, TCP_Client_Connection *con); +static int tcp_send_ping_request(const Logger *logger, TCP_Client_Connection *con); -/* return 1 on success. +/** return 1 on success.   * return 0 if could not send packet.   * return -1 on failure.   */ -int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length) +int send_data(const Logger *logger, TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length)  {      if (con_id >= NUM_CLIENT_CONNECTIONS) {          return -1; @@ -510,21 +353,22 @@ int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, u          return -1;      } -    if (tcp_send_ping_response(con) == 0 || tcp_send_ping_request(con) == 0) { +    if (tcp_send_ping_response(logger, con) == 0 || tcp_send_ping_request(logger, con) == 0) {          return 0;      }      VLA(uint8_t, packet, 1 + length);      packet[0] = con_id + NUM_RESERVED_PORTS;      memcpy(packet + 1, data, length); -    return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0); +    return write_packet_TCP_secure_connection(logger, &con->con, packet, SIZEOF_VLA(packet), 0);  } -/* return 1 on success. +/** return 1 on success.   * return 0 if could not send packet.   * return -1 on failure.   */ -int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data, uint16_t length) +int send_oob_packet(const Logger *logger, TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data, +                    uint16_t length)  {      if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) {          return -1; @@ -534,11 +378,11 @@ int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const      packet[0] = TCP_PACKET_OOB_SEND;      memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);      memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length); -    return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0); +    return write_packet_TCP_secure_connection(logger, &con->con, packet, SIZEOF_VLA(packet), 0);  } -/* Set the number that will be used as an argument in the callbacks related to con_id. +/** Set the number that will be used as an argument in the callbacks related to con_id.   *   * When not set by this function, the number is -1.   * @@ -571,23 +415,23 @@ void oob_data_handler(TCP_Client_Connection *con, tcp_oob_data_cb *oob_data_call      con->oob_data_callback_object = object;  } -/* return 1 on success. +/** return 1 on success.   * return 0 if could not send packet.   * return -1 on failure (connection must be killed).   */ -static int client_send_disconnect_notification(TCP_Client_Connection *con, uint8_t id) +static int client_send_disconnect_notification(const Logger *logger, TCP_Client_Connection *con, uint8_t id)  {      uint8_t packet[1 + 1];      packet[0] = TCP_PACKET_DISCONNECT_NOTIFICATION;      packet[1] = id; -    return write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1); +    return write_packet_TCP_secure_connection(logger, &con->con, packet, sizeof(packet), 1);  } -/* return 1 on success. +/** return 1 on success.   * return 0 if could not send packet.   * return -1 on failure (connection must be killed).   */ -static int tcp_send_ping_request(TCP_Client_Connection *con) +static int tcp_send_ping_request(const Logger *logger, TCP_Client_Connection *con)  {      if (!con->ping_request_id) {          return 1; @@ -596,7 +440,7 @@ static int tcp_send_ping_request(TCP_Client_Connection *con)      uint8_t packet[1 + sizeof(uint64_t)];      packet[0] = TCP_PACKET_PING;      memcpy(packet + 1, &con->ping_request_id, sizeof(uint64_t)); -    const int ret = write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1); +    const int ret = write_packet_TCP_secure_connection(logger, &con->con, packet, sizeof(packet), 1);      if (ret == 1) {          con->ping_request_id = 0; @@ -605,11 +449,11 @@ static int tcp_send_ping_request(TCP_Client_Connection *con)      return ret;  } -/* return 1 on success. +/** return 1 on success.   * return 0 if could not send packet.   * return -1 on failure (connection must be killed).   */ -static int tcp_send_ping_response(TCP_Client_Connection *con) +static int tcp_send_ping_response(const Logger *logger, TCP_Client_Connection *con)  {      if (!con->ping_response_id) {          return 1; @@ -618,7 +462,7 @@ static int tcp_send_ping_response(TCP_Client_Connection *con)      uint8_t packet[1 + sizeof(uint64_t)];      packet[0] = TCP_PACKET_PONG;      memcpy(packet + 1, &con->ping_response_id, sizeof(uint64_t)); -    const int ret = write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1); +    const int ret = write_packet_TCP_secure_connection(logger, &con->con, packet, sizeof(packet), 1);      if (ret == 1) {          con->ping_response_id = 0; @@ -627,11 +471,11 @@ static int tcp_send_ping_response(TCP_Client_Connection *con)      return ret;  } -/* return 1 on success. +/** return 1 on success.   * return 0 if could not send packet.   * return -1 on failure (connection must be killed).   */ -int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id) +int send_disconnect_request(const Logger *logger, TCP_Client_Connection *con, uint8_t con_id)  {      if (con_id >= NUM_CLIENT_CONNECTIONS) {          return -1; @@ -639,19 +483,19 @@ int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id)      con->connections[con_id].status = 0;      con->connections[con_id].number = 0; -    return client_send_disconnect_notification(con, con_id + NUM_RESERVED_PORTS); +    return client_send_disconnect_notification(logger, con, con_id + NUM_RESERVED_PORTS);  } -/* return 1 on success. +/** return 1 on success.   * return 0 if could not send packet.   * return -1 on failure (connection must be killed).   */ -int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t length) +int send_onion_request(const Logger *logger, TCP_Client_Connection *con, const uint8_t *data, uint16_t length)  {      VLA(uint8_t, packet, 1 + length);      packet[0] = TCP_PACKET_ONION_REQUEST;      memcpy(packet + 1, data, length); -    return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0); +    return write_packet_TCP_secure_connection(logger, &con->con, packet, SIZEOF_VLA(packet), 0);  }  void onion_response_handler(TCP_Client_Connection *con, tcp_onion_response_cb *onion_callback, void *object) @@ -660,27 +504,27 @@ void onion_response_handler(TCP_Client_Connection *con, tcp_onion_response_cb *o      con->onion_callback_object = object;  } -/* Create new TCP connection to ip_port/public_key +/** Create new TCP connection to ip_port/public_key   */ -TCP_Client_Connection *new_TCP_connection(const Mono_Time *mono_time, IP_Port ip_port, const uint8_t *public_key, -        const uint8_t *self_public_key, const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info) +TCP_Client_Connection *new_TCP_connection(const Logger *logger, const Mono_Time *mono_time, const IP_Port *ip_port, +        const uint8_t *public_key, const uint8_t *self_public_key, const uint8_t *self_secret_key, +        const TCP_Proxy_Info *proxy_info)  {      if (networking_at_startup() != 0) {          return nullptr;      } -    if (!net_family_is_ipv4(ip_port.ip.family) && !net_family_is_ipv6(ip_port.ip.family)) { +    if (!net_family_is_ipv4(ip_port->ip.family) && !net_family_is_ipv6(ip_port->ip.family)) {          return nullptr;      } -    TCP_Proxy_Info default_proxyinfo; +    const TCP_Proxy_Info default_proxyinfo = {0};      if (proxy_info == nullptr) { -        default_proxyinfo.proxy_type = TCP_PROXY_NONE;          proxy_info = &default_proxyinfo;      } -    Family family = ip_port.ip.family; +    Family family = ip_port->ip.family;      if (proxy_info->proxy_type != TCP_PROXY_NONE) {          family = proxy_info->ip_port.ip.family; @@ -697,37 +541,40 @@ TCP_Client_Connection *new_TCP_connection(const Mono_Time *mono_time, IP_Port ip          return nullptr;      } -    if (!(set_socket_nonblock(sock) && connect_sock_to(sock, ip_port, proxy_info))) { +    if (!(set_socket_nonblock(sock) && connect_sock_to(logger, sock, ip_port, proxy_info))) {          kill_sock(sock);          return nullptr;      } -    TCP_Client_Connection *temp = (TCP_Client_Connection *)calloc(sizeof(TCP_Client_Connection), 1); +    TCP_Client_Connection *temp = (TCP_Client_Connection *)calloc(1, sizeof(TCP_Client_Connection));      if (temp == nullptr) {          kill_sock(sock);          return nullptr;      } -    temp->sock = sock; +    temp->con.sock = sock; +    temp->con.ip_port = *ip_port;      memcpy(temp->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);      memcpy(temp->self_public_key, self_public_key, CRYPTO_PUBLIC_KEY_SIZE); -    encrypt_precompute(temp->public_key, self_secret_key, temp->shared_key); -    temp->ip_port = ip_port; +    encrypt_precompute(temp->public_key, self_secret_key, temp->con.shared_key); +    temp->ip_port = *ip_port;      temp->proxy_info = *proxy_info;      switch (proxy_info->proxy_type) { -        case TCP_PROXY_HTTP: +        case TCP_PROXY_HTTP: {              temp->status = TCP_CLIENT_PROXY_HTTP_CONNECTING;              proxy_http_generate_connection_request(temp);              break; +        } -        case TCP_PROXY_SOCKS5: +        case TCP_PROXY_SOCKS5: {              temp->status = TCP_CLIENT_PROXY_SOCKS5_CONNECTING; -            proxy_socks5_generate_handshake(temp); +            proxy_socks5_generate_greetings(temp);              break; +        } -        case TCP_PROXY_NONE: +        case TCP_PROXY_NONE: {              temp->status = TCP_CLIENT_CONNECTING;              if (generate_handshake(temp) == -1) { @@ -737,6 +584,7 @@ TCP_Client_Connection *new_TCP_connection(const Mono_Time *mono_time, IP_Port ip              }              break; +        }      }      temp->kill_at = mono_time_get(mono_time) + TCP_CONNECTION_TIMEOUT; @@ -744,10 +592,11 @@ TCP_Client_Connection *new_TCP_connection(const Mono_Time *mono_time, IP_Port ip      return temp;  } -/* return 0 on success +/** return 0 on success   * return -1 on failure   */ -static int handle_TCP_client_packet(TCP_Client_Connection *conn, const uint8_t *data, uint16_t length, void *userdata) +static int handle_TCP_client_packet(const Logger *logger, TCP_Client_Connection *conn, const uint8_t *data, +                                    uint16_t length, void *userdata)  {      if (length <= 1) {          return -1; @@ -842,7 +691,7 @@ static int handle_TCP_client_packet(TCP_Client_Connection *conn, const uint8_t *              uint64_t ping_id;              memcpy(&ping_id, data + 1, sizeof(uint64_t));              conn->ping_response_id = ping_id; -            tcp_send_ping_response(conn); +            tcp_send_ping_response(logger, conn);              return 0;          } @@ -903,8 +752,8 @@ static int handle_TCP_client_packet(TCP_Client_Connection *conn, const uint8_t *  static bool tcp_process_packet(const Logger *logger, TCP_Client_Connection *conn, void *userdata)  {      uint8_t packet[MAX_PACKET_SIZE]; -    const int len = read_packet_TCP_secure_connection(logger, conn->sock, &conn->next_packet_length, conn->shared_key, -                    conn->recv_nonce, packet, sizeof(packet)); +    const int len = read_packet_TCP_secure_connection(logger, conn->con.sock, &conn->next_packet_length, +                    conn->con.shared_key, conn->recv_nonce, packet, sizeof(packet), &conn->ip_port);      if (len == 0) {          return false; @@ -915,7 +764,7 @@ static bool tcp_process_packet(const Logger *logger, TCP_Client_Connection *conn          return false;      } -    if (handle_TCP_client_packet(conn, packet, len, userdata) == -1) { +    if (handle_TCP_client_packet(logger, conn, packet, len, userdata) == -1) {          conn->status = TCP_CLIENT_DISCONNECTED;          return false;      } @@ -926,9 +775,9 @@ static bool tcp_process_packet(const Logger *logger, TCP_Client_Connection *conn  static int do_confirmed_TCP(const Logger *logger, TCP_Client_Connection *conn, const Mono_Time *mono_time,                              void *userdata)  { -    client_send_pending_data(conn); -    tcp_send_ping_response(conn); -    tcp_send_ping_request(conn); +    send_pending_data(logger, &conn->con); +    tcp_send_ping_response(logger, conn); +    tcp_send_ping_request(logger, conn);      if (mono_time_is_timeout(mono_time, conn->last_pinged, TCP_PING_FREQUENCY)) {          uint64_t ping_id = random_u64(); @@ -939,7 +788,7 @@ static int do_confirmed_TCP(const Logger *logger, TCP_Client_Connection *conn, c          conn->ping_request_id = ping_id;          conn->ping_id = ping_id; -        tcp_send_ping_request(conn); +        tcp_send_ping_request(logger, conn);          conn->last_pinged = mono_time_get(mono_time);      } @@ -956,17 +805,17 @@ static int do_confirmed_TCP(const Logger *logger, TCP_Client_Connection *conn, c      return 0;  } -/* Run the TCP connection +/** Run the TCP connection   */ -void do_TCP_connection(const Logger *logger, Mono_Time *mono_time, TCP_Client_Connection *tcp_connection, -                       void *userdata) +void do_TCP_connection(const Logger *logger, const Mono_Time *mono_time, +                       TCP_Client_Connection *tcp_connection, void *userdata)  {      if (tcp_connection->status == TCP_CLIENT_DISCONNECTED) {          return;      }      if (tcp_connection->status == TCP_CLIENT_PROXY_HTTP_CONNECTING) { -        if (client_send_pending_data(tcp_connection) == 0) { +        if (send_pending_data(logger, &tcp_connection->con) == 0) {              int ret = proxy_http_read_connection_response(logger, tcp_connection);              if (ret == -1) { @@ -982,7 +831,7 @@ void do_TCP_connection(const Logger *logger, Mono_Time *mono_time, TCP_Client_Co      }      if (tcp_connection->status == TCP_CLIENT_PROXY_SOCKS5_CONNECTING) { -        if (client_send_pending_data(tcp_connection) == 0) { +        if (send_pending_data(logger, &tcp_connection->con) == 0) {              int ret = socks5_read_handshake_response(logger, tcp_connection);              if (ret == -1) { @@ -998,7 +847,7 @@ void do_TCP_connection(const Logger *logger, Mono_Time *mono_time, TCP_Client_Co      }      if (tcp_connection->status == TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED) { -        if (client_send_pending_data(tcp_connection) == 0) { +        if (send_pending_data(logger, &tcp_connection->con) == 0) {              int ret = proxy_socks5_read_connection_response(logger, tcp_connection);              if (ret == -1) { @@ -1014,14 +863,14 @@ void do_TCP_connection(const Logger *logger, Mono_Time *mono_time, TCP_Client_Co      }      if (tcp_connection->status == TCP_CLIENT_CONNECTING) { -        if (client_send_pending_data(tcp_connection) == 0) { +        if (send_pending_data(logger, &tcp_connection->con) == 0) {              tcp_connection->status = TCP_CLIENT_UNCONFIRMED;          }      }      if (tcp_connection->status == TCP_CLIENT_UNCONFIRMED) {          uint8_t data[TCP_SERVER_HANDSHAKE_SIZE]; -        int len = read_TCP_packet(logger, tcp_connection->sock, data, sizeof(data)); +        int len = read_TCP_packet(logger, tcp_connection->con.sock, data, sizeof(data), &tcp_connection->con.ip_port);          if (sizeof(data) == len) {              if (handle_handshake(tcp_connection, data) == 0) { @@ -1043,7 +892,7 @@ void do_TCP_connection(const Logger *logger, Mono_Time *mono_time, TCP_Client_Co      }  } -/* Kill the TCP connection +/** Kill the TCP connection   */  void kill_TCP_connection(TCP_Client_Connection *tcp_connection)  { @@ -1051,8 +900,8 @@ void kill_TCP_connection(TCP_Client_Connection *tcp_connection)          return;      } -    wipe_priority_list(tcp_connection->priority_queue_start); -    kill_sock(tcp_connection->sock); +    wipe_priority_list(tcp_connection->con.priority_queue_start); +    kill_sock(tcp_connection->con.sock);      crypto_memzero(tcp_connection, sizeof(TCP_Client_Connection));      free(tcp_connection);  } diff --git a/protocols/Tox/libtox/src/toxcore/TCP_client.h b/protocols/Tox/libtox/src/toxcore/TCP_client.h index ed4304cb00..dd170d7849 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_client.h +++ b/protocols/Tox/libtox/src/toxcore/TCP_client.h @@ -3,14 +3,14 @@   * Copyright © 2014 Tox project.   */ -/* +/**   * Implementation of the TCP relay client part of Tox.   */  #ifndef C_TOXCORE_TOXCORE_TCP_CLIENT_H  #define C_TOXCORE_TOXCORE_TCP_CLIENT_H -#include "TCP_server.h" -#include "crypto_core.h" +#include "mono_time.h" +#include "network.h"  #define TCP_CONNECTION_TIMEOUT 10 @@ -47,47 +47,48 @@ uint32_t tcp_con_custom_uint(const TCP_Client_Connection *con);  void tcp_con_set_custom_object(TCP_Client_Connection *con, void *object);  void tcp_con_set_custom_uint(TCP_Client_Connection *con, uint32_t value); -/* Create new TCP connection to ip_port/public_key +/** Create new TCP connection to ip_port/public_key   */ -TCP_Client_Connection *new_TCP_connection(const Mono_Time *mono_time, IP_Port ip_port, const uint8_t *public_key, -        const uint8_t *self_public_key, const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info); +TCP_Client_Connection *new_TCP_connection(const Logger *logger, const Mono_Time *mono_time, const IP_Port *ip_port, +        const uint8_t *public_key, const uint8_t *self_public_key, const uint8_t *self_secret_key, +        const TCP_Proxy_Info *proxy_info); -/* Run the TCP connection +/** Run the TCP connection   */ -void do_TCP_connection(const Logger *logger, Mono_Time *mono_time, TCP_Client_Connection *tcp_connection, -                       void *userdata); +void do_TCP_connection(const Logger *logger, const Mono_Time *mono_time, +                       TCP_Client_Connection *tcp_connection, void *userdata); -/* Kill the TCP connection +/** Kill the TCP connection   */  void kill_TCP_connection(TCP_Client_Connection *tcp_connection);  typedef int tcp_onion_response_cb(void *object, const uint8_t *data, uint16_t length, void *userdata); -/* return 1 on success. +/** return 1 on success.   * return 0 if could not send packet.   * return -1 on failure (connection must be killed).   */ -int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t length); +int send_onion_request(const Logger *logger, TCP_Client_Connection *con, const uint8_t *data, uint16_t length);  void onion_response_handler(TCP_Client_Connection *con, tcp_onion_response_cb *onion_callback, void *object);  typedef int tcp_routing_response_cb(void *object, uint8_t connection_id, const uint8_t *public_key);  typedef int tcp_routing_status_cb(void *object, uint32_t number, uint8_t connection_id, uint8_t status); -/* return 1 on success. +/** return 1 on success.   * return 0 if could not send packet.   * return -1 on failure (connection must be killed).   */ -int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key); +int send_routing_request(const Logger *logger, TCP_Client_Connection *con, const uint8_t *public_key);  void routing_response_handler(TCP_Client_Connection *con, tcp_routing_response_cb *response_callback, void *object);  void routing_status_handler(TCP_Client_Connection *con, tcp_routing_status_cb *status_callback, void *object); -/* return 1 on success. +/** return 1 on success.   * return 0 if could not send packet.   * return -1 on failure (connection must be killed).   */ -int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id); +int send_disconnect_request(const Logger *logger, TCP_Client_Connection *con, uint8_t con_id); -/* Set the number that will be used as an argument in the callbacks related to con_id. +/** Set the number that will be used as an argument in the callbacks related to con_id.   *   * When not set by this function, the number is -1.   * @@ -99,21 +100,22 @@ int set_tcp_connection_number(TCP_Client_Connection *con, uint8_t con_id, uint32  typedef int tcp_routing_data_cb(void *object, uint32_t number, uint8_t connection_id, const uint8_t *data,                                  uint16_t length, void *userdata); -/* return 1 on success. +/** return 1 on success.   * return 0 if could not send packet.   * return -1 on failure.   */ -int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length); +int send_data(const Logger *logger, TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length);  void routing_data_handler(TCP_Client_Connection *con, tcp_routing_data_cb *data_callback, void *object);  typedef int tcp_oob_data_cb(void *object, const uint8_t *public_key, const uint8_t *data, uint16_t length,                              void *userdata); -/* return 1 on success. +/** return 1 on success.   * return 0 if could not send packet.   * return -1 on failure.   */ -int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data, uint16_t length); +int send_oob_packet(const Logger *logger, TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data, +                    uint16_t length);  void oob_data_handler(TCP_Client_Connection *con, tcp_oob_data_cb *oob_data_callback, void *object); diff --git a/protocols/Tox/libtox/src/toxcore/TCP_common.c b/protocols/Tox/libtox/src/toxcore/TCP_common.c new file mode 100644 index 0000000000..237df20f89 --- /dev/null +++ b/protocols/Tox/libtox/src/toxcore/TCP_common.c @@ -0,0 +1,291 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2016-2018 The TokTok team. + * Copyright © 2014 Tox project. + */ + +#include "TCP_common.h" + +#include <stdlib.h> +#include <string.h> + +void wipe_priority_list(TCP_Priority_List *p) +{ +    while (p) { +        TCP_Priority_List *pp = p; +        p = p->next; +        free(pp->data); +        free(pp); +    } +} + +/** return 0 if pending data was sent completely + * return -1 if it wasn't + */ +int send_pending_data_nonpriority(const Logger *logger, TCP_Connection *con) +{ +    if (con->last_packet_length == 0) { +        return 0; +    } + +    const uint16_t left = con->last_packet_length - con->last_packet_sent; +    const int len = net_send(logger, con->sock, con->last_packet + con->last_packet_sent, left, &con->ip_port); + +    if (len <= 0) { +        return -1; +    } + +    if (len == left) { +        con->last_packet_length = 0; +        con->last_packet_sent = 0; +        return 0; +    } + +    con->last_packet_sent += len; +    return -1; +} + +/** return 0 if pending data was sent completely + * return -1 if it wasn't + */ +int send_pending_data(const Logger *logger, TCP_Connection *con) +{ +    /* finish sending current non-priority packet */ +    if (send_pending_data_nonpriority(logger, con) == -1) { +        return -1; +    } + +    TCP_Priority_List *p = con->priority_queue_start; + +    while (p) { +        const uint16_t left = p->size - p->sent; +        const int len = net_send(logger, con->sock, p->data + p->sent, left, &con->ip_port); + +        if (len != left) { +            if (len > 0) { +                p->sent += len; +            } + +            break; +        } + +        TCP_Priority_List *pp = p; +        p = p->next; +        free(pp->data); +        free(pp); +    } + +    con->priority_queue_start = p; + +    if (!p) { +        con->priority_queue_end = nullptr; +        return 0; +    } + +    return -1; +} + +/** return 0 on failure (only if calloc fails) + * return 1 on success + */ +bool add_priority(TCP_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent) +{ +    TCP_Priority_List *p = con->priority_queue_end; +    TCP_Priority_List *new_list = (TCP_Priority_List *)calloc(1, sizeof(TCP_Priority_List)); + +    if (new_list == nullptr) { +        return false; +    } + +    new_list->next = nullptr; +    new_list->size = size; +    new_list->sent = sent; +    new_list->data = (uint8_t *)malloc(size); + +    if (new_list->data == nullptr) { +        free(new_list); +        return false; +    } + +    memcpy(new_list->data, packet, size); + +    if (p) { +        p->next = new_list; +    } else { +        con->priority_queue_start = new_list; +    } + +    con->priority_queue_end = new_list; +    return true; +} + +/** return 1 on success. + * return 0 if could not send packet. + * return -1 on failure (connection must be killed). + */ +int write_packet_TCP_secure_connection(const Logger *logger, TCP_Connection *con, const uint8_t *data, uint16_t length, +                                       bool priority) +{ +    if (length + CRYPTO_MAC_SIZE > MAX_PACKET_SIZE) { +        return -1; +    } + +    bool sendpriority = 1; + +    if (send_pending_data(logger, con) == -1) { +        if (priority) { +            sendpriority = 0; +        } else { +            return 0; +        } +    } + +    VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE); + +    uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE); +    memcpy(packet, &c_length, sizeof(uint16_t)); +    int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); + +    if ((unsigned int)len != (SIZEOF_VLA(packet) - sizeof(uint16_t))) { +        return -1; +    } + +    if (priority) { +        len = sendpriority ? net_send(logger, con->sock, packet, SIZEOF_VLA(packet), &con->ip_port) : 0; + +        if (len <= 0) { +            len = 0; +        } + +        increment_nonce(con->sent_nonce); + +        if ((unsigned int)len == SIZEOF_VLA(packet)) { +            return 1; +        } + +        return add_priority(con, packet, SIZEOF_VLA(packet), len); +    } + +    len = net_send(logger, con->sock, packet, SIZEOF_VLA(packet), &con->ip_port); + +    if (len <= 0) { +        return 0; +    } + +    increment_nonce(con->sent_nonce); + +    if ((unsigned int)len == SIZEOF_VLA(packet)) { +        return 1; +    } + +    memcpy(con->last_packet, packet, SIZEOF_VLA(packet)); +    con->last_packet_length = SIZEOF_VLA(packet); +    con->last_packet_sent = len; +    return 1; +} + +/** Read length bytes from socket. + * + * return length on success + * return -1 on failure/no data in buffer. + */ +int read_TCP_packet(const Logger *logger, Socket sock, uint8_t *data, uint16_t length, const IP_Port *ip_port) +{ +    const uint16_t count = net_socket_data_recv_buffer(sock); + +    if (count < length) { +        LOGGER_TRACE(logger, "recv buffer has %d bytes, but requested %d bytes", count, length); +        return -1; +    } + +    const int len = net_recv(logger, sock, data, length, ip_port); + +    if (len != length) { +        LOGGER_ERROR(logger, "FAIL recv packet"); +        return -1; +    } + +    return len; +} + +/** Read the next two bytes in TCP stream then convert them to + * length (host byte order). + * + * return length on success + * return 0 if nothing has been read from socket. + * return -1 on failure. + */ +static uint16_t read_TCP_length(const Logger *logger, Socket sock, const IP_Port *ip_port) +{ +    const uint16_t count = net_socket_data_recv_buffer(sock); + +    if (count >= sizeof(uint16_t)) { +        uint8_t length_buf[sizeof(uint16_t)]; +        const int len = net_recv(logger, sock, length_buf, sizeof(length_buf), ip_port); + +        if (len != sizeof(uint16_t)) { +            LOGGER_ERROR(logger, "FAIL recv packet"); +            return 0; +        } + +        uint16_t length; +        net_unpack_u16(length_buf, &length); + +        if (length > MAX_PACKET_SIZE) { +            LOGGER_WARNING(logger, "TCP packet too large: %d > %d", length, MAX_PACKET_SIZE); +            return -1; +        } + +        return length; +    } + +    return 0; +} + +/** return length of received packet on success. + * return 0 if could not read any packet. + * return -1 on failure (connection must be killed). + */ +int read_packet_TCP_secure_connection(const Logger *logger, Socket sock, uint16_t *next_packet_length, +                                      const uint8_t *shared_key, uint8_t *recv_nonce, uint8_t *data, +                                      uint16_t max_len, const IP_Port *ip_port) +{ +    if (*next_packet_length == 0) { +        const uint16_t len = read_TCP_length(logger, sock, ip_port); + +        if (len == (uint16_t) -1) { +            return -1; +        } + +        if (len == 0) { +            return 0; +        } + +        *next_packet_length = len; +    } + +    if (max_len + CRYPTO_MAC_SIZE < *next_packet_length) { +        LOGGER_DEBUG(logger, "packet too large"); +        return -1; +    } + +    VLA(uint8_t, data_encrypted, *next_packet_length); +    const int len_packet = read_TCP_packet(logger, sock, data_encrypted, *next_packet_length, ip_port); + +    if (len_packet != *next_packet_length) { +        LOGGER_WARNING(logger, "invalid packet length: %d, expected %d", len_packet, *next_packet_length); +        return 0; +    } + +    *next_packet_length = 0; + +    const int len = decrypt_data_symmetric(shared_key, recv_nonce, data_encrypted, len_packet, data); + +    if (len + CRYPTO_MAC_SIZE != len_packet) { +        LOGGER_WARNING(logger, "decrypted length %d does not match expected length %d", len + CRYPTO_MAC_SIZE, len_packet); +        return -1; +    } + +    increment_nonce(recv_nonce); + +    return len; +} diff --git a/protocols/Tox/libtox/src/toxcore/TCP_common.h b/protocols/Tox/libtox/src/toxcore/TCP_common.h new file mode 100644 index 0000000000..92c0a9a3d9 --- /dev/null +++ b/protocols/Tox/libtox/src/toxcore/TCP_common.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2016-2018 The TokTok team. + * Copyright © 2014 Tox project. + */ + +#ifndef C_TOXCORE_TOXCORE_TCP_COMMON_H +#define C_TOXCORE_TOXCORE_TCP_COMMON_H + +#include "crypto_core.h" +#include "network.h" + +typedef struct TCP_Priority_List TCP_Priority_List; +struct TCP_Priority_List { +    TCP_Priority_List *next; +    uint16_t size; +    uint16_t sent; +    uint8_t *data; +}; + +void wipe_priority_list(TCP_Priority_List *p); + +#define NUM_RESERVED_PORTS 16 +#define NUM_CLIENT_CONNECTIONS (256 - NUM_RESERVED_PORTS) + +#define TCP_PACKET_ROUTING_REQUEST  0 +#define TCP_PACKET_ROUTING_RESPONSE 1 +#define TCP_PACKET_CONNECTION_NOTIFICATION 2 +#define TCP_PACKET_DISCONNECT_NOTIFICATION 3 +#define TCP_PACKET_PING 4 +#define TCP_PACKET_PONG 5 +#define TCP_PACKET_OOB_SEND 6 +#define TCP_PACKET_OOB_RECV 7 +#define TCP_PACKET_ONION_REQUEST  8 +#define TCP_PACKET_ONION_RESPONSE 9 + +#define TCP_HANDSHAKE_PLAIN_SIZE (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE) +#define TCP_SERVER_HANDSHAKE_SIZE (CRYPTO_NONCE_SIZE + TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE) +#define TCP_CLIENT_HANDSHAKE_SIZE (CRYPTO_PUBLIC_KEY_SIZE + TCP_SERVER_HANDSHAKE_SIZE) +#define TCP_MAX_OOB_DATA_LENGTH 1024 + +/** frequency to ping connected nodes and timeout in seconds */ +#define TCP_PING_FREQUENCY 30 +#define TCP_PING_TIMEOUT 10 + +#define MAX_PACKET_SIZE 2048 + +typedef struct TCP_Connection { +    Socket sock; +    IP_Port ip_port;  // for debugging. +    uint8_t sent_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of sent packets. */ +    uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; +    uint8_t last_packet[2 + MAX_PACKET_SIZE]; +    uint16_t last_packet_length; +    uint16_t last_packet_sent; + +    TCP_Priority_List *priority_queue_start; +    TCP_Priority_List *priority_queue_end; +} TCP_Connection; + +/** return 0 if pending data was sent completely + * return -1 if it wasn't + */ +int send_pending_data_nonpriority(const Logger *logger, TCP_Connection *con); + +/** return 0 if pending data was sent completely + * return -1 if it wasn't + */ +int send_pending_data(const Logger *logger, TCP_Connection *con); + +/** return 0 on failure (only if calloc fails) + * return 1 on success + */ +bool add_priority(TCP_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent); + +/** return 1 on success. + * return 0 if could not send packet. + * return -1 on failure (connection must be killed). + */ +int write_packet_TCP_secure_connection(const Logger *logger, TCP_Connection *con, const uint8_t *data, uint16_t length, +                                       bool priority); + +/** Read length bytes from socket. + * + * return length on success + * return -1 on failure/no data in buffer. + */ +int read_TCP_packet(const Logger *logger, Socket sock, uint8_t *data, uint16_t length, const IP_Port *ip_port); + +/** return length of received packet on success. + * return 0 if could not read any packet. + * return -1 on failure (connection must be killed). + */ +int read_packet_TCP_secure_connection(const Logger *logger, Socket sock, uint16_t *next_packet_length, +                                      const uint8_t *shared_key, uint8_t *recv_nonce, uint8_t *data, +                                      uint16_t max_len, const IP_Port *ip_port); + +#endif diff --git a/protocols/Tox/libtox/src/toxcore/TCP_connection.c b/protocols/Tox/libtox/src/toxcore/TCP_connection.c index ac933cc3cc..4b406097c2 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_connection.c +++ b/protocols/Tox/libtox/src/toxcore/TCP_connection.c @@ -3,24 +3,21 @@   * Copyright © 2015 Tox project.   */ -/* +/**   * Handles TCP relay connections between two Tox clients.   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -  #include "TCP_connection.h"  #include <assert.h>  #include <stdlib.h>  #include <string.h> +#include "TCP_client.h"  #include "mono_time.h"  #include "util.h" -  struct TCP_Connections { +    const Logger *logger;      Mono_Time *mono_time;      DHT *dht; @@ -55,7 +52,12 @@ const uint8_t *tcp_connections_public_key(const TCP_Connections *tcp_c)  } -/* Set the size of the array to num. +uint32_t tcp_connections_count(const TCP_Connections *tcp_c) +{ +    return tcp_c->tcp_connections_length; +} + +/** Set the size of the array to num.   *   *  return -1 if realloc fails.   *  return 0 if it succeeds. @@ -140,16 +142,14 @@ static bool tcp_connections_number_is_valid(const TCP_Connections *tcp_c, int tc      return true;  } -/* Create a new empty connection. +/** Create a new empty connection.   *   * return -1 on failure.   * return connections_number on success.   */  static int create_connection(TCP_Connections *tcp_c)  { -    uint32_t i; - -    for (i = 0; i < tcp_c->connections_length; ++i) { +    for (uint32_t i = 0; i < tcp_c->connections_length; ++i) {          if (tcp_c->connections[i].status == TCP_CONN_NONE) {              return i;          } @@ -166,7 +166,7 @@ static int create_connection(TCP_Connections *tcp_c)      return id;  } -/* Create a new empty tcp connection. +/** Create a new empty tcp connection.   *   * return -1 on failure.   * return tcp_connections_number on success. @@ -190,7 +190,7 @@ static int create_tcp_connection(TCP_Connections *tcp_c)      return id;  } -/* Wipe a connection. +/** Wipe a connection.   *   * return -1 on failure.   * return 0 on success. @@ -218,7 +218,7 @@ static int wipe_connection(TCP_Connections *tcp_c, int connections_number)      return 0;  } -/* Wipe a connection. +/** Wipe a connection.   *   * return -1 on failure.   * return 0 on success. @@ -265,14 +265,35 @@ static TCP_con *get_tcp_connection(const TCP_Connections *tcp_c, int tcp_connect      return &tcp_c->tcp_connections[tcp_connections_number];  } -/* Send a packet to the TCP connection. +/** Returns the number of connected TCP relays */ +uint32_t tcp_connected_relays_count(const TCP_Connections *tcp_c) +{ +    uint32_t count = 0; + +    for (uint32_t i = 0; i < tcp_connections_count(tcp_c); ++i) { +        const TCP_con *tcp_con = get_tcp_connection(tcp_c, i); + +        if (tcp_con == nullptr) { +            continue; +        } + +        if (tcp_con->status == TCP_CONN_CONNECTED) { +            ++count; +        } +    } + +    return count; +} + +/** Send a packet to the TCP connection.   *   * return -1 on failure.   * return 0 on success.   */ -int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, const uint8_t *packet, uint16_t length) +int send_packet_tcp_connection(const TCP_Connections *tcp_c, int connections_number, const uint8_t *packet, +                               uint16_t length)  { -    TCP_Connection_to *con_to = get_connection(tcp_c, connections_number); +    const TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);      if (!con_to) {          return -1; @@ -280,12 +301,11 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c      // TODO(irungentoo): detect and kill bad relays.      // TODO(irungentoo): thread safety? -    unsigned int i;      int ret = -1;      bool limit_reached = 0; -    for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { +    for (unsigned int i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {          uint32_t tcp_con_num = con_to->connections[i].tcp_connection;          uint8_t status = con_to->connections[i].status;          uint8_t connection_id = con_to->connections[i].connection_id; @@ -298,7 +318,7 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c                  continue;              } -            ret = send_data(tcp_con->connection, connection_id, packet, length); +            ret = send_data(tcp_c->logger, tcp_con->connection, connection_id, packet, length);              if (ret == 0) {                  limit_reached = 1; @@ -318,7 +338,7 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c          ret = 0;          /* Send oob packets to all relays tied to the connection. */ -        for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { +        for (unsigned int i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {              uint32_t tcp_con_num = con_to->connections[i].tcp_connection;              uint8_t status = con_to->connections[i].status; @@ -330,7 +350,7 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c                      continue;                  } -                if (send_oob_packet(tcp_con->connection, con_to->public_key, packet, length) == 1) { +                if (send_oob_packet(tcp_c->logger, tcp_con->connection, con_to->public_key, packet, length) == 1) {                      ret += 1;                  }              } @@ -346,7 +366,7 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c      return -1;  } -/* Return a random TCP connection number for use in send_tcp_onion_request. +/** Return a random TCP connection number for use in send_tcp_onion_request.   *   * TODO(irungentoo): This number is just the index of an array that the elements   * can change without warning. @@ -354,12 +374,12 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c   * return TCP connection number on success.   * return -1 on failure.   */ -int get_random_tcp_onion_conn_number(TCP_Connections *tcp_c) +int get_random_tcp_onion_conn_number(const TCP_Connections *tcp_c)  {      const uint32_t r = random_u32();      for (uint32_t i = 0; i < tcp_c->tcp_connections_length; ++i) { -        uint32_t index = ((i + r) % tcp_c->tcp_connections_length); +        uint32_t index = (i + r) % tcp_c->tcp_connections_length;          if (tcp_c->tcp_connections[index].onion && tcp_c->tcp_connections[index].status == TCP_CONN_CONNECTED) {              return index; @@ -369,7 +389,7 @@ int get_random_tcp_onion_conn_number(TCP_Connections *tcp_c)      return -1;  } -/* Send an onion packet via the TCP relay corresponding to tcp_connections_number. +/** Send an onion packet via the TCP relay corresponding to tcp_connections_number.   *   * return 0 on success.   * return -1 on failure. @@ -382,7 +402,8 @@ int tcp_send_onion_request(TCP_Connections *tcp_c, uint32_t tcp_connections_numb      }      if (tcp_c->tcp_connections[tcp_connections_number].status == TCP_CONN_CONNECTED) { -        int ret = send_onion_request(tcp_c->tcp_connections[tcp_connections_number].connection, data, length); +        const int ret = send_onion_request(tcp_c->logger, tcp_c->tcp_connections[tcp_connections_number].connection, data, +                                           length);          if (ret == 1) {              return 0; @@ -392,13 +413,13 @@ int tcp_send_onion_request(TCP_Connections *tcp_c, uint32_t tcp_connections_numb      return -1;  } -/* Send an oob packet via the TCP relay corresponding to tcp_connections_number. +/** Send an oob packet via the TCP relay corresponding to tcp_connections_number.   *   * return 0 on success.   * return -1 on failure.   */ -int tcp_send_oob_packet(TCP_Connections *tcp_c, unsigned int tcp_connections_number, const uint8_t *public_key, -                        const uint8_t *packet, uint16_t length) +int tcp_send_oob_packet(const TCP_Connections *tcp_c, unsigned int tcp_connections_number, +                        const uint8_t *public_key, const uint8_t *packet, uint16_t length)  {      TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); @@ -410,7 +431,7 @@ int tcp_send_oob_packet(TCP_Connections *tcp_c, unsigned int tcp_connections_num          return -1;      } -    int ret = send_oob_packet(tcp_con->connection, public_key, packet, length); +    const int ret = send_oob_packet(tcp_c->logger, tcp_con->connection, public_key, packet, length);      if (ret == 1) {          return 0; @@ -419,7 +440,26 @@ int tcp_send_oob_packet(TCP_Connections *tcp_c, unsigned int tcp_connections_num      return -1;  } -/* Set the callback for TCP data packets. +static int find_tcp_connection_relay(const TCP_Connections *tcp_c, const uint8_t *relay_pk); + +/** Send an oob packet via the TCP relay corresponding to relay_pk. + * + * return 0 on success. + * return -1 on failure. + */ +int tcp_send_oob_packet_using_relay(const TCP_Connections *tcp_c, const uint8_t *relay_pk, const uint8_t *public_key, +                                    const uint8_t *packet, uint16_t length) +{ +    int tcp_con_number = find_tcp_connection_relay(tcp_c, relay_pk); + +    if (tcp_con_number < 0) { +        return -1; +    } + +    return tcp_send_oob_packet(tcp_c, tcp_con_number, public_key, packet, length); +} + +/** Set the callback for TCP data packets.   */  void set_packet_tcp_connection_callback(TCP_Connections *tcp_c, tcp_data_cb *tcp_data_callback, void *object)  { @@ -427,7 +467,7 @@ void set_packet_tcp_connection_callback(TCP_Connections *tcp_c, tcp_data_cb *tcp      tcp_c->tcp_data_callback_object = object;  } -/* Set the callback for TCP onion packets. +/** Set the callback for TCP oob data packets.   */  void set_oob_packet_tcp_connection_callback(TCP_Connections *tcp_c, tcp_oob_cb *tcp_oob_callback, void *object)  { @@ -435,7 +475,7 @@ void set_oob_packet_tcp_connection_callback(TCP_Connections *tcp_c, tcp_oob_cb *      tcp_c->tcp_oob_callback_object = object;  } -/* Set the callback for TCP oob data packets. +/** Set the callback for TCP onion packets.   */  void set_onion_packet_tcp_connection_callback(TCP_Connections *tcp_c, tcp_onion_cb *tcp_onion_callback, void *object)  { @@ -443,18 +483,15 @@ void set_onion_packet_tcp_connection_callback(TCP_Connections *tcp_c, tcp_onion_      tcp_c->tcp_onion_callback_object = object;  } - -/* Find the TCP connection with public_key. +/** Find the TCP connection with public_key.   *   * return connections_number on success.   * return -1 on failure.   */ -static int find_tcp_connection_to(TCP_Connections *tcp_c, const uint8_t *public_key) +static int find_tcp_connection_to(const TCP_Connections *tcp_c, const uint8_t *public_key)  { -    unsigned int i; - -    for (i = 0; i < tcp_c->connections_length; ++i) { -        TCP_Connection_to *con_to = get_connection(tcp_c, i); +    for (unsigned int i = 0; i < tcp_c->connections_length; ++i) { +        const TCP_Connection_to *con_to = get_connection(tcp_c, i);          if (con_to) {              if (public_key_cmp(con_to->public_key, public_key) == 0) { @@ -466,15 +503,15 @@ static int find_tcp_connection_to(TCP_Connections *tcp_c, const uint8_t *public_      return -1;  } -/* Find the TCP connection to a relay with relay_pk. +/** Find the TCP connection to a relay with relay_pk.   *   * return connections_number on success.   * return -1 on failure.   */ -static int find_tcp_connection_relay(TCP_Connections *tcp_c, const uint8_t *relay_pk) +static int find_tcp_connection_relay(const TCP_Connections *tcp_c, const uint8_t *relay_pk)  {      for (uint32_t i = 0; i < tcp_c->tcp_connections_length; ++i) { -        TCP_con *tcp_con = get_tcp_connection(tcp_c, i); +        const TCP_con *tcp_con = get_tcp_connection(tcp_c, i);          if (tcp_con) {              if (tcp_con->status == TCP_CONN_SLEEPING) { @@ -492,7 +529,7 @@ static int find_tcp_connection_relay(TCP_Connections *tcp_c, const uint8_t *rela      return -1;  } -/* Create a new TCP connection to public_key. +/** Create a new TCP connection to public_key.   *   * public_key must be the counterpart to the secret key that the other peer used with new_tcp_connections().   * @@ -522,20 +559,18 @@ int new_tcp_connection_to(TCP_Connections *tcp_c, const uint8_t *public_key, int      return connections_number;  } -/* return 0 on success. +/** return 0 on success.   * return -1 on failure.   */  int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number)  { -    TCP_Connection_to *con_to = get_connection(tcp_c, connections_number); +    const TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);      if (!con_to) {          return -1;      } -    unsigned int i; - -    for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { +    for (unsigned int i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {          if (con_to->connections[i].tcp_connection) {              unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;              TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); @@ -545,7 +580,7 @@ int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number)              }              if (tcp_con->status == TCP_CONN_CONNECTED) { -                send_disconnect_request(tcp_con->connection, con_to->connections[i].connection_id); +                send_disconnect_request(tcp_c->logger, tcp_con->connection, con_to->connections[i].connection_id);              }              if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) { @@ -561,7 +596,7 @@ int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number)      return wipe_connection(tcp_c, connections_number);  } -/* Set connection status. +/** Set connection status.   *   * status of 1 means we are using the connection.   * status of 0 means we are not using it. @@ -571,7 +606,7 @@ int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number)   * return 0 on success.   * return -1 on failure.   */ -int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number, bool status) +int set_tcp_connection_to_status(const TCP_Connections *tcp_c, int connections_number, bool status)  {      TCP_Connection_to *con_to = get_connection(tcp_c, connections_number); @@ -585,9 +620,7 @@ int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number,              return -1;          } -        unsigned int i; - -        for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { +        for (unsigned int i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {              if (con_to->connections[i].tcp_connection) {                  unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;                  TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); @@ -611,9 +644,7 @@ int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number,          return -1;      } -    unsigned int i; - -    for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { +    for (unsigned int i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {          if (con_to->connections[i].tcp_connection) {              unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;              TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); @@ -632,11 +663,9 @@ int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number,      return 0;  } -static bool tcp_connection_in_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number) +static bool tcp_connection_in_conn(const TCP_Connection_to *con_to, unsigned int tcp_connections_number)  { -    unsigned int i; - -    for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { +    for (unsigned int i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {          if (con_to->connections[i].tcp_connection == (tcp_connections_number + 1)) {              return 1;          } @@ -645,18 +674,16 @@ static bool tcp_connection_in_conn(TCP_Connection_to *con_to, unsigned int tcp_c      return 0;  } -/* return index on success. +/** return index on success.   * return -1 on failure.   */  static int add_tcp_connection_to_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number)  { -    unsigned int i; -      if (tcp_connection_in_conn(con_to, tcp_connections_number)) {          return -1;      } -    for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { +    for (unsigned int i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {          if (con_to->connections[i].tcp_connection == 0) {              con_to->connections[i].tcp_connection = tcp_connections_number + 1;              con_to->connections[i].status = TCP_CONNECTIONS_STATUS_NONE; @@ -668,14 +695,12 @@ static int add_tcp_connection_to_conn(TCP_Connection_to *con_to, unsigned int tc      return -1;  } -/* return index on success. +/** return index on success.   * return -1 on failure.   */  static int rm_tcp_connection_from_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number)  { -    unsigned int i; - -    for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { +    for (unsigned int i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {          if (con_to->connections[i].tcp_connection == (tcp_connections_number + 1)) {              con_to->connections[i].tcp_connection = 0;              con_to->connections[i].status = TCP_CONNECTIONS_STATUS_NONE; @@ -687,10 +712,10 @@ static int rm_tcp_connection_from_conn(TCP_Connection_to *con_to, unsigned int t      return -1;  } -/* return number of online connections on success. +/** return number of online connections on success.   * return -1 on failure.   */ -static unsigned int online_tcp_connection_from_conn(TCP_Connection_to *con_to) +static unsigned int online_tcp_connection_from_conn(const TCP_Connection_to *con_to)  {      unsigned int count = 0; @@ -705,15 +730,14 @@ static unsigned int online_tcp_connection_from_conn(TCP_Connection_to *con_to)      return count;  } -/* return index on success. +/** return index on success.   * return -1 on failure.   */  static int set_tcp_connection_status(TCP_Connection_to *con_to, unsigned int tcp_connections_number, -                                     unsigned int status, uint8_t connection_id) +                                     uint8_t status, +                                     uint8_t connection_id)  { -    unsigned int i; - -    for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { +    for (unsigned int i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {          if (con_to->connections[i].tcp_connection == (tcp_connections_number + 1)) {              if (con_to->connections[i].status == status) { @@ -729,12 +753,12 @@ static int set_tcp_connection_status(TCP_Connection_to *con_to, unsigned int tcp      return -1;  } -/* Kill a TCP relay connection. +/** Kill a TCP relay connection.   *   * return 0 on success.   * return -1 on failure.   */ -static int kill_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number) +int kill_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number)  {      TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); @@ -742,9 +766,7 @@ static int kill_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections          return -1;      } -    unsigned int i; - -    for (i = 0; i < tcp_c->connections_length; ++i) { +    for (unsigned int i = 0; i < tcp_c->connections_length; ++i) {          TCP_Connection_to *con_to = get_connection(tcp_c, i);          if (con_to) { @@ -777,7 +799,7 @@ static int reconnect_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connec      uint8_t relay_pk[CRYPTO_PUBLIC_KEY_SIZE];      memcpy(relay_pk, tcp_con_public_key(tcp_con->connection), CRYPTO_PUBLIC_KEY_SIZE);      kill_TCP_connection(tcp_con->connection); -    tcp_con->connection = new_TCP_connection(tcp_c->mono_time, ip_port, relay_pk, tcp_c->self_public_key, +    tcp_con->connection = new_TCP_connection(tcp_c->logger, tcp_c->mono_time, &ip_port, relay_pk, tcp_c->self_public_key,                            tcp_c->self_secret_key, &tcp_c->proxy_info);      if (!tcp_con->connection) { @@ -785,9 +807,7 @@ static int reconnect_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connec          return -1;      } -    unsigned int i; - -    for (i = 0; i < tcp_c->connections_length; ++i) { +    for (unsigned int i = 0; i < tcp_c->connections_length; ++i) {          TCP_Connection_to *con_to = get_connection(tcp_c, i);          if (con_to) { @@ -831,9 +851,7 @@ static int sleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connection      kill_TCP_connection(tcp_con->connection);      tcp_con->connection = nullptr; -    unsigned int i; - -    for (i = 0; i < tcp_c->connections_length; ++i) { +    for (unsigned int i = 0; i < tcp_c->connections_length; ++i) {          TCP_Connection_to *con_to = get_connection(tcp_c, i);          if (con_to) { @@ -867,8 +885,8 @@ static int unsleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connecti          return -1;      } -    tcp_con->connection = new_TCP_connection(tcp_c->mono_time, tcp_con->ip_port, tcp_con->relay_pk, tcp_c->self_public_key, -                          tcp_c->self_secret_key, &tcp_c->proxy_info); +    tcp_con->connection = new_TCP_connection(tcp_c->logger, tcp_c->mono_time, &tcp_con->ip_port, tcp_con->relay_pk, +                          tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info);      if (!tcp_con->connection) {          kill_tcp_relay_connection(tcp_c, tcp_connections_number); @@ -883,12 +901,13 @@ static int unsleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connecti      return 0;  } -/* Send a TCP routing request. +/** Send a TCP routing request.   *   * return 0 on success.   * return -1 on failure.   */ -static int send_tcp_relay_routing_request(TCP_Connections *tcp_c, int tcp_connections_number, uint8_t *public_key) +static int send_tcp_relay_routing_request(const TCP_Connections *tcp_c, int tcp_connections_number, +        const uint8_t *public_key)  {      TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); @@ -900,7 +919,7 @@ static int send_tcp_relay_routing_request(TCP_Connections *tcp_c, int tcp_connec          return -1;      } -    if (send_routing_request(tcp_con->connection, public_key) != 1) { +    if (send_routing_request(tcp_c->logger, tcp_con->connection, public_key) != 1) {          return -1;      } @@ -910,7 +929,7 @@ static int send_tcp_relay_routing_request(TCP_Connections *tcp_c, int tcp_connec  static int tcp_response_callback(void *object, uint8_t connection_id, const uint8_t *public_key)  {      TCP_Client_Connection *tcp_client_con = (TCP_Client_Connection *)object; -    TCP_Connections *tcp_c = (TCP_Connections *)tcp_con_custom_object(tcp_client_con); +    const TCP_Connections *tcp_c = (const TCP_Connections *)tcp_con_custom_object(tcp_client_con);      unsigned int tcp_connections_number = tcp_con_custom_uint(tcp_client_con);      TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); @@ -942,8 +961,8 @@ static int tcp_response_callback(void *object, uint8_t connection_id, const uint  static int tcp_status_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t status)  { -    TCP_Client_Connection *tcp_client_con = (TCP_Client_Connection *)object; -    TCP_Connections *tcp_c = (TCP_Connections *)tcp_con_custom_object(tcp_client_con); +    const TCP_Client_Connection *tcp_client_con = (const TCP_Client_Connection *)object; +    const TCP_Connections *tcp_c = (const TCP_Connections *)tcp_con_custom_object(tcp_client_con);      unsigned int tcp_connections_number = tcp_con_custom_uint(tcp_client_con);      TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); @@ -985,17 +1004,17 @@ static int tcp_conn_data_callback(void *object, uint32_t number, uint8_t connect          return -1;      } -    TCP_Client_Connection *tcp_client_con = (TCP_Client_Connection *)object; +    const TCP_Client_Connection *tcp_client_con = (TCP_Client_Connection *)object;      TCP_Connections *tcp_c = (TCP_Connections *)tcp_con_custom_object(tcp_client_con);      unsigned int tcp_connections_number = tcp_con_custom_uint(tcp_client_con); -    TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); +    const TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);      if (!tcp_con) {          return -1;      } -    TCP_Connection_to *con_to = get_connection(tcp_c, number); +    const TCP_Connection_to *con_to = get_connection(tcp_c, number);      if (!con_to) {          return -1; @@ -1015,11 +1034,11 @@ static int tcp_conn_oob_callback(void *object, const uint8_t *public_key, const          return -1;      } -    TCP_Client_Connection *tcp_client_con = (TCP_Client_Connection *)object; +    const TCP_Client_Connection *tcp_client_con = (const TCP_Client_Connection *)object;      TCP_Connections *tcp_c = (TCP_Connections *)tcp_con_custom_object(tcp_client_con);      unsigned int tcp_connections_number = tcp_con_custom_uint(tcp_client_con); -    TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); +    const TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);      if (!tcp_con) {          return -1; @@ -1028,7 +1047,7 @@ static int tcp_conn_oob_callback(void *object, const uint8_t *public_key, const      /* TODO(irungentoo): optimize */      int connections_number = find_tcp_connection_to(tcp_c, public_key); -    TCP_Connection_to *con_to = get_connection(tcp_c, connections_number); +    const TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);      if (con_to && tcp_connection_in_conn(con_to, tcp_connections_number)) {          return tcp_conn_data_callback(object, connections_number, 0, data, length, userdata); @@ -1052,7 +1071,7 @@ static int tcp_onion_callback(void *object, const uint8_t *data, uint16_t length      return 0;  } -/* Set callbacks for the TCP relay connection. +/** Set callbacks for the TCP relay connection.   *   * return 0 on success.   * return -1 on failure. @@ -1118,15 +1137,17 @@ static int tcp_relay_on_online(TCP_Connections *tcp_c, int tcp_connections_numbe      return 0;  } -static int add_tcp_relay_instance(TCP_Connections *tcp_c, IP_Port ip_port, const uint8_t *relay_pk) +static int add_tcp_relay_instance(TCP_Connections *tcp_c, const IP_Port *ip_port, const uint8_t *relay_pk)  { -    if (net_family_is_tcp_ipv4(ip_port.ip.family)) { -        ip_port.ip.family = net_family_ipv4; -    } else if (net_family_is_tcp_ipv6(ip_port.ip.family)) { -        ip_port.ip.family = net_family_ipv6; +    IP_Port ipp_copy = *ip_port; + +    if (net_family_is_tcp_ipv4(ipp_copy.ip.family)) { +        ipp_copy.ip.family = net_family_ipv4; +    } else if (net_family_is_tcp_ipv6(ipp_copy.ip.family)) { +        ipp_copy.ip.family = net_family_ipv6;      } -    if (!net_family_is_ipv4(ip_port.ip.family) && !net_family_is_ipv6(ip_port.ip.family)) { +    if (!net_family_is_ipv4(ipp_copy.ip.family) && !net_family_is_ipv6(ipp_copy.ip.family)) {          return -1;      } @@ -1138,7 +1159,7 @@ static int add_tcp_relay_instance(TCP_Connections *tcp_c, IP_Port ip_port, const      TCP_con *tcp_con = &tcp_c->tcp_connections[tcp_connections_number]; -    tcp_con->connection = new_TCP_connection(tcp_c->mono_time, ip_port, relay_pk, tcp_c->self_public_key, +    tcp_con->connection = new_TCP_connection(tcp_c->logger, tcp_c->mono_time, &ipp_copy, relay_pk, tcp_c->self_public_key,                            tcp_c->self_secret_key, &tcp_c->proxy_info);      if (!tcp_con->connection) { @@ -1150,12 +1171,12 @@ static int add_tcp_relay_instance(TCP_Connections *tcp_c, IP_Port ip_port, const      return tcp_connections_number;  } -/* Add a TCP relay to the TCP_Connections instance. +/** Add a TCP relay to the TCP_Connections instance.   *   * return 0 on success.   * return -1 on failure.   */ -int add_tcp_relay_global(TCP_Connections *tcp_c, IP_Port ip_port, const uint8_t *relay_pk) +int add_tcp_relay_global(TCP_Connections *tcp_c, const IP_Port *ip_port, const uint8_t *relay_pk)  {      int tcp_connections_number = find_tcp_connection_relay(tcp_c, relay_pk); @@ -1170,12 +1191,15 @@ int add_tcp_relay_global(TCP_Connections *tcp_c, IP_Port ip_port, const uint8_t      return 0;  } -/* Add a TCP relay tied to a connection. +/** Add a TCP relay tied to a connection. + * + * NOTE: This can only be used during the tcp_oob_callback.   *   * return 0 on success.   * return -1 on failure.   */ -int add_tcp_number_relay_connection(TCP_Connections *tcp_c, int connections_number, unsigned int tcp_connections_number) +int add_tcp_number_relay_connection(const TCP_Connections *tcp_c, int connections_number, +                                    unsigned int tcp_connections_number)  {      TCP_Connection_to *con_to = get_connection(tcp_c, connections_number); @@ -1206,14 +1230,15 @@ int add_tcp_number_relay_connection(TCP_Connections *tcp_c, int connections_numb      return 0;  } -/* Add a TCP relay tied to a connection. +/** Add a TCP relay tied to a connection.   *   * This should be called with the same relay by two peers who want to create a TCP connection with each other.   *   * return 0 on success.   * return -1 on failure.   */ -int add_tcp_relay_connection(TCP_Connections *tcp_c, int connections_number, IP_Port ip_port, const uint8_t *relay_pk) +int add_tcp_relay_connection(TCP_Connections *tcp_c, int connections_number, const IP_Port *ip_port, +                             const uint8_t *relay_pk)  {      TCP_Connection_to *con_to = get_connection(tcp_c, connections_number); @@ -1233,7 +1258,7 @@ int add_tcp_relay_connection(TCP_Connections *tcp_c, int connections_number, IP_      tcp_connections_number = add_tcp_relay_instance(tcp_c, ip_port, relay_pk); -    TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); +    const TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);      if (!tcp_con) {          return -1; @@ -1246,12 +1271,12 @@ int add_tcp_relay_connection(TCP_Connections *tcp_c, int connections_number, IP_      return 0;  } -/* return number of online tcp relays tied to the connection on success. +/** return number of online tcp relays tied to the connection on success.   * return 0 on failure.   */ -unsigned int tcp_connection_to_online_tcp_relays(TCP_Connections *tcp_c, int connections_number) +unsigned int tcp_connection_to_online_tcp_relays(const TCP_Connections *tcp_c, int connections_number)  { -    TCP_Connection_to *con_to = get_connection(tcp_c, connections_number); +    const TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);      if (!con_to) {          return 0; @@ -1260,19 +1285,19 @@ unsigned int tcp_connection_to_online_tcp_relays(TCP_Connections *tcp_c, int con      return online_tcp_connection_from_conn(con_to);  } -/* Copy a maximum of max_num TCP relays we are connected to to tcp_relays. +/** Copy a maximum of max_num TCP relays we are connected to to tcp_relays.   * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6.   *   * return number of relays copied to tcp_relays on success.   * return 0 on failure.   */ -uint32_t tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_relays, uint16_t max_num) +uint32_t tcp_copy_connected_relays(const TCP_Connections *tcp_c, Node_format *tcp_relays, uint16_t max_num)  {      const uint32_t r = random_u32();      uint32_t copied = 0;      for (uint32_t i = 0; (i < tcp_c->tcp_connections_length) && (copied < max_num); ++i) { -        TCP_con *tcp_con = get_tcp_connection(tcp_c, (i + r) % tcp_c->tcp_connections_length); +        const TCP_con *tcp_con = get_tcp_connection(tcp_c, (i + r) % tcp_c->tcp_connections_length);          if (!tcp_con) {              continue; @@ -1297,7 +1322,7 @@ uint32_t tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_rela      return copied;  } -/* Set if we want TCP_connection to allocate some connection for onion use. +/** Set if we want TCP_connection to allocate some connection for onion use.   *   * If status is 1, allocate some connections. if status is 0, don't.   * @@ -1363,14 +1388,15 @@ int set_tcp_onion_status(TCP_Connections *tcp_c, bool status)      return 0;  } -/* Returns a new TCP_Connections object associated with the secret_key. +/** Returns a new TCP_Connections object associated with the secret_key.   *   * In order for others to connect to this instance new_tcp_connection_to() must be called with the   * public_key associated with secret_key.   *   * Returns NULL on failure.   */ -TCP_Connections *new_tcp_connections(Mono_Time *mono_time, const uint8_t *secret_key, TCP_Proxy_Info *proxy_info) +TCP_Connections *new_tcp_connections(const Logger *logger, Mono_Time *mono_time, const uint8_t *secret_key, +                                     const TCP_Proxy_Info *proxy_info)  {      if (secret_key == nullptr) {          return nullptr; @@ -1382,6 +1408,7 @@ TCP_Connections *new_tcp_connections(Mono_Time *mono_time, const uint8_t *secret          return nullptr;      } +    temp->logger = logger;      temp->mono_time = mono_time;      memcpy(temp->self_secret_key, secret_key, CRYPTO_SECRET_KEY_SIZE); @@ -1423,7 +1450,8 @@ static void do_tcp_conns(const Logger *logger, TCP_Connections *tcp_c, void *use                  tcp_relay_on_online(tcp_c, i);              } -            if (tcp_con->status == TCP_CONN_CONNECTED && !tcp_con->onion && tcp_con->lock_count +            if (tcp_con->status == TCP_CONN_CONNECTED +                    && !tcp_con->onion && tcp_con->lock_count                      && tcp_con->lock_count == tcp_con->sleep_count                      && mono_time_is_timeout(tcp_c->mono_time, tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) {                  sleep_tcp_relay_connection(tcp_c, i); @@ -1438,42 +1466,36 @@ static void do_tcp_conns(const Logger *logger, TCP_Connections *tcp_c, void *use  static void kill_nonused_tcp(TCP_Connections *tcp_c)  { -    if (tcp_c->tcp_connections_length == 0) { +    if (tcp_c->tcp_connections_length <= RECOMMENDED_FRIEND_TCP_CONNECTIONS) {          return;      } -    uint32_t num_online = 0; -    uint32_t num_kill = 0; -    VLA(unsigned int, to_kill, tcp_c->tcp_connections_length); - -    for (uint32_t i = 0; i < tcp_c->tcp_connections_length; ++i) { -        TCP_con *tcp_con = get_tcp_connection(tcp_c, i); - -        if (tcp_con) { -            if (tcp_con->status == TCP_CONN_CONNECTED) { -                if (!tcp_con->onion && !tcp_con->lock_count -                        && mono_time_is_timeout(tcp_c->mono_time, tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) { -                    to_kill[num_kill] = i; -                    ++num_kill; -                } - -                ++num_online; -            } -        } -    } +    const uint32_t num_online = tcp_connected_relays_count(tcp_c);      if (num_online <= RECOMMENDED_FRIEND_TCP_CONNECTIONS) {          return;      } -    uint32_t n = num_online - RECOMMENDED_FRIEND_TCP_CONNECTIONS; +    const uint32_t max_kill_count = num_online - RECOMMENDED_FRIEND_TCP_CONNECTIONS; +    uint32_t kill_count = 0; -    if (n < num_kill) { -        num_kill = n; -    } +    for (uint32_t i = 0; i < tcp_c->tcp_connections_length && kill_count < max_kill_count; ++i) { +        const TCP_con *tcp_con = get_tcp_connection(tcp_c, i); + +        if (tcp_con == nullptr) { +            continue; +        } + +        if (tcp_con->status == TCP_CONN_CONNECTED) { +            if (tcp_con->onion || tcp_con->lock_count) {  // connection is in use so we skip it +                continue; +            } -    for (uint32_t i = 0; i < num_kill; ++i) { -        kill_tcp_relay_connection(tcp_c, to_kill[i]); +            if (mono_time_is_timeout(tcp_c->mono_time, tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) { +                kill_tcp_relay_connection(tcp_c, i); +                ++kill_count; +            } +        }      }  } @@ -1489,6 +1511,8 @@ void kill_tcp_connections(TCP_Connections *tcp_c)          kill_TCP_connection(tcp_c->tcp_connections[i].connection);      } +    crypto_memzero(tcp_c->self_secret_key, sizeof(tcp_c->self_secret_key)); +      free(tcp_c->tcp_connections);      free(tcp_c->connections);      free(tcp_c); diff --git a/protocols/Tox/libtox/src/toxcore/TCP_connection.h b/protocols/Tox/libtox/src/toxcore/TCP_connection.h index 0ae3304541..84890b98d7 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_connection.h +++ b/protocols/Tox/libtox/src/toxcore/TCP_connection.h @@ -3,21 +3,25 @@   * Copyright © 2015 Tox project.   */ -/* +/**   * Handles TCP relay connections between two Tox clients.   */  #ifndef C_TOXCORE_TOXCORE_TCP_CONNECTION_H  #define C_TOXCORE_TOXCORE_TCP_CONNECTION_H +#include "DHT.h"  // for Node_format  #include "TCP_client.h" +#include "TCP_common.h" + +#include <stdbool.h>  #define TCP_CONN_NONE 0  #define TCP_CONN_VALID 1 -/* NOTE: only used by TCP_con */ +/** NOTE: only used by TCP_con */  #define TCP_CONN_CONNECTED 2 -/* Connection is not connected but can be quickly reconnected in case it is needed. */ +/** Connection is not connected but can be quickly reconnected in case it is needed. */  #define TCP_CONN_SLEEPING 3  #define TCP_CONNECTIONS_STATUS_NONE 0 @@ -26,20 +30,20 @@  #define MAX_FRIEND_TCP_CONNECTIONS 6 -/* Time until connection to friend gets killed (if it doesn't get locked within that time) */ +/** Time until connection to friend gets killed (if it doesn't get locked within that time) */  #define TCP_CONNECTION_ANNOUNCE_TIMEOUT TCP_CONNECTION_TIMEOUT -/* The amount of recommended connections for each friend +/** The amount of recommended connections for each friend   * NOTE: Must be at most (MAX_FRIEND_TCP_CONNECTIONS / 2) */  #define RECOMMENDED_FRIEND_TCP_CONNECTIONS (MAX_FRIEND_TCP_CONNECTIONS / 2) -/* Number of TCP connections used for onion purposes. */ +/** Number of TCP connections used for onion purposes. */  #define NUM_ONION_TCP_CONNECTIONS RECOMMENDED_FRIEND_TCP_CONNECTIONS  typedef struct TCP_Conn_to {      uint32_t tcp_connection; -    unsigned int status; -    unsigned int connection_id; +    uint8_t status; +    uint8_t connection_id;  } TCP_Conn_to;  typedef struct TCP_Connection_to { @@ -69,14 +73,20 @@ typedef struct TCP_Connections TCP_Connections;  const uint8_t *tcp_connections_public_key(const TCP_Connections *tcp_c); -/* Send a packet to the TCP connection. +uint32_t tcp_connections_count(const TCP_Connections *tcp_c); + +/** Returns the number of connected TCP relays */ +uint32_t tcp_connected_relays_count(const TCP_Connections *tcp_c); + +/** Send a packet to the TCP connection.   *   * return -1 on failure.   * return 0 on success.   */ -int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, const uint8_t *packet, uint16_t length); +int send_packet_tcp_connection(const TCP_Connections *tcp_c, int connections_number, const uint8_t *packet, +                               uint16_t length); -/* Return a random TCP connection number for use in send_tcp_onion_request. +/** Return a random TCP connection number for use in send_tcp_onion_request.   *   * TODO(irungentoo): This number is just the index of an array that the elements   * can change without warning. @@ -84,9 +94,9 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c   * return TCP connection number on success.   * return -1 on failure.   */ -int get_random_tcp_onion_conn_number(TCP_Connections *tcp_c); +int get_random_tcp_onion_conn_number(const TCP_Connections *tcp_c); -/* Send an onion packet via the TCP relay corresponding to tcp_connections_number. +/** Send an onion packet via the TCP relay corresponding to tcp_connections_number.   *   * return 0 on success.   * return -1 on failure. @@ -94,7 +104,7 @@ int get_random_tcp_onion_conn_number(TCP_Connections *tcp_c);  int tcp_send_onion_request(TCP_Connections *tcp_c, unsigned int tcp_connections_number, const uint8_t *data,                             uint16_t length); -/* Set if we want TCP_connection to allocate some connection for onion use. +/** Set if we want TCP_connection to allocate some connection for onion use.   *   * If status is 1, allocate some connections. if status is 0, don't.   * @@ -103,34 +113,37 @@ int tcp_send_onion_request(TCP_Connections *tcp_c, unsigned int tcp_connections_   */  int set_tcp_onion_status(TCP_Connections *tcp_c, bool status); -/* Send an oob packet via the TCP relay corresponding to tcp_connections_number. +/** Send an oob packet via the TCP relay corresponding to tcp_connections_number.   *   * return 0 on success.   * return -1 on failure.   */ -int tcp_send_oob_packet(TCP_Connections *tcp_c, unsigned int tcp_connections_number, const uint8_t *public_key, +int tcp_send_oob_packet(const TCP_Connections *tcp_c, unsigned int tcp_connections_number, const uint8_t *public_key,                          const uint8_t *packet, uint16_t length);  typedef int tcp_data_cb(void *object, int id, const uint8_t *data, uint16_t length, void *userdata); -/* Set the callback for TCP data packets. +int tcp_send_oob_packet_using_relay(const TCP_Connections *tcp_c, const uint8_t *relay_pk, const uint8_t *public_key, +                                    const uint8_t *packet, uint16_t length); + +/** Set the callback for TCP data packets.   */  void set_packet_tcp_connection_callback(TCP_Connections *tcp_c, tcp_data_cb *tcp_data_callback, void *object);  typedef int tcp_onion_cb(void *object, const uint8_t *data, uint16_t length, void *userdata); -/* Set the callback for TCP onion packets. +/** Set the callback for TCP onion packets.   */  void set_onion_packet_tcp_connection_callback(TCP_Connections *tcp_c, tcp_onion_cb *tcp_onion_callback, void *object);  typedef int tcp_oob_cb(void *object, const uint8_t *public_key, unsigned int tcp_connections_number,                         const uint8_t *data, uint16_t length, void *userdata); -/* Set the callback for TCP oob data packets. +/** Set the callback for TCP oob data packets.   */  void set_oob_packet_tcp_connection_callback(TCP_Connections *tcp_c, tcp_oob_cb *tcp_oob_callback, void *object); -/* Create a new TCP connection to public_key. +/** Create a new TCP connection to public_key.   *   * public_key must be the counterpart to the secret key that the other peer used with new_tcp_connections().   * @@ -141,12 +154,12 @@ void set_oob_packet_tcp_connection_callback(TCP_Connections *tcp_c, tcp_oob_cb *   */  int new_tcp_connection_to(TCP_Connections *tcp_c, const uint8_t *public_key, int id); -/* return 0 on success. +/** return 0 on success.   * return -1 on failure.   */  int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number); -/* Set connection status. +/** Set connection status.   *   * status of 1 means we are using the connection.   * status of 0 means we are not using it. @@ -156,59 +169,61 @@ int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number);   * return 0 on success.   * return -1 on failure.   */ -int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number, bool status); +int set_tcp_connection_to_status(const TCP_Connections *tcp_c, int connections_number, bool status); -/* return number of online tcp relays tied to the connection on success. +/** return number of online tcp relays tied to the connection on success.   * return 0 on failure.   */ -unsigned int tcp_connection_to_online_tcp_relays(TCP_Connections *tcp_c, int connections_number); +unsigned int tcp_connection_to_online_tcp_relays(const TCP_Connections *tcp_c, int connections_number); -/* Add a TCP relay tied to a connection. +/** Add a TCP relay tied to a connection.   *   * NOTE: This can only be used during the tcp_oob_callback.   *   * return 0 on success.   * return -1 on failure.   */ -int add_tcp_number_relay_connection(TCP_Connections *tcp_c, int connections_number, +int add_tcp_number_relay_connection(const TCP_Connections *tcp_c, int connections_number,                                      unsigned int tcp_connections_number); -/* Add a TCP relay tied to a connection. +/** Add a TCP relay tied to a connection.   *   * This should be called with the same relay by two peers who want to create a TCP connection with each other.   *   * return 0 on success.   * return -1 on failure.   */ -int add_tcp_relay_connection(TCP_Connections *tcp_c, int connections_number, IP_Port ip_port, const uint8_t *relay_pk); +int add_tcp_relay_connection(TCP_Connections *tcp_c, int connections_number, const IP_Port *ip_port, +                             const uint8_t *relay_pk); -/* Add a TCP relay to the instance. +/** Add a TCP relay to the TCP_Connections instance.   *   * return 0 on success.   * return -1 on failure.   */ -int add_tcp_relay_global(TCP_Connections *tcp_c, IP_Port ip_port, const uint8_t *relay_pk); +int add_tcp_relay_global(TCP_Connections *tcp_c, const IP_Port *ip_port, const uint8_t *relay_pk); -/* Copy a maximum of max_num TCP relays we are connected to to tcp_relays. +/** Copy a maximum of max_num TCP relays we are connected to to tcp_relays.   * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6.   *   * return number of relays copied to tcp_relays on success.   * return 0 on failure.   */ -uint32_t tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_relays, uint16_t max_num); +uint32_t tcp_copy_connected_relays(const TCP_Connections *tcp_c, Node_format *tcp_relays, uint16_t max_num); -/* Returns a new TCP_Connections object associated with the secret_key. +/** Returns a new TCP_Connections object associated with the secret_key.   *   * In order for others to connect to this instance new_tcp_connection_to() must be called with the   * public_key associated with secret_key.   *   * Returns NULL on failure.   */ -TCP_Connections *new_tcp_connections(Mono_Time *mono_time, const uint8_t *secret_key, TCP_Proxy_Info *proxy_info); +TCP_Connections *new_tcp_connections(const Logger *logger, Mono_Time *mono_time, const uint8_t *secret_key, +                                     const TCP_Proxy_Info *proxy_info); -void do_tcp_connections(const Logger *logger, TCP_Connections *tcp_c, void *userdata); +int kill_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number); +void do_tcp_connections(const Logger *logger, TCP_Connections *tcp_c, void *userdata);  void kill_tcp_connections(TCP_Connections *tcp_c);  #endif - diff --git a/protocols/Tox/libtox/src/toxcore/TCP_server.c b/protocols/Tox/libtox/src/toxcore/TCP_server.c index 79a9e560c3..4f7fe12121 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_server.c +++ b/protocols/Tox/libtox/src/toxcore/TCP_server.c @@ -3,13 +3,9 @@   * Copyright © 2014 Tox project.   */ -/* +/**   * Implementation of the TCP relay server part of Tox.   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -  #include "TCP_server.h"  #include <stdlib.h> @@ -23,6 +19,8 @@  #include <unistd.h>  #endif +#include "TCP_common.h" +#include "list.h"  #include "mono_time.h"  #include "util.h" @@ -42,20 +40,13 @@ typedef struct TCP_Secure_Conn {  } TCP_Secure_Conn;  typedef struct TCP_Secure_Connection { -    Socket sock; +    TCP_Connection con; +      uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];      uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of received packets. */ -    uint8_t sent_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of sent packets. */ -    uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];      uint16_t next_packet_length;      TCP_Secure_Conn connections[NUM_CLIENT_CONNECTIONS]; -    uint8_t last_packet[2 + MAX_PACKET_SIZE];      uint8_t status; -    uint16_t last_packet_length; -    uint16_t last_packet_sent; - -    TCP_Priority_List *priority_queue_start; -    TCP_Priority_List *priority_queue_end;      uint64_t identifier; @@ -101,7 +92,7 @@ size_t tcp_server_listen_count(const TCP_Server *tcp_server)      return tcp_server->num_listening_socks;  } -/* This is needed to compile on Android below API 21 +/** This is needed to compile on Android below API 21   */  #ifdef TCP_SERVER_USE_EPOLL  #ifndef EPOLLRDHUP @@ -109,7 +100,7 @@ size_t tcp_server_listen_count(const TCP_Server *tcp_server)  #endif  #endif -/* Increase the size of the connection list +/** Increase the size of the connection list   *   *  return -1 on failure   *  return 0 on success. @@ -139,26 +130,17 @@ static int alloc_new_connections(TCP_Server *tcp_server, uint32_t num)      return 0;  } -void wipe_priority_list(TCP_Priority_List *p) -{ -    while (p) { -        TCP_Priority_List *pp = p; -        p = p->next; -        free(pp); -    } -} -  static void wipe_secure_connection(TCP_Secure_Connection *con)  {      if (con->status) { -        wipe_priority_list(con->priority_queue_start); +        wipe_priority_list(con->con.priority_queue_start);          crypto_memzero(con, sizeof(TCP_Secure_Connection));      }  }  static void move_secure_connection(TCP_Secure_Connection *con_new, TCP_Secure_Connection *con_old)  { -    memcpy(con_new, con_old, sizeof(TCP_Secure_Connection)); +    *con_new = *con_old;      crypto_memzero(con_old, sizeof(TCP_Secure_Connection));  } @@ -177,7 +159,7 @@ static void free_accepted_connection_array(TCP_Server *tcp_server)      tcp_server->size_accepted_connections = 0;  } -/* return index corresponding to connection with peer on success +/** return index corresponding to connection with peer on success   * return -1 on failure.   */  static int get_TCP_connection_index(const TCP_Server *tcp_server, const uint8_t *public_key) @@ -188,7 +170,7 @@ static int get_TCP_connection_index(const TCP_Server *tcp_server, const uint8_t  static int kill_accepted(TCP_Server *tcp_server, int index); -/* Add accepted TCP connection to the list. +/** Add accepted TCP connection to the list.   *   * return index on success   * return -1 on failure @@ -209,9 +191,7 @@ static int add_accepted(TCP_Server *tcp_server, const Mono_Time *mono_time, TCP_          index = tcp_server->num_accepted_connections;      } else { -        uint32_t i; - -        for (i = tcp_server->size_accepted_connections; i != 0; --i) { +        for (uint32_t i = tcp_server->size_accepted_connections; i != 0; --i) {              if (tcp_server->accepted_connection_array[i - 1].status == TCP_STATUS_NO_STATUS) {                  index = i - 1;                  break; @@ -239,7 +219,7 @@ static int add_accepted(TCP_Server *tcp_server, const Mono_Time *mono_time, TCP_      return index;  } -/* Delete accepted connection from list. +/** Delete accepted connection from list.   *   * return 0 on success   * return -1 on failure @@ -268,274 +248,17 @@ static int del_accepted(TCP_Server *tcp_server, int index)      return 0;  } -/* Read the next two bytes in TCP stream then convert them to - * length (host byte order). - * - * return length on success - * return 0 if nothing has been read from socket. - * return -1 on failure. - */ -uint16_t read_TCP_length(const Logger *logger, Socket sock) -{ -    const unsigned int count = net_socket_data_recv_buffer(sock); - -    if (count >= sizeof(uint16_t)) { -        uint16_t length; -        const int len = net_recv(sock, &length, sizeof(uint16_t)); - -        if (len != sizeof(uint16_t)) { -            LOGGER_ERROR(logger, "FAIL recv packet"); -            return 0; -        } - -        length = net_ntohs(length); - -        if (length > MAX_PACKET_SIZE) { -            return -1; -        } - -        return length; -    } - -    return 0; -} - -/* Read length bytes from socket. - * - * return length on success - * return -1 on failure/no data in buffer. - */ -int read_TCP_packet(const Logger *logger, Socket sock, uint8_t *data, uint16_t length) -{ -    unsigned int count = net_socket_data_recv_buffer(sock); - -    if (count >= length) { -        const int len = net_recv(sock, data, length); - -        if (len != length) { -            LOGGER_ERROR(logger, "FAIL recv packet"); -            return -1; -        } - -        return len; -    } - -    return -1; -} - -/* return length of received packet on success. - * return 0 if could not read any packet. - * return -1 on failure (connection must be killed). - */ -int read_packet_TCP_secure_connection(const Logger *logger, Socket sock, uint16_t *next_packet_length, -                                      const uint8_t *shared_key, uint8_t *recv_nonce, uint8_t *data, uint16_t max_len) -{ -    if (*next_packet_length == 0) { -        uint16_t len = read_TCP_length(logger, sock); - -        if (len == (uint16_t) -1) { -            return -1; -        } - -        if (len == 0) { -            return 0; -        } - -        *next_packet_length = len; -    } - -    if (max_len + CRYPTO_MAC_SIZE < *next_packet_length) { -        return -1; -    } - -    VLA(uint8_t, data_encrypted, *next_packet_length); -    int len_packet = read_TCP_packet(logger, sock, data_encrypted, *next_packet_length); - -    if (len_packet != *next_packet_length) { -        return 0; -    } - -    *next_packet_length = 0; - -    int len = decrypt_data_symmetric(shared_key, recv_nonce, data_encrypted, len_packet, data); - -    if (len + CRYPTO_MAC_SIZE != len_packet) { -        return -1; -    } - -    increment_nonce(recv_nonce); - -    return len; -} - -/* return 0 if pending data was sent completely - * return -1 if it wasn't - */ -static int send_pending_data_nonpriority(TCP_Secure_Connection *con) -{ -    if (con->last_packet_length == 0) { -        return 0; -    } - -    const uint16_t left = con->last_packet_length - con->last_packet_sent; -    const int len = net_send(con->sock, con->last_packet + con->last_packet_sent, left); - -    if (len <= 0) { -        return -1; -    } - -    if (len == left) { -        con->last_packet_length = 0; -        con->last_packet_sent = 0; -        return 0; -    } - -    con->last_packet_sent += len; -    return -1; -} - -/* return 0 if pending data was sent completely - * return -1 if it wasn't - */ -static int send_pending_data(TCP_Secure_Connection *con) -{ -    /* finish sending current non-priority packet */ -    if (send_pending_data_nonpriority(con) == -1) { -        return -1; -    } - -    TCP_Priority_List *p = con->priority_queue_start; - -    while (p) { -        const uint16_t left = p->size - p->sent; -        const int len = net_send(con->sock, p->data + p->sent, left); - -        if (len != left) { -            if (len > 0) { -                p->sent += len; -            } - -            break; -        } - -        TCP_Priority_List *pp = p; -        p = p->next; -        free(pp); -    } - -    con->priority_queue_start = p; - -    if (!p) { -        con->priority_queue_end = nullptr; -        return 0; -    } - -    return -1; -} - -/* return 0 on failure (only if malloc fails) - * return 1 on success - */ -static bool add_priority(TCP_Secure_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent) -{ -    TCP_Priority_List *p = con->priority_queue_end; -    TCP_Priority_List *new_list = (TCP_Priority_List *)malloc(sizeof(TCP_Priority_List) + size); - -    if (!new_list) { -        return 0; -    } - -    new_list->next = nullptr; -    new_list->size = size; -    new_list->sent = sent; -    memcpy(new_list->data, packet, size); - -    if (p) { -        p->next = new_list; -    } else { -        con->priority_queue_start = new_list; -    } - -    con->priority_queue_end = new_list; -    return 1; -} - -/* return 1 on success. - * return 0 if could not send packet. - * return -1 on failure (connection must be killed). - */ -static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length, -        bool priority) -{ -    if (length + CRYPTO_MAC_SIZE > MAX_PACKET_SIZE) { -        return -1; -    } - -    bool sendpriority = 1; - -    if (send_pending_data(con) == -1) { -        if (priority) { -            sendpriority = 0; -        } else { -            return 0; -        } -    } - -    VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE); - -    const uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE); -    memcpy(packet, &c_length, sizeof(uint16_t)); -    int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); - -    if ((unsigned int)len != (SIZEOF_VLA(packet) - sizeof(uint16_t))) { -        return -1; -    } - -    if (priority) { -        len = sendpriority ? net_send(con->sock, packet, SIZEOF_VLA(packet)) : 0; - -        if (len <= 0) { -            len = 0; -        } - -        increment_nonce(con->sent_nonce); - -        if ((unsigned int)len == SIZEOF_VLA(packet)) { -            return 1; -        } - -        return add_priority(con, packet, SIZEOF_VLA(packet), len); -    } - -    len = net_send(con->sock, packet, SIZEOF_VLA(packet)); - -    if (len <= 0) { -        return 0; -    } - -    increment_nonce(con->sent_nonce); - -    if ((unsigned int)len == SIZEOF_VLA(packet)) { -        return 1; -    } - -    memcpy(con->last_packet, packet, SIZEOF_VLA(packet)); -    con->last_packet_length = SIZEOF_VLA(packet); -    con->last_packet_sent = len; -    return 1; -} - -/* Kill a TCP_Secure_Connection +/** Kill a TCP_Secure_Connection   */  static void kill_TCP_secure_connection(TCP_Secure_Connection *con)  { -    kill_sock(con->sock); +    kill_sock(con->con.sock);      wipe_secure_connection(con);  }  static int rm_connection_index(TCP_Server *tcp_server, TCP_Secure_Connection *con, uint8_t con_number); -/* Kill an accepted TCP_Secure_Connection +/** Kill an accepted TCP_Secure_Connection   *   * return -1 on failure.   * return 0 on success. @@ -546,13 +269,11 @@ static int kill_accepted(TCP_Server *tcp_server, int index)          return -1;      } -    uint32_t i; - -    for (i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) { +    for (uint32_t i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) {          rm_connection_index(tcp_server, &tcp_server->accepted_connection_array[index], i);      } -    Socket sock = tcp_server->accepted_connection_array[index].sock; +    Socket sock = tcp_server->accepted_connection_array[index].con.sock;      if (del_accepted(tcp_server, index) != 0) {          return -1; @@ -562,17 +283,19 @@ static int kill_accepted(TCP_Server *tcp_server, int index)      return 0;  } -/* return 1 if everything went well. +/** return 1 if everything went well.   * return -1 if the connection must be killed.   */ -static int handle_TCP_handshake(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length, +static int handle_TCP_handshake(const Logger *logger, TCP_Secure_Connection *con, const uint8_t *data, uint16_t length,                                  const uint8_t *self_secret_key)  {      if (length != TCP_CLIENT_HANDSHAKE_SIZE) { +        LOGGER_WARNING(logger, "invalid handshake length: %d != %d", length, TCP_CLIENT_HANDSHAKE_SIZE);          return -1;      }      if (con->status != TCP_STATUS_CONNECTED) { +        LOGGER_WARNING(logger, "TCP connection %u not connected", (unsigned int)con->identifier);          return -1;      } @@ -583,6 +306,8 @@ static int handle_TCP_handshake(TCP_Secure_Connection *con, const uint8_t *data,                                       data + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE, plain);      if (len != TCP_HANDSHAKE_PLAIN_SIZE) { +        LOGGER_WARNING(logger, "invalid TCP handshake decrypted length: %d != %d", len, TCP_HANDSHAKE_PLAIN_SIZE); +        crypto_memzero(shared_key, sizeof(shared_key));          return -1;      } @@ -590,8 +315,8 @@ static int handle_TCP_handshake(TCP_Secure_Connection *con, const uint8_t *data,      uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE];      uint8_t resp_plain[TCP_HANDSHAKE_PLAIN_SIZE];      crypto_new_keypair(resp_plain, temp_secret_key); -    random_nonce(con->sent_nonce); -    memcpy(resp_plain + CRYPTO_PUBLIC_KEY_SIZE, con->sent_nonce, CRYPTO_NONCE_SIZE); +    random_nonce(con->con.sent_nonce); +    memcpy(resp_plain + CRYPTO_PUBLIC_KEY_SIZE, con->con.sent_nonce, CRYPTO_NONCE_SIZE);      memcpy(con->recv_nonce, plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_NONCE_SIZE);      uint8_t response[TCP_SERVER_HANDSHAKE_SIZE]; @@ -601,90 +326,98 @@ static int handle_TCP_handshake(TCP_Secure_Connection *con, const uint8_t *data,                                   response + CRYPTO_NONCE_SIZE);      if (len != TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE) { +        crypto_memzero(shared_key, sizeof(shared_key));          return -1;      } -    if (TCP_SERVER_HANDSHAKE_SIZE != net_send(con->sock, response, TCP_SERVER_HANDSHAKE_SIZE)) { +    IP_Port ipp = {0}; + +    if (TCP_SERVER_HANDSHAKE_SIZE != net_send(logger, con->con.sock, response, TCP_SERVER_HANDSHAKE_SIZE, &ipp)) { +        crypto_memzero(shared_key, sizeof(shared_key));          return -1;      } -    encrypt_precompute(plain, temp_secret_key, con->shared_key); +    encrypt_precompute(plain, temp_secret_key, con->con.shared_key);      con->status = TCP_STATUS_UNCONFIRMED; + +    crypto_memzero(shared_key, sizeof(shared_key)); +      return 1;  } -/* return 1 if connection handshake was handled correctly. +/** return 1 if connection handshake was handled correctly.   * return 0 if we didn't get it yet.   * return -1 if the connection must be killed.   */  static int read_connection_handshake(const Logger *logger, TCP_Secure_Connection *con, const uint8_t *self_secret_key)  {      uint8_t data[TCP_CLIENT_HANDSHAKE_SIZE]; -    const int len = read_TCP_packet(logger, con->sock, data, TCP_CLIENT_HANDSHAKE_SIZE); +    const int len = read_TCP_packet(logger, con->con.sock, data, TCP_CLIENT_HANDSHAKE_SIZE, &con->con.ip_port); -    if (len != -1) { -        return handle_TCP_handshake(con, data, len, self_secret_key); +    if (len == -1) { +        LOGGER_TRACE(logger, "connection handshake is not ready yet"); +        return 0;      } -    return 0; +    return handle_TCP_handshake(logger, con, data, len, self_secret_key);  } -/* return 1 on success. +/** return 1 on success.   * return 0 if could not send packet.   * return -1 on failure (connection must be killed).   */ -static int send_routing_response(TCP_Secure_Connection *con, uint8_t rpid, const uint8_t *public_key) +static int send_routing_response(const Logger *logger, TCP_Secure_Connection *con, uint8_t rpid, +                                 const uint8_t *public_key)  {      uint8_t data[1 + 1 + CRYPTO_PUBLIC_KEY_SIZE];      data[0] = TCP_PACKET_ROUTING_RESPONSE;      data[1] = rpid;      memcpy(data + 2, public_key, CRYPTO_PUBLIC_KEY_SIZE); -    return write_packet_TCP_secure_connection(con, data, sizeof(data), 1); +    return write_packet_TCP_secure_connection(logger, &con->con, data, sizeof(data), 1);  } -/* return 1 on success. +/** return 1 on success.   * return 0 if could not send packet.   * return -1 on failure (connection must be killed).   */ -static int send_connect_notification(TCP_Secure_Connection *con, uint8_t id) +static int send_connect_notification(const Logger *logger, TCP_Secure_Connection *con, uint8_t id)  {      uint8_t data[2] = {TCP_PACKET_CONNECTION_NOTIFICATION, (uint8_t)(id + NUM_RESERVED_PORTS)}; -    return write_packet_TCP_secure_connection(con, data, sizeof(data), 1); +    return write_packet_TCP_secure_connection(logger, &con->con, data, sizeof(data), 1);  } -/* return 1 on success. +/** return 1 on success.   * return 0 if could not send packet.   * return -1 on failure (connection must be killed).   */ -static int send_disconnect_notification(TCP_Secure_Connection *con, uint8_t id) +static int send_disconnect_notification(const Logger *logger, TCP_Secure_Connection *con, uint8_t id)  {      uint8_t data[2] = {TCP_PACKET_DISCONNECT_NOTIFICATION, (uint8_t)(id + NUM_RESERVED_PORTS)}; -    return write_packet_TCP_secure_connection(con, data, sizeof(data), 1); +    return write_packet_TCP_secure_connection(logger, &con->con, data, sizeof(data), 1);  } -/* return 0 on success. +/** return 0 on success.   * return -1 on failure (connection must be killed).   */  static int handle_TCP_routing_req(TCP_Server *tcp_server, uint32_t con_id, const uint8_t *public_key)  { -    uint32_t i;      uint32_t index = -1;      TCP_Secure_Connection *con = &tcp_server->accepted_connection_array[con_id];      /* If person tries to cennect to himself we deny the request*/      if (public_key_cmp(con->public_key, public_key) == 0) { -        if (send_routing_response(con, 0, public_key) == -1) { +        if (send_routing_response(tcp_server->logger, con, 0, public_key) == -1) {              return -1;          }          return 0;      } -    for (i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) { +    for (uint32_t i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) {          if (con->connections[i].status != 0) {              if (public_key_cmp(public_key, con->connections[i].public_key) == 0) { -                if (send_routing_response(con, i + NUM_RESERVED_PORTS, public_key) == -1) { +                if (send_routing_response(tcp_server->logger, con, i + NUM_RESERVED_PORTS, public_key) == -1) {                      return -1;                  } @@ -696,14 +429,14 @@ static int handle_TCP_routing_req(TCP_Server *tcp_server, uint32_t con_id, const      }      if (index == (uint32_t) -1) { -        if (send_routing_response(con, 0, public_key) == -1) { +        if (send_routing_response(tcp_server->logger, con, 0, public_key) == -1) {              return -1;          }          return 0;      } -    int ret = send_routing_response(con, index + NUM_RESERVED_PORTS, public_key); +    int ret = send_routing_response(tcp_server->logger, con, index + NUM_RESERVED_PORTS, public_key);      if (ret == 0) {          return 0; @@ -721,7 +454,7 @@ static int handle_TCP_routing_req(TCP_Server *tcp_server, uint32_t con_id, const          uint32_t other_id = -1;          TCP_Secure_Connection *other_conn = &tcp_server->accepted_connection_array[other_index]; -        for (i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) { +        for (uint32_t i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) {              if (other_conn->connections[i].status == 1                      && public_key_cmp(other_conn->connections[i].public_key, con->public_key) == 0) {                  other_id = i; @@ -737,15 +470,15 @@ static int handle_TCP_routing_req(TCP_Server *tcp_server, uint32_t con_id, const              other_conn->connections[other_id].index = con_id;              other_conn->connections[other_id].other_id = index;              // TODO(irungentoo): return values? -            send_connect_notification(con, index); -            send_connect_notification(other_conn, other_id); +            send_connect_notification(tcp_server->logger, con, index); +            send_connect_notification(tcp_server->logger, other_conn, other_id);          }      }      return 0;  } -/* return 0 on success. +/** return 0 on success.   * return -1 on failure (connection must be killed).   */  static int handle_TCP_oob_send(TCP_Server *tcp_server, uint32_t con_id, const uint8_t *public_key, const uint8_t *data, @@ -755,7 +488,7 @@ static int handle_TCP_oob_send(TCP_Server *tcp_server, uint32_t con_id, const ui          return -1;      } -    TCP_Secure_Connection *con = &tcp_server->accepted_connection_array[con_id]; +    const TCP_Secure_Connection *con = &tcp_server->accepted_connection_array[con_id];      int other_index = get_TCP_connection_index(tcp_server, public_key); @@ -764,14 +497,14 @@ static int handle_TCP_oob_send(TCP_Server *tcp_server, uint32_t con_id, const ui          resp_packet[0] = TCP_PACKET_OOB_RECV;          memcpy(resp_packet + 1, con->public_key, CRYPTO_PUBLIC_KEY_SIZE);          memcpy(resp_packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length); -        write_packet_TCP_secure_connection(&tcp_server->accepted_connection_array[other_index], resp_packet, -                                           SIZEOF_VLA(resp_packet), 0); +        write_packet_TCP_secure_connection(tcp_server->logger, &tcp_server->accepted_connection_array[other_index].con, +                                           resp_packet, SIZEOF_VLA(resp_packet), 0);      }      return 0;  } -/* Remove connection with con_number from the connections array of con. +/** Remove connection with con_number from the connections array of con.   *   * return -1 on failure.   * return 0 on success. @@ -783,10 +516,9 @@ static int rm_connection_index(TCP_Server *tcp_server, TCP_Secure_Connection *co      }      if (con->connections[con_number].status) { -        uint32_t index = con->connections[con_number].index; -        uint8_t other_id = con->connections[con_number].other_id; -          if (con->connections[con_number].status == 2) { +            const uint32_t index = con->connections[con_number].index; +            const uint8_t other_id = con->connections[con_number].other_id;              if (index >= tcp_server->size_accepted_connections) {                  return -1; @@ -796,7 +528,7 @@ static int rm_connection_index(TCP_Server *tcp_server, TCP_Secure_Connection *co              tcp_server->accepted_connection_array[index].connections[other_id].index = 0;              tcp_server->accepted_connection_array[index].connections[other_id].status = 1;              // TODO(irungentoo): return values? -            send_disconnect_notification(&tcp_server->accepted_connection_array[index], other_id); +            send_disconnect_notification(tcp_server->logger, &tcp_server->accepted_connection_array[index], other_id);          }          con->connections[con_number].index = 0; @@ -808,10 +540,10 @@ static int rm_connection_index(TCP_Server *tcp_server, TCP_Secure_Connection *co      return -1;  } -static int handle_onion_recv_1(void *object, IP_Port dest, const uint8_t *data, uint16_t length) +static int handle_onion_recv_1(void *object, const IP_Port *dest, const uint8_t *data, uint16_t length)  {      TCP_Server *tcp_server = (TCP_Server *)object; -    uint32_t index = dest.ip.ip.v6.uint32[0]; +    uint32_t index = dest->ip.ip.v6.uint32[0];      if (index >= tcp_server->size_accepted_connections) {          return 1; @@ -819,7 +551,7 @@ static int handle_onion_recv_1(void *object, IP_Port dest, const uint8_t *data,      TCP_Secure_Connection *con = &tcp_server->accepted_connection_array[index]; -    if (con->identifier != dest.ip.ip.v6.uint64[1]) { +    if (con->identifier != dest->ip.ip.v6.uint64[1]) {          return 1;      } @@ -827,14 +559,14 @@ static int handle_onion_recv_1(void *object, IP_Port dest, const uint8_t *data,      memcpy(packet + 1, data, length);      packet[0] = TCP_PACKET_ONION_RESPONSE; -    if (write_packet_TCP_secure_connection(con, packet, SIZEOF_VLA(packet), 0) != 1) { +    if (write_packet_TCP_secure_connection(tcp_server->logger, &con->con, packet, SIZEOF_VLA(packet), 0) != 1) {          return 1;      }      return 0;  } -/* return 0 on success +/** return 0 on success   * return -1 on failure   */  static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint8_t *data, uint16_t length) @@ -843,7 +575,7 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint          return -1;      } -    TCP_Secure_Connection *con = &tcp_server->accepted_connection_array[con_id]; +    TCP_Secure_Connection *const con = &tcp_server->accepted_connection_array[con_id];      switch (data[0]) {          case TCP_PACKET_ROUTING_REQUEST: { @@ -851,6 +583,7 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint                  return -1;              } +            LOGGER_TRACE(tcp_server->logger, "handling routing request for %d", con_id);              return handle_TCP_routing_req(tcp_server, con_id, data + 1);          } @@ -859,6 +592,7 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint                  return -1;              } +            LOGGER_TRACE(tcp_server->logger, "handling connection notification for %d", con_id);              break;          } @@ -867,6 +601,7 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint                  return -1;              } +            LOGGER_TRACE(tcp_server->logger, "handling disconnect notification for %d", con_id);              return rm_connection_index(tcp_server, con, data[1] - NUM_RESERVED_PORTS);          } @@ -875,10 +610,12 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint                  return -1;              } +            LOGGER_TRACE(tcp_server->logger, "handling ping for %d", con_id); +              uint8_t response[1 + sizeof(uint64_t)];              response[0] = TCP_PACKET_PONG;              memcpy(response + 1, data + 1, sizeof(uint64_t)); -            write_packet_TCP_secure_connection(con, response, sizeof(response), 1); +            write_packet_TCP_secure_connection(tcp_server->logger, &con->con, response, sizeof(response), 1);              return 0;          } @@ -887,6 +624,8 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint                  return -1;              } +            LOGGER_TRACE(tcp_server->logger, "handling pong for %d", con_id); +              uint64_t ping_id;              memcpy(&ping_id, data + 1, sizeof(uint64_t)); @@ -906,11 +645,15 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint                  return -1;              } +            LOGGER_TRACE(tcp_server->logger, "handling oob send for %d", con_id); +              return handle_TCP_oob_send(tcp_server, con_id, data + 1, data + 1 + CRYPTO_PUBLIC_KEY_SIZE,                                         length - (1 + CRYPTO_PUBLIC_KEY_SIZE));          }          case TCP_PACKET_ONION_REQUEST: { +            LOGGER_TRACE(tcp_server->logger, "handling onion request for %d", con_id); +              if (tcp_server->onion) {                  if (length <= 1 + CRYPTO_NONCE_SIZE + ONION_SEND_BASE * 2) {                      return -1; @@ -922,7 +665,7 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint                  source.ip.ip.v6.uint32[0] = con_id;                  source.ip.ip.v6.uint32[1] = 0;                  source.ip.ip.v6.uint64[1] = con->identifier; -                onion_send_1(tcp_server->onion, data + 1 + CRYPTO_NONCE_SIZE, length - (1 + CRYPTO_NONCE_SIZE), source, +                onion_send_1(tcp_server->onion, data + 1 + CRYPTO_NONCE_SIZE, length - (1 + CRYPTO_NONCE_SIZE), &source,                               data + 1);              } @@ -930,6 +673,7 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint          }          case TCP_PACKET_ONION_RESPONSE: { +            LOGGER_TRACE(tcp_server->logger, "handling onion response for %d", con_id);              return -1;          } @@ -938,7 +682,8 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint                  return -1;              } -            uint8_t c_id = data[0] - NUM_RESERVED_PORTS; +            const uint8_t c_id = data[0] - NUM_RESERVED_PORTS; +            LOGGER_TRACE(tcp_server->logger, "handling packet id %d for %d", c_id, con_id);              if (c_id >= NUM_CLIENT_CONNECTIONS) {                  return -1; @@ -952,12 +697,13 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint                  return 0;              } -            uint32_t index = con->connections[c_id].index; -            uint8_t other_c_id = con->connections[c_id].other_id + NUM_RESERVED_PORTS; +            const uint32_t index = con->connections[c_id].index; +            const uint8_t other_c_id = con->connections[c_id].other_id + NUM_RESERVED_PORTS;              VLA(uint8_t, new_data, length);              memcpy(new_data, data, length);              new_data[0] = other_c_id; -            int ret = write_packet_TCP_secure_connection(&tcp_server->accepted_connection_array[index], new_data, length, 0); +            const int ret = write_packet_TCP_secure_connection(tcp_server->logger, +                            &tcp_server->accepted_connection_array[index].con, new_data, length, 0);              if (ret == -1) {                  return -1; @@ -972,12 +718,12 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint  static int confirm_TCP_connection(TCP_Server *tcp_server, const Mono_Time *mono_time, TCP_Secure_Connection *con, -                                  const uint8_t *data, -                                  uint16_t length) +                                  const uint8_t *data, uint16_t length)  { -    int index = add_accepted(tcp_server, mono_time, con); +    const int index = add_accepted(tcp_server, mono_time, con);      if (index == -1) { +        LOGGER_DEBUG(tcp_server->logger, "dropping connection %u: not accepted", (unsigned int)con->identifier);          kill_TCP_secure_connection(con);          return -1;      } @@ -985,6 +731,8 @@ static int confirm_TCP_connection(TCP_Server *tcp_server, const Mono_Time *mono_      wipe_secure_connection(con);      if (handle_TCP_packet(tcp_server, index, data, length) == -1) { +        LOGGER_DEBUG(tcp_server->logger, "dropping connection %u: data packet (len=%d) not handled", +                     (unsigned int)con->identifier, length);          kill_accepted(tcp_server, index);          return -1;      } @@ -992,7 +740,7 @@ static int confirm_TCP_connection(TCP_Server *tcp_server, const Mono_Time *mono_      return index;  } -/* return index on success +/** return index on success   * return -1 on failure   */  static int accept_connection(TCP_Server *tcp_server, Socket sock) @@ -1011,16 +759,17 @@ static int accept_connection(TCP_Server *tcp_server, Socket sock)          return -1;      } -    uint16_t index = tcp_server->incoming_connection_queue_index % MAX_INCOMING_CONNECTIONS; +    const uint16_t index = tcp_server->incoming_connection_queue_index % MAX_INCOMING_CONNECTIONS;      TCP_Secure_Connection *conn = &tcp_server->incoming_connection_queue[index];      if (conn->status != TCP_STATUS_NO_STATUS) { +        LOGGER_DEBUG(tcp_server->logger, "connection %d dropped before accepting", index);          kill_TCP_secure_connection(conn);      }      conn->status = TCP_STATUS_CONNECTED; -    conn->sock = sock; +    conn->con.sock = sock;      conn->next_packet_length = 0;      ++tcp_server->incoming_connection_queue_index; @@ -1094,16 +843,13 @@ TCP_Server *new_TCP_server(const Logger *logger, uint8_t ipv6_enabled, uint16_t      const Family family = ipv6_enabled ? net_family_ipv6 : net_family_ipv4; -    uint32_t i; -#ifdef TCP_SERVER_USE_EPOLL -    struct epoll_event ev; -#endif - -    for (i = 0; i < num_sockets; ++i) { +    for (uint32_t i = 0; i < num_sockets; ++i) {          Socket sock = new_listening_TCP_socket(family, ports[i]);          if (sock_valid(sock)) {  #ifdef TCP_SERVER_USE_EPOLL +            struct epoll_event ev; +              ev.events = EPOLLIN | EPOLLET;              ev.data.u64 = sock.socket | ((uint64_t)TCP_SOCKET_LISTENING << 32); @@ -1140,9 +886,7 @@ TCP_Server *new_TCP_server(const Logger *logger, uint8_t ipv6_enabled, uint16_t  #ifndef TCP_SERVER_USE_EPOLL  static void do_TCP_accept_new(TCP_Server *tcp_server)  { -    uint32_t i; - -    for (i = 0; i < tcp_server->num_listening_socks; ++i) { +    for (uint32_t i = 0; i < tcp_server->num_listening_socks; ++i) {          Socket sock;          do { @@ -1154,44 +898,54 @@ static void do_TCP_accept_new(TCP_Server *tcp_server)  static int do_incoming(TCP_Server *tcp_server, uint32_t i)  { -    if (tcp_server->incoming_connection_queue[i].status != TCP_STATUS_CONNECTED) { +    TCP_Secure_Connection *const conn = &tcp_server->incoming_connection_queue[i]; + +    if (conn->status != TCP_STATUS_CONNECTED) {          return -1;      } -    int ret = read_connection_handshake(tcp_server->logger, &tcp_server->incoming_connection_queue[i], -                                        tcp_server->secret_key); +    LOGGER_TRACE(tcp_server->logger, "handling incoming TCP connection %d", i); + +    const int ret = read_connection_handshake(tcp_server->logger, conn, tcp_server->secret_key);      if (ret == -1) { -        kill_TCP_secure_connection(&tcp_server->incoming_connection_queue[i]); -    } else if (ret == 1) { -        int index_new = tcp_server->unconfirmed_connection_queue_index % MAX_INCOMING_CONNECTIONS; -        TCP_Secure_Connection *conn_old = &tcp_server->incoming_connection_queue[i]; -        TCP_Secure_Connection *conn_new = &tcp_server->unconfirmed_connection_queue[index_new]; - -        if (conn_new->status != TCP_STATUS_NO_STATUS) { -            kill_TCP_secure_connection(conn_new); -        } +        LOGGER_TRACE(tcp_server->logger, "incoming connection %d dropped due to failed handshake", i); +        kill_TCP_secure_connection(conn); +        return -1; +    } + +    if (ret != 1) { +        return -1; +    } -        move_secure_connection(conn_new, conn_old); -        ++tcp_server->unconfirmed_connection_queue_index; +    const int index_new = tcp_server->unconfirmed_connection_queue_index % MAX_INCOMING_CONNECTIONS; +    TCP_Secure_Connection *conn_old = conn; +    TCP_Secure_Connection *conn_new = &tcp_server->unconfirmed_connection_queue[index_new]; -        return index_new; +    if (conn_new->status != TCP_STATUS_NO_STATUS) { +        LOGGER_WARNING(tcp_server->logger, "incoming connection %d would overwrite existing", i); +        kill_TCP_secure_connection(conn_new);      } -    return -1; +    move_secure_connection(conn_new, conn_old); +    ++tcp_server->unconfirmed_connection_queue_index; + +    return index_new;  }  static int do_unconfirmed(TCP_Server *tcp_server, const Mono_Time *mono_time, uint32_t i)  { -    TCP_Secure_Connection *conn = &tcp_server->unconfirmed_connection_queue[i]; +    TCP_Secure_Connection *const conn = &tcp_server->unconfirmed_connection_queue[i];      if (conn->status != TCP_STATUS_UNCONFIRMED) {          return -1;      } +    LOGGER_TRACE(tcp_server->logger, "handling unconfirmed TCP connection %d", i); +      uint8_t packet[MAX_PACKET_SIZE]; -    int len = read_packet_TCP_secure_connection(tcp_server->logger, conn->sock, &conn->next_packet_length, conn->shared_key, -              conn->recv_nonce, packet, sizeof(packet)); +    const int len = read_packet_TCP_secure_connection(tcp_server->logger, conn->con.sock, &conn->next_packet_length, +                    conn->con.shared_key, conn->recv_nonce, packet, sizeof(packet), &conn->con.ip_port);      if (len == 0) {          return -1; @@ -1210,8 +964,9 @@ static bool tcp_process_secure_packet(TCP_Server *tcp_server, uint32_t i)      TCP_Secure_Connection *const conn = &tcp_server->accepted_connection_array[i];      uint8_t packet[MAX_PACKET_SIZE]; -    int len = read_packet_TCP_secure_connection(tcp_server->logger, conn->sock, &conn->next_packet_length, conn->shared_key, -              conn->recv_nonce, packet, sizeof(packet)); +    const int len = read_packet_TCP_secure_connection(tcp_server->logger, conn->con.sock, &conn->next_packet_length, +                    conn->con.shared_key, conn->recv_nonce, packet, sizeof(packet), &conn->con.ip_port); +    LOGGER_TRACE(tcp_server->logger, "processing packet for %d: %d", i, len);      if (len == 0) {          return false; @@ -1223,6 +978,7 @@ static bool tcp_process_secure_packet(TCP_Server *tcp_server, uint32_t i)      }      if (handle_TCP_packet(tcp_server, i, packet, len) == -1) { +        LOGGER_TRACE(tcp_server->logger, "dropping connection %d: data packet (len=%d) not handled", i, len);          kill_accepted(tcp_server, i);          return false;      } @@ -1264,9 +1020,8 @@ static void do_TCP_confirmed(TCP_Server *tcp_server, const Mono_Time *mono_time)      tcp_server->last_run_pinged = mono_time_get(mono_time);  #endif -    uint32_t i; -    for (i = 0; i < tcp_server->size_accepted_connections; ++i) { +    for (uint32_t i = 0; i < tcp_server->size_accepted_connections; ++i) {          TCP_Secure_Connection *conn = &tcp_server->accepted_connection_array[i];          if (conn->status != TCP_STATUS_CONFIRMED) { @@ -1283,7 +1038,7 @@ static void do_TCP_confirmed(TCP_Server *tcp_server, const Mono_Time *mono_time)              }              memcpy(ping + 1, &ping_id, sizeof(uint64_t)); -            int ret = write_packet_TCP_secure_connection(conn, ping, sizeof(ping), 1); +            int ret = write_packet_TCP_secure_connection(tcp_server->logger, &conn->con, ping, sizeof(ping), 1);              if (ret == 1) {                  conn->last_pinged = mono_time_get(mono_time); @@ -1301,7 +1056,7 @@ static void do_TCP_confirmed(TCP_Server *tcp_server, const Mono_Time *mono_time)              continue;          } -        send_pending_data(conn); +        send_pending_data(tcp_server->logger, &conn->con);  #ifndef TCP_SERVER_USE_EPOLL @@ -1328,20 +1083,24 @@ static bool tcp_epoll_process(TCP_Server *tcp_server, const Mono_Time *mono_time              switch (status) {                  case TCP_SOCKET_LISTENING: {                      // should never happen +                    LOGGER_ERROR(tcp_server->logger, "connection %d was in listening state", index);                      break;                  }                  case TCP_SOCKET_INCOMING: { +                    LOGGER_TRACE(tcp_server->logger, "incoming connection %d dropped", index);                      kill_TCP_secure_connection(&tcp_server->incoming_connection_queue[index]);                      break;                  }                  case TCP_SOCKET_UNCONFIRMED: { +                    LOGGER_TRACE(tcp_server->logger, "unconfirmed connection %d dropped", index);                      kill_TCP_secure_connection(&tcp_server->unconfirmed_connection_queue[index]);                      break;                  }                  case TCP_SOCKET_CONFIRMED: { +                    LOGGER_TRACE(tcp_server->logger, "confirmed connection %d dropped", index);                      kill_accepted(tcp_server, index);                      break;                  } @@ -1365,7 +1124,7 @@ static bool tcp_epoll_process(TCP_Server *tcp_server, const Mono_Time *mono_time                          break;                      } -                    int index_new = accept_connection(tcp_server, sock_new); +                    const int index_new = accept_connection(tcp_server, sock_new);                      if (index_new == -1) {                          continue; @@ -1378,6 +1137,7 @@ static bool tcp_epoll_process(TCP_Server *tcp_server, const Mono_Time *mono_time                      ev.data.u64 = sock_new.socket | ((uint64_t)TCP_SOCKET_INCOMING << 32) | ((uint64_t)index_new << 40);                      if (epoll_ctl(tcp_server->efd, EPOLL_CTL_ADD, sock_new.socket, &ev) == -1) { +                        LOGGER_DEBUG(tcp_server->logger, "new connection %d was dropped due to epoll error %d", index, net_error());                          kill_TCP_secure_connection(&tcp_server->incoming_connection_queue[index_new]);                          continue;                      } @@ -1390,10 +1150,12 @@ static bool tcp_epoll_process(TCP_Server *tcp_server, const Mono_Time *mono_time                  const int index_new = do_incoming(tcp_server, index);                  if (index_new != -1) { +                    LOGGER_TRACE(tcp_server->logger, "incoming connection %d was accepted as %d", index, index_new);                      events[n].events = EPOLLIN | EPOLLET | EPOLLRDHUP;                      events[n].data.u64 = sock.socket | ((uint64_t)TCP_SOCKET_UNCONFIRMED << 32) | ((uint64_t)index_new << 40);                      if (epoll_ctl(tcp_server->efd, EPOLL_CTL_MOD, sock.socket, &events[n]) == -1) { +                        LOGGER_DEBUG(tcp_server->logger, "incoming connection %d was dropped due to epoll error %d", index, net_error());                          kill_TCP_secure_connection(&tcp_server->unconfirmed_connection_queue[index_new]);                          break;                      } @@ -1406,11 +1168,13 @@ static bool tcp_epoll_process(TCP_Server *tcp_server, const Mono_Time *mono_time                  const int index_new = do_unconfirmed(tcp_server, mono_time, index);                  if (index_new != -1) { +                    LOGGER_TRACE(tcp_server->logger, "unconfirmed connection %d was confirmed as %d", index, index_new);                      events[n].events = EPOLLIN | EPOLLET | EPOLLRDHUP;                      events[n].data.u64 = sock.socket | ((uint64_t)TCP_SOCKET_CONFIRMED << 32) | ((uint64_t)index_new << 40);                      if (epoll_ctl(tcp_server->efd, EPOLL_CTL_MOD, sock.socket, &events[n]) == -1) {                          // remove from confirmed connections +                        LOGGER_DEBUG(tcp_server->logger, "unconfirmed connection %d was dropped due to epoll error %d", index, net_error());                          kill_accepted(tcp_server, index_new);                          break;                      } @@ -1438,7 +1202,7 @@ static void do_TCP_epoll(TCP_Server *tcp_server, const Mono_Time *mono_time)  }  #endif -void do_TCP_server(TCP_Server *tcp_server, Mono_Time *mono_time) +void do_TCP_server(TCP_Server *tcp_server, const Mono_Time *mono_time)  {  #ifdef TCP_SERVER_USE_EPOLL      do_TCP_epoll(tcp_server, mono_time); @@ -1475,6 +1239,8 @@ void kill_TCP_server(TCP_Server *tcp_server)      free_accepted_connection_array(tcp_server); +    crypto_memzero(tcp_server->secret_key, sizeof(tcp_server->secret_key)); +      free(tcp_server->socks_listening);      free(tcp_server);  } diff --git a/protocols/Tox/libtox/src/toxcore/TCP_server.h b/protocols/Tox/libtox/src/toxcore/TCP_server.h index 46dd03304f..3269ed3b0a 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_server.h +++ b/protocols/Tox/libtox/src/toxcore/TCP_server.h @@ -3,47 +3,21 @@   * Copyright © 2014 Tox project.   */ -/* +/**   * Implementation of the TCP relay server part of Tox.   */  #ifndef C_TOXCORE_TOXCORE_TCP_SERVER_H  #define C_TOXCORE_TOXCORE_TCP_SERVER_H  #include "crypto_core.h" -#include "list.h"  #include "onion.h"  #define MAX_INCOMING_CONNECTIONS 256  #define TCP_MAX_BACKLOG MAX_INCOMING_CONNECTIONS -#define MAX_PACKET_SIZE 2048 - -#define TCP_HANDSHAKE_PLAIN_SIZE (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE) -#define TCP_SERVER_HANDSHAKE_SIZE (CRYPTO_NONCE_SIZE + TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE) -#define TCP_CLIENT_HANDSHAKE_SIZE (CRYPTO_PUBLIC_KEY_SIZE + TCP_SERVER_HANDSHAKE_SIZE) -#define TCP_MAX_OOB_DATA_LENGTH 1024 - -#define NUM_RESERVED_PORTS 16 -#define NUM_CLIENT_CONNECTIONS (256 - NUM_RESERVED_PORTS) - -#define TCP_PACKET_ROUTING_REQUEST  0 -#define TCP_PACKET_ROUTING_RESPONSE 1 -#define TCP_PACKET_CONNECTION_NOTIFICATION 2 -#define TCP_PACKET_DISCONNECT_NOTIFICATION 3 -#define TCP_PACKET_PING 4 -#define TCP_PACKET_PONG 5 -#define TCP_PACKET_OOB_SEND 6 -#define TCP_PACKET_OOB_RECV 7 -#define TCP_PACKET_ONION_REQUEST  8 -#define TCP_PACKET_ONION_RESPONSE 9 -  #define ARRAY_ENTRY_SIZE 6 -/* frequency to ping connected nodes and timeout in seconds */ -#define TCP_PING_FREQUENCY 30 -#define TCP_PING_TIMEOUT 10 -  typedef enum TCP_Status {      TCP_STATUS_NO_STATUS,      TCP_STATUS_CONNECTED, @@ -51,57 +25,23 @@ typedef enum TCP_Status {      TCP_STATUS_CONFIRMED,  } TCP_Status; -typedef struct TCP_Priority_List TCP_Priority_List; - -struct TCP_Priority_List { -    TCP_Priority_List *next; -    uint16_t size; -    uint16_t sent; -    uint8_t data[]; -}; - -void wipe_priority_list(TCP_Priority_List *p); -  typedef struct TCP_Server TCP_Server;  const uint8_t *tcp_server_public_key(const TCP_Server *tcp_server);  size_t tcp_server_listen_count(const TCP_Server *tcp_server); -/* Create new TCP server instance. +/** Create new TCP server instance.   */  TCP_Server *new_TCP_server(const Logger *logger, uint8_t ipv6_enabled, uint16_t num_sockets, const uint16_t *ports,                             const uint8_t *secret_key, Onion *onion); -/* Run the TCP_server +/** Run the TCP_server   */ -void do_TCP_server(TCP_Server *tcp_server, Mono_Time *mono_time); +void do_TCP_server(TCP_Server *tcp_server, const Mono_Time *mono_time); -/* Kill the TCP server +/** Kill the TCP server   */  void kill_TCP_server(TCP_Server *tcp_server); -/* Read the next two bytes in TCP stream then convert them to - * length (host byte order). - * - * return length on success - * return 0 if nothing has been read from socket. - * return -1 on failure. - */ -uint16_t read_TCP_length(const Logger *logger, Socket sock); - -/* Read length bytes from socket. - * - * return length on success - * return -1 on failure/no data in buffer. - */ -int read_TCP_packet(const Logger *logger, Socket sock, uint8_t *data, uint16_t length); - -/* return length of received packet on success. - * return 0 if could not read any packet. - * return -1 on failure (connection must be killed). - */ -int read_packet_TCP_secure_connection(const Logger *logger, Socket sock, uint16_t *next_packet_length, -                                      const uint8_t *shared_key, uint8_t *recv_nonce, uint8_t *data, uint16_t max_len); -  #endif diff --git a/protocols/Tox/libtox/src/toxcore/ccompat.h b/protocols/Tox/libtox/src/toxcore/ccompat.h index 34def21bf9..295cd10d9b 100644 --- a/protocols/Tox/libtox/src/toxcore/ccompat.h +++ b/protocols/Tox/libtox/src/toxcore/ccompat.h @@ -1,9 +1,17 @@ -/* +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2016-2021 The TokTok team. + */ + +/**   * C language compatibility macros for varying compiler support.   */  #ifndef C_TOXCORE_TOXCORE_CCOMPAT_H  #define C_TOXCORE_TOXCORE_CCOMPAT_H +#include <stdbool.h> + +bool unused_for_tokstyle(void); +  //!TOKSTYLE-  // Variable length arrays. @@ -15,7 +23,7 @@  // "function") is used. Note the semantic difference: alloca'd memory does not  // get freed at the end of the declaration's scope. Do not use VLA() in loops or  // you may run out of stack space. -#if !defined(_MSC_VER) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#if !defined(DISABLE_VLA) && !defined(_MSC_VER) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L  // C99 VLAs.  #define VLA(type, name, size) type name[size]  #define SIZEOF_VLA sizeof @@ -24,6 +32,11 @@  // Emulation using alloca.  #ifdef _WIN32  #include <malloc.h> +#elif defined(__COMPCERT__) +// TODO(iphydf): This leaks memory like crazy, so compcert is useless for now. +// Once we're rid of VLAs, we can remove this and compcert becomes useful. +#define alloca malloc +#include <stdlib.h>  #elif defined(__linux__)  #include <alloca.h>  #else @@ -43,7 +56,7 @@  #if !defined(__cplusplus) || __cplusplus < 201103L  #define nullptr NULL  #ifndef static_assert -#define static_assert(cond, msg) extern int unused_for_static_assert +#define static_assert(cond, msg) extern const int unused_for_static_assert  #endif  #endif diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core.api.h b/protocols/Tox/libtox/src/toxcore/crypto_core.api.h deleted file mode 100644 index 0db3a42001..0000000000 --- a/protocols/Tox/libtox/src/toxcore/crypto_core.api.h +++ /dev/null @@ -1,253 +0,0 @@ -%{ -/* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. - * Copyright © 2013 Tox project. - */ - -/* - * Functions for the core crypto. - */ -#ifndef C_TOXCORE_TOXCORE_CRYPTO_CORE_H -#define C_TOXCORE_TOXCORE_CRYPTO_CORE_H - -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif -%} - -/** - * The number of bytes in a Tox public key. - */ -const CRYPTO_PUBLIC_KEY_SIZE = 32; - -/** - * The number of bytes in a Tox secret key. - */ -const CRYPTO_SECRET_KEY_SIZE = 32; - -/** - * The number of bytes in a shared key computed from public and secret keys. - */ -const CRYPTO_SHARED_KEY_SIZE = 32; - -/** - * The number of bytes in a symmetric key. - */ -const CRYPTO_SYMMETRIC_KEY_SIZE = CRYPTO_SHARED_KEY_SIZE; - -/** - * The number of bytes needed for the MAC (message authentication code) in an - * encrypted message. - */ -const CRYPTO_MAC_SIZE = 16; - -/** - * The number of bytes in a nonce used for encryption/decryption. - */ -const CRYPTO_NONCE_SIZE = 24; - -/** - * The number of bytes in a SHA256 hash. - */ -const CRYPTO_SHA256_SIZE = 32; - -/** - * The number of bytes in a SHA512 hash. - */ -const CRYPTO_SHA512_SIZE = 64; - -/** - * A `memcmp`-like function whose running time does not depend on the input - * bytes, only on the input length. Useful to compare sensitive data where - * timing attacks could reveal that data. - * - * This means for instance that comparing "aaaa" and "aaaa" takes 4 time, and - * "aaaa" and "baaa" also takes 4 time. With a regular `memcmp`, the latter may - * take 1 time, because it immediately knows that the two strings are not equal. - */ -static int32_t crypto_memcmp(const uint8_t *p1, const uint8_t *p2, size_t length); - -/** - * A `bzero`-like function which won't be optimised away by the compiler. Some - * compilers will inline `bzero` or `memset` if they can prove that there will - * be no reads to the written data. Use this function if you want to be sure the - * memory is indeed zeroed. - */ -static void crypto_memzero(void *data, size_t length); - -/** - * Compute a SHA256 hash (32 bytes). - */ -static void crypto_sha256(uint8_t[CRYPTO_SHA256_SIZE] hash, const uint8_t[length] data); - -/** - * Compute a SHA512 hash (64 bytes). - */ -static void crypto_sha512(uint8_t[CRYPTO_SHA512_SIZE] hash, const uint8_t[length] data); - -/** - * Compare 2 public keys of length CRYPTO_PUBLIC_KEY_SIZE, not vulnerable to - * timing attacks. - * - * @return 0 if both mem locations of length are equal, -1 if they are not. - */ -static int32_t public_key_cmp( -    const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] pk1, -    const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] pk2); - -namespace random { - -/** - * Return a random 8 bit integer. - */ -static uint8_t u08(); - -/** - * Return a random 16 bit integer. - */ -static uint16_t u16(); - -/** - * Return a random 32 bit integer. - */ -static uint32_t u32(); - -/** - * Return a random 64 bit integer. - */ -static uint64_t u64(); - -/** - * Fill the given nonce with random bytes. - */ -static void nonce(uint8_t[CRYPTO_NONCE_SIZE] nonce); - -/** - * Fill an array of bytes with random values. - */ -static void bytes(uint8_t[length] bytes); - -} - -/** - * Check if a Tox public key CRYPTO_PUBLIC_KEY_SIZE is valid or not. This - * should only be used for input validation. - * - * @return false if it isn't, true if it is. - */ -static bool public_key_valid(const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key); - -/** - * Generate a new random keypair. Every call to this function is likely to - * generate a different keypair. - */ -static int32_t crypto_new_keypair( -    uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key, -    uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key); - -/** - * Derive the public key from a given secret key. - */ -static void crypto_derive_public_key( -    uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key, -    const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key); - -/** - * Encrypt plain text of the given length to encrypted of length + - * $CRYPTO_MAC_SIZE using the public key ($CRYPTO_PUBLIC_KEY_SIZE bytes) of the - * receiver and the secret key of the sender and a $CRYPTO_NONCE_SIZE byte - * nonce. - * - * @return -1 if there was a problem, length of encrypted data if everything - * was fine. - */ -static int32_t encrypt_data( -    const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key, -    const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key, -    const uint8_t[CRYPTO_NONCE_SIZE] nonce, -    const uint8_t[length] plain, -    uint8_t *encrypted); - - -/** - * Decrypt encrypted text of the given length to plain text of the given length - * - $CRYPTO_MAC_SIZE using the public key ($CRYPTO_PUBLIC_KEY_SIZE bytes) of - * the sender, the secret key of the receiver and a $CRYPTO_NONCE_SIZE byte - * nonce. - * - * @return -1 if there was a problem (decryption failed), length of plain text - * data if everything was fine. - */ -static int32_t decrypt_data( -    const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key, -    const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key, -    const uint8_t[CRYPTO_NONCE_SIZE] nonce, -    const uint8_t[length] encrypted, -    uint8_t *plain); - -/** - * Fast encrypt/decrypt operations. Use if this is not a one-time communication. - * $encrypt_precompute does the shared-key generation once so it does not have - * to be performed on every encrypt/decrypt. - */ -static int32_t encrypt_precompute( -    const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key, -    const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key, -    uint8_t[CRYPTO_SHARED_KEY_SIZE] shared_key); - -/** - * Encrypts plain of length length to encrypted of length + $CRYPTO_MAC_SIZE - * using a shared key $CRYPTO_SYMMETRIC_KEY_SIZE big and a $CRYPTO_NONCE_SIZE - * byte nonce. - * - * @return -1 if there was a problem, length of encrypted data if everything - * was fine. - */ -static int32_t encrypt_data_symmetric( -    const uint8_t[CRYPTO_SHARED_KEY_SIZE] shared_key, -    const uint8_t[CRYPTO_NONCE_SIZE] nonce, -    const uint8_t[length] plain, -    uint8_t *encrypted); - -/** - * Decrypts encrypted of length length to plain of length length - - * $CRYPTO_MAC_SIZE using a shared key CRYPTO_SHARED_KEY_SIZE big and a - * $CRYPTO_NONCE_SIZE byte nonce. - * - * @return -1 if there was a problem (decryption failed), length of plain data - * if everything was fine. - */ -static int32_t decrypt_data_symmetric( -    const uint8_t[CRYPTO_SHARED_KEY_SIZE] shared_key, -    const uint8_t[CRYPTO_NONCE_SIZE] nonce, -    const uint8_t[length] encrypted, -    uint8_t *plain); - -/** - * Increment the given nonce by 1 in big endian (rightmost byte incremented - * first). - */ -static void increment_nonce(uint8_t[CRYPTO_NONCE_SIZE] nonce); - -/** - * Increment the given nonce by a given number. The number should be in host - * byte order. - */ -static void increment_nonce_number(uint8_t[CRYPTO_NONCE_SIZE] nonce, uint32_t host_order_num); - -/** - * Fill a key CRYPTO_SYMMETRIC_KEY_SIZE big with random bytes. - */ -static void new_symmetric_key(uint8_t[CRYPTO_SYMMETRIC_KEY_SIZE] key); - -%{ -#ifdef __cplusplus -}  // extern "C" -#endif - -#endif // C_TOXCORE_TOXCORE_CRYPTO_CORE_H -%} diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core.c b/protocols/Tox/libtox/src/toxcore/crypto_core.c index 35e3a60307..3402395b63 100644 --- a/protocols/Tox/libtox/src/toxcore/crypto_core.c +++ b/protocols/Tox/libtox/src/toxcore/crypto_core.c @@ -3,15 +3,11 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * Functions for the core crypto.   *   * NOTE: This code has to be perfect. We don't mess around with encryption.   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -  #include "crypto_core.h"  #include <stdlib.h> @@ -20,7 +16,7 @@  #include "ccompat.h"  #ifndef VANILLA_NACL -/* We use libsodium by default. */ +// We use libsodium by default.  #include <sodium.h>  #else  #include <crypto_box.h> @@ -30,10 +26,18 @@  #include <crypto_verify_16.h>  #include <crypto_verify_32.h>  #include <randombytes.h> +#endif + +#ifndef crypto_box_MACBYTES  #define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)  #endif  //!TOKSTYLE- +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +#include "../testing/fuzzing/fuzz_adapter.h" +#endif +//!TOKSTYLE+ +  static_assert(CRYPTO_PUBLIC_KEY_SIZE == crypto_box_PUBLICKEYBYTES,                "CRYPTO_PUBLIC_KEY_SIZE should be equal to crypto_box_PUBLICKEYBYTES");  static_assert(CRYPTO_SECRET_KEY_SIZE == crypto_box_SECRETKEYBYTES, @@ -52,25 +56,84 @@ static_assert(CRYPTO_SHA512_SIZE == crypto_hash_sha512_BYTES,                "CRYPTO_SHA512_SIZE should be equal to crypto_hash_sha512_BYTES");  static_assert(CRYPTO_PUBLIC_KEY_SIZE == 32,                "CRYPTO_PUBLIC_KEY_SIZE is required to be 32 bytes for public_key_cmp to work"); -//!TOKSTYLE+ +#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)  static uint8_t *crypto_malloc(size_t bytes)  { -    return (uint8_t *)malloc(bytes); +    uint8_t *ptr = (uint8_t *)malloc(bytes); + +    if (ptr != nullptr) { +        crypto_memlock(ptr, bytes); +    } + +    return ptr;  }  static void crypto_free(uint8_t *ptr, size_t bytes)  {      if (ptr != nullptr) {          crypto_memzero(ptr, bytes); +        crypto_memunlock(ptr, bytes);      }      free(ptr);  } +#endif  // !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) + +void crypto_memzero(void *data, size_t length) +{ +#ifndef VANILLA_NACL +    sodium_memzero(data, length); +#else +    memset(data, 0, length); +#endif +} + +bool crypto_memlock(void *data, size_t length) +{ +#ifndef VANILLA_NACL + +    if (sodium_mlock(data, length) != 0) { +        return false; +    } + +    return true; +#else +    return false; +#endif +} + +bool crypto_memunlock(void *data, size_t length) +{ +#ifndef VANILLA_NACL + +    if (sodium_munlock(data, length) != 0) { +        return false; +    } + +    return true; +#else +    return false; +#endif +}  int32_t public_key_cmp(const uint8_t *pk1, const uint8_t *pk2)  { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    // Hope that this is better for the fuzzer +    return memcmp(pk1, pk2, CRYPTO_PUBLIC_KEY_SIZE) == 0 ? 0 : -1; +#else      return crypto_verify_32(pk1, pk2); +#endif +} + +int32_t crypto_sha512_cmp(const uint8_t *cksum1, const uint8_t *cksum2) +{ +#ifndef VANILLA_NACL +    return crypto_verify_64(cksum1, cksum2); +#else +    return crypto_verify_32(cksum1, cksum2) && crypto_verify_32(cksum1 + 8, cksum2 + 8); +#endif  }  uint8_t random_u08(void) @@ -101,6 +164,15 @@ uint64_t random_u64(void)      return randnum;  } +uint32_t random_range_u32(uint32_t upper_bound) +{ +#ifdef VANILLA_NACL +    return random_u32() % upper_bound; +#else +    return randombytes_uniform(upper_bound); +#endif  // VANILLA_NACL +} +  bool public_key_valid(const uint8_t *public_key)  {      if (public_key[31] >= 128) { /* Last bit of key is always zero. */ @@ -110,11 +182,6 @@ bool public_key_valid(const uint8_t *public_key)      return 1;  } -/* Precomputes the shared key from their public_key and our secret_key. - * This way we can avoid an expensive elliptic curve scalar multiply for each - * encrypt/decrypt operation. - * shared_key has to be crypto_box_BEFORENMBYTES bytes long. - */  int32_t encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key,                             uint8_t *shared_key)  { @@ -128,6 +195,13 @@ int32_t encrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce,          return -1;      } +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    // Don't encrypt anything. +    memcpy(encrypted, plain, length); +    // Zero MAC to avoid uninitialized memory reads. +    memset(encrypted + length, 0, crypto_box_MACBYTES); +#else +      const size_t size_temp_plain = length + crypto_box_ZEROBYTES;      const size_t size_temp_encrypted = length + crypto_box_MACBYTES + crypto_box_BOXZEROBYTES; @@ -140,6 +214,11 @@ int32_t encrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce,          return -1;      } +    // crypto_box_afternm requires the entire range of the output array be +    // initialised with something. It doesn't matter what it's initialised with, +    // so we'll pick 0x00. +    memset(temp_encrypted, 0, size_temp_encrypted); +      memset(temp_plain, 0, crypto_box_ZEROBYTES);      // Pad the message with 32 0 bytes.      memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); @@ -156,7 +235,7 @@ int32_t encrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce,      crypto_free(temp_plain, size_temp_plain);      crypto_free(temp_encrypted, size_temp_encrypted); - +#endif      return length + crypto_box_MACBYTES;  } @@ -167,6 +246,11 @@ int32_t decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce,          return -1;      } +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    assert(length >= crypto_box_MACBYTES); +    memcpy(plain, encrypted, length - crypto_box_MACBYTES);  // Don't encrypt anything +#else +      const size_t size_temp_plain = length + crypto_box_ZEROBYTES;      const size_t size_temp_encrypted = length + crypto_box_BOXZEROBYTES; @@ -179,6 +263,11 @@ int32_t decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce,          return -1;      } +    // crypto_box_open_afternm requires the entire range of the output array be +    // initialised with something. It doesn't matter what it's initialised with, +    // so we'll pick 0x00. +    memset(temp_plain, 0, size_temp_plain); +      memset(temp_encrypted, 0, crypto_box_BOXZEROBYTES);      // Pad the message with 16 0 bytes.      memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); @@ -194,6 +283,7 @@ int32_t decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce,      crypto_free(temp_plain, size_temp_plain);      crypto_free(temp_encrypted, size_temp_encrypted); +#endif      return length - crypto_box_MACBYTES;  } @@ -225,7 +315,6 @@ int32_t decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const      return ret;  } -/* Increment the given nonce by 1. */  void increment_nonce(uint8_t *nonce)  {      /* TODO(irungentoo): use `increment_nonce_number(nonce, 1)` or @@ -236,61 +325,42 @@ void increment_nonce(uint8_t *nonce)       * that loop bounds and their potential underflow or overflow       * are independent of user-controlled input (you may have heard of the Heartbleed bug).       */ -    uint32_t i = crypto_box_NONCEBYTES;      uint_fast16_t carry = 1U; -    for (; i != 0; --i) { +    for (uint32_t i = crypto_box_NONCEBYTES; i != 0; --i) {          carry += (uint_fast16_t)nonce[i - 1];          nonce[i - 1] = (uint8_t)carry;          carry >>= 8;      }  } -static uint32_t host_to_network(uint32_t x) -{ -#if !defined(BYTE_ORDER) || BYTE_ORDER == LITTLE_ENDIAN -    return ((x >> 24) & 0x000000FF) |  // move byte 3 to byte 0 -           ((x >> 8) & 0x0000FF00) |   // move byte 2 to byte 1 -           ((x << 8) & 0x00FF0000) |   // move byte 1 to byte 2 -           ((x << 24) & 0xFF000000);   // move byte 0 to byte 3 -#else -    return x; -#endif -} - -/* increment the given nonce by num */ -void increment_nonce_number(uint8_t *nonce, uint32_t host_order_num) +void increment_nonce_number(uint8_t *nonce, uint32_t increment)  {      /* NOTE don't use breaks inside this loop       * In particular, make sure, as far as possible,       * that loop bounds and their potential underflow or overflow       * are independent of user-controlled input (you may have heard of the Heartbleed bug).       */ -    const uint32_t big_endian_num = host_to_network(host_order_num); -    const uint8_t *const num_vec = (const uint8_t *)&big_endian_num;      uint8_t num_as_nonce[crypto_box_NONCEBYTES] = {0}; -    num_as_nonce[crypto_box_NONCEBYTES - 4] = num_vec[0]; -    num_as_nonce[crypto_box_NONCEBYTES - 3] = num_vec[1]; -    num_as_nonce[crypto_box_NONCEBYTES - 2] = num_vec[2]; -    num_as_nonce[crypto_box_NONCEBYTES - 1] = num_vec[3]; +    num_as_nonce[crypto_box_NONCEBYTES - 4] = increment >> 24; +    num_as_nonce[crypto_box_NONCEBYTES - 3] = increment >> 16; +    num_as_nonce[crypto_box_NONCEBYTES - 2] = increment >> 8; +    num_as_nonce[crypto_box_NONCEBYTES - 1] = increment; -    uint32_t i = crypto_box_NONCEBYTES;      uint_fast16_t carry = 0U; -    for (; i != 0; --i) { +    for (uint32_t i = crypto_box_NONCEBYTES; i != 0; --i) {          carry += (uint_fast16_t)nonce[i - 1] + (uint_fast16_t)num_as_nonce[i - 1];          nonce[i - 1] = (uint8_t)carry;          carry >>= 8;      }  } -/* Fill the given nonce with random bytes. */  void random_nonce(uint8_t *nonce)  {      random_bytes(nonce, crypto_box_NONCEBYTES);  } -/* Fill a key CRYPTO_SYMMETRIC_KEY_SIZE big with random bytes */  void new_symmetric_key(uint8_t *key)  {      random_bytes(key, CRYPTO_SYMMETRIC_KEY_SIZE); @@ -298,7 +368,14 @@ void new_symmetric_key(uint8_t *key)  int32_t crypto_new_keypair(uint8_t *public_key, uint8_t *secret_key)  { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    random_bytes(secret_key, CRYPTO_SECRET_KEY_SIZE); +    memset(public_key, 0, CRYPTO_PUBLIC_KEY_SIZE);  // Make MSAN happy +    crypto_scalarmult_curve25519_base(public_key, secret_key); +    return 0; +#else      return crypto_box_keypair(public_key, secret_key); +#endif  }  void crypto_derive_public_key(uint8_t *public_key, const uint8_t *secret_key) @@ -318,5 +395,9 @@ void crypto_sha512(uint8_t *hash, const uint8_t *data, size_t length)  void random_bytes(uint8_t *data, size_t length)  { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    fuzz_random_bytes(data, length); +#else      randombytes(data, length); +#endif  } diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core.h b/protocols/Tox/libtox/src/toxcore/crypto_core.h index 425c3244f0..f3709abaac 100644 --- a/protocols/Tox/libtox/src/toxcore/crypto_core.h +++ b/protocols/Tox/libtox/src/toxcore/crypto_core.h @@ -3,8 +3,8 @@   * Copyright © 2013 Tox project.   */ -/* - * Functions for the core crypto. +/** @file + * @brief Functions for the core crypto.   */  #ifndef C_TOXCORE_TOXCORE_CRYPTO_CORE_H  #define C_TOXCORE_TOXCORE_CRYPTO_CORE_H @@ -18,182 +18,183 @@ extern "C" {  #endif  /** - * The number of bytes in a Tox public key. + * @brief The number of bytes in a Tox public key used for encryption.   */  #define CRYPTO_PUBLIC_KEY_SIZE         32 -uint32_t crypto_public_key_size(void); -  /** - * The number of bytes in a Tox secret key. + * @brief The number of bytes in a Tox secret key used for encryption.   */  #define CRYPTO_SECRET_KEY_SIZE         32 -uint32_t crypto_secret_key_size(void); -  /** - * The number of bytes in a shared key computed from public and secret keys. + * @brief The number of bytes in a shared key computed from public and secret keys.   */  #define CRYPTO_SHARED_KEY_SIZE         32 -uint32_t crypto_shared_key_size(void); -  /** - * The number of bytes in a symmetric key. + * @brief The number of bytes in a symmetric key.   */  #define CRYPTO_SYMMETRIC_KEY_SIZE      CRYPTO_SHARED_KEY_SIZE -uint32_t crypto_symmetric_key_size(void); -  /** - * The number of bytes needed for the MAC (message authentication code) in an + * @brief The number of bytes needed for the MAC (message authentication code) in an   * encrypted message.   */  #define CRYPTO_MAC_SIZE                16 -uint32_t crypto_mac_size(void); -  /** - * The number of bytes in a nonce used for encryption/decryption. + * @brief The number of bytes in a nonce used for encryption/decryption.   */  #define CRYPTO_NONCE_SIZE              24 -uint32_t crypto_nonce_size(void); -  /** - * The number of bytes in a SHA256 hash. + * @brief The number of bytes in a SHA256 hash.   */  #define CRYPTO_SHA256_SIZE             32 -uint32_t crypto_sha256_size(void); -  /** - * The number of bytes in a SHA512 hash. + * @brief The number of bytes in a SHA512 hash.   */  #define CRYPTO_SHA512_SIZE             64 -uint32_t crypto_sha512_size(void); -  /** - * A `memcmp`-like function whose running time does not depend on the input - * bytes, only on the input length. Useful to compare sensitive data where - * timing attacks could reveal that data. + * @brief A `bzero`-like function which won't be optimised away by the compiler.   * - * This means for instance that comparing "aaaa" and "aaaa" takes 4 time, and - * "aaaa" and "baaa" also takes 4 time. With a regular `memcmp`, the latter may - * take 1 time, because it immediately knows that the two strings are not equal. - */ -int32_t crypto_memcmp(const uint8_t *p1, const uint8_t *p2, size_t length); - -/** - * A `bzero`-like function which won't be optimised away by the compiler. Some - * compilers will inline `bzero` or `memset` if they can prove that there will - * be no reads to the written data. Use this function if you want to be sure the - * memory is indeed zeroed. + * Some compilers will inline `bzero` or `memset` if they can prove that there + * will be no reads to the written data. Use this function if you want to be + * sure the memory is indeed zeroed.   */  void crypto_memzero(void *data, size_t length);  /** - * Compute a SHA256 hash (32 bytes). + * @brief Compute a SHA256 hash (32 bytes).   */  void crypto_sha256(uint8_t *hash, const uint8_t *data, size_t length);  /** - * Compute a SHA512 hash (64 bytes). + * @brief Compute a SHA512 hash (64 bytes).   */  void crypto_sha512(uint8_t *hash, const uint8_t *data, size_t length);  /** - * Compare 2 public keys of length CRYPTO_PUBLIC_KEY_SIZE, not vulnerable to + * @brief Compare 2 public keys of length @ref CRYPTO_PUBLIC_KEY_SIZE, not vulnerable to   * timing attacks.   * - * @return 0 if both mem locations of length are equal, -1 if they are not. + * @retval 0 if both mem locations of length are equal + * @retval -1 if they are not   */  int32_t public_key_cmp(const uint8_t *pk1, const uint8_t *pk2);  /** - * Return a random 8 bit integer. + * @brief Compare 2 SHA512 checksums of length CRYPTO_SHA512_SIZE, not vulnerable to + * timing attacks. + * + * @return 0 if both mem locations of length are equal, -1 if they are not. + */ +int32_t crypto_sha512_cmp(const uint8_t *cksum1, const uint8_t *cksum2); + +/** + * @brief Return a random 8 bit integer.   */  uint8_t random_u08(void);  /** - * Return a random 16 bit integer. + * @brief Return a random 16 bit integer.   */  uint16_t random_u16(void);  /** - * Return a random 32 bit integer. + * @brief Return a random 32 bit integer.   */  uint32_t random_u32(void);  /** - * Return a random 64 bit integer. + * @brief Return a random 64 bit integer.   */  uint64_t random_u64(void);  /** - * Fill the given nonce with random bytes. + * @brief Return a random 32 bit integer between 0 and upper_bound (excluded). + * + * On libsodium builds this function guarantees a uniform distribution of possible outputs. + * On vanilla NACL builds this function is equivalent to `random() % upper_bound`. + */ +uint32_t random_range_u32(uint32_t upper_bound); + +/** + * @brief Fill the given nonce with random bytes.   */  void random_nonce(uint8_t *nonce);  /** - * Fill an array of bytes with random values. + * @brief Fill an array of bytes with random values.   */  void random_bytes(uint8_t *bytes, size_t length);  /** - * Check if a Tox public key CRYPTO_PUBLIC_KEY_SIZE is valid or not. This - * should only be used for input validation. + * @brief Check if a Tox public key CRYPTO_PUBLIC_KEY_SIZE is valid or not. + * + * This should only be used for input validation.   *   * @return false if it isn't, true if it is.   */  bool public_key_valid(const uint8_t *public_key);  /** - * Generate a new random keypair. Every call to this function is likely to - * generate a different keypair. + * @brief Generate a new random keypair. + * + * Every call to this function is likely to generate a different keypair.   */  int32_t crypto_new_keypair(uint8_t *public_key, uint8_t *secret_key);  /** - * Derive the public key from a given secret key. + * @brief Derive the public key from a given secret key.   */  void crypto_derive_public_key(uint8_t *public_key, const uint8_t *secret_key);  /** - * Encrypt plain text of the given length to encrypted of length + - * CRYPTO_MAC_SIZE using the public key (CRYPTO_PUBLIC_KEY_SIZE bytes) of the - * receiver and the secret key of the sender and a CRYPTO_NONCE_SIZE byte - * nonce. + * @brief Encrypt message to send from secret key to public key.   * - * @return -1 if there was a problem, length of encrypted data if everything - * was fine. + * Encrypt plain text of the given length to encrypted of + * `length + CRYPTO_MAC_SIZE` using the public key (@ref CRYPTO_PUBLIC_KEY_SIZE + * bytes) of the receiver and the secret key of the sender and a + * @ref CRYPTO_NONCE_SIZE byte nonce. + * + * @retval -1 if there was a problem. + * @retval >=0 length of encrypted data if everything was fine.   */  int32_t encrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *plain,                       size_t length, uint8_t *encrypted);  /** - * Decrypt encrypted text of the given length to plain text of the given length - * - CRYPTO_MAC_SIZE using the public key (CRYPTO_PUBLIC_KEY_SIZE bytes) of - * the sender, the secret key of the receiver and a CRYPTO_NONCE_SIZE byte - * nonce. + * @brief Decrypt message from public key to secret key. + * + * Decrypt encrypted text of the given @p length to plain text of the given + * `length - CRYPTO_MAC_SIZE` using the public key (@ref CRYPTO_PUBLIC_KEY_SIZE + * bytes) of the sender, the secret key of the receiver and a + * @ref CRYPTO_NONCE_SIZE byte nonce.   * - * @return -1 if there was a problem (decryption failed), length of plain text - * data if everything was fine. + * @retval -1 if there was a problem (decryption failed). + * @retval >=0 length of plain text data if everything was fine.   */  int32_t decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,                       const uint8_t *encrypted, size_t length, uint8_t *plain);  /** - * Fast encrypt/decrypt operations. Use if this is not a one-time communication. - * encrypt_precompute does the shared-key generation once so it does not have - * to be performed on every encrypt/decrypt. + * @brief Fast encrypt/decrypt operations. + * + * Use if this is not a one-time communication. @ref encrypt_precompute does the + * shared-key generation once so it does not have to be performed on every + * encrypt/decrypt.   */  int32_t encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key, uint8_t *shared_key);  /** - * Encrypts plain of length length to encrypted of length + CRYPTO_MAC_SIZE - * using a shared key CRYPTO_SYMMETRIC_KEY_SIZE big and a CRYPTO_NONCE_SIZE + * @brief Encrypt message with precomputed shared key. + * + * Encrypts plain of length length to encrypted of length + @ref CRYPTO_MAC_SIZE + * using a shared key @ref CRYPTO_SYMMETRIC_KEY_SIZE big and a @ref CRYPTO_NONCE_SIZE   * byte nonce.   *   * @return -1 if there was a problem, length of encrypted data if everything @@ -203,9 +204,11 @@ int32_t encrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce,                                 uint8_t *encrypted);  /** + * @brief Decrypt message with precomputed shared key. + *   * Decrypts encrypted of length length to plain of length length - - * CRYPTO_MAC_SIZE using a shared key CRYPTO_SHARED_KEY_SIZE big and a - * CRYPTO_NONCE_SIZE byte nonce. + * @ref CRYPTO_MAC_SIZE using a shared key @ref CRYPTO_SHARED_KEY_SIZE big and a + * @ref CRYPTO_NONCE_SIZE byte nonce.   *   * @return -1 if there was a problem (decryption failed), length of plain data   * if everything was fine. @@ -214,22 +217,46 @@ int32_t decrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce,                                 uint8_t *plain);  /** - * Increment the given nonce by 1 in big endian (rightmost byte incremented + * @brief Increment the given nonce by 1 in big endian (rightmost byte incremented   * first).   */  void increment_nonce(uint8_t *nonce);  /** - * Increment the given nonce by a given number. The number should be in host - * byte order. + * @brief Increment the given nonce by a given number. + * + * The number should be in host byte order.   */ -void increment_nonce_number(uint8_t *nonce, uint32_t host_order_num); +void increment_nonce_number(uint8_t *nonce, uint32_t increment);  /** - * Fill a key CRYPTO_SYMMETRIC_KEY_SIZE big with random bytes. + * @brief Fill a key @ref CRYPTO_SYMMETRIC_KEY_SIZE big with random bytes.   */  void new_symmetric_key(uint8_t *key); +/** + * @brief Locks `length` bytes of memory pointed to by `data`. + * + * This will attempt to prevent the specified memory region from being swapped + * to disk. + * + * @return true on success. + */ +bool crypto_memlock(void *data, size_t length); + +/** + * @brief Unlocks `length` bytes of memory pointed to by `data`. + * + * This allows the specified memory region to be swapped to disk. + * + * This function call has the side effect of zeroing the specified memory region + * whether or not it succeeds. Therefore it should only be used once the memory + * is no longer in use. + * + * @return true on success. + */ +bool crypto_memunlock(void *data, size_t length); +  #ifdef __cplusplus  }  // extern "C"  #endif diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core_mem.c b/protocols/Tox/libtox/src/toxcore/crypto_core_mem.c deleted file mode 100644 index b8c0bd9b98..0000000000 --- a/protocols/Tox/libtox/src/toxcore/crypto_core_mem.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * ISC License - * - * Copyright (c) 2013-2016 - * Frank Denis <j at pureftpd dot org> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "crypto_core.h" - -#ifndef VANILLA_NACL -/* We use libsodium by default. */ -#include <sodium.h> -#else -#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) -#include <windows.h> -#include <wincrypt.h> -#endif -#endif - - -void crypto_memzero(void *data, size_t length) -{ -#ifndef VANILLA_NACL -    sodium_memzero(data, length); -#elif defined(_WIN32) -    SecureZeroMemory(data, length); -#elif defined(HAVE_MEMSET_S) - -    if (length > 0U) { -        errno_t code = memset_s(data, (rsize_t) length, 0, (rsize_t) length); - -        if (code != 0) { -            abort(); /* LCOV_EXCL_LINE */ -        } -    } - -#elif defined(HAVE_EXPLICIT_BZERO) -    explicit_bzero(data, length); -#else -    //!TOKSTYLE- -    volatile uint8_t *volatile pnt = data; -    //!TOKSTYLE+ -    size_t i = (size_t) 0U; - -    while (i < length) { -        pnt[i] = 0U; -        ++i; -    } - -#endif -} - -int32_t crypto_memcmp(const uint8_t *p1, const uint8_t *p2, size_t length) -{ -#ifndef VANILLA_NACL -    return sodium_memcmp(p1, p2, length); -#else -    //!TOKSTYLE- -    const volatile uint8_t *volatile b1 = p1; -    const volatile uint8_t *volatile b2 = p2; -    //!TOKSTYLE+ - -    size_t i; -    uint8_t d = (uint8_t) 0U; - -    for (i = 0U; i < length; ++i) { -        d |= b1[i] ^ b2[i]; -    } - -    return (1 & ((d - 1) >> 8)) - 1; -#endif -} diff --git a/protocols/Tox/libtox/src/toxcore/friend_connection.c b/protocols/Tox/libtox/src/toxcore/friend_connection.c index 496b83b505..8a46194848 100644 --- a/protocols/Tox/libtox/src/toxcore/friend_connection.c +++ b/protocols/Tox/libtox/src/toxcore/friend_connection.c @@ -3,13 +3,9 @@   * Copyright © 2014 Tox project.   */ -/* +/**   * Connection to friends.   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -  #include "friend_connection.h"  #include <stdlib.h> @@ -29,7 +25,7 @@ typedef struct Friend_Conn_Callbacks {      int callback_id;  } Friend_Conn_Callbacks; -typedef struct Friend_Conn { +struct Friend_Conn {      uint8_t status;      uint8_t real_public_key[CRYPTO_PUBLIC_KEY_SIZE]; @@ -54,7 +50,7 @@ typedef struct Friend_Conn {      uint16_t tcp_relay_counter;      bool hosting_tcp_relay; -} Friend_Conn; +};  struct Friend_Connections { @@ -79,13 +75,23 @@ struct Friend_Connections {      bool local_discovery_enabled;  }; +int friend_conn_get_onion_friendnum(const Friend_Conn *fc) +{ +    return fc->onion_friendnum; +} +  Net_Crypto *friendconn_net_crypto(const Friend_Connections *fr_c)  {      return fr_c->net_crypto;  } +const IP_Port *friend_conn_get_dht_ip_port(const Friend_Conn *fc) +{ +    return &fc->dht_ip_port; +} + -/* return true if the friendcon_id is valid. +/** return true if the friendcon_id is valid.   * return false if the friendcon_id is not valid.   */  static bool friendconn_id_valid(const Friend_Connections *fr_c, int friendcon_id) @@ -96,7 +102,7 @@ static bool friendconn_id_valid(const Friend_Connections *fr_c, int friendcon_id  } -/* Set the size of the friend connections list to num. +/** Set the size of the friend connections list to num.   *   *  return false if realloc fails.   *  return true if it succeeds. @@ -119,7 +125,7 @@ static bool realloc_friendconns(Friend_Connections *fr_c, uint32_t num)      return true;  } -/* Create a new empty friend connection. +/** Create a new empty friend connection.   *   * return -1 on failure.   * return friendcon_id on success. @@ -143,7 +149,7 @@ static int create_friend_conn(Friend_Connections *fr_c)      return id;  } -/* Wipe a friend connection. +/** Wipe a friend connection.   *   * return -1 on failure.   * return 0 on success. @@ -172,7 +178,7 @@ static int wipe_friend_conn(Friend_Connections *fr_c, int friendcon_id)      return 0;  } -static Friend_Conn *get_conn(const Friend_Connections *fr_c, int friendcon_id) +Friend_Conn *get_conn(const Friend_Connections *fr_c, int friendcon_id)  {      if (!friendconn_id_valid(fr_c, friendcon_id)) {          return nullptr; @@ -181,13 +187,13 @@ static Friend_Conn *get_conn(const Friend_Connections *fr_c, int friendcon_id)      return &fr_c->conns[friendcon_id];  } -/* return friendcon_id corresponding to the real public key on success. +/** return friendcon_id corresponding to the real public key on success.   * return -1 on failure.   */ -int getfriend_conn_id_pk(Friend_Connections *fr_c, const uint8_t *real_pk) +int getfriend_conn_id_pk(const Friend_Connections *fr_c, const uint8_t *real_pk)  {      for (uint32_t i = 0; i < fr_c->num_cons; ++i) { -        Friend_Conn *friend_con = get_conn(fr_c, i); +        const Friend_Conn *friend_con = get_conn(fr_c, i);          if (friend_con) {              if (public_key_cmp(friend_con->real_public_key, real_pk) == 0) { @@ -199,13 +205,16 @@ int getfriend_conn_id_pk(Friend_Connections *fr_c, const uint8_t *real_pk)      return -1;  } -/* Add a TCP relay associated to the friend. +/** Add a TCP relay associated to the friend.   *   * return -1 on failure.   * return 0 on success.   */ -int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, IP_Port ip_port, const uint8_t *public_key) +static int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, const IP_Port *ip_port, +                                const uint8_t *public_key)  { +    IP_Port ipp_copy = *ip_port; +      Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id);      if (!friend_con) { @@ -213,9 +222,9 @@ int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, IP_Port ip_      }      /* Local ip and same pk means that they are hosting a TCP relay. */ -    if (ip_is_local(ip_port.ip) && public_key_cmp(friend_con->dht_temp_pk, public_key) == 0) { +    if (ip_is_local(&ipp_copy.ip) && public_key_cmp(friend_con->dht_temp_pk, public_key) == 0) {          if (!net_family_is_unspec(friend_con->dht_ip_port.ip.family)) { -            ip_port.ip = friend_con->dht_ip_port.ip; +            ipp_copy.ip = friend_con->dht_ip_port.ip;          } else {              friend_con->hosting_tcp_relay = 0;          } @@ -230,14 +239,14 @@ int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, IP_Port ip_          }      } -    friend_con->tcp_relays[index].ip_port = ip_port; +    friend_con->tcp_relays[index].ip_port = ipp_copy;      memcpy(friend_con->tcp_relays[index].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);      ++friend_con->tcp_relay_counter; -    return add_tcp_relay_peer(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, public_key); +    return add_tcp_relay_peer(fr_c->net_crypto, friend_con->crypt_connection_id, &ipp_copy, public_key);  } -/* Connect to number saved relays for friend. */ +/** Connect to number saved relays for friend. */  static void connect_to_saved_tcp_relays(Friend_Connections *fr_c, int friendcon_id, unsigned int number)  {      const Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id); @@ -250,7 +259,7 @@ static void connect_to_saved_tcp_relays(Friend_Connections *fr_c, int friendcon_          const uint16_t index = (friend_con->tcp_relay_counter - (i + 1)) % FRIEND_MAX_STORED_TCP_RELAYS;          if (!net_family_is_unspec(friend_con->tcp_relays[index].ip_port.ip.family)) { -            if (add_tcp_relay_peer(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->tcp_relays[index].ip_port, +            if (add_tcp_relay_peer(fr_c->net_crypto, friend_con->crypt_connection_id, &friend_con->tcp_relays[index].ip_port,                                     friend_con->tcp_relays[index].public_key) == 0) {                  --number;              } @@ -266,7 +275,7 @@ static unsigned int send_relays(Friend_Connections *fr_c, int friendcon_id)          return 0;      } -    Node_format nodes[MAX_SHARED_RELAYS]; +    Node_format nodes[MAX_SHARED_RELAYS] = {{{0}}};      uint8_t data[1024];      const int n = copy_connected_tcp_relays(fr_c->net_crypto, nodes, MAX_SHARED_RELAYS); @@ -274,7 +283,7 @@ static unsigned int send_relays(Friend_Connections *fr_c, int friendcon_id)      for (int i = 0; i < n; ++i) {          /* Associated the relays being sent with this connection.           * On receiving the peer will do the same which will establish the connection. */ -        friend_add_tcp_relay(fr_c, friendcon_id, nodes[i].ip_port, nodes[i].public_key); +        friend_add_tcp_relay(fr_c, friendcon_id, &nodes[i].ip_port, nodes[i].public_key);      }      int length = pack_nodes(data + 1, sizeof(data) - 1, nodes, n); @@ -294,8 +303,8 @@ static unsigned int send_relays(Friend_Connections *fr_c, int friendcon_id)      return 0;  } -/* callback for recv TCP relay nodes. */ -static int tcp_relay_node_callback(void *object, uint32_t number, IP_Port ip_port, const uint8_t *public_key) +/** callback for recv TCP relay nodes. */ +static int tcp_relay_node_callback(void *object, uint32_t number, const IP_Port *ip_port, const uint8_t *public_key)  {      Friend_Connections *fr_c = (Friend_Connections *)object;      const Friend_Conn *friend_con = get_conn(fr_c, number); @@ -312,8 +321,8 @@ static int tcp_relay_node_callback(void *object, uint32_t number, IP_Port ip_por  }  static int friend_new_connection(Friend_Connections *fr_c, int friendcon_id); -/* Callback for DHT ip_port changes. */ -static void dht_ip_callback(void *object, int32_t number, IP_Port ip_port) +/** Callback for DHT ip_port changes. */ +static void dht_ip_callback(void *object, int32_t number, const IP_Port *ip_port)  {      Friend_Connections *const fr_c = (Friend_Connections *)object;      Friend_Conn *const friend_con = get_conn(fr_c, number); @@ -327,7 +336,7 @@ static void dht_ip_callback(void *object, int32_t number, IP_Port ip_port)      }      set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, 1); -    friend_con->dht_ip_port = ip_port; +    friend_con->dht_ip_port = *ip_port;      friend_con->dht_ip_port_lastrecv = mono_time_get(fr_c->mono_time);      if (friend_con->hosting_tcp_relay) { @@ -405,7 +414,7 @@ static int handle_status(void *object, int number, uint8_t status, void *userdat      return 0;  } -/* Callback for dht public key changes. */ +/** Callback for dht public key changes. */  static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_public_key, void *userdata)  {      Friend_Connections *const fr_c = (Friend_Connections *)object; @@ -467,7 +476,7 @@ static int handle_packet(void *object, int number, const uint8_t *data, uint16_t          }          for (int j = 0; j < n; ++j) { -            friend_add_tcp_relay(fr_c, number, nodes[j].ip_port, nodes[j].public_key); +            friend_add_tcp_relay(fr_c, number, &nodes[j].ip_port, nodes[j].public_key);          }          return 0; @@ -496,7 +505,7 @@ static int handle_lossy_packet(void *object, int number, const uint8_t *data, ui          return -1;      } -    Friend_Connections *const fr_c = (Friend_Connections *)object; +    const Friend_Connections *const fr_c = (const Friend_Connections *)object;      const Friend_Conn *friend_con = get_conn(fr_c, number);      if (!friend_con) { @@ -520,7 +529,7 @@ static int handle_lossy_packet(void *object, int number, const uint8_t *data, ui      return 0;  } -static int handle_new_connections(void *object, New_Connection *n_c) +static int handle_new_connections(void *object, const New_Connection *n_c)  {      Friend_Connections *const fr_c = (Friend_Connections *)object;      const int friendcon_id = getfriend_conn_id_pk(fr_c, n_c->public_key); @@ -546,7 +555,7 @@ static int handle_new_connections(void *object, New_Connection *n_c)      friend_con->crypt_connection_id = id;      if (!net_family_is_ipv4(n_c->source.ip.family) && !net_family_is_ipv6(n_c->source.ip.family)) { -        set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0); +        set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, &friend_con->dht_ip_port, 0);      } else {          friend_con->dht_ip_port = n_c->source;          friend_con->dht_ip_port_lastrecv = mono_time_get(fr_c->mono_time); @@ -611,12 +620,12 @@ static int send_ping(const Friend_Connections *fr_c, int friendcon_id)      return -1;  } -/* Increases lock_count for the connection with friendcon_id by 1. +/** Increases lock_count for the connection with friendcon_id by 1.   *   * return 0 on success.   * return -1 on failure.   */ -int friend_connection_lock(Friend_Connections *fr_c, int friendcon_id) +int friend_connection_lock(const Friend_Connections *fr_c, int friendcon_id)  {      Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id); @@ -628,11 +637,11 @@ int friend_connection_lock(Friend_Connections *fr_c, int friendcon_id)      return 0;  } -/* return FRIENDCONN_STATUS_CONNECTED if the friend is connected. +/** return FRIENDCONN_STATUS_CONNECTED if the friend is connected.   * return FRIENDCONN_STATUS_CONNECTING if the friend isn't connected.   * return FRIENDCONN_STATUS_NONE on failure.   */ -unsigned int friend_con_connected(Friend_Connections *fr_c, int friendcon_id) +unsigned int friend_con_connected(const Friend_Connections *fr_c, int friendcon_id)  {      const Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id); @@ -643,12 +652,12 @@ unsigned int friend_con_connected(Friend_Connections *fr_c, int friendcon_id)      return friend_con->status;  } -/* Copy public keys associated to friendcon_id. +/** Copy public keys associated to friendcon_id.   *   * return 0 on success.   * return -1 on failure.   */ -int get_friendcon_public_keys(uint8_t *real_pk, uint8_t *dht_temp_pk, Friend_Connections *fr_c, int friendcon_id) +int get_friendcon_public_keys(uint8_t *real_pk, uint8_t *dht_temp_pk, const Friend_Connections *fr_c, int friendcon_id)  {      const Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id); @@ -667,20 +676,20 @@ int get_friendcon_public_keys(uint8_t *real_pk, uint8_t *dht_temp_pk, Friend_Con      return 0;  } -/* Set temp dht key for connection. +/** Set temp dht key for connection.   */  void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_temp_pk, void *userdata)  {      dht_pk_callback(fr_c, friendcon_id, dht_temp_pk, userdata);  } -/* Set the callbacks for the friend connection. +/** 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.   *   * return 0 on success.   * return -1 on failure   */ -int friend_connection_callbacks(Friend_Connections *fr_c, int friendcon_id, unsigned int index, +int friend_connection_callbacks(const Friend_Connections *fr_c, int friendcon_id, unsigned int index,                                  fc_status_cb *status_callback,                                  fc_data_cb *data_callback,                                  fc_lossy_data_cb *lossy_data_callback, @@ -706,19 +715,19 @@ int friend_connection_callbacks(Friend_Connections *fr_c, int friendcon_id, unsi      return 0;  } -/* Set global status callback for friend connections. */ +/** 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 the crypt_connection_id for the connection.   *   * return crypt_connection_id on success.   * return -1 on failure.   */ -int friend_connection_crypt_connection_id(Friend_Connections *fr_c, int friendcon_id) +int friend_connection_crypt_connection_id(const Friend_Connections *fr_c, int friendcon_id)  {      const Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id); @@ -729,7 +738,7 @@ int friend_connection_crypt_connection_id(Friend_Connections *fr_c, int friendco      return friend_con->crypt_connection_id;  } -/* Create a new friend connection. +/** Create a new friend connection.   * If one to that real public key already exists, increase lock count and return it.   *   * return -1 on failure. @@ -769,7 +778,7 @@ int new_friend_connection(Friend_Connections *fr_c, const uint8_t *real_public_k      return friendcon_id;  } -/* Kill a friend connection. +/** Kill a friend connection.   *   * return -1 on failure.   * return 0 on success. @@ -798,7 +807,7 @@ int kill_friend_connection(Friend_Connections *fr_c, int friendcon_id)  } -/* Set friend request callback. +/** Set friend request callback.   *   * This function will be called every time a friend request packet is received.   */ @@ -809,7 +818,7 @@ void set_friend_request_callback(Friend_Connections *fr_c, fr_request_cb *fr_req      oniondata_registerhandler(fr_c->onion_c, CRYPTO_PACKET_FRIEND_REQ, fr_request_callback, object);  } -/* Send a Friend request packet. +/** Send a Friend request packet.   *   *  return -1 if failure.   *  return  0 if it sent the friend request directly to the friend. @@ -847,7 +856,7 @@ int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint3      return num;  } -/* Create new friend_connections instance. */ +/** Create new friend_connections instance. */  Friend_Connections *new_friend_connections(const Logger *logger, const Mono_Time *mono_time, Onion_Client *onion_c,          bool local_discovery_enabled)  { @@ -879,7 +888,7 @@ Friend_Connections *new_friend_connections(const Logger *logger, const Mono_Time      return temp;  } -/* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */ +/** Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */  static void lan_discovery(Friend_Connections *fr_c)  {      if (fr_c->last_lan_discovery + LAN_DISCOVERY_INTERVAL < mono_time_get(fr_c->mono_time)) { @@ -888,11 +897,11 @@ static void lan_discovery(Friend_Connections *fr_c)          last = last > TOX_PORTRANGE_TO ? TOX_PORTRANGE_TO : last;          // Always send to default port -        lan_discovery_send(net_htons(TOX_PORT_DEFAULT), fr_c->dht); +        lan_discovery_send(dht_get_net(fr_c->dht), dht_get_self_public_key(fr_c->dht), net_htons(TOX_PORT_DEFAULT));          // And check some extra ports          for (uint16_t port = first; port < last; ++port) { -            lan_discovery_send(net_htons(port), fr_c->dht); +            lan_discovery_send(dht_get_net(fr_c->dht), dht_get_self_public_key(fr_c->dht), net_htons(port));          }          // Don't include default port in port range @@ -901,7 +910,7 @@ static void lan_discovery(Friend_Connections *fr_c)      }  } -/* main friend_connections loop. */ +/** main friend_connections loop. */  void do_friend_connections(Friend_Connections *fr_c, void *userdata)  {      const uint64_t temp_time = mono_time_get(fr_c->mono_time); @@ -925,8 +934,8 @@ void do_friend_connections(Friend_Connections *fr_c, void *userdata)                  if (friend_con->dht_lock) {                      if (friend_new_connection(fr_c, i) == 0) { -                        set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0); -                        connect_to_saved_tcp_relays(fr_c, i, (MAX_FRIEND_TCP_CONNECTIONS / 2)); /* Only fill it half up. */ +                        set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, &friend_con->dht_ip_port, 0); +                        connect_to_saved_tcp_relays(fr_c, i, MAX_FRIEND_TCP_CONNECTIONS / 2); /* Only fill it half up. */                      }                  }              } else if (friend_con->status == FRIENDCONN_STATUS_CONNECTED) { @@ -953,7 +962,7 @@ void do_friend_connections(Friend_Connections *fr_c, void *userdata)      }  } -/* Free everything related with friend_connections. */ +/** Free everything related with friend_connections. */  void kill_friend_connections(Friend_Connections *fr_c)  {      if (!fr_c) { diff --git a/protocols/Tox/libtox/src/toxcore/friend_connection.h b/protocols/Tox/libtox/src/toxcore/friend_connection.h index fecd745565..4986b3bfb9 100644 --- a/protocols/Tox/libtox/src/toxcore/friend_connection.h +++ b/protocols/Tox/libtox/src/toxcore/friend_connection.h @@ -3,7 +3,7 @@   * Copyright © 2014 Tox project.   */ -/* +/**   * Connection to friends.   */  #ifndef C_TOXCORE_TOXCORE_FRIEND_CONNECTION_H @@ -22,21 +22,21 @@  #define PACKET_ID_SHARE_RELAYS 17  #define PACKET_ID_FRIEND_REQUESTS 18 -/* Interval between the sending of ping packets. */ +/** Interval between the sending of ping packets. */  #define FRIEND_PING_INTERVAL 8 -/* If no packets are received from friend in this time interval, kill the connection. */ +/** If no packets are received from friend in this time interval, kill the connection. */  #define FRIEND_CONNECTION_TIMEOUT (FRIEND_PING_INTERVAL * 4) -/* Time before friend is removed from the DHT after last hearing about him. */ +/** Time before friend is removed from the DHT after last hearing about him. */  #define FRIEND_DHT_TIMEOUT BAD_NODE_TIMEOUT  #define FRIEND_MAX_STORED_TCP_RELAYS (MAX_FRIEND_TCP_CONNECTIONS * 4) -/* Max number of tcp relays sent to friends */ +/** Max number of tcp relays sent to friends */  #define MAX_SHARED_RELAYS RECOMMENDED_FRIEND_TCP_CONNECTIONS -/* Interval between the sending of tcp relay information */ +/** Interval between the sending of tcp relay information */  #define SHARE_RELAYS_INTERVAL (5 * 60) @@ -50,71 +50,64 @@ typedef struct Friend_Connections Friend_Connections;  Net_Crypto *friendconn_net_crypto(const Friend_Connections *fr_c); -/* return friendcon_id corresponding to the real public key on success. +/** return friendcon_id corresponding to the real public key on success.   * return -1 on failure.   */ -int getfriend_conn_id_pk(Friend_Connections *fr_c, const uint8_t *real_pk); +int getfriend_conn_id_pk(const Friend_Connections *fr_c, const uint8_t *real_pk); -/* Increases lock_count for the connection with friendcon_id by 1. +/** Increases lock_count for the connection with friendcon_id by 1.   *   * return 0 on success.   * return -1 on failure.   */ -int friend_connection_lock(Friend_Connections *fr_c, int friendcon_id); +int friend_connection_lock(const Friend_Connections *fr_c, int friendcon_id); -/* return FRIENDCONN_STATUS_CONNECTED if the friend is connected. +/** return FRIENDCONN_STATUS_CONNECTED if the friend is connected.   * return FRIENDCONN_STATUS_CONNECTING if the friend isn't connected.   * return FRIENDCONN_STATUS_NONE on failure.   */ -unsigned int friend_con_connected(Friend_Connections *fr_c, int friendcon_id); +unsigned int friend_con_connected(const Friend_Connections *fr_c, int friendcon_id); -/* Copy public keys associated to friendcon_id. +/** Copy public keys associated to friendcon_id.   *   * return 0 on success.   * return -1 on failure.   */ -int get_friendcon_public_keys(uint8_t *real_pk, uint8_t *dht_temp_pk, Friend_Connections *fr_c, int friendcon_id); +int get_friendcon_public_keys(uint8_t *real_pk, uint8_t *dht_temp_pk, const Friend_Connections *fr_c, int friendcon_id); -/* Set temp dht key for connection. +/** Set temp dht key for connection.   */  void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_temp_pk, void *userdata); -/* Add a TCP relay associated to the friend. - * - * return -1 on failure. - * return 0 on success. - */ -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. */ +/** 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. +/** 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.   *   * return 0 on success.   * return -1 on failure   */ -int friend_connection_callbacks(Friend_Connections *fr_c, int friendcon_id, unsigned int index, +int friend_connection_callbacks(const Friend_Connections *fr_c, int friendcon_id, unsigned int index,                                  fc_status_cb *status_callback,                                  fc_data_cb *data_callback,                                  fc_lossy_data_cb *lossy_data_callback,                                  void *object, int number); -/* return the crypt_connection_id for the connection. +/** return the crypt_connection_id for the connection.   *   * return crypt_connection_id on success.   * return -1 on failure.   */ -int friend_connection_crypt_connection_id(Friend_Connections *fr_c, int friendcon_id); +int friend_connection_crypt_connection_id(const Friend_Connections *fr_c, int friendcon_id); -/* Create a new friend connection. +/** Create a new friend connection.   * If one to that real public key already exists, increase lock count and return it.   *   * return -1 on failure. @@ -122,14 +115,14 @@ int friend_connection_crypt_connection_id(Friend_Connections *fr_c, int friendco   */  int new_friend_connection(Friend_Connections *fr_c, const uint8_t *real_public_key); -/* Kill a friend connection. +/** Kill a friend connection.   *   * return -1 on failure.   * return 0 on success.   */  int kill_friend_connection(Friend_Connections *fr_c, int friendcon_id); -/* Send a Friend request packet. +/** Send a Friend request packet.   *   *  return -1 if failure.   *  return  0 if it sent the friend request directly to the friend. @@ -141,20 +134,26 @@ int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint3  typedef int fr_request_cb(void *object, const uint8_t *source_pubkey, const uint8_t *data, uint16_t len,                            void *userdata); -/* Set friend request callback. +/** Set friend request callback.   * - * This function will be called every time a friend request is received. + * This function will be called every time a friend request packet is received.   */  void set_friend_request_callback(Friend_Connections *fr_c, fr_request_cb *fr_request_callback, void *object); -/* Create new friend_connections instance. */ +/** Create new friend_connections instance. */  Friend_Connections *new_friend_connections(const Logger *logger, const Mono_Time *mono_time, Onion_Client *onion_c,          bool local_discovery_enabled); -/* main friend_connections loop. */ +/** main friend_connections loop. */  void do_friend_connections(Friend_Connections *fr_c, void *userdata); -/* Free everything related with friend_connections. */ +/** Free everything related with friend_connections. */  void kill_friend_connections(Friend_Connections *fr_c); +typedef struct Friend_Conn Friend_Conn; + +Friend_Conn *get_conn(const Friend_Connections *fr_c, int friendcon_id); +int friend_conn_get_onion_friendnum(const Friend_Conn *fc); +const IP_Port *friend_conn_get_dht_ip_port(const Friend_Conn *fc); +  #endif diff --git a/protocols/Tox/libtox/src/toxcore/friend_requests.c b/protocols/Tox/libtox/src/toxcore/friend_requests.c index c6c9a0e048..f4d572996d 100644 --- a/protocols/Tox/libtox/src/toxcore/friend_requests.c +++ b/protocols/Tox/libtox/src/toxcore/friend_requests.c @@ -3,13 +3,9 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * Handle friend requests.   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -  #include "friend_requests.h"  #include <stdlib.h> @@ -17,7 +13,7 @@  #include "util.h" -/* NOTE: The following is just a temporary fix for the multiple friend requests received at the same time problem. +/** NOTE: The following is just a temporary fix for the multiple friend requests received at the same time problem.   * TODO(irungentoo): Make this better (This will most likely tie in with the way we will handle spam.)   */  #define MAX_RECEIVED_STORED 32 @@ -39,7 +35,7 @@ struct Friend_Requests {      struct Received_Requests received;  }; -/* Set and get the nospam variable used to prevent one type of friend request spam. */ +/** Set and get the nospam variable used to prevent one type of friend request spam. */  void set_nospam(Friend_Requests *fr, uint32_t num)  {      fr->nospam = num; @@ -51,7 +47,8 @@ uint32_t get_nospam(const Friend_Requests *fr)  } -/* Set the function that will be executed when a friend request is received. */ +/** Set the function that will be executed when a friend request for us is received. + */  void callback_friendrequest(Friend_Requests *fr, fr_friend_request_cb *function, void *object)  {      fr->handle_friendrequest = function; @@ -59,14 +56,16 @@ void callback_friendrequest(Friend_Requests *fr, fr_friend_request_cb *function,      fr->handle_friendrequest_object = object;  } -/* Set the function used to check if a friend request should be displayed to the user or not. */ +/** Set the function used to check if a friend request should be displayed to the user or not. + * It must return 0 if the request is ok (anything else if it is bad.) + */  void set_filter_function(Friend_Requests *fr, filter_function_cb *function, void *userdata)  {      fr->filter_function = function;      fr->filter_function_userdata = userdata;  } -/* Add to list of received friend requests. */ +/** Add to list of received friend requests. */  static void addto_receivedlist(Friend_Requests *fr, const uint8_t *real_pk)  {      if (fr->received.requests_index >= MAX_RECEIVED_STORED) { @@ -77,7 +76,7 @@ static void addto_receivedlist(Friend_Requests *fr, const uint8_t *real_pk)      ++fr->received.requests_index;  } -/* Check if a friend request was already received. +/** Check if a friend request was already received.   *   *  return false if it did not.   *  return true if it did. @@ -93,7 +92,7 @@ static bool request_received(const Friend_Requests *fr, const uint8_t *real_pk)      return false;  } -/* Remove real pk from received.requests list. +/** Remove real_pk from received_requests list.   *   *  return 0 if it removed it successfully.   *  return -1 if it didn't find it. diff --git a/protocols/Tox/libtox/src/toxcore/friend_requests.h b/protocols/Tox/libtox/src/toxcore/friend_requests.h index e3a03a51e8..bb2b10b81c 100644 --- a/protocols/Tox/libtox/src/toxcore/friend_requests.h +++ b/protocols/Tox/libtox/src/toxcore/friend_requests.h @@ -3,7 +3,7 @@   * Copyright © 2014 Tox project.   */ -/* +/**   * Handle friend requests.   */  #ifndef C_TOXCORE_TOXCORE_FRIEND_REQUESTS_H @@ -15,11 +15,11 @@  typedef struct Friend_Requests Friend_Requests; -/* Set and get the nospam variable used to prevent one type of friend request spam. */ +/** Set and get the nospam variable used to prevent one type of friend request spam. */  void set_nospam(Friend_Requests *fr, uint32_t num);  uint32_t get_nospam(const Friend_Requests *fr); -/* Remove real_pk from received_requests list. +/** Remove real_pk from received_requests list.   *   *  return 0 if it removed it successfully.   *  return -1 if it didn't find it. @@ -29,18 +29,18 @@ int remove_request_received(Friend_Requests *fr, const uint8_t *real_pk);  typedef void fr_friend_request_cb(void *object, const uint8_t *public_key, const uint8_t *message, size_t length,                                    void *user_data); -/* Set the function that will be executed when a friend request for us is received. +/** Set the function that will be executed when a friend request for us is received.   */  void callback_friendrequest(Friend_Requests *fr, fr_friend_request_cb *function, void *object);  typedef int filter_function_cb(const uint8_t *public_key, void *user_data); -/* Set the function used to check if a friend request should be displayed to the user or not. +/** Set the function used to check if a friend request should be displayed to the user or not.   * It must return 0 if the request is ok (anything else if it is bad.)   */  void set_filter_function(Friend_Requests *fr, filter_function_cb *function, void *userdata); -/* Sets up friendreq packet handlers. */ +/** Sets up friendreq packet handlers. */  void friendreq_init(Friend_Requests *fr, Friend_Connections *fr_c);  Friend_Requests *friendreq_new(void); diff --git a/protocols/Tox/libtox/src/toxcore/group.c b/protocols/Tox/libtox/src/toxcore/group.c index 4b331f986e..fd7c491a1d 100644 --- a/protocols/Tox/libtox/src/toxcore/group.c +++ b/protocols/Tox/libtox/src/toxcore/group.c @@ -3,13 +3,9 @@   * Copyright © 2014 Tox project.   */ -/* +/**   * Slightly better groupchats implementation.   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -  #include "group.h"  #include <assert.h> @@ -58,7 +54,15 @@ typedef enum Peer_Id {  #define MIN_MESSAGE_PACKET_LEN (sizeof(uint16_t) * 2 + sizeof(uint32_t) + 1) -/* return false if the groupnumber is not valid. +static_assert(GROUP_ID_LENGTH == CRYPTO_PUBLIC_KEY_SIZE, +              "GROUP_ID_LENGTH should be equal to CRYPTO_PUBLIC_KEY_SIZE"); + +static bool group_id_eq(const uint8_t *a, const uint8_t *b) +{ +    return public_key_cmp(a, b) == 0; +} + +/** return false if the groupnumber is not valid.   * return true if the groupnumber is valid.   */  static bool is_groupnumber_valid(const Group_Chats *g_c, uint32_t groupnumber) @@ -69,7 +73,7 @@ static bool is_groupnumber_valid(const Group_Chats *g_c, uint32_t groupnumber)  } -/* Set the size of the groupchat list to num. +/** Set the size of the groupchat list to num.   *   *  return false if realloc fails.   *  return true if it succeeds. @@ -99,7 +103,7 @@ static void setup_conference(Group_c *g)      g->maxfrozen = MAX_FROZEN_DEFAULT;  } -/* Create a new empty groupchat connection. +/** Create a new empty groupchat connection.   *   * return -1 on failure.   * return groupnumber on success. @@ -123,7 +127,7 @@ static int32_t create_group_chat(Group_Chats *g_c)  } -/* Wipe a groupchat. +/** Wipe a groupchat.   *   * return true on success.   */ @@ -159,7 +163,7 @@ static Group_c *get_group_c(const Group_Chats *g_c, uint32_t groupnumber)      return &g_c->chats[groupnumber];  } -/* +/**   * check if peer with real_pk is in peer array.   *   * return peer index if peer is in group. @@ -167,7 +171,6 @@ static Group_c *get_group_c(const Group_Chats *g_c, uint32_t groupnumber)   *   * TODO(irungentoo): make this more efficient.   */ -  static int peer_in_group(const Group_c *g, const uint8_t *real_pk)  {      for (uint32_t i = 0; i < g->numpeers; ++i) { @@ -190,7 +193,7 @@ static int frozen_in_group(const Group_c *g, const uint8_t *real_pk)      return -1;  } -/* +/**   * check if group with the given type and id is in group array.   *   * return group number if peer is in list. @@ -201,7 +204,7 @@ static int frozen_in_group(const Group_c *g, const uint8_t *real_pk)  static int32_t get_group_num(const Group_Chats *g_c, const uint8_t type, const uint8_t *id)  {      for (uint16_t i = 0; i < g_c->num_chats; ++i) { -        if (g_c->chats[i].type == type && crypto_memcmp(g_c->chats[i].id, id, GROUP_ID_LENGTH) == 0) { +        if (g_c->chats[i].type == type && group_id_eq(g_c->chats[i].id, id)) {              return i;          }      } @@ -212,7 +215,7 @@ static int32_t get_group_num(const Group_Chats *g_c, const uint8_t type, const u  int32_t conference_by_id(const Group_Chats *g_c, const uint8_t *id)  {      for (uint16_t i = 0; i < g_c->num_chats; ++i) { -        if (crypto_memcmp(g_c->chats[i].id, id, GROUP_ID_LENGTH) == 0) { +        if (group_id_eq(g_c->chats[i].id, id)) {              return i;          }      } @@ -220,7 +223,7 @@ int32_t conference_by_id(const Group_Chats *g_c, const uint8_t *id)      return -1;  } -/* +/**   * check if peer with peer_number is in peer array.   *   * return peer index if peer is in chat. @@ -295,7 +298,7 @@ static bool add_to_closest(Group_c *g, const uint8_t *real_pk, const uint8_t *te          comp_val = calculate_comp_value(real_pk, g->real_pk); -        for (unsigned int i = (DESIRED_CLOSEST / 2); i < DESIRED_CLOSEST; ++i) { +        for (unsigned int i = DESIRED_CLOSEST / 2; i < DESIRED_CLOSEST; ++i) {              uint64_t comp = calculate_comp_value(g->closest_peers[i].real_pk, g->real_pk);              if (comp > comp_val && comp > comp_d) { @@ -334,7 +337,7 @@ static bool add_to_closest(Group_c *g, const uint8_t *real_pk, const uint8_t *te      return true;  } -static bool pk_in_closest_peers(const Group_c *g, uint8_t *real_pk) +static bool pk_in_closest_peers(const Group_c *g, const uint8_t *real_pk)  {      for (unsigned int i = 0; i < DESIRED_CLOSEST; ++i) {          if (!g->closest_peers[i].entry) { @@ -377,8 +380,8 @@ static void purge_closest(Group_Chats *g_c, uint32_t groupnumber)      }  } -static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t type, -                              const uint8_t *id); +static int send_packet_online(const Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, +                              uint8_t type, const uint8_t *id);  static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, Group_c *g, uint8_t reason,                                   uint8_t lock); @@ -483,7 +486,7 @@ static bool delete_frozen(Group_c *g, uint32_t 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)); +        Group_Peer *const frozen_temp = (Group_Peer *)realloc(g->frozen, sizeof(Group_Peer) * g->numfrozen);          if (frozen_temp == nullptr) {              return false; @@ -495,7 +498,7 @@ static bool delete_frozen(Group_c *g, uint32_t frozen_index)      return true;  } -/* Update last_active timestamp on peer, and thaw the peer if it is frozen. +/** Update last_active timestamp on peer, and thaw the peer if it is frozen.   *   * return peer index if peer is in the conference.   * return -1 otherwise, and on error. @@ -578,7 +581,7 @@ static void delete_any_peer_with_pk(Group_Chats *g_c, uint32_t groupnumber, cons      }  } -/* Add a peer to the group chat, or update an existing peer. +/** Add a peer to the group chat, or update an existing peer.   *   * fresh indicates whether we should consider this information on the peer to   * be current, and so should update temp_pk and consider the peer active. @@ -686,7 +689,7 @@ static void remove_from_closest(Group_c *g, int peer_index)      }  } -/* +/**   * Delete a peer from the group chat.   *   * return true on success @@ -728,7 +731,7 @@ static bool delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void              g->group[peer_index] = g->group[g->numpeers];          } -        Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * (g->numpeers)); +        Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * g->numpeers);          if (temp == nullptr) {              return false; @@ -753,11 +756,11 @@ static int cmp_u64(uint64_t a, uint64_t b)      return (a > b) - (a < b);  } -/* Order peers with friends first and with more recently active earlier */ +/** Order peers with friends first and with more recently active earlier */  static int cmp_frozen(const void *a, const void *b)  { -    const Group_Peer *pa = (const Group_Peer *) a; -    const Group_Peer *pb = (const Group_Peer *) b; +    const Group_Peer *pa = (const Group_Peer *)a; +    const Group_Peer *pb = (const Group_Peer *)b;      if (pa->is_friend ^ pb->is_friend) {          return pa->is_friend ? -1 : 1; @@ -766,7 +769,7 @@ static int cmp_frozen(const void *a, const void *b)      return cmp_u64(pb->last_active, pa->last_active);  } -/* Delete frozen peers as necessary to ensure at most g->maxfrozen remain. +/** Delete frozen peers as necessary to ensure at most g->maxfrozen remain.   *   * return true if any frozen peers are removed.   */ @@ -832,7 +835,7 @@ static bool freeze_peer(Group_Chats *g_c, uint32_t groupnumber, int peer_index,  } -/* Set the nick for a peer. +/** Set the nick for a peer.   *   * do_gc_callback indicates whether we want to trigger callbacks set by the client   * via the public API. This should be set to false if this function is called @@ -874,7 +877,7 @@ static bool setnick(Group_Chats *g_c, uint32_t groupnumber, int peer_index, cons      return true;  } -/* Set the title for a group. +/** Set the title for a group.   *   * return true on success.   */ @@ -908,10 +911,10 @@ static bool settitle(Group_Chats *g_c, uint32_t groupnumber, int peer_index, con      return true;  } -/* Check if the group has no online connection, and freeze all peers if so */ +/** Check if the group has no online connection, and freeze all peers if so */  static void check_disconnected(Group_Chats *g_c, uint32_t groupnumber, void *userdata)  { -    Group_c *g = get_group_c(g_c, groupnumber); +    const Group_c *g = get_group_c(g_c, groupnumber);      if (!g) {          return; @@ -957,7 +960,7 @@ static void set_conns_type_connections(Group_Chats *g_c, uint32_t groupnumber, i      }  } -/* Set the type for all connections with friendcon_id */ +/** Set the type for all connections with friendcon_id */  static void set_conns_status_groups(Group_Chats *g_c, int friendcon_id, uint8_t type, void *userdata)  {      for (uint16_t i = 0; i < g_c->num_chats; ++i) { @@ -1014,7 +1017,7 @@ static int g_handle_status(void *object, int friendcon_id, uint8_t status, void  static int g_handle_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata);  static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata); -/* Add friend to group chat. +/** Add friend to group chat.   *   * return connections index on success   * return -1 on failure. @@ -1066,9 +1069,9 @@ static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, Group_c *g,      return ind;  } -static unsigned int send_peer_introduced(Group_Chats *g_c, int friendcon_id, uint16_t group_num); +static unsigned int send_peer_introduced(const Group_Chats *g_c, int friendcon_id, uint16_t group_num); -/* Removes reason for keeping connection. +/** Removes reason for keeping connection.   *   * Kills connection if this was the last reason.   */ @@ -1094,7 +1097,7 @@ static void remove_connection_reason(Group_Chats *g_c, Group_c *g, uint16_t i, u      }  } -/* Creates a new groupchat and puts it in the chats array. +/** Creates a new groupchat and puts it in the chats array.   *   * type is one of `GROUPCHAT_TYPE_*`   * @@ -1130,7 +1133,7 @@ int add_groupchat(Group_Chats *g_c, uint8_t type)  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 +/** Delete a groupchat from the chats array, informing the group first as   * appropriate.   *   * return 0 on success. @@ -1184,7 +1187,7 @@ static const Group_Peer *peer_in_list(const Group_c *g, uint32_t peernumber, boo  } -/* Copy the public key of (frozen, if frozen is true) peernumber who is in +/** 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 @@ -1209,7 +1212,7 @@ int group_peer_pubkey(const Group_Chats *g_c, uint32_t groupnumber, uint32_t pee      return 0;  } -/* +/**   * Return the size of (frozen, if frozen is true) peernumber's name.   *   * return -1 if groupnumber is invalid. @@ -1232,7 +1235,7 @@ int group_peername_size(const Group_Chats *g_c, uint32_t groupnumber, uint32_t p      return peer->nick_len;  } -/* Copy the name of (frozen, if frozen is true) peernumber who is in +/** 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 @@ -1260,12 +1263,12 @@ int group_peername(const Group_Chats *g_c, uint32_t groupnumber, uint32_t peernu      return peer->nick_len;  } -/* Copy last active timestamp of frozennumber who is in groupnumber to +/** 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 frozennumber is invalid. + * return -2 if peernumber is invalid.   */  int group_frozen_last_active(const Group_Chats *g_c, uint32_t groupnumber, uint32_t peernumber,                               uint64_t *last_active) @@ -1284,7 +1287,7 @@ int group_frozen_last_active(const Group_Chats *g_c, uint32_t groupnumber, uint3      return 0;  } -/* Set maximum number of frozen peers. +/** Set maximum number of frozen peers.   *   * return 0 on success.   * return -1 if groupnumber is invalid. @@ -1302,7 +1305,7 @@ int group_set_max_frozen(const Group_Chats *g_c, uint32_t groupnumber, uint32_t      return 0;  } -/* Return the number of (frozen, if frozen is true) peers in the group chat on +/** Return the number of (frozen, if frozen is true) peers in the group chat on   * success.   * return -1 if groupnumber is invalid.   */ @@ -1317,7 +1320,7 @@ int group_number_peers(const Group_Chats *g_c, uint32_t groupnumber, bool frozen      return frozen ? g->numfrozen : g->numpeers;  } -/* return 1 if the peernumber corresponds to ours. +/** return 1 if the peernumber corresponds to ours.   * return 0 if the peernumber is not ours.   * return -1 if groupnumber is invalid.   * return -2 if peernumber is invalid. @@ -1342,7 +1345,7 @@ int group_peernumber_is_ours(const Group_Chats *g_c, uint32_t groupnumber, uint3      return g->peer_number == g->group[peernumber].peer_number;  } -/* return the type of groupchat (GROUPCHAT_TYPE_) that groupnumber is. +/** return the type of groupchat (GROUPCHAT_TYPE_) that groupnumber is.   *   * return -1 on failure.   * return type on success. @@ -1358,7 +1361,7 @@ int group_get_type(const Group_Chats *g_c, uint32_t groupnumber)      return g->type;  } -/* Copies the unique id of `group_chat[groupnumber]` into `id`. +/** Copies the unique id of `group_chat[groupnumber]` into `id`.   *   * return false on failure.   * return true on success. @@ -1378,12 +1381,12 @@ bool conference_get_id(const Group_Chats *g_c, uint32_t groupnumber, uint8_t *id      return true;  } -/* Send a group packet to friendcon_id. +/** Send a group packet to friendcon_id.   *   *  return 1 on success   *  return 0 on failure   */ -static unsigned int send_packet_group_peer(Friend_Connections *fr_c, int friendcon_id, uint8_t packet_id, +static unsigned int send_packet_group_peer(const Friend_Connections *fr_c, int friendcon_id, uint8_t packet_id,          uint16_t group_num, const uint8_t *data, uint16_t length)  {      if (1 + sizeof(uint16_t) + length > MAX_CRYPTO_DATA_SIZE) { @@ -1399,12 +1402,12 @@ static unsigned int send_packet_group_peer(Friend_Connections *fr_c, int friendc                               SIZEOF_VLA(packet), 0) != -1;  } -/* Send a group lossy packet to friendcon_id. +/** Send a group lossy packet to friendcon_id.   *   *  return 1 on success   *  return 0 on failure   */ -static unsigned int send_lossy_group_peer(Friend_Connections *fr_c, int friendcon_id, uint8_t packet_id, +static unsigned int send_lossy_group_peer(const Friend_Connections *fr_c, int friendcon_id, uint8_t packet_id,          uint16_t group_num, const uint8_t *data, uint16_t length)  {      if (1 + sizeof(uint16_t) + length > MAX_CRYPTO_DATA_SIZE) { @@ -1420,16 +1423,16 @@ static unsigned int send_lossy_group_peer(Friend_Connections *fr_c, int friendco                                    packet, SIZEOF_VLA(packet)) != -1;  } -/* invite friendnumber to groupnumber. +/** invite friendnumber to groupnumber.   *   * return 0 on success.   * return -1 if groupnumber is invalid.   * return -2 if invite packet failed to send.   * return -3 if we are not connected to the group chat.   */ -int invite_friend(Group_Chats *g_c, uint32_t friendnumber, uint32_t groupnumber) +int invite_friend(const Group_Chats *g_c, uint32_t friendnumber, 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; @@ -1453,7 +1456,7 @@ int invite_friend(Group_Chats *g_c, uint32_t friendnumber, uint32_t groupnumber)      return -2;  } -/* Send a rejoin packet to a peer if we have a friend connection to the peer. +/** Send a rejoin packet to a peer if we have a friend connection to the peer.   * return true if a packet was sent.   * return false otherwise.   */ @@ -1480,12 +1483,12 @@ static bool try_send_rejoin(Group_Chats *g_c, Group_c *g, const uint8_t *real_pk      return true;  } -static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num); +static unsigned int send_peer_query(const Group_Chats *g_c, int friendcon_id, uint16_t group_num);  static bool send_invite_response(Group_Chats *g_c, int groupnumber, uint32_t friendnumber, const uint8_t *data,                                   uint16_t length); -/* Join a group (we need to have been invited first.) +/** Join a group (we need to have been invited first.)   *   * expected_type is the groupchat type we expect the chat we are joining to   * have. @@ -1546,7 +1549,7 @@ static bool send_invite_response(Group_Chats *g_c, int groupnumber, uint32_t fri          return false;      } -    const bool member = (g->status == GROUPCHAT_STATUS_CONNECTED); +    const bool member = g->status == GROUPCHAT_STATUS_CONNECTED;      VLA(uint8_t, response, member ? INVITE_MEMBER_PACKET_SIZE : INVITE_ACCEPT_PACKET_SIZE);      response[0] = member ? INVITE_MEMBER_ID : INVITE_ACCEPT_ID; @@ -1591,31 +1594,31 @@ static bool send_invite_response(Group_Chats *g_c, int groupnumber, uint32_t fri      return true;  } -/* Set handlers for custom lossy packets. */ +/** Set handlers for custom lossy packets. */  void group_lossy_packet_registerhandler(Group_Chats *g_c, uint8_t byte, lossy_packet_cb *function)  {      g_c->lossy_packethandlers[byte].function = function;  } -/* Set the callback for group invites. */ +/** Set the callback for group invites. */  void g_callback_group_invite(Group_Chats *g_c, g_conference_invite_cb *function)  {      g_c->invite_callback = function;  } -/* Set the callback for group connection. */ +/** Set the callback for group connection. */  void g_callback_group_connected(Group_Chats *g_c, g_conference_connected_cb *function)  {      g_c->connected_callback = function;  } -/* Set the callback for group messages. */ +/** Set the callback for group messages. */  void g_callback_group_message(Group_Chats *g_c, g_conference_message_cb *function)  {      g_c->message_callback = function;  } -/* Set callback function for peer nickname changes. +/** Set callback function for peer nickname changes.   *   * It gets called every time a peer changes their nickname.   */ @@ -1624,7 +1627,7 @@ void g_callback_peer_name(Group_Chats *g_c, peer_name_cb *function)      g_c->peer_name_callback = function;  } -/* Set callback function for peer list changes. +/** Set callback function for peer list changes.   *   * It gets called every time the name list changes(new peer, deleted peer)   */ @@ -1633,13 +1636,13 @@ void g_callback_peer_list_changed(Group_Chats *g_c, peer_list_changed_cb *functi      g_c->peer_list_changed_callback = function;  } -/* Set callback function for title changes. */ +/** Set callback function for title changes. */  void g_callback_group_title(Group_Chats *g_c, title_cb *function)  {      g_c->title_callback = function;  } -/* Set a function to be called when a new peer joins a group chat. +/** Set a function to be called when a new peer joins a group chat.   *   * return 0 on success.   * return -1 on failure. @@ -1656,12 +1659,12 @@ int callback_groupchat_peer_new(const Group_Chats *g_c, uint32_t groupnumber, pe      return 0;  } -/* Set a function to be called when a peer leaves a group chat. +/** Set a function to be called when a peer leaves a group chat.   *   * return 0 on success.   * return -1 on failure.   */ -int callback_groupchat_peer_delete(Group_Chats *g_c, uint32_t groupnumber, peer_on_leave_cb *function) +int callback_groupchat_peer_delete(const Group_Chats *g_c, uint32_t groupnumber, peer_on_leave_cb *function)  {      Group_c *g = get_group_c(g_c, groupnumber); @@ -1673,12 +1676,12 @@ int callback_groupchat_peer_delete(Group_Chats *g_c, uint32_t groupnumber, peer_      return 0;  } -/* Set a function to be called when the group chat is deleted. +/** Set a function to be called when the group chat is deleted.   *   * return 0 on success.   * return -1 on failure.   */ -int callback_groupchat_delete(Group_Chats *g_c, uint32_t groupnumber, group_on_delete_cb *function) +int callback_groupchat_delete(const Group_Chats *g_c, uint32_t groupnumber, group_on_delete_cb *function)  {      Group_c *g = get_group_c(g_c, groupnumber); @@ -1693,7 +1696,7 @@ int callback_groupchat_delete(Group_Chats *g_c, uint32_t groupnumber, group_on_d  static int send_message_group(const Group_Chats *g_c, uint32_t groupnumber, uint8_t message_id, const uint8_t *data,                                uint16_t len); -/* send a ping message +/** send a ping message   * return true on success   */  static bool group_ping_send(const Group_Chats *g_c, uint32_t groupnumber) @@ -1705,11 +1708,11 @@ static bool group_ping_send(const Group_Chats *g_c, uint32_t groupnumber)      return false;  } -/* send a new_peer message +/** send a new_peer message   * return true on success   */  static bool group_new_peer_send(const Group_Chats *g_c, uint32_t groupnumber, uint16_t peer_num, const uint8_t *real_pk, -                                uint8_t *temp_pk) +                                const uint8_t *temp_pk)  {      uint8_t packet[GROUP_MESSAGE_NEW_PEER_LENGTH]; @@ -1725,7 +1728,7 @@ static bool group_new_peer_send(const Group_Chats *g_c, uint32_t groupnumber, ui      return false;  } -/* send a kill_peer message +/** send a kill_peer message   * return true on success   */  static bool group_kill_peer_send(const Group_Chats *g_c, uint32_t groupnumber, uint16_t peer_num) @@ -1742,7 +1745,7 @@ static bool group_kill_peer_send(const Group_Chats *g_c, uint32_t groupnumber, u      return false;  } -/* send a freeze_peer message +/** 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) @@ -1759,7 +1762,7 @@ static bool group_freeze_peer_send(const Group_Chats *g_c, uint32_t groupnumber,      return false;  } -/* send a name message +/** send a name message   * return true on success   */  static bool group_name_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *nick, uint16_t nick_len) @@ -1775,7 +1778,7 @@ static bool group_name_send(const Group_Chats *g_c, uint32_t groupnumber, const      return false;  } -/* send message to announce leaving group +/** send message to announce leaving group   * return true on success   */  static bool group_leave(const Group_Chats *g_c, uint32_t groupnumber, bool permanent) @@ -1794,7 +1797,7 @@ static bool group_leave(const Group_Chats *g_c, uint32_t groupnumber, bool perma  } -/* set the group's title, limited to MAX_NAME_LENGTH +/** set the group's title, limited to MAX_NAME_LENGTH   * return 0 on success   * return -1 if groupnumber is invalid.   * return -2 if title is too long or empty. @@ -1831,7 +1834,7 @@ int group_title_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t      return -3;  } -/* return the group's title size. +/** return the group's title size.   * return -1 of groupnumber is invalid.   * return -2 if title is too long or empty.   */ @@ -1850,7 +1853,7 @@ int group_title_get_size(const Group_Chats *g_c, uint32_t groupnumber)      return g->title_len;  } -/* Get group title from groupnumber and put it in title. +/** Get group title from groupnumber and put it in title.   * Title needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.   *   * return length of copied title if success. @@ -1919,7 +1922,7 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con                  return;              } else { -                Group_c *g = get_group_c(g_c, groupnumber); +                const Group_c *g = get_group_c(g_c, groupnumber);                  if (g && g->status == GROUPCHAT_STATUS_CONNECTED) {                      send_invite_response(g_c, groupnumber, friendnumber, invite_data, invite_length); @@ -1931,7 +1934,7 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con          case INVITE_ACCEPT_ID:          case INVITE_MEMBER_ID: { -            const bool member = (data[0] == INVITE_MEMBER_ID); +            const bool member = data[0] == INVITE_MEMBER_ID;              if (length != (member ? INVITE_MEMBER_PACKET_SIZE : INVITE_ACCEPT_PACKET_SIZE)) {                  return; @@ -1952,7 +1955,7 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con                  return;              } -            if (crypto_memcmp(data + 1 + sizeof(uint16_t) * 2 + 1, g->id, GROUP_ID_LENGTH) != 0) { +            if (!group_id_eq(data + 1 + sizeof(uint16_t) * 2 + 1, g->id)) {                  return;              } @@ -2008,12 +2011,13 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con              break;          } -        default: +        default: {              return; +        }      }  } -/* Find index of friend in the connections list. +/** Find index of friend in the connections list.   *   * return index on success   * return -1 on failure. @@ -2033,7 +2037,7 @@ static int friend_in_connections(const Group_c *g, int friendcon_id)      return -1;  } -/* return number of connections. +/** return number of connections.   */  static unsigned int count_connected(const Group_c *g)  { @@ -2048,8 +2052,8 @@ static unsigned int count_connected(const Group_c *g)      return count;  } -static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t type, -                              const uint8_t *id) +static int send_packet_online(const Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, +                              uint8_t type, const uint8_t *id)  {      uint8_t packet[1 + ONLINE_PACKET_DATA_SIZE];      group_num = net_htons(group_num); @@ -2061,9 +2065,9 @@ static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16                               sizeof(packet), 0) != -1;  } -static bool ping_groupchat(Group_Chats *g_c, uint32_t groupnumber); +static bool ping_groupchat(const Group_Chats *g_c, uint32_t groupnumber); -static int handle_packet_online(Group_Chats *g_c, int friendcon_id, const uint8_t *data, uint16_t length) +static int handle_packet_online(const Group_Chats *g_c, int friendcon_id, const uint8_t *data, uint16_t length)  {      if (length != ONLINE_PACKET_DATA_SIZE) {          return -1; @@ -2161,10 +2165,10 @@ static int handle_packet_rejoin(Group_Chats *g_c, int friendcon_id, const uint8_  // we could send title with invite, but then if it changes between sending and accepting inv, joinee won't see it -/* return 1 on success. +/** return 1 on success.   * return 0 on failure   */ -static unsigned int send_peer_introduced(Group_Chats *g_c, int friendcon_id, uint16_t group_num) +static unsigned int send_peer_introduced(const Group_Chats *g_c, int friendcon_id, uint16_t group_num)  {      uint8_t packet[1];      packet[0] = PEER_INTRODUCED_ID; @@ -2172,20 +2176,20 @@ static unsigned int send_peer_introduced(Group_Chats *g_c, int friendcon_id, uin  } -/* return 1 on success. +/** return 1 on success.   * return 0 on failure   */ -static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num) +static unsigned int send_peer_query(const Group_Chats *g_c, int friendcon_id, uint16_t group_num)  {      uint8_t packet[1];      packet[0] = PEER_QUERY_ID;      return send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, packet, sizeof(packet));  } -/* return number of peers sent on success. +/** return number of peers sent on success.   * return 0 on failure.   */ -static unsigned int send_peers(Group_Chats *g_c, const Group_c *g, int friendcon_id, uint16_t group_num) +static unsigned int send_peers(const Group_Chats *g_c, const Group_c *g, int friendcon_id, uint16_t group_num)  {      uint8_t response_packet[MAX_CRYPTO_DATA_SIZE - (1 + sizeof(uint16_t))];      response_packet[0] = PEER_RESPONSE_ID; @@ -2193,12 +2197,12 @@ static unsigned int send_peers(Group_Chats *g_c, const Group_c *g, int friendcon      uint16_t sent = 0; -    for (uint32_t i = 0;; ++i) { +    for (uint32_t i = 0; i <= g->numpeers; ++i) {          if (i == g->numpeers                  || (p - response_packet) + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE * 2 + 1 + g->group[i].nick_len >                  sizeof(response_packet)) {              if (send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, response_packet, -                                       (p - response_packet))) { +                                       p - response_packet)) {                  sent = i;              } else {                  return sent; @@ -2308,37 +2312,36 @@ static void handle_direct_packet(Group_Chats *g_c, uint32_t groupnumber, const u      switch (data[0]) {          case PEER_INTRODUCED_ID: {              remove_connection_reason(g_c, g, connection_index, GROUPCHAT_CONNECTION_REASON_INTRODUCING); +            break;          } -        break; -          case PEER_QUERY_ID: {              if (g->connections[connection_index].type != GROUPCHAT_CONNECTION_ONLINE) {                  return;              }              send_peers(g_c, g, g->connections[connection_index].number, g->connections[connection_index].group_number); +            break;          } -        break;          case PEER_RESPONSE_ID: {              handle_send_peers(g_c, groupnumber, data + 1, length - 1, userdata); +            break;          } -        break;          case PEER_TITLE_ID: {              if (!g->title_fresh) {                  settitle(g_c, groupnumber, -1, data + 1, length - 1, userdata);              } -        } -        break; +            break; +        }      }  } -/* Send message to all connections except receiver (if receiver isn't -1) +/** Send message to all connections except receiver (if receiver isn't -1)   * NOTE: this function appends the group chat number to the data passed to it.   *   * return number of messages sent. @@ -2366,18 +2369,17 @@ static unsigned int send_message_all_connections(const Group_Chats *g_c, const G      return sent;  } -/* Send lossy message to all connections except receiver (if receiver isn't -1) +/** Send lossy message to all connections except receiver (if receiver isn't -1)   * NOTE: this function appends the group chat number to the data passed to it.   *   * return number of messages sent.   */  static unsigned int send_lossy_all_connections(const Group_Chats *g_c, const Group_c *g, const uint8_t *data, -        uint16_t length, -        int receiver) +        uint16_t length, int receiver)  {      unsigned int sent = 0;      unsigned int num_connected_closest = 0; -    unsigned int connected_closest[DESIRED_CLOSEST]; +    unsigned int connected_closest[DESIRED_CLOSEST] = {0};      for (unsigned int i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {          if (g->connections[i].type != GROUPCHAT_CONNECTION_ONLINE) { @@ -2434,7 +2436,7 @@ static unsigned int send_lossy_all_connections(const Group_Chats *g_c, const Gro      return sent;  } -/* Send data of len with message_id to groupnumber. +/** Send data of len with message_id to groupnumber.   *   * return number of peers it was sent to on success.   * return -1 if groupnumber is invalid. @@ -2487,7 +2489,7 @@ static int send_message_group(const Group_Chats *g_c, uint32_t groupnumber, uint      return ret;  } -/* send a group message +/** send a group message   * return 0 on success   * see: send_message_group() for error codes.   */ @@ -2502,7 +2504,7 @@ int group_message_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8      return ret;  } -/* send a group action +/** send a group action   * return 0 on success   * see: send_message_group() for error codes.   */ @@ -2517,7 +2519,7 @@ int group_action_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_      return ret;  } -/* High level function to send custom lossy packets. +/** High level function to send custom lossy packets.   *   * return -1 on failure.   * return 0 on success. @@ -2548,7 +2550,7 @@ int send_group_lossy_packet(const Group_Chats *g_c, uint32_t groupnumber, const  static Message_Info *find_message_slot_or_reject(uint32_t message_number, uint8_t message_id, Group_Peer *peer)  { -    const bool ignore_older = (message_id == GROUP_MESSAGE_NAME_ID || message_id == GROUP_MESSAGE_TITLE_ID); +    const bool ignore_older = message_id == GROUP_MESSAGE_NAME_ID || message_id == GROUP_MESSAGE_TITLE_ID;      Message_Info *i; @@ -2569,7 +2571,7 @@ static Message_Info *find_message_slot_or_reject(uint32_t message_number, uint8_      return i;  } -/* Stores message info in peer->last_message_infos. +/** Stores message info in peer->last_message_infos.   *   * return true if message should be processed.   * return false otherwise. @@ -2672,8 +2674,9 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber,      const bool direct_from_sender = id_equal(g->group[index].real_pk, real_pk);      switch (message_id) { -        case GROUP_MESSAGE_PING_ID: +        case GROUP_MESSAGE_PING_ID: {              break; +        }          case GROUP_MESSAGE_NEW_PEER_ID: {              if (msg_data_len != GROUP_MESSAGE_NEW_PEER_LENGTH) { @@ -2685,8 +2688,8 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber,              new_peer_number = net_ntohs(new_peer_number);              addpeer(g_c, groupnumber, msg_data + sizeof(uint16_t), msg_data + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE,                      new_peer_number, userdata, true, true); +            break;          } -        break;          case GROUP_MESSAGE_KILL_PEER_ID:          case GROUP_MESSAGE_FREEZE_PEER_ID: { @@ -2708,22 +2711,25 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber,                  return;                  // TODO(irungentoo):              } + +            break;          } -        break;          case GROUP_MESSAGE_NAME_ID: {              if (!setnick(g_c, groupnumber, index, msg_data, msg_data_len, userdata, true)) {                  return;              } + +            break;          } -        break;          case GROUP_MESSAGE_TITLE_ID: {              if (!settitle(g_c, groupnumber, index, msg_data, msg_data_len, userdata)) {                  return;              } + +            break;          } -        break;          case PACKET_ID_MESSAGE: {              if (msg_data_len == 0) { @@ -2759,8 +2765,9 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber,              break;          } -        default: +        default: {              return; +        }      }      /* If the packet was received from the peer who sent the message, relay it @@ -2816,7 +2823,7 @@ static int g_handle_packet(void *object, int friendcon_id, const uint8_t *data,      return -1;  } -/* Did we already receive the lossy packet or not. +/** Did we already receive the lossy packet or not.   *   * return -1 on failure.   * return 0 if packet was not received. @@ -2870,7 +2877,7 @@ static int lossy_packet_not_received(const Group_c *g, int peer_index, uint16_t  } -/* Does this group type make use of lossy packets? */ +/** Does this group type make use of lossy packets? */  static bool type_uses_lossy(uint8_t type)  {      return (type == GROUPCHAT_TYPE_AV); @@ -2878,7 +2885,7 @@ static bool type_uses_lossy(uint8_t type)  static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata)  { -    Group_Chats *g_c = (Group_Chats *)object; +    const Group_Chats *g_c = (const Group_Chats *)object;      if (data[0] != PACKET_ID_LOSSY_CONFERENCE) {          return -1; @@ -2948,7 +2955,7 @@ static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uin      return 0;  } -/* Set the object that is tied to the group chat. +/** Set the object that is tied to the group chat.   *   * return 0 on success.   * return -1 on failure @@ -2965,7 +2972,7 @@ int group_set_object(const Group_Chats *g_c, uint32_t groupnumber, void *object)      return 0;  } -/* Set the object that is tied to the group peer. +/** Set the object that is tied to the group peer.   *   * return 0 on success.   * return -1 on failure @@ -2986,7 +2993,7 @@ int group_peer_set_object(const Group_Chats *g_c, uint32_t groupnumber, uint32_t      return 0;  } -/* Return the object tied to the group chat previously set by group_set_object. +/** Return the object tied to the group chat previously set by group_set_object.   *   * return NULL on failure.   * return object on success. @@ -3002,7 +3009,7 @@ void *group_get_object(const Group_Chats *g_c, uint32_t groupnumber)      return g->object;  } -/* Return the object tied to the group chat peer previously set by group_peer_set_object. +/** Return the object tied to the group chat peer previously set by group_peer_set_object.   *   * return NULL on failure.   * return object on success. @@ -3022,10 +3029,10 @@ void *group_peer_get_object(const Group_Chats *g_c, uint32_t groupnumber, uint32      return g->group[peernumber].object;  } -/* Interval in seconds to send ping messages */ +/** Interval in seconds to send ping messages */  #define GROUP_PING_INTERVAL 20 -static bool ping_groupchat(Group_Chats *g_c, uint32_t groupnumber) +static bool ping_groupchat(const Group_Chats *g_c, uint32_t groupnumber)  {      Group_c *g = get_group_c(g_c, groupnumber); @@ -3042,7 +3049,7 @@ static bool ping_groupchat(Group_Chats *g_c, uint32_t groupnumber)      return true;  } -/* Seconds of inactivity after which to freeze a peer */ +/** Seconds of inactivity after which to freeze a peer */  #define FREEZE_TIMEOUT (GROUP_PING_INTERVAL * 3)  static bool groupchat_freeze_timedout(Group_Chats *g_c, uint32_t groupnumber, void *userdata) @@ -3070,30 +3077,26 @@ static bool groupchat_freeze_timedout(Group_Chats *g_c, uint32_t groupnumber, vo      return true;  } -/* Push non-empty slots to start. */ +/** Push non-empty slots to start. */  static void squash_connections(Group_c *g)  { -    uint16_t i = 0; +    uint16_t num_connected = 0; -    for (uint16_t j = 0; j < MAX_GROUP_CONNECTIONS; ++j) { -        if (g->connections[j].type != GROUPCHAT_CONNECTION_NONE) { -            g->connections[i] = g->connections[j]; -            ++i; +    for (uint16_t i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { +        if (g->connections[i].type != GROUPCHAT_CONNECTION_NONE) { +            g->connections[num_connected] = g->connections[i]; +            ++num_connected;          }      } -    for (; i < MAX_GROUP_CONNECTIONS; ++i) { +    for (uint16_t i = num_connected; i < MAX_GROUP_CONNECTIONS; ++i) {          g->connections[i].type = GROUPCHAT_CONNECTION_NONE;      }  }  #define MIN_EMPTY_CONNECTIONS (1 + MAX_GROUP_CONNECTIONS / 10) -/* Remove old connections as necessary to ensure we have space for new - * connections. This invalidates connections array indices (which is - * why we do this periodically rather than on adding a connection). - */ -static void clean_connections(Group_Chats *g_c, Group_c *g) +static uint16_t empty_connection_count(const Group_c *g)  {      uint16_t to_clear = MIN_EMPTY_CONNECTIONS; @@ -3107,7 +3110,16 @@ static void clean_connections(Group_Chats *g_c, Group_c *g)          }      } -    for (; to_clear > 0; --to_clear) { +    return to_clear; +} + +/** Remove old connections as necessary to ensure we have space for new + * connections. This invalidates connections array indices (which is + * why we do this periodically rather than on adding a connection). + */ +static void clean_connections(Group_Chats *g_c, Group_c *g) +{ +    for (uint16_t to_clear = empty_connection_count(g); to_clear > 0; --to_clear) {          // Remove a connection. Prefer non-closest connections, and given          // that prefer non-online connections, and given that prefer earlier          // slots. @@ -3137,9 +3149,9 @@ static void clean_connections(Group_Chats *g_c, Group_c *g)      squash_connections(g);  } -/* Send current name (set in messenger) to all online groups. +/** Send current name (set in messenger) to all online groups.   */ -void send_name_all_groups(Group_Chats *g_c) +void send_name_all_groups(const Group_Chats *g_c)  {      for (uint16_t i = 0; i < g_c->num_chats; ++i) {          Group_c *g = get_group_c(g_c, i); @@ -3205,7 +3217,7 @@ static uint32_t saved_conf_size(const Group_c *g)      return len;  } -/* Save a future message number. The save will remain valid until we have sent +/** Save a future message number. The save will remain valid until we have sent   * this many more messages. */  #define SAVE_OFFSET_MESSAGE_NUMBER (1 << 16)  #define SAVE_OFFSET_LOSSY_MESSAGE_NUMBER (1 << 13) @@ -3326,7 +3338,7 @@ static State_Load_Status load_conferences(Group_Chats *g_c, const uint8_t *data,          data += sizeof(uint32_t);          if (g->numfrozen > 0) { -            g->frozen = (Group_Peer *)malloc(sizeof(Group_Peer) * g->numfrozen); +            g->frozen = (Group_Peer *)calloc(g->numfrozen, sizeof(Group_Peer));              if (g->frozen == nullptr) {                  return STATE_LOAD_STATUS_ERROR; @@ -3417,8 +3429,8 @@ bool conferences_load_state_section(Group_Chats *g_c, const uint8_t *data, uint3  } -/* Create new groupchat instance. */ -Group_Chats *new_groupchats(Mono_Time *mono_time, Messenger *m) +/** Create new groupchat instance. */ +Group_Chats *new_groupchats(const Mono_Time *mono_time, Messenger *m)  {      if (!m) {          return nullptr; @@ -3441,7 +3453,7 @@ Group_Chats *new_groupchats(Mono_Time *mono_time, Messenger *m)      return temp;  } -/* main groupchats loop. */ +/** main groupchats loop. */  void do_groupchats(Group_Chats *g_c, void *userdata)  {      for (uint16_t i = 0; i < g_c->num_chats; ++i) { @@ -3467,7 +3479,7 @@ void do_groupchats(Group_Chats *g_c, void *userdata)      // TODO(irungentoo):  } -/* Free everything related with group chats. */ +/** Free everything related with group chats. */  void kill_groupchats(Group_Chats *g_c)  {      for (uint16_t i = 0; i < g_c->num_chats; ++i) { @@ -3480,7 +3492,7 @@ void kill_groupchats(Group_Chats *g_c)      free(g_c);  } -/* Return the number of chats in the instance m. +/** Return the number of chats in the instance m.   * You should use this to determine how much memory to allocate   * for copy_chatlist.   */ @@ -3497,7 +3509,7 @@ uint32_t count_chatlist(const Group_Chats *g_c)      return ret;  } -/* Copy a list of valid chat IDs into the array out_list. +/** Copy a list of valid chat IDs into the array out_list.   * If out_list is NULL, returns 0.   * Otherwise, returns the number of elements copied.   * If the array was too small, the contents diff --git a/protocols/Tox/libtox/src/toxcore/group.h b/protocols/Tox/libtox/src/toxcore/group.h index eb8db55f10..a2e51cd443 100644 --- a/protocols/Tox/libtox/src/toxcore/group.h +++ b/protocols/Tox/libtox/src/toxcore/group.h @@ -3,7 +3,7 @@   * Copyright © 2014 Tox project.   */ -/* +/**   * Slightly better groupchats implementation.   */  #ifndef C_TOXCORE_TOXCORE_GROUP_H @@ -66,13 +66,13 @@ typedef enum Groupchat_Connection_Type {      GROUPCHAT_CONNECTION_ONLINE,  } Groupchat_Connection_Type; -/* Connection is to one of the closest DESIRED_CLOSEST peers */ +/** Connection is to one of the closest DESIRED_CLOSEST peers */  #define GROUPCHAT_CONNECTION_REASON_CLOSEST     (1 << 0) -/* Connection is to a peer we are introducing to the conference */ +/** Connection is to a peer we are introducing to the conference */  #define GROUPCHAT_CONNECTION_REASON_INTRODUCING (1 << 1) -/* Connection is to a peer who is introducing us to the conference */ +/** Connection is to a peer who is introducing us to the conference */  #define GROUPCHAT_CONNECTION_REASON_INTRODUCER  (1 << 2)  typedef struct Groupchat_Connection { @@ -136,35 +136,35 @@ typedef struct Group_c {      group_on_delete_cb *group_on_delete;  } Group_c; -/* Callback for group invites. +/** Callback for group invites.   *   * data of length is what needs to be passed to join_groupchat().   */  typedef void g_conference_invite_cb(Messenger *m, uint32_t friend_number, int type, const uint8_t *cookie,                                      size_t length, void *user_data); -/* Callback for group connection. */ +/** Callback for group connection. */  typedef void g_conference_connected_cb(Messenger *m, uint32_t conference_number, void *user_data); -/* Callback for group messages. */ +/** Callback for group messages. */  typedef void g_conference_message_cb(Messenger *m, uint32_t conference_number, uint32_t peer_number, int type,                                       const uint8_t *message, size_t length, void *user_data); -/* Callback for peer nickname changes. */ +/** Callback for peer nickname changes. */  typedef void peer_name_cb(Messenger *m, uint32_t conference_number, uint32_t peer_number, const uint8_t *name,                            size_t length, void *user_data); -/* Set callback function for peer list changes. */ +/** Set callback function for peer list changes. */  typedef void peer_list_changed_cb(Messenger *m, uint32_t conference_number, void *user_data); -/* Callback for title changes. +/** Callback for title changes.   *   * If peer_number == -1, then author is unknown (e.g. initial joining the group).   */  typedef void title_cb(Messenger *m, uint32_t conference_number, uint32_t peer_number, const uint8_t *title,                        size_t length, void *user_data); -/* Callback for lossy packets. +/** Callback for lossy packets.   *   * NOTE: Handler must return 0 if packet is to be relayed, -1 if the packet should not be relayed.   */ @@ -194,32 +194,32 @@ typedef struct Group_Chats {      Group_Lossy_Handler lossy_packethandlers[256];  } Group_Chats; -/* Set the callback for group invites. */ +/** Set the callback for group invites. */  void g_callback_group_invite(Group_Chats *g_c, g_conference_invite_cb *function); -/* Set the callback for group connection. */ +/** Set the callback for group connection. */  void g_callback_group_connected(Group_Chats *g_c, g_conference_connected_cb *function); -/* Set the callback for group messages. */ +/** Set the callback for group messages. */  void g_callback_group_message(Group_Chats *g_c, g_conference_message_cb *function); -/* Set callback function for title changes. */ +/** Set callback function for title changes. */  void g_callback_group_title(Group_Chats *g_c, title_cb *function); -/* Set callback function for peer nickname changes. +/** Set callback function for peer nickname changes.   *   * It gets called every time a peer changes their nickname.   */  void g_callback_peer_name(Group_Chats *g_c, peer_name_cb *function); -/* Set callback function for peer list changes. +/** Set callback function for peer list changes.   *   * It gets called every time the name list changes(new peer, deleted peer)   */  void g_callback_peer_list_changed(Group_Chats *g_c, peer_list_changed_cb *function); -/* Creates a new groupchat and puts it in the chats array. +/** Creates a new groupchat and puts it in the chats array.   *   * type is one of `GROUPCHAT_TYPE_*`   * @@ -228,7 +228,7 @@ 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, informing the group first as +/** Delete a groupchat from the chats array, informing the group first as   * appropriate.   *   * return 0 on success. @@ -236,9 +236,8 @@ int add_groupchat(Group_Chats *g_c, uint8_t type);   */  int del_groupchat(Group_Chats *g_c, uint32_t groupnumber, bool leave_permanently); -/* 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. +/** 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. @@ -246,7 +245,7 @@ int del_groupchat(Group_Chats *g_c, uint32_t groupnumber, bool leave_permanently   */  int group_peer_pubkey(const Group_Chats *g_c, uint32_t groupnumber, uint32_t peernumber, uint8_t *pk, bool frozen); -/* +/**   * Return the size of (frozen, if frozen is true) peernumber's name.   *   * return -1 if groupnumber is invalid. @@ -254,9 +253,8 @@ int group_peer_pubkey(const Group_Chats *g_c, uint32_t groupnumber, uint32_t pee   */  int group_peername_size(const Group_Chats *g_c, uint32_t groupnumber, uint32_t peernumber, bool frozen); -/* 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. +/** 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. @@ -264,7 +262,7 @@ int group_peername_size(const Group_Chats *g_c, uint32_t groupnumber, uint32_t p   */  int group_peername(const Group_Chats *g_c, uint32_t groupnumber, uint32_t peernumber, uint8_t *name, bool frozen); -/* Copy last active timestamp of frozen peernumber who is in groupnumber to +/** Copy last active timestamp of frozen peernumber who is in groupnumber to   * last_active.   *   * return 0 on success. @@ -274,22 +272,23 @@ int group_peername(const Group_Chats *g_c, uint32_t groupnumber, uint32_t peernu  int group_frozen_last_active(const Group_Chats *g_c, uint32_t groupnumber, uint32_t peernumber,                               uint64_t *last_active); -/* Set maximum number of frozen peers. +/** Set maximum number of frozen peers.   *   * return 0 on success.   * return -1 if groupnumber is invalid.   */  int group_set_max_frozen(const Group_Chats *g_c, uint32_t groupnumber, uint32_t maxfrozen); -/* invite friendnumber to groupnumber +/** invite friendnumber to groupnumber.   *   * return 0 on success.   * return -1 if groupnumber is invalid.   * return -2 if invite packet failed to send. + * return -3 if we are not connected to the group chat.   */ -int invite_friend(Group_Chats *g_c, uint32_t friendnumber, uint32_t groupnumber); +int invite_friend(const Group_Chats *g_c, uint32_t friendnumber, uint32_t groupnumber); -/* Join a group (you need to have been invited first.) +/** Join a group (we need to have been invited first.)   *   * expected_type is the groupchat type we expect the chat we are joining to   * have. @@ -305,19 +304,19 @@ int invite_friend(Group_Chats *g_c, uint32_t friendnumber, uint32_t groupnumber)  int join_groupchat(Group_Chats *g_c, uint32_t friendnumber, uint8_t expected_type, const uint8_t *data,                     uint16_t length); -/* send a group message +/** send a group message   * return 0 on success   * see: send_message_group() for error codes.   */  int group_message_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *message, uint16_t length); -/* send a group action +/** send a group action   * return 0 on success   * see: send_message_group() for error codes.   */  int group_action_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *action, uint16_t length); -/* set the group's title, limited to MAX_NAME_LENGTH +/** set the group's title, limited to MAX_NAME_LENGTH   * return 0 on success   * return -1 if groupnumber is invalid.   * return -2 if title is too long or empty. @@ -326,13 +325,13 @@ int group_action_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_  int group_title_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *title, uint8_t title_len); -/* return the group's title size. +/** return the group's title size.   * return -1 of groupnumber is invalid.   * return -2 if title is too long or empty.   */  int group_title_get_size(const Group_Chats *g_c, uint32_t groupnumber); -/* Get group title from groupnumber and put it in title. +/** Get group title from groupnumber and put it in title.   * Title needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.   *   * return length of copied title if success. @@ -341,13 +340,13 @@ 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 (frozen, if frozen is true) peers in the group chat on +/** 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, bool frozen); -/* return 1 if the peernumber corresponds to ours. +/** return 1 if the peernumber corresponds to ours.   * return 0 if the peernumber is not ours.   * return -1 if groupnumber is invalid.   * return -2 if peernumber is invalid. @@ -355,37 +354,37 @@ int group_number_peers(const Group_Chats *g_c, uint32_t groupnumber, bool frozen   */  int group_peernumber_is_ours(const Group_Chats *g_c, uint32_t groupnumber, uint32_t peernumber); -/* Set handlers for custom lossy packets. */ +/** Set handlers for custom lossy packets. */  void group_lossy_packet_registerhandler(Group_Chats *g_c, uint8_t byte, lossy_packet_cb *function); -/* High level function to send custom lossy packets. +/** High level function to send custom lossy packets.   *   * return -1 on failure.   * return 0 on success.   */  int send_group_lossy_packet(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *data, uint16_t length); -/* Return the number of chats in the instance m. +/** Return the number of chats in the instance m.   * You should use this to determine how much memory to allocate   * for copy_chatlist.   */  uint32_t count_chatlist(const Group_Chats *g_c); -/* Copy a list of valid chat IDs into the array out_list. +/** Copy a list of valid chat IDs into the array out_list.   * If out_list is NULL, returns 0.   * Otherwise, returns the number of elements copied.   * If the array was too small, the contents   * of out_list will be truncated to list_size. */  uint32_t copy_chatlist(const Group_Chats *g_c, uint32_t *out_list, uint32_t list_size); -/* return the type of groupchat (GROUPCHAT_TYPE_) that groupnumber is. +/** return the type of groupchat (GROUPCHAT_TYPE_) that groupnumber is.   *   * return -1 on failure.   * return type on success.   */  int group_get_type(const Group_Chats *g_c, uint32_t groupnumber); -/* Copies the unique id of `group_chat[groupnumber]` into id. +/** Copies the unique id of `group_chat[groupnumber]` into `id`.   *   * return false on failure.   * return true on success. @@ -394,63 +393,63 @@ bool conference_get_id(const Group_Chats *g_c, uint32_t groupnumber, uint8_t *id  int32_t conference_by_id(const Group_Chats *g_c, const uint8_t *id); -/* Send current name (set in messenger) to all online groups. +/** Send current name (set in messenger) to all online groups.   */ -void send_name_all_groups(Group_Chats *g_c); +void send_name_all_groups(const Group_Chats *g_c); -/* Set the object that is tied to the group chat. +/** Set the object that is tied to the group chat.   *   * return 0 on success.   * return -1 on failure   */  int group_set_object(const Group_Chats *g_c, uint32_t groupnumber, void *object); -/* Set the object that is tied to the group peer. +/** Set the object that is tied to the group peer.   *   * return 0 on success.   * return -1 on failure   */  int group_peer_set_object(const Group_Chats *g_c, uint32_t groupnumber, uint32_t peernumber, void *object); -/* Return the object tied to the group chat previously set by group_set_object. +/** Return the object tied to the group chat previously set by group_set_object.   *   * return NULL on failure.   * return object on success.   */  void *group_get_object(const Group_Chats *g_c, uint32_t groupnumber); -/* Return the object tied to the group chat peer previously set by group_peer_set_object. +/** Return the object tied to the group chat peer previously set by group_peer_set_object.   *   * return NULL on failure.   * return object on success.   */  void *group_peer_get_object(const Group_Chats *g_c, uint32_t groupnumber, uint32_t peernumber); -/* Set a function to be called when a new peer joins a group chat. +/** Set a function to be called when a new peer joins a group chat.   *   * return 0 on success.   * return -1 on failure.   */  int callback_groupchat_peer_new(const Group_Chats *g_c, uint32_t groupnumber, peer_on_join_cb *function); -/* Set a function to be called when a peer leaves a group chat. +/** Set a function to be called when a peer leaves a group chat.   *   * return 0 on success.   * return -1 on failure.   */ -int callback_groupchat_peer_delete(Group_Chats *g_c, uint32_t groupnumber, peer_on_leave_cb *function); +int callback_groupchat_peer_delete(const Group_Chats *g_c, uint32_t groupnumber, peer_on_leave_cb *function); -/* Set a function to be called when the group chat is deleted. +/** Set a function to be called when the group chat is deleted.   *   * return 0 on success.   * return -1 on failure.   */ -int callback_groupchat_delete(Group_Chats *g_c, uint32_t groupnumber, group_on_delete_cb *function); +int callback_groupchat_delete(const Group_Chats *g_c, uint32_t groupnumber, group_on_delete_cb *function); -/* Return size of the conferences data (for saving). */ +/** 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()) */ +/** 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);  /** @@ -465,13 +464,13 @@ uint8_t *conferences_save(const Group_Chats *g_c, uint8_t *data);  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); +/** Create new groupchat instance. */ +Group_Chats *new_groupchats(const Mono_Time *mono_time, Messenger *m); -/* main groupchats loop. */ +/** main groupchats loop. */  void do_groupchats(Group_Chats *g_c, void *userdata); -/* Free everything related with group chats. */ +/** Free everything related with group chats. */  void kill_groupchats(Group_Chats *g_c);  #endif diff --git a/protocols/Tox/libtox/src/toxcore/list.c b/protocols/Tox/libtox/src/toxcore/list.c index fca8cea898..02a0b1e536 100644 --- a/protocols/Tox/libtox/src/toxcore/list.c +++ b/protocols/Tox/libtox/src/toxcore/list.c @@ -3,15 +3,11 @@   * Copyright © 2014 Tox project.   */ -/* +/**   * Simple struct with functions to create a list which associates ids with data   * -Allows for finding ids associated with data such as IPs or public keys in a short time   * -Should only be used if there are relatively few add/remove calls to the list   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -  #include "list.h"  #include <stdbool.h> @@ -20,7 +16,7 @@  #include "ccompat.h" -/* Basically, the elements in the list are placed in order so that they can be searched for easily +/** Basically, the elements in the list are placed in order so that they can be searched for easily   * -each element is seen as a big-endian integer when ordering them   * -the ids array is maintained so that each id always matches   * -the search algorithm cuts down the time to find the id associated with a piece of data @@ -37,7 +33,7 @@ list_index(uint32_t i)      return ~i;  } -/* Find data in list +/** Find data in list   *   * return value:   *  >= 0 : index of data in array @@ -78,7 +74,7 @@ static int find(const BS_List *list, const uint8_t *data)                  return list_index(i);              } -            delta = (delta) / 2; +            delta = delta / 2;              if (delta == 0) {                  delta = 1; @@ -94,7 +90,7 @@ static int find(const BS_List *list, const uint8_t *data)              // move up              i -= delta; -            delta = (delta) / 2; +            delta = delta / 2;              if (delta == 0) {                  delta = 1; diff --git a/protocols/Tox/libtox/src/toxcore/list.h b/protocols/Tox/libtox/src/toxcore/list.h index afe4240b76..1cbf142282 100644 --- a/protocols/Tox/libtox/src/toxcore/list.h +++ b/protocols/Tox/libtox/src/toxcore/list.h @@ -3,7 +3,7 @@   * Copyright © 2014 Tox project.   */ -/* +/**   * Simple struct with functions to create a list which associates ids with data   * -Allows for finding ids associated with data such as IPs or public keys in a short time   * -Should only be used if there are relatively few add/remove calls to the list @@ -13,6 +13,10 @@  #include <stdint.h> +#ifdef __cplusplus +extern "C" { +#endif +  typedef struct BS_List {      uint32_t n; // number of elements      uint32_t capacity; // number of elements memory is allocated for @@ -21,7 +25,7 @@ typedef struct BS_List {      int *ids; // array of element ids  } BS_List; -/* Initialize a list, element_size is the size of the elements in the list and +/** Initialize a list, element_size is the size of the elements in the list and   * initial_capacity is the number of elements the memory will be initially allocated for   *   * return value: @@ -30,10 +34,10 @@ typedef struct BS_List {   */  int bs_list_init(BS_List *list, uint32_t element_size, uint32_t initial_capacity); -/* Free a list initiated with list_init */ +/** Free a list initiated with list_init */  void bs_list_free(BS_List *list); -/* Retrieve the id of an element in the list +/** Retrieve the id of an element in the list   *   * return value:   *  >= 0 : id associated with data @@ -41,7 +45,7 @@ void bs_list_free(BS_List *list);   */  int bs_list_find(const BS_List *list, const uint8_t *data); -/* Add an element with associated id to the list +/** Add an element with associated id to the list   *   * return value:   *  1 : success @@ -49,7 +53,7 @@ int bs_list_find(const BS_List *list, const uint8_t *data);   */  int bs_list_add(BS_List *list, const uint8_t *data, int id); -/* Remove element from the list +/** Remove element from the list   *   * return value:   *  1 : success @@ -57,4 +61,8 @@ int bs_list_add(BS_List *list, const uint8_t *data, int id);   */  int bs_list_remove(BS_List *list, const uint8_t *data, int id); +#ifdef __cplusplus +}  // extern "C" +#endif +  #endif diff --git a/protocols/Tox/libtox/src/toxcore/logger.c b/protocols/Tox/libtox/src/toxcore/logger.c index 00e85c36ff..67e4a3e5ce 100644 --- a/protocols/Tox/libtox/src/toxcore/logger.c +++ b/protocols/Tox/libtox/src/toxcore/logger.c @@ -1,15 +1,11 @@  /* SPDX-License-Identifier: GPL-3.0-or-later   * Copyright © 2016-2018 The TokTok team. - * Copyright © 2013,2015 Tox project. + * Copyright © 2013-2015 Tox project.   */ -/* +/**   * Text logging abstraction.   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -  #include "logger.h"  #include <assert.h> @@ -62,9 +58,10 @@ static const Logger logger_stderr = {  };  #endif -/** +/*   * Public Functions   */ +  Logger *logger_new(void)  {      return (Logger *)calloc(1, sizeof(Logger)); @@ -102,7 +99,7 @@ void logger_write(const Logger *log, Logger_Level level, const char *file, int l      // The full path may contain PII of the person compiling toxcore (their      // username and directory layout).      const char *filename = strrchr(file, '/'); -    file = filename ? filename + 1 : file; +    file = filename != nullptr ? filename + 1 : file;  #if defined(_WIN32) || defined(__CYGWIN__)      // On Windows, the path separator *may* be a backslash, so we look for that      // one too. diff --git a/protocols/Tox/libtox/src/toxcore/logger.h b/protocols/Tox/libtox/src/toxcore/logger.h index cbd8752b9b..c3d8f66d61 100644 --- a/protocols/Tox/libtox/src/toxcore/logger.h +++ b/protocols/Tox/libtox/src/toxcore/logger.h @@ -3,7 +3,7 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * Logger abstraction backed by callbacks for writing.   */  #ifndef C_TOXCORE_TOXCORE_LOGGER_H diff --git a/protocols/Tox/libtox/src/toxcore/mono_time.c b/protocols/Tox/libtox/src/toxcore/mono_time.c index 876902f52f..e207996df6 100644 --- a/protocols/Tox/libtox/src/toxcore/mono_time.c +++ b/protocols/Tox/libtox/src/toxcore/mono_time.c @@ -8,6 +8,11 @@  #if !defined(OS_WIN32) && (defined(_WIN32) || defined(__WIN32__) || defined(WIN32))  #define OS_WIN32 +#endif + +#include "mono_time.h" + +#ifdef OS_WIN32  #define WIN32_LEAN_AND_MEAN  #include <windows.h>  #endif @@ -21,15 +26,19 @@  #include <sys/time.h>  #endif -#include "mono_time.h" -  #include <pthread.h>  #include <stdlib.h>  #include <time.h>  #include "ccompat.h" -/* don't call into system billions of times for no reason */ +//!TOKSTYLE- +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +#include "../testing/fuzzing/fuzz_adapter.h" +#endif +//!TOKSTYLE+ + +/** don't call into system billions of times for no reason */  struct Mono_Time {      uint64_t time;      uint64_t base_time; @@ -95,15 +104,23 @@ static uint64_t current_time_monotonic_default(Mono_Time *mono_time, void *user_      return time;  } + +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +static uint64_t current_time_monotonic_dummy(Mono_Time *mono_time, void *user_data) +{ +    return fuzz_get_count(); +} +#endif +  Mono_Time *mono_time_new(void)  { -    Mono_Time *mono_time = (Mono_Time *)malloc(sizeof(Mono_Time)); +    Mono_Time *mono_time = (Mono_Time *)calloc(1, sizeof(Mono_Time));      if (mono_time == nullptr) {          return nullptr;      } -    mono_time->time_update_lock = (pthread_rwlock_t *)malloc(sizeof(pthread_rwlock_t)); +    mono_time->time_update_lock = (pthread_rwlock_t *)calloc(1, sizeof(pthread_rwlock_t));      if (mono_time->time_update_lock == nullptr) {          free(mono_time); @@ -116,7 +133,11 @@ Mono_Time *mono_time_new(void)          return nullptr;      } +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    mono_time->current_time_callback = current_time_monotonic_dummy; +#else      mono_time->current_time_callback = current_time_monotonic_default; +#endif      mono_time->user_data = nullptr;  #ifdef OS_WIN32 @@ -133,7 +154,11 @@ Mono_Time *mono_time_new(void)  #endif      mono_time->time = 0; +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    mono_time->base_time = 0; // Maximum reproducibility +#else      mono_time->base_time = (uint64_t)time(nullptr) - (current_time_monotonic(mono_time) / 1000ULL); +#endif      mono_time_update(mono_time); @@ -171,11 +196,16 @@ void mono_time_update(Mono_Time *mono_time)  uint64_t mono_time_get(const Mono_Time *mono_time)  { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    // Fuzzing is only single thread for now, no locking needed */ +    return mono_time->time; +#else      uint64_t time = 0;      pthread_rwlock_rdlock(mono_time->time_update_lock);      time = mono_time->time;      pthread_rwlock_unlock(mono_time->time_update_lock);      return time; +#endif  }  bool mono_time_is_timeout(const Mono_Time *mono_time, uint64_t timestamp, uint64_t timeout) @@ -195,7 +225,10 @@ void mono_time_set_current_time_callback(Mono_Time *mono_time,      }  } -/* 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)  {      /* For WIN32 we don't want to change overflow state of mono_time here */ diff --git a/protocols/Tox/libtox/src/toxcore/mono_time.h b/protocols/Tox/libtox/src/toxcore/mono_time.h index 0951fc7499..b27e9aaf13 100644 --- a/protocols/Tox/libtox/src/toxcore/mono_time.h +++ b/protocols/Tox/libtox/src/toxcore/mono_time.h @@ -12,8 +12,6 @@  extern "C" {  #endif -#ifndef MONO_TIME_DEFINED -#define MONO_TIME_DEFINED  /**   * The timer portion of the toxcore event loop.   * @@ -44,7 +42,6 @@ extern "C" {   * implementation should at least theoretically match the specification.   */  typedef struct Mono_Time Mono_Time; -#endif /* MONO_TIME_DEFINED */  Mono_Time *mono_time_new(void);  void mono_time_free(Mono_Time *mono_time); @@ -73,7 +70,8 @@ uint64_t current_time_monotonic(Mono_Time *mono_time);  typedef uint64_t mono_time_current_time_cb(Mono_Time *mono_time, void *user_data); -/* Override implementation of current_time_monotonic() (for tests). +/** + * Override implementation of current_time_monotonic() (for tests).   *   * The caller is obligated to ensure that current_time_monotonic() continues   * to increase monotonically. diff --git a/protocols/Tox/libtox/src/toxcore/net_crypto.c b/protocols/Tox/libtox/src/toxcore/net_crypto.c index 97383a059a..77ba2294ce 100644 --- a/protocols/Tox/libtox/src/toxcore/net_crypto.c +++ b/protocols/Tox/libtox/src/toxcore/net_crypto.c @@ -3,21 +3,18 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * Functions for the core network crypto.   *   * NOTE: This code has to be perfect. We don't mess around with encryption.   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -  #include "net_crypto.h"  #include <math.h>  #include <stdlib.h>  #include <string.h> +#include "list.h"  #include "mono_time.h"  #include "util.h" @@ -34,14 +31,16 @@ typedef struct Packets_Array {  } Packets_Array;  typedef enum Crypto_Conn_State { -    CRYPTO_CONN_FREE = 0,            /* the connection slot is free. This value is 0 so it is valid after -                                      * `crypto_memzero(...)` of the parent struct -                                      */ +    /* the connection slot is free. This value is 0 so it is valid after +     * `crypto_memzero(...)` of the parent struct +     */ +    CRYPTO_CONN_FREE = 0,      CRYPTO_CONN_NO_CONNECTION,       /* the connection is allocated, but not yet used */      CRYPTO_CONN_COOKIE_REQUESTING,   /* we are sending cookie request packets */      CRYPTO_CONN_HANDSHAKE_SENT,      /* we are sending handshake packets */ -    CRYPTO_CONN_NOT_CONFIRMED,       /* we are sending handshake packets. -                                      * we have received one from the other, but no data */ +    /* we are sending handshake packets. +     * we have received one from the other, but no data */ +    CRYPTO_CONN_NOT_CONFIRMED,      CRYPTO_CONN_ESTABLISHED,         /* the connection is established */  } Crypto_Conn_State; @@ -193,7 +192,7 @@ static bool crypt_connection_id_is_valid(const Net_Crypto *c, int crypt_connecti      return true;  } -/* cookie timeout in seconds */ +/** cookie timeout in seconds */  #define COOKIE_TIMEOUT 15  #define COOKIE_DATA_LENGTH (uint16_t)(CRYPTO_PUBLIC_KEY_SIZE * 2)  #define COOKIE_CONTENTS_LENGTH (uint16_t)(sizeof(uint64_t) + COOKIE_DATA_LENGTH) @@ -203,7 +202,7 @@ static bool crypt_connection_id_is_valid(const Net_Crypto *c, int crypt_connecti  #define COOKIE_REQUEST_LENGTH (uint16_t)(1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE)  #define COOKIE_RESPONSE_LENGTH (uint16_t)(1 + CRYPTO_NONCE_SIZE + COOKIE_LENGTH + sizeof(uint64_t) + CRYPTO_MAC_SIZE) -/* Create a cookie request packet and put it in packet. +/** Create a cookie request packet and put it in packet.   * dht_public_key is the dht public key of the other   *   * packet must be of size COOKIE_REQUEST_LENGTH or bigger. @@ -211,8 +210,8 @@ static bool crypt_connection_id_is_valid(const Net_Crypto *c, int crypt_connecti   * return -1 on failure.   * return COOKIE_REQUEST_LENGTH on success.   */ -static int create_cookie_request(const Net_Crypto *c, uint8_t *packet, uint8_t *dht_public_key, uint64_t number, -                                 uint8_t *shared_key) +static int create_cookie_request(const Net_Crypto *c, uint8_t *packet, const uint8_t *dht_public_key, +                                 uint64_t number, uint8_t *shared_key)  {      uint8_t plain[COOKIE_REQUEST_PLAIN_LENGTH];      uint8_t padding[CRYPTO_PUBLIC_KEY_SIZE] = {0}; @@ -237,12 +236,12 @@ static int create_cookie_request(const Net_Crypto *c, uint8_t *packet, uint8_t *      return (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + len);  } -/* Create cookie of length COOKIE_LENGTH from bytes of length COOKIE_DATA_LENGTH using encryption_key +/** Create cookie of length COOKIE_LENGTH from bytes of length COOKIE_DATA_LENGTH using encryption_key   *   * return -1 on failure.   * return 0 on success.   */ -static int create_cookie(const Logger *log, const Mono_Time *mono_time, uint8_t *cookie, const uint8_t *bytes, +static int create_cookie(const Mono_Time *mono_time, uint8_t *cookie, const uint8_t *bytes,                           const uint8_t *encryption_key)  {      uint8_t contents[COOKIE_CONTENTS_LENGTH]; @@ -259,12 +258,12 @@ static int create_cookie(const Logger *log, const Mono_Time *mono_time, uint8_t      return 0;  } -/* Open cookie of length COOKIE_LENGTH to bytes of length COOKIE_DATA_LENGTH using encryption_key +/** Open cookie of length COOKIE_LENGTH to bytes of length COOKIE_DATA_LENGTH using encryption_key   *   * return -1 on failure.   * return 0 on success.   */ -static int open_cookie(const Logger *log, const Mono_Time *mono_time, uint8_t *bytes, const uint8_t *cookie, +static int open_cookie(const Mono_Time *mono_time, uint8_t *bytes, const uint8_t *cookie,                         const uint8_t *encryption_key)  {      uint8_t contents[COOKIE_CONTENTS_LENGTH]; @@ -288,7 +287,7 @@ static int open_cookie(const Logger *log, const Mono_Time *mono_time, uint8_t *b  } -/* Create a cookie response packet and put it in packet. +/** Create a cookie response packet and put it in packet.   * request_plain must be COOKIE_REQUEST_PLAIN_LENGTH bytes.   * packet must be of size COOKIE_RESPONSE_LENGTH or bigger.   * @@ -303,7 +302,7 @@ static int create_cookie_response(const Net_Crypto *c, uint8_t *packet, const ui      memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);      uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)]; -    if (create_cookie(c->log, c->mono_time, plain, cookie_plain, c->secret_symmetric_key) != 0) { +    if (create_cookie(c->mono_time, plain, cookie_plain, c->secret_symmetric_key) != 0) {          return -1;      } @@ -319,7 +318,7 @@ static int create_cookie_response(const Net_Crypto *c, uint8_t *packet, const ui      return COOKIE_RESPONSE_LENGTH;  } -/* Handle the cookie request packet of length length. +/** Handle the cookie request packet of length length.   * Put what was in the request in request_plain (must be of size COOKIE_REQUEST_PLAIN_LENGTH)   * Put the key used to decrypt the request into shared_key (of size CRYPTO_SHARED_KEY_SIZE) for use in the response.   * @@ -346,12 +345,12 @@ static int handle_cookie_request(const Net_Crypto *c, uint8_t *request_plain, ui      return 0;  } -/* Handle the cookie request packet (for raw UDP) +/** Handle the cookie request packet (for raw UDP)   */ -static int udp_handle_cookie_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length, +static int udp_handle_cookie_request(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length,                                       void *userdata)  { -    Net_Crypto *c = (Net_Crypto *)object; +    const Net_Crypto *c = (const Net_Crypto *)object;      uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH];      uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];      uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE]; @@ -373,9 +372,10 @@ static int udp_handle_cookie_request(void *object, IP_Port source, const uint8_t      return 0;  } -/* Handle the cookie request packet (for TCP) +/** Handle the cookie request packet (for TCP)   */ -static int tcp_handle_cookie_request(Net_Crypto *c, int connections_number, const uint8_t *packet, uint16_t length) +static int tcp_handle_cookie_request(const Net_Crypto *c, int connections_number, const uint8_t *packet, +                                     uint16_t length)  {      uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH];      uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; @@ -395,7 +395,7 @@ static int tcp_handle_cookie_request(Net_Crypto *c, int connections_number, cons      return ret;  } -/* Handle the cookie request packet (for TCP oob packets) +/** Handle the cookie request packet (for TCP oob packets)   */  static int tcp_oob_handle_cookie_request(const Net_Crypto *c, unsigned int tcp_connections_number,          const uint8_t *dht_public_key, const uint8_t *packet, uint16_t length) @@ -422,7 +422,7 @@ static int tcp_oob_handle_cookie_request(const Net_Crypto *c, unsigned int tcp_c      return ret;  } -/* Handle a cookie response packet of length encrypted with shared_key. +/** Handle a cookie response packet of length encrypted with shared_key.   * put the cookie in the response in cookie   *   * cookie must be of length COOKIE_LENGTH. @@ -430,7 +430,7 @@ static int tcp_oob_handle_cookie_request(const Net_Crypto *c, unsigned int tcp_c   * return -1 on failure.   * return COOKIE_LENGTH on success.   */ -static int handle_cookie_response(const Logger *log, uint8_t *cookie, uint64_t *number, +static int handle_cookie_response(uint8_t *cookie, uint64_t *number,                                    const uint8_t *packet, uint16_t length,                                    const uint8_t *shared_key)  { @@ -453,7 +453,7 @@ static int handle_cookie_response(const Logger *log, uint8_t *cookie, uint64_t *  #define HANDSHAKE_PACKET_LENGTH (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH + CRYPTO_MAC_SIZE) -/* Create a handshake packet and put it in packet. +/** Create a handshake packet and put it in packet.   * cookie must be COOKIE_LENGTH bytes.   * packet must be of size HANDSHAKE_PACKET_LENGTH or bigger.   * @@ -471,7 +471,7 @@ static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const u      memcpy(cookie_plain, peer_real_pk, CRYPTO_PUBLIC_KEY_SIZE);      memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, peer_dht_pubkey, CRYPTO_PUBLIC_KEY_SIZE); -    if (create_cookie(c->log, c->mono_time, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE, +    if (create_cookie(c->mono_time, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE,                        cookie_plain, c->secret_symmetric_key) != 0) {          return -1;      } @@ -490,7 +490,7 @@ static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const u      return HANDSHAKE_PACKET_LENGTH;  } -/* Handle a crypto handshake packet of length. +/** Handle a crypto handshake packet of length.   * put the nonce contained in the packet in nonce,   * the session public key in session_pk   * the real public key of the peer in peer_real_pk @@ -517,14 +517,12 @@ static int handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t      uint8_t cookie_plain[COOKIE_DATA_LENGTH]; -    if (open_cookie(c->log, c->mono_time, cookie_plain, packet + 1, c->secret_symmetric_key) != 0) { +    if (open_cookie(c->mono_time, cookie_plain, packet + 1, c->secret_symmetric_key) != 0) {          return -1;      } -    if (expected_real_pk) { -        if (public_key_cmp(cookie_plain, expected_real_pk) != 0) { -            return -1; -        } +    if (expected_real_pk && public_key_cmp(cookie_plain, expected_real_pk) != 0) { +        return -1;      }      uint8_t cookie_hash[CRYPTO_SHA512_SIZE]; @@ -539,8 +537,7 @@ static int handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t          return -1;      } -    if (crypto_memcmp(cookie_hash, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, -                      CRYPTO_SHA512_SIZE) != 0) { +    if (crypto_sha512_cmp(cookie_hash, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE) != 0) {          return -1;      } @@ -563,12 +560,12 @@ static Crypto_Connection *get_crypto_connection(const Net_Crypto *c, int crypt_c  } -/* Associate an ip_port to a connection. +/** Associate an ip_port to a connection.   *   * return -1 on failure.   * return 0 on success.   */ -static int add_ip_port_connection(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port) +static int add_ip_port_connection(Net_Crypto *c, int crypt_connection_id, const IP_Port *ip_port)  {      Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -576,24 +573,24 @@ static int add_ip_port_connection(Net_Crypto *c, int crypt_connection_id, IP_Por          return -1;      } -    if (net_family_is_ipv4(ip_port.ip.family)) { -        if (!ipport_equal(&ip_port, &conn->ip_portv4) && !ip_is_lan(conn->ip_portv4.ip)) { -            if (!bs_list_add(&c->ip_port_list, (uint8_t *)&ip_port, crypt_connection_id)) { +    if (net_family_is_ipv4(ip_port->ip.family)) { +        if (!ipport_equal(ip_port, &conn->ip_portv4) && !ip_is_lan(&conn->ip_portv4.ip)) { +            if (!bs_list_add(&c->ip_port_list, (const uint8_t *)ip_port, crypt_connection_id)) {                  return -1;              }              bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv4, crypt_connection_id); -            conn->ip_portv4 = ip_port; +            conn->ip_portv4 = *ip_port;              return 0;          } -    } else if (net_family_is_ipv6(ip_port.ip.family)) { -        if (!ipport_equal(&ip_port, &conn->ip_portv6)) { -            if (!bs_list_add(&c->ip_port_list, (uint8_t *)&ip_port, crypt_connection_id)) { +    } else if (net_family_is_ipv6(ip_port->ip.family)) { +        if (!ipport_equal(ip_port, &conn->ip_portv6)) { +            if (!bs_list_add(&c->ip_port_list, (const uint8_t *)ip_port, crypt_connection_id)) {                  return -1;              }              bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv6, crypt_connection_id); -            conn->ip_portv6 = ip_port; +            conn->ip_portv6 = *ip_port;              return 0;          }      } @@ -601,16 +598,16 @@ static int add_ip_port_connection(Net_Crypto *c, int crypt_connection_id, IP_Por      return -1;  } -/* Return the IP_Port that should be used to send packets to the other peer. +/** Return the IP_Port that should be used to send packets to the other peer.   *   * return IP_Port with family 0 on failure.   * return IP_Port on success.   */ -static IP_Port return_ip_port_connection(Net_Crypto *c, int crypt_connection_id) +static IP_Port return_ip_port_connection(const Net_Crypto *c, int crypt_connection_id)  { -    const IP_Port empty = {{{0}}}; +    const IP_Port empty = {0}; -    Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); +    const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);      if (conn == nullptr) {          return empty; @@ -631,7 +628,7 @@ static IP_Port return_ip_port_connection(Net_Crypto *c, int crypt_connection_id)      /* Prefer IP_Ports which haven't timed out to those which have.       * To break ties, prefer ipv4 lan, then ipv6, then non-lan ipv4.       */ -    if (v4 && ip_is_lan(conn->ip_portv4.ip)) { +    if (v4 && ip_is_lan(&conn->ip_portv4.ip)) {          return conn->ip_portv4;      } @@ -643,7 +640,7 @@ static IP_Port return_ip_port_connection(Net_Crypto *c, int crypt_connection_id)          return conn->ip_portv4;      } -    if (ip_is_lan(conn->ip_portv4.ip)) { +    if (ip_is_lan(&conn->ip_portv4.ip)) {          return conn->ip_portv4;      } @@ -658,7 +655,7 @@ static IP_Port return_ip_port_connection(Net_Crypto *c, int crypt_connection_id)      return empty;  } -/* Sends a packet to the peer using the fastest route. +/** Sends a packet to the peer using the fastest route.   *   * return -1 on failure.   * return 0 on success. @@ -685,7 +682,7 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t          crypto_connection_status(c, crypt_connection_id, &direct_connected, nullptr);          if (direct_connected) { -            if ((uint32_t)sendpacket(dht_get_net(c->dht), ip_port, data, length) == length) { +            if ((uint32_t)sendpacket(dht_get_net(c->dht), &ip_port, data, length) == length) {                  pthread_mutex_unlock(conn->mutex);                  return 0;              } @@ -699,7 +696,7 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t          if ((((UDP_DIRECT_TIMEOUT / 2) + conn->direct_send_attempt_time) < current_time && length < 96)                  || data[0] == NET_PACKET_COOKIE_REQUEST || data[0] == NET_PACKET_CRYPTO_HS) { -            if ((uint32_t)sendpacket(dht_get_net(c->dht), ip_port, data, length) == length) { +            if ((uint32_t)sendpacket(dht_get_net(c->dht), &ip_port, data, length) == length) {                  direct_send_attempt = 1;                  conn->direct_send_attempt_time = mono_time_get(c->mono_time);              } @@ -726,10 +723,10 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t      return -1;  } -/** START: Array Related functions */ +/*** START: Array Related functions */ -/* Return number of packets in array +/** Return number of packets in array   * Note that holes are counted too.   */  static uint32_t num_packets_array(const Packets_Array *array) @@ -737,12 +734,12 @@ static uint32_t num_packets_array(const Packets_Array *array)      return array->buffer_end - array->buffer_start;  } -/* Add data with packet number to array. +/** Add data with packet number to array.   *   * return -1 on failure.   * return 0 on success.   */ -static int add_data_to_buffer(const Logger *log, Packets_Array *array, uint32_t number, const Packet_Data *data) +static int add_data_to_buffer(Packets_Array *array, uint32_t number, const Packet_Data *data)  {      if (number - array->buffer_start >= CRYPTO_PACKET_BUFFER_SIZE) {          return -1; @@ -754,13 +751,13 @@ static int add_data_to_buffer(const Logger *log, Packets_Array *array, uint32_t          return -1;      } -    Packet_Data *new_d = (Packet_Data *)malloc(sizeof(Packet_Data)); +    Packet_Data *new_d = (Packet_Data *)calloc(1, sizeof(Packet_Data));      if (new_d == nullptr) {          return -1;      } -    memcpy(new_d, data, sizeof(Packet_Data)); +    *new_d = *data;      array->buffer[num] = new_d;      if (number - array->buffer_start >= num_packets_array(array)) { @@ -770,13 +767,13 @@ static int add_data_to_buffer(const Logger *log, Packets_Array *array, uint32_t      return 0;  } -/* Get pointer of data with packet number. +/** Get pointer of data with packet number.   *   * return -1 on failure.   * return 0 if data at number is empty.   * return 1 if data pointer was put in data.   */ -static int get_data_pointer(const Logger *log, const Packets_Array *array, Packet_Data **data, uint32_t number) +static int get_data_pointer(const Packets_Array *array, Packet_Data **data, uint32_t number)  {      const uint32_t num_spots = num_packets_array(array); @@ -794,12 +791,12 @@ static int get_data_pointer(const Logger *log, const Packets_Array *array, Packe      return 1;  } -/* Add data to end of array. +/** Add data to end of array.   *   * return -1 on failure.   * return packet number on success.   */ -static int64_t add_data_end_of_buffer(const Logger *log, Packets_Array *array, const Packet_Data *data) +static int64_t add_data_end_of_buffer(Packets_Array *array, const Packet_Data *data)  {      const uint32_t num_spots = num_packets_array(array); @@ -807,25 +804,25 @@ static int64_t add_data_end_of_buffer(const Logger *log, Packets_Array *array, c          return -1;      } -    Packet_Data *new_d = (Packet_Data *)malloc(sizeof(Packet_Data)); +    Packet_Data *new_d = (Packet_Data *)calloc(1, sizeof(Packet_Data));      if (new_d == nullptr) {          return -1;      } -    memcpy(new_d, data, sizeof(Packet_Data)); +    *new_d = *data;      uint32_t id = array->buffer_end;      array->buffer[id % CRYPTO_PACKET_BUFFER_SIZE] = new_d;      ++array->buffer_end;      return id;  } -/* Read data from beginning of array. +/** Read data from beginning of array.   *   * return -1 on failure.   * return packet number on success.   */ -static int64_t read_data_beg_buffer(const Logger *log, Packets_Array *array, Packet_Data *data) +static int64_t read_data_beg_buffer(Packets_Array *array, Packet_Data *data)  {      if (array->buffer_end == array->buffer_start) {          return -1; @@ -837,7 +834,7 @@ static int64_t read_data_beg_buffer(const Logger *log, Packets_Array *array, Pac          return -1;      } -    memcpy(data, array->buffer[num], sizeof(Packet_Data)); +    *data = *array->buffer[num];      uint32_t id = array->buffer_start;      ++array->buffer_start;      free(array->buffer[num]); @@ -845,12 +842,12 @@ static int64_t read_data_beg_buffer(const Logger *log, Packets_Array *array, Pac      return id;  } -/* Delete all packets in array before number (but not number) +/** Delete all packets in array before number (but not number)   *   * return -1 on failure.   * return 0 on success   */ -static int clear_buffer_until(const Logger *log, Packets_Array *array, uint32_t number) +static int clear_buffer_until(Packets_Array *array, uint32_t number)  {      const uint32_t num_spots = num_packets_array(array); @@ -890,12 +887,12 @@ static int clear_buffer(Packets_Array *array)      return 0;  } -/* Set array buffer end to number. +/** Set array buffer end to number.   *   * return -1 on failure.   * return 0 on success.   */ -static int set_buffer_end(const Logger *log, Packets_Array *array, uint32_t number) +static int set_buffer_end(Packets_Array *array, uint32_t number)  {      if (number - array->buffer_start > CRYPTO_PACKET_BUFFER_SIZE) {          return -1; @@ -909,13 +906,13 @@ static int set_buffer_end(const Logger *log, Packets_Array *array, uint32_t numb      return 0;  } -/* Create a packet request packet from recv_array and send_buffer_end into +/** Create a packet request packet from recv_array and send_buffer_end into   * data of length.   *   * return -1 on failure.   * return length of packet on success.   */ -static int generate_request_packet(const Logger *log, uint8_t *data, uint16_t length, const Packets_Array *recv_array) +static int generate_request_packet(uint8_t *data, uint16_t length, const Packets_Array *recv_array)  {      if (length == 0) {          return -1; @@ -962,14 +959,15 @@ static int generate_request_packet(const Logger *log, uint8_t *data, uint16_t le      return cur_len;  } -/* Handle a request data packet. +/** Handle a request data packet.   * Remove all the packets the other received from the array.   *   * return -1 on failure.   * return number of requested packets on success.   */ -static int handle_request_packet(Mono_Time *mono_time, const Logger *log, Packets_Array *send_array, -                                 const uint8_t *data, uint16_t length, uint64_t *latest_send_time, uint64_t rtt_time) +static int handle_request_packet(Mono_Time *mono_time, Packets_Array *send_array, +                                 const uint8_t *data, uint16_t length, +                                 uint64_t *latest_send_time, uint64_t rtt_time)  {      if (length == 0) {          return -1; @@ -1014,11 +1012,7 @@ static int handle_request_packet(Mono_Time *mono_time, const Logger *log, Packet              ++requested;          } else {              if (send_array->buffer[num]) { -                uint64_t sent_time = send_array->buffer[num]->sent_time; - -                if (l_sent_time < sent_time) { -                    l_sent_time = sent_time; -                } +                l_sent_time = max_u64(l_sent_time, send_array->buffer[num]->sent_time);                  free(send_array->buffer[num]);                  send_array->buffer[num] = nullptr; @@ -1039,9 +1033,7 @@ static int handle_request_packet(Mono_Time *mono_time, const Logger *log, Packet          }      } -    if (*latest_send_time < l_sent_time) { -        *latest_send_time = l_sent_time; -    } +    *latest_send_time = max_u64(*latest_send_time, l_sent_time);      return requested;  } @@ -1050,7 +1042,7 @@ static int handle_request_packet(Mono_Time *mono_time, const Logger *log, Packet  #define MAX_DATA_DATA_PACKET_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE)) -/* Creates and sends a data packet to the peer using the fastest route. +/** Creates and sends a data packet to the peer using the fastest route.   *   * return -1 on failure.   * return 0 on success. @@ -1086,7 +1078,7 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_      return send_packet_to(c, crypt_connection_id, packet, SIZEOF_VLA(packet));  } -/* Creates and sends a data packet with buffer_start and num to the peer using the fastest route. +/** Creates and sends a data packet with buffer_start and num to the peer using the fastest route.   *   * return -1 on failure.   * return 0 on success. @@ -1123,7 +1115,7 @@ static int reset_max_speed_reached(Net_Crypto *c, int crypt_connection_id)      if (conn->maximum_speed_reached) {          Packet_Data *dt = nullptr;          const uint32_t packet_num = conn->send_array.buffer_end - 1; -        const int ret = get_data_pointer(c->log, &conn->send_array, &dt, packet_num); +        const int ret = get_data_pointer(&conn->send_array, &dt, packet_num);          if (ret == 1 && dt->sent_time == 0) {              if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, @@ -1140,7 +1132,7 @@ static int reset_max_speed_reached(Net_Crypto *c, int crypt_connection_id)      return 0;  } -/*  return -1 if data could not be put in packet queue. +/**  return -1 if data could not be put in packet queue.   *  return positive packet number if data was put into the queue.   */  static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length, @@ -1169,7 +1161,7 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, cons      dt.length = length;      memcpy(dt.data, data, length);      pthread_mutex_lock(conn->mutex); -    int64_t packet_num = add_data_end_of_buffer(c->log, &conn->send_array, &dt); +    int64_t packet_num = add_data_end_of_buffer(&conn->send_array, &dt);      pthread_mutex_unlock(conn->mutex);      if (packet_num == -1) { @@ -1183,7 +1175,7 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, cons      if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, data, length) == 0) {          Packet_Data *dt1 = nullptr; -        if (get_data_pointer(c->log, &conn->send_array, &dt1, packet_num) == 1) { +        if (get_data_pointer(&conn->send_array, &dt1, packet_num) == 1) {              dt1->sent_time = current_time_monotonic(c->mono_time);          }      } else { @@ -1194,7 +1186,7 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, cons      return packet_num;  } -/* Get the lowest 2 bytes from the nonce and convert +/** Get the lowest 2 bytes from the nonce and convert   * them to host byte format before returning them.   */  static uint16_t get_nonce_uint16(const uint8_t *nonce) @@ -1206,7 +1198,7 @@ static uint16_t get_nonce_uint16(const uint8_t *nonce)  #define DATA_NUM_THRESHOLD 21845 -/* Handle a data packet. +/** Handle a data packet.   * Decrypt packet of length and put it into data.   * data must be at least MAX_DATA_DATA_PACKET_SIZE big.   * @@ -1249,21 +1241,21 @@ static int handle_data_packet(const Net_Crypto *c, int crypt_connection_id, uint      return len;  } -/* Send a request packet. +/** Send a request packet.   *   * return -1 on failure.   * return 0 on success.   */  static int send_request_packet(Net_Crypto *c, int crypt_connection_id)  { -    Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); +    const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);      if (conn == nullptr) {          return -1;      }      uint8_t data[MAX_CRYPTO_DATA_SIZE]; -    int len = generate_request_packet(c->log, data, sizeof(data), &conn->recv_array); +    int len = generate_request_packet(data, sizeof(data), &conn->recv_array);      if (len == -1) {          return -1; @@ -1273,7 +1265,7 @@ static int send_request_packet(Net_Crypto *c, int crypt_connection_id)                                     len);  } -/* Send up to max num previously requested data packets. +/** Send up to max num previously requested data packets.   *   * return -1 on failure.   * return number of packets sent on success. @@ -1284,7 +1276,7 @@ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32          return -1;      } -    Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); +    const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);      if (conn == nullptr) {          return -1; @@ -1297,7 +1289,7 @@ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32      for (uint32_t i = 0; i < array_size; ++i) {          Packet_Data *dt;          const uint32_t packet_num = i + conn->send_array.buffer_start; -        const int ret = get_data_pointer(c->log, &conn->send_array, &dt, packet_num); +        const int ret = get_data_pointer(&conn->send_array, &dt, packet_num);          if (ret == -1) {              return -1; @@ -1326,7 +1318,7 @@ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32  } -/* Add a new temp packet to send repeatedly. +/** Add a new temp packet to send repeatedly.   *   * return -1 on failure.   * return 0 on success. @@ -1361,7 +1353,7 @@ static int new_temp_packet(const Net_Crypto *c, int crypt_connection_id, const u      return 0;  } -/* Clear the temp packet. +/** Clear the temp packet.   *   * return -1 on failure.   * return 0 on success. @@ -1386,7 +1378,7 @@ static int clear_temp_packet(const Net_Crypto *c, int crypt_connection_id)  } -/* Send the temp packet. +/** Send the temp packet.   *   * return -1 on failure.   * return 0 on success. @@ -1412,7 +1404,7 @@ static int send_temp_packet(Net_Crypto *c, int crypt_connection_id)      return 0;  } -/* Create a handshake packet and set it as a temp packet. +/** Create a handshake packet and set it as a temp packet.   * cookie must be COOKIE_LENGTH.   *   * return -1 on failure. @@ -1421,7 +1413,7 @@ static int send_temp_packet(Net_Crypto *c, int crypt_connection_id)  static int create_send_handshake(Net_Crypto *c, int crypt_connection_id, const uint8_t *cookie,                                   const uint8_t *dht_public_key)  { -    Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); +    const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);      if (conn == nullptr) {          return -1; @@ -1442,14 +1434,14 @@ static int create_send_handshake(Net_Crypto *c, int crypt_connection_id, const u      return 0;  } -/* Send a kill packet. +/** Send a kill packet.   *   * return -1 on failure.   * return 0 on success.   */  static int send_kill_packet(Net_Crypto *c, int crypt_connection_id)  { -    Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); +    const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);      if (conn == nullptr) {          return -1; @@ -1462,7 +1454,7 @@ static int send_kill_packet(Net_Crypto *c, int crypt_connection_id)  static void connection_kill(Net_Crypto *c, int crypt_connection_id, void *userdata)  { -    Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); +    const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);      if (conn == nullptr) {          return; @@ -1487,7 +1479,7 @@ static void connection_kill(Net_Crypto *c, int crypt_connection_id, void *userda      pthread_mutex_unlock(&c->connections_mutex);  } -/* Handle a received data packet. +/** Handle a received data packet.   *   * return -1 on failure.   * return 0 on success. @@ -1524,16 +1516,16 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const      if (buffer_start != conn->send_array.buffer_start) {          Packet_Data *packet_time; -        if (get_data_pointer(c->log, &conn->send_array, &packet_time, conn->send_array.buffer_start) == 1) { +        if (get_data_pointer(&conn->send_array, &packet_time, conn->send_array.buffer_start) == 1) {              rtt_calc_time = packet_time->sent_time;          } -        if (clear_buffer_until(c->log, &conn->send_array, buffer_start) != 0) { +        if (clear_buffer_until(&conn->send_array, buffer_start) != 0) {              return -1;          }      } -    uint8_t *real_data = data + (sizeof(uint32_t) * 2); +    const uint8_t *real_data = data + (sizeof(uint32_t) * 2);      uint16_t real_length = len - (sizeof(uint32_t) * 2);      while (real_data[0] == PACKET_ID_PADDING) { /* Remove Padding */ @@ -1569,26 +1561,27 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const              rtt_time = DEFAULT_TCP_PING_CONNECTION;          } -        int requested = handle_request_packet(c->mono_time, c->log, &conn->send_array, real_data, real_length, &rtt_calc_time, -                                              rtt_time); +        int requested = handle_request_packet(c->mono_time, &conn->send_array, +                                              real_data, real_length, +                                              &rtt_calc_time, rtt_time);          if (requested == -1) {              return -1;          } -        set_buffer_end(c->log, &conn->recv_array, num); +        set_buffer_end(&conn->recv_array, num);      } else if (real_data[0] >= PACKET_ID_RANGE_LOSSLESS_START && real_data[0] <= PACKET_ID_RANGE_LOSSLESS_END) {          Packet_Data dt = {0};          dt.length = real_length;          memcpy(dt.data, real_data, real_length); -        if (add_data_to_buffer(c->log, &conn->recv_array, num, &dt) != 0) { +        if (add_data_to_buffer(&conn->recv_array, num, &dt) != 0) {              return -1;          }          while (1) {              pthread_mutex_lock(conn->mutex); -            int ret = read_data_beg_buffer(c->log, &conn->recv_array, &dt); +            const int ret = read_data_beg_buffer(&conn->recv_array, &dt);              pthread_mutex_unlock(conn->mutex);              if (ret == -1) { @@ -1612,7 +1605,7 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const          ++conn->packet_counter;      } else if (real_data[0] >= PACKET_ID_RANGE_LOSSY_START && real_data[0] <= PACKET_ID_RANGE_LOSSY_END) { -        set_buffer_end(c->log, &conn->recv_array, num); +        set_buffer_end(&conn->recv_array, num);          if (conn->connection_lossy_data_callback) {              conn->connection_lossy_data_callback(conn->connection_lossy_data_callback_object, @@ -1633,99 +1626,124 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const      return 0;  } -/* Handle a packet that was received for the connection. - * - * return -1 on failure. - * return 0 on success. - */ -static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length, -                                    bool udp, void *userdata) +static int handle_packet_cookie_response(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length)  { -    if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) { +    Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + +    if (conn == nullptr) {          return -1;      } +    if (conn->status != CRYPTO_CONN_COOKIE_REQUESTING) { +        return -1; +    } + +    uint8_t cookie[COOKIE_LENGTH]; +    uint64_t number; + +    if (handle_cookie_response(cookie, &number, packet, length, conn->shared_key) != sizeof(cookie)) { +        return -1; +    } + +    if (number != conn->cookie_request_number) { +        return -1; +    } + +    if (create_send_handshake(c, crypt_connection_id, cookie, conn->dht_public_key) != 0) { +        return -1; +    } + +    conn->status = CRYPTO_CONN_HANDSHAKE_SENT; +    return 0; +} + +static int handle_packet_crypto_hs(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length, +                                   void *userdata) +{      Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);      if (conn == nullptr) {          return -1;      } -    switch (packet[0]) { -        case NET_PACKET_COOKIE_RESPONSE: { -            if (conn->status != CRYPTO_CONN_COOKIE_REQUESTING) { -                return -1; -            } +    if (conn->status != CRYPTO_CONN_COOKIE_REQUESTING +            && conn->status != CRYPTO_CONN_HANDSHAKE_SENT +            && conn->status != CRYPTO_CONN_NOT_CONFIRMED) { +        return -1; +    } -            uint8_t cookie[COOKIE_LENGTH]; -            uint64_t number; +    uint8_t peer_real_pk[CRYPTO_PUBLIC_KEY_SIZE]; +    uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE]; +    uint8_t cookie[COOKIE_LENGTH]; -            if (handle_cookie_response(c->log, cookie, &number, packet, length, conn->shared_key) != sizeof(cookie)) { -                return -1; -            } +    if (handle_crypto_handshake(c, conn->recv_nonce, conn->peersessionpublic_key, peer_real_pk, dht_public_key, cookie, +                                packet, length, conn->public_key) != 0) { +        return -1; +    } -            if (number != conn->cookie_request_number) { -                return -1; -            } +    if (public_key_cmp(dht_public_key, conn->dht_public_key) == 0) { +        encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key); -            if (create_send_handshake(c, crypt_connection_id, cookie, conn->dht_public_key) != 0) { +        if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING) { +            if (create_send_handshake(c, crypt_connection_id, cookie, dht_public_key) != 0) {                  return -1;              } +        } -            conn->status = CRYPTO_CONN_HANDSHAKE_SENT; -            return 0; +        conn->status = CRYPTO_CONN_NOT_CONFIRMED; +    } else { +        if (conn->dht_pk_callback) { +            conn->dht_pk_callback(conn->dht_pk_callback_object, conn->dht_pk_callback_number, dht_public_key, userdata);          } +    } -        case NET_PACKET_CRYPTO_HS: { -            if (conn->status != CRYPTO_CONN_COOKIE_REQUESTING -                    && conn->status != CRYPTO_CONN_HANDSHAKE_SENT -                    && conn->status != CRYPTO_CONN_NOT_CONFIRMED) { -                return -1; -            } +    return 0; +} -            uint8_t peer_real_pk[CRYPTO_PUBLIC_KEY_SIZE]; -            uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE]; -            uint8_t cookie[COOKIE_LENGTH]; +static int handle_packet_crypto_data(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length, +                                     bool udp, void *userdata) +{ +    const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); -            if (handle_crypto_handshake(c, conn->recv_nonce, conn->peersessionpublic_key, peer_real_pk, dht_public_key, cookie, -                                        packet, length, conn->public_key) != 0) { -                return -1; -            } +    if (conn == nullptr) { +        return -1; +    } -            if (public_key_cmp(dht_public_key, conn->dht_public_key) == 0) { -                encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key); +    if (conn->status != CRYPTO_CONN_NOT_CONFIRMED && conn->status != CRYPTO_CONN_ESTABLISHED) { +        return -1; +    } -                if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING) { -                    if (create_send_handshake(c, crypt_connection_id, cookie, dht_public_key) != 0) { -                        return -1; -                    } -                } +    return handle_data_packet_core(c, crypt_connection_id, packet, length, udp, userdata); +} -                conn->status = CRYPTO_CONN_NOT_CONFIRMED; -            } else { -                if (conn->dht_pk_callback) { -                    conn->dht_pk_callback(conn->dht_pk_callback_object, conn->dht_pk_callback_number, dht_public_key, userdata); -                } -            } +/** Handle a packet that was received for the connection. + * + * return -1 on failure. + * return 0 on success. + */ +static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length, +                                    bool udp, void *userdata) +{ +    if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) { +        return -1; +    } -            return 0; -        } +    switch (packet[0]) { +        case NET_PACKET_COOKIE_RESPONSE: +            return handle_packet_cookie_response(c, crypt_connection_id, packet, length); -        case NET_PACKET_CRYPTO_DATA: { -            if (conn->status != CRYPTO_CONN_NOT_CONFIRMED && conn->status != CRYPTO_CONN_ESTABLISHED) { -                return -1; -            } +        case NET_PACKET_CRYPTO_HS: +            return handle_packet_crypto_hs(c, crypt_connection_id, packet, length, userdata); -            return handle_data_packet_core(c, crypt_connection_id, packet, length, udp, userdata); -        } +        case NET_PACKET_CRYPTO_DATA: +            return handle_packet_crypto_data(c, crypt_connection_id, packet, length, udp, userdata); -        default: { +        default:              return -1; -        }      }  } -/* Set the size of the friend list to numfriends. +/** Set the size of the friend list to numfriends.   *   *  return -1 if realloc fails.   *  return 0 if it succeeds. @@ -1750,7 +1768,7 @@ static int realloc_cryptoconnection(Net_Crypto *c, uint32_t num)  } -/* Create a new empty crypto connection. +/** Create a new empty crypto connection.   *   * return -1 on failure.   * return connection id on success. @@ -1791,7 +1809,7 @@ static int create_crypto_connection(Net_Crypto *c)          c->crypto_connections[id].last_packets_left_rem = 0;          c->crypto_connections[id].packet_send_rate_requested = 0;          c->crypto_connections[id].last_packets_left_requested_rem = 0; -        c->crypto_connections[id].mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t)); +        c->crypto_connections[id].mutex = (pthread_mutex_t *)calloc(1, sizeof(pthread_mutex_t));          if (c->crypto_connections[id].mutex == nullptr) {              pthread_mutex_unlock(&c->connections_mutex); @@ -1811,7 +1829,7 @@ static int create_crypto_connection(Net_Crypto *c)      return id;  } -/* Wipe a crypto connection. +/** Wipe a crypto connection.   *   * return -1 on failure.   * return 0 on success. @@ -1853,7 +1871,7 @@ static int wipe_crypto_connection(Net_Crypto *c, int crypt_connection_id)      return 0;  } -/* Get crypto connection id from public key of peer. +/** Get crypto connection id from public key of peer.   *   *  return -1 if there are no connections like we are looking for.   *  return id if it found it. @@ -1873,14 +1891,14 @@ static int getcryptconnection_id(const Net_Crypto *c, const uint8_t *public_key)      return -1;  } -/* Add a source to the crypto connection. +/** Add a source to the crypto connection.   * This is to be used only when we have received a packet from that source.   *   *  return -1 on failure.   *  return positive number on success.   *  0 if source was a direct UDP connection.   */ -static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id, IP_Port source) +static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id, const IP_Port *source)  {      Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -1888,12 +1906,12 @@ static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id,          return -1;      } -    if (net_family_is_ipv4(source.ip.family) || net_family_is_ipv6(source.ip.family)) { +    if (net_family_is_ipv4(source->ip.family) || net_family_is_ipv6(source->ip.family)) {          if (add_ip_port_connection(c, crypt_connection_id, source) != 0) {              return -1;          } -        if (net_family_is_ipv4(source.ip.family)) { +        if (net_family_is_ipv4(source->ip.family)) {              conn->direct_lastrecv_timev4 = mono_time_get(c->mono_time);          } else {              conn->direct_lastrecv_timev6 = mono_time_get(c->mono_time); @@ -1902,8 +1920,8 @@ static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id,          return 0;      } -    if (net_family_is_tcp_family(source.ip.family)) { -        if (add_tcp_number_relay_connection(c->tcp_c, conn->connection_number_tcp, source.ip.ip.v6.uint32[0]) == 0) { +    if (net_family_is_tcp_family(source->ip.family)) { +        if (add_tcp_number_relay_connection(c->tcp_c, conn->connection_number_tcp, source->ip.ip.v6.uint32[0]) == 0) {              return 1;          }      } @@ -1912,7 +1930,7 @@ static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id,  } -/* Set function to be called when someone requests a new connection to us. +/** Set function to be called when someone requests a new connection to us.   *   * The set function should return -1 on failure and 0 on success.   * @@ -1924,13 +1942,13 @@ void new_connection_handler(Net_Crypto *c, new_connection_cb *new_connection_cal      c->new_connection_callback_object = object;  } -/* Handle a handshake packet by someone who wants to initiate a new connection with us. +/** Handle a handshake packet by someone who wants to initiate a new connection with us.   * This calls the callback set by new_connection_handler() if the handshake is ok.   *   * return -1 on failure.   * return 0 on success.   */ -static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, const uint8_t *data, uint16_t length, +static int handle_new_connection_handshake(Net_Crypto *c, const IP_Port *source, const uint8_t *data, uint16_t length,          void *userdata)  {      New_Connection n_c; @@ -1940,7 +1958,7 @@ static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, const          return -1;      } -    n_c.source = source; +    n_c.source = *source;      n_c.cookie_length = COOKIE_LENGTH;      if (handle_crypto_handshake(c, n_c.recv_nonce, n_c.peersessionpublic_key, n_c.public_key, n_c.dht_public_key, @@ -1988,12 +2006,12 @@ static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, const      return ret;  } -/* Accept a crypto connection. +/** Accept a crypto connection.   *   * return -1 on failure.   * return connection id on success.   */ -int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) +int accept_crypto_connection(Net_Crypto *c, const New_Connection *n_c)  {      if (getcryptconnection_id(c, n_c->public_key) != -1) {          return -1; @@ -2044,11 +2062,11 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c)      conn->packet_send_rate_requested = CRYPTO_PACKET_MIN_RATE;      conn->packets_left = CRYPTO_MIN_QUEUE_LENGTH;      conn->rtt_time = DEFAULT_PING_CONNECTION; -    crypto_connection_add_source(c, crypt_connection_id, n_c->source); +    crypto_connection_add_source(c, crypt_connection_id, &n_c->source);      return crypt_connection_id;  } -/* Create a crypto connection. +/** Create a crypto connection.   * If one to that real public key already exists, return it.   *   * return -1 on failure. @@ -2106,14 +2124,14 @@ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const u      return crypt_connection_id;  } -/* Set the direct ip of the crypto connection. +/** Set the direct ip of the crypto connection.   *   * Connected is 0 if we are not sure we are connected to that person, 1 if we are sure.   *   * return -1 on failure.   * return 0 on success.   */ -int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, bool connected) +int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, const IP_Port *ip_port, bool connected)  {      Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -2127,7 +2145,7 @@ int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port,      const uint64_t direct_lastrecv_time = connected ? mono_time_get(c->mono_time) : 0; -    if (net_family_is_ipv4(ip_port.ip.family)) { +    if (net_family_is_ipv4(ip_port->ip.family)) {          conn->direct_lastrecv_timev4 = direct_lastrecv_time;      } else {          conn->direct_lastrecv_timev6 = direct_lastrecv_time; @@ -2146,7 +2164,7 @@ static int tcp_data_callback(void *object, int crypt_connection_id, const uint8_          return -1;      } -    Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); +    const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);      if (conn == nullptr) {          return -1; @@ -2189,7 +2207,7 @@ static int tcp_oob_callback(void *object, const uint8_t *public_key, unsigned in          source.ip.family = net_family_tcp_family;          source.ip.ip.v6.uint32[0] = tcp_connections_number; -        if (handle_new_connection_handshake(c, source, data, length, userdata) != 0) { +        if (handle_new_connection_handshake(c, &source, data, length, userdata) != 0) {              return -1;          } @@ -2199,14 +2217,14 @@ static int tcp_oob_callback(void *object, const uint8_t *public_key, unsigned in      return -1;  } -/* Add a tcp relay, associating it to a crypt_connection_id. +/** Add a tcp relay, associating it to a crypt_connection_id.   *   * return 0 if it was added.   * return -1 if it wasn't.   */ -int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, const uint8_t *public_key) +int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, const IP_Port *ip_port, const uint8_t *public_key)  { -    Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); +    const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);      if (conn == nullptr) {          return -1; @@ -2218,12 +2236,12 @@ int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port,      return ret;  } -/* Add a tcp relay to the array. +/** Add a tcp relay to the array.   *   * return 0 if it was added.   * return -1 if it wasn't.   */ -int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, const uint8_t *public_key) +int add_tcp_relay(Net_Crypto *c, const IP_Port *ip_port, const uint8_t *public_key)  {      pthread_mutex_lock(&c->tcp_mutex);      int ret = add_tcp_relay_global(c->tcp_c, ip_port, public_key); @@ -2231,7 +2249,7 @@ int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, const uint8_t *public_key)      return ret;  } -/* Return a random TCP connection number for use in send_tcp_onion_request. +/** Return a random TCP connection number for use in send_tcp_onion_request.   *   * TODO(irungentoo): This number is just the index of an array that the elements can   * change without warning. @@ -2248,7 +2266,7 @@ int get_random_tcp_con_number(Net_Crypto *c)      return ret;  } -/* Send an onion packet via the TCP relay corresponding to tcp_connections_number. +/** Send an onion packet via the TCP relay corresponding to tcp_connections_number.   *   * return 0 on success.   * return -1 on failure. @@ -2262,7 +2280,7 @@ int send_tcp_onion_request(Net_Crypto *c, unsigned int tcp_connections_number, c      return ret;  } -/* Copy a maximum of num TCP relays we are connected to to tcp_relays. +/** Copy a maximum of num TCP relays we are connected to to tcp_relays.   * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6.   *   * return number of relays copied to tcp_relays on success. @@ -2288,7 +2306,7 @@ static void do_tcp(Net_Crypto *c, void *userdata)      pthread_mutex_unlock(&c->tcp_mutex);      for (uint32_t i = 0; i < c->crypto_connections_length; ++i) { -        Crypto_Connection *conn = get_crypto_connection(c, i); +        const Crypto_Connection *conn = get_crypto_connection(c, i);          if (conn == nullptr) {              continue; @@ -2310,7 +2328,7 @@ static void do_tcp(Net_Crypto *c, void *userdata)      }  } -/* Set function to be called when connection with crypt_connection_id goes connects/disconnects. +/** Set function to be called when connection with crypt_connection_id goes connects/disconnects.   *   * The set function should return -1 on failure and 0 on success.   * Note that if this function is set, the connection will clear itself on disconnect. @@ -2335,7 +2353,7 @@ int connection_status_handler(const Net_Crypto *c, int crypt_connection_id,      return 0;  } -/* Set function to be called when connection with crypt_connection_id receives a data packet of length. +/** Set function to be called when connection with crypt_connection_id receives a lossless data packet of length.   *   * The set function should return -1 on failure and 0 on success.   * Object and id will be passed to this function untouched. @@ -2358,7 +2376,7 @@ int connection_data_handler(const Net_Crypto *c, int crypt_connection_id,      return 0;  } -/* Set function to be called when connection with crypt_connection_id receives a lossy data packet of length. +/** Set function to be called when connection with crypt_connection_id receives a lossy data packet of length.   *   * The set function should return -1 on failure and 0 on success.   * Object and id will be passed to this function untouched. @@ -2366,7 +2384,7 @@ int connection_data_handler(const Net_Crypto *c, int crypt_connection_id,   * return -1 on failure.   * return 0 on success.   */ -int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id, +int connection_lossy_data_handler(const Net_Crypto *c, int crypt_connection_id,                                    connection_lossy_data_cb *connection_lossy_data_callback,                                    void *object, int id)  { @@ -2383,7 +2401,7 @@ int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id,  } -/* Set the function for this friend that will be callbacked with object and number if +/** Set the function for this friend that will be callbacked with object and number if   * the friend sends us a different dht public key than we have associated to him.   *   * If this function is called, the connection should be recreated with the new public key. @@ -2393,7 +2411,7 @@ int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id,   * return -1 on failure.   * return 0 on success.   */ -int nc_dht_pk_callback(Net_Crypto *c, int crypt_connection_id, dht_pk_cb *function, void *object, uint32_t number) +int nc_dht_pk_callback(const Net_Crypto *c, int crypt_connection_id, dht_pk_cb *function, void *object, uint32_t number)  {      Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -2407,19 +2425,19 @@ int nc_dht_pk_callback(Net_Crypto *c, int crypt_connection_id, dht_pk_cb *functi      return 0;  } -/* Get the crypto connection id from the ip_port. +/** Get the crypto connection id from the ip_port.   *   * return -1 on failure.   * return connection id on success.   */ -static int crypto_id_ip_port(const Net_Crypto *c, IP_Port ip_port) +static int crypto_id_ip_port(const Net_Crypto *c, const IP_Port *ip_port)  { -    return bs_list_find(&c->ip_port_list, (uint8_t *)&ip_port); +    return bs_list_find(&c->ip_port_list, (const uint8_t *)ip_port);  }  #define CRYPTO_MIN_PACKET_SIZE (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE) -/* Handle raw UDP packets coming directly from the socket. +/** Handle raw UDP packets coming directly from the socket.   *   * Handles:   * Cookie response packets. @@ -2427,7 +2445,8 @@ static int crypto_id_ip_port(const Net_Crypto *c, IP_Port ip_port)   * Crypto data packets.   *   */ -static int udp_handle_packet(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) +static int udp_handle_packet(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, +                             void *userdata)  {      Net_Crypto *c = (Net_Crypto *)object; @@ -2461,7 +2480,7 @@ static int udp_handle_packet(void *object, IP_Port source, const uint8_t *packet      pthread_mutex_lock(conn->mutex); -    if (net_family_is_ipv4(source.ip.family)) { +    if (net_family_is_ipv4(source->ip.family)) {          conn->direct_lastrecv_timev4 = mono_time_get(c->mono_time);      } else {          conn->direct_lastrecv_timev6 = mono_time_get(c->mono_time); @@ -2471,19 +2490,19 @@ static int udp_handle_packet(void *object, IP_Port source, const uint8_t *packet      return 0;  } -/* The dT for the average packet receiving rate calculations. +/** The dT for the average packet receiving rate calculations.   * Also used as the */  #define PACKET_COUNTER_AVERAGE_INTERVAL 50 -/* Ratio of recv queue size / recv packet rate (in seconds) times +/** Ratio of recv queue size / recv packet rate (in seconds) times   * the number of ms between request packets to send at that ratio   */  #define REQUEST_PACKETS_COMPARE_CONSTANT (0.125 * 100.0) -/* Timeout for increasing speed after congestion event (in ms). */ +/** Timeout for increasing speed after congestion event (in ms). */  #define CONGESTION_EVENT_TIMEOUT 1000 -/* If the send queue is SEND_QUEUE_RATIO times larger than the +/** If the send queue is SEND_QUEUE_RATIO times larger than the   * calculated link speed the packet send speed will be reduced   * by a value depending on this number.   */ @@ -2515,8 +2534,8 @@ static void send_crypto_packets(Net_Crypto *c)          if (conn->status == CRYPTO_CONN_ESTABLISHED) {              if (conn->packet_recv_rate > CRYPTO_PACKET_MIN_RATE) { -                double request_packet_interval = (REQUEST_PACKETS_COMPARE_CONSTANT / ((num_packets_array( -                                                      &conn->recv_array) + 1.0) / (conn->packet_recv_rate + 1.0))); +                double request_packet_interval = REQUEST_PACKETS_COMPARE_CONSTANT / ((num_packets_array( +                                                     &conn->recv_array) + 1.0) / (conn->packet_recv_rate + 1.0));                  double request_packet_interval2 = ((CRYPTO_PACKET_MIN_RATE / conn->packet_recv_rate) *                                                     (double)CRYPTO_SEND_PACKET_INTERVAL) + (double)PACKET_COUNTER_AVERAGE_INTERVAL; @@ -2585,8 +2604,8 @@ static void send_crypto_packets(Net_Crypto *c)                      long signed int total_resent = 0;                      // TODO(irungentoo): use real delay -                    unsigned int delay = (unsigned int)((conn->rtt_time / PACKET_COUNTER_AVERAGE_INTERVAL) + 0.5); -                    unsigned int packets_set_rem_array = (CONGESTION_LAST_SENT_ARRAY_SIZE - CONGESTION_QUEUE_ARRAY_SIZE); +                    unsigned int delay = (unsigned int)(((double)conn->rtt_time / PACKET_COUNTER_AVERAGE_INTERVAL) + 0.5); +                    unsigned int packets_set_rem_array = CONGESTION_LAST_SENT_ARRAY_SIZE - CONGESTION_QUEUE_ARRAY_SIZE;                      if (delay > packets_set_rem_array) {                          delay = packets_set_rem_array; @@ -2608,17 +2627,17 @@ static void send_crypto_packets(Net_Crypto *c)                      /* if queue is too big only allow resending packets. */                      uint32_t npackets = num_packets_array(&conn->send_array); -                    double min_speed = 1000.0 * (((double)(total_sent)) / ((double)(CONGESTION_QUEUE_ARRAY_SIZE) * +                    double min_speed = 1000.0 * (((double)total_sent) / ((double)CONGESTION_QUEUE_ARRAY_SIZE *                                                   PACKET_COUNTER_AVERAGE_INTERVAL)); -                    double min_speed_request = 1000.0 * (((double)(total_sent + total_resent)) / ((double)( -                            CONGESTION_QUEUE_ARRAY_SIZE) * PACKET_COUNTER_AVERAGE_INTERVAL)); +                    double min_speed_request = 1000.0 * (((double)(total_sent + total_resent)) / ( +                            (double)CONGESTION_QUEUE_ARRAY_SIZE * PACKET_COUNTER_AVERAGE_INTERVAL));                      if (min_speed < CRYPTO_PACKET_MIN_RATE) {                          min_speed = CRYPTO_PACKET_MIN_RATE;                      } -                    double send_array_ratio = (((double)npackets) / min_speed); +                    double send_array_ratio = (double)npackets / min_speed;                      // TODO(irungentoo): Improve formula?                      if (send_array_ratio > SEND_QUEUE_RATIO && CRYPTO_MIN_QUEUE_LENGTH < npackets) { @@ -2725,7 +2744,7 @@ static void send_crypto_packets(Net_Crypto *c)      }  } -/* Return 1 if max speed was reached for this connection (no more data can be physically through the pipe). +/** Return 1 if max speed was reached for this connection (no more data can be physically through the pipe).   * Return 0 if it wasn't reached.   */  bool max_speed_reached(Net_Crypto *c, int crypt_connection_id) @@ -2733,12 +2752,12 @@ bool max_speed_reached(Net_Crypto *c, int crypt_connection_id)      return reset_max_speed_reached(c, crypt_connection_id) != 0;  } -/* returns the number of packet slots left in the sendbuffer. +/** returns the number of packet slots left in the sendbuffer.   * return 0 if failure.   */  uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connection_id)  { -    Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); +    const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);      if (conn == nullptr) {          return 0; @@ -2753,12 +2772,12 @@ uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connecti      return max_packets;  } -/* Sends a lossless cryptopacket. +/** Sends a lossless cryptopacket.   *   * return -1 if data could not be put in packet queue.   * return positive packet number if data was put into the queue.   * - * The first byte of data must in the PACKET_ID_RANGE_LOSSLESS. + * The first byte of data must be in the PACKET_ID_RANGE_LOSSLESS.   *   * congestion_control: should congestion control apply to this packet?   */ @@ -2802,7 +2821,7 @@ int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t      return ret;  } -/* Check if packet_number was received by the other side. +/** Check if packet_number was received by the other side.   *   * packet_number must be a valid packet number of a packet sent on this connection.   * @@ -2816,9 +2835,9 @@ int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t   * It CANNOT be simplified to `packet_number < buffer_start`, as it will fail   * when `buffer_end < buffer_start`.   */ -int cryptpacket_received(Net_Crypto *c, int crypt_connection_id, uint32_t packet_number) +int cryptpacket_received(const Net_Crypto *c, int crypt_connection_id, uint32_t packet_number)  { -    Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); +    const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);      if (conn == nullptr) {          return -1; @@ -2834,12 +2853,12 @@ int cryptpacket_received(Net_Crypto *c, int crypt_connection_id, uint32_t packet      return 0;  } -/* Sends a lossy cryptopacket. +/** Sends a lossy cryptopacket.   *   * return -1 on failure.   * return 0 on success.   * - * The first byte of data must in the PACKET_ID_RANGE_LOSSY. + * The first byte of data must be in the PACKET_ID_RANGE_LOSSY.   */  int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length)  { @@ -2874,7 +2893,7 @@ int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t      return ret;  } -/* Kill a crypto connection. +/** Kill a crypto connection.   *   * return -1 on failure.   * return 0 on success. @@ -2908,7 +2927,7 @@ int crypto_kill(Net_Crypto *c, int crypt_connection_id)  bool crypto_connection_status(const Net_Crypto *c, int crypt_connection_id, bool *direct_connected,                                unsigned int *online_tcp_relays)  { -    Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); +    const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);      if (conn == nullptr) {          return false; @@ -2938,8 +2957,8 @@ void new_keys(Net_Crypto *c)      crypto_new_keypair(c->self_public_key, c->self_secret_key);  } -/* Save the public and private keys to the keys array. - * Length must be CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE. +/** Save the public and private keys to the keys array. + *  Length must be CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE.   *   * TODO(irungentoo): Save only secret key.   */ @@ -2949,7 +2968,7 @@ void save_keys(const Net_Crypto *c, uint8_t *keys)      memcpy(keys + CRYPTO_PUBLIC_KEY_SIZE, c->self_secret_key, CRYPTO_SECRET_KEY_SIZE);  } -/* Load the secret key. +/** Load the secret key.   * Length must be CRYPTO_SECRET_KEY_SIZE.   */  void load_secret_key(Net_Crypto *c, const uint8_t *sk) @@ -2958,10 +2977,10 @@ void load_secret_key(Net_Crypto *c, const uint8_t *sk)      crypto_derive_public_key(c->self_public_key, c->self_secret_key);  } -/* Run this to (re)initialize net_crypto. - * Sets all the global connection variables to their default values. +/** Create new instance of Net_Crypto. + *  Sets all the global connection variables to their default values.   */ -Net_Crypto *new_net_crypto(const Logger *log, Mono_Time *mono_time, DHT *dht, TCP_Proxy_Info *proxy_info) +Net_Crypto *new_net_crypto(const Logger *log, Mono_Time *mono_time, DHT *dht, const TCP_Proxy_Info *proxy_info)  {      if (dht == nullptr) {          return nullptr; @@ -2976,7 +2995,7 @@ Net_Crypto *new_net_crypto(const Logger *log, Mono_Time *mono_time, DHT *dht, TC      temp->log = log;      temp->mono_time = mono_time; -    temp->tcp_c = new_tcp_connections(mono_time, dht_get_self_secret_key(dht), proxy_info); +    temp->tcp_c = new_tcp_connections(log, mono_time, dht_get_self_secret_key(dht), proxy_info);      if (temp->tcp_c == nullptr) {          free(temp); @@ -3013,7 +3032,7 @@ Net_Crypto *new_net_crypto(const Logger *log, Mono_Time *mono_time, DHT *dht, TC  static void kill_timedout(Net_Crypto *c, void *userdata)  {      for (uint32_t i = 0; i < c->crypto_connections_length; ++i) { -        Crypto_Connection *conn = get_crypto_connection(c, i); +        const Crypto_Connection *conn = get_crypto_connection(c, i);          if (conn == nullptr) {              continue; @@ -3039,14 +3058,14 @@ static void kill_timedout(Net_Crypto *c, void *userdata)      }  } -/* return the optimal interval in ms for running do_net_crypto. +/** return the optimal interval in ms for running do_net_crypto.   */  uint32_t crypto_run_interval(const Net_Crypto *c)  {      return c->current_sleep_time;  } -/* Main loop. */ +/** Main loop. */  void do_net_crypto(Net_Crypto *c, void *userdata)  {      kill_timedout(c, userdata); @@ -3056,9 +3075,7 @@ void do_net_crypto(Net_Crypto *c, void *userdata)  void kill_net_crypto(Net_Crypto *c)  { -    uint32_t i; - -    for (i = 0; i < c->crypto_connections_length; ++i) { +    for (uint32_t i = 0; i < c->crypto_connections_length; ++i) {          crypto_kill(c, i);      } diff --git a/protocols/Tox/libtox/src/toxcore/net_crypto.h b/protocols/Tox/libtox/src/toxcore/net_crypto.h index 33275708af..9a3bd1e21c 100644 --- a/protocols/Tox/libtox/src/toxcore/net_crypto.h +++ b/protocols/Tox/libtox/src/toxcore/net_crypto.h @@ -3,45 +3,45 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * Functions for the core network crypto.   */  #ifndef C_TOXCORE_TOXCORE_NET_CRYPTO_H  #define C_TOXCORE_TOXCORE_NET_CRYPTO_H +#include <pthread.h> +  #include "DHT.h"  #include "LAN_discovery.h"  #include "TCP_connection.h"  #include "logger.h" -#include <pthread.h> - -/** Crypto payloads. */ +/*** Crypto payloads. */ -/** Ranges. */ +/*** Ranges. */ -/* Packets in this range are reserved for net_crypto internal use. */ +/** Packets in this range are reserved for net_crypto internal use. */  #define PACKET_ID_RANGE_RESERVED_START 0  #define PACKET_ID_RANGE_RESERVED_END 15 -/* Packets in this range are reserved for Messenger use. */ +/** Packets in this range are reserved for Messenger use. */  #define PACKET_ID_RANGE_LOSSLESS_START 16  #define PACKET_ID_RANGE_LOSSLESS_NORMAL_START 16  #define PACKET_ID_RANGE_LOSSLESS_NORMAL_END 159 -/* Packets in this range can be used for anything. */ +/** Packets in this range can be used for anything. */  #define PACKET_ID_RANGE_LOSSLESS_CUSTOM_START 160  #define PACKET_ID_RANGE_LOSSLESS_CUSTOM_END 191  #define PACKET_ID_RANGE_LOSSLESS_END 191 -/* Packets in this range are reserved for AV use. */ +/** Packets in this range are reserved for AV use. */  #define PACKET_ID_RANGE_LOSSY_START 192  #define PACKET_ID_RANGE_LOSSY_AV_START 192  #define PACKET_ID_RANGE_LOSSY_AV_SIZE 8  #define PACKET_ID_RANGE_LOSSY_AV_END 199 -/* Packets in this range can be used for anything. */ +/** Packets in this range can be used for anything. */  #define PACKET_ID_RANGE_LOSSY_CUSTOM_START 200  #define PACKET_ID_RANGE_LOSSY_CUSTOM_END 254  #define PACKET_ID_RANGE_LOSSY_END 254 -/** Messages. */ +/*** Messages. */  #define PACKET_ID_PADDING 0 // Denotes padding  #define PACKET_ID_REQUEST 1 // Used to request unreceived packets @@ -66,45 +66,45 @@  #define PACKET_ID_REJOIN_CONFERENCE 100  #define PACKET_ID_LOSSY_CONFERENCE 199 -/* Maximum size of receiving and sending packet buffers. */ +/** Maximum size of receiving and sending packet buffers. */  #define CRYPTO_PACKET_BUFFER_SIZE 32768 // Must be a power of 2 -/* Minimum packet rate per second. */ +/** Minimum packet rate per second. */  #define CRYPTO_PACKET_MIN_RATE 4.0 -/* Minimum packet queue max length. */ +/** Minimum packet queue max length. */  #define CRYPTO_MIN_QUEUE_LENGTH 64 -/* Maximum total size of packets that net_crypto sends. */ +/** Maximum total size of packets that net_crypto sends. */  #define MAX_CRYPTO_PACKET_SIZE (uint16_t)1400  #define CRYPTO_DATA_PACKET_MIN_SIZE (uint16_t)(1 + sizeof(uint16_t) + (sizeof(uint32_t) + sizeof(uint32_t)) + CRYPTO_MAC_SIZE) -/* Max size of data in packets */ +/** Max size of data in packets */  #define MAX_CRYPTO_DATA_SIZE (uint16_t)(MAX_CRYPTO_PACKET_SIZE - CRYPTO_DATA_PACKET_MIN_SIZE) -/* Interval in ms between sending cookie request/handshake packets. */ +/** Interval in ms between sending cookie request/handshake packets. */  #define CRYPTO_SEND_PACKET_INTERVAL 1000 -/* The maximum number of times we try to send the cookie request and handshake +/** The maximum number of times we try to send the cookie request and handshake   * before giving up. */  #define MAX_NUM_SENDPACKET_TRIES 8 -/* The timeout of no received UDP packets before the direct UDP connection is considered dead. */ +/** The timeout of no received UDP packets before the direct UDP connection is considered dead. */  #define UDP_DIRECT_TIMEOUT 8  #define MAX_TCP_CONNECTIONS 64  #define MAX_TCP_RELAYS_PEER 4 -/* All packets will be padded a number of bytes based on this number. */ +/** All packets will be padded a number of bytes based on this number. */  #define CRYPTO_MAX_PADDING 8 -/* Base current transfer speed on last CONGESTION_QUEUE_ARRAY_SIZE number of points taken +/** Base current transfer speed on last CONGESTION_QUEUE_ARRAY_SIZE number of points taken   * at the dT defined in net_crypto.c */  #define CONGESTION_QUEUE_ARRAY_SIZE 12  #define CONGESTION_LAST_SENT_ARRAY_SIZE (CONGESTION_QUEUE_ARRAY_SIZE * 2) -/* Default connection ping in ms. */ +/** Default connection ping in ms. */  #define DEFAULT_PING_CONNECTION 1000  #define DEFAULT_TCP_PING_CONNECTION 500 @@ -129,9 +129,9 @@ typedef int connection_status_cb(void *object, int id, uint8_t status, void *use  typedef int connection_data_cb(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);  typedef int connection_lossy_data_cb(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);  typedef void dht_pk_cb(void *data, int32_t number, const uint8_t *dht_public_key, void *userdata); -typedef int new_connection_cb(void *object, New_Connection *n_c); +typedef int new_connection_cb(void *object, const New_Connection *n_c); -/* Set function to be called when someone requests a new connection to us. +/** Set function to be called when someone requests a new connection to us.   *   * The set function should return -1 on failure and 0 on success.   * @@ -139,14 +139,14 @@ typedef int new_connection_cb(void *object, New_Connection *n_c);   */  void new_connection_handler(Net_Crypto *c, new_connection_cb *new_connection_callback, void *object); -/* Accept a crypto connection. +/** Accept a crypto connection.   *   * return -1 on failure.   * return connection id on success.   */ -int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c); +int accept_crypto_connection(Net_Crypto *c, const New_Connection *n_c); -/* Create a crypto connection. +/** Create a crypto connection.   * If one to that real public key already exists, return it.   *   * return -1 on failure. @@ -154,16 +154,16 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c);   */  int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const uint8_t *dht_public_key); -/* Set the direct ip of the crypto connection. +/** Set the direct ip of the crypto connection.   *   * Connected is 0 if we are not sure we are connected to that person, 1 if we are sure.   *   * return -1 on failure.   * return 0 on success.   */ -int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, bool connected); +int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, const IP_Port *ip_port, bool connected); -/* Set function to be called when connection with crypt_connection_id goes connects/disconnects. +/** Set function to be called when connection with crypt_connection_id goes connects/disconnects.   *   * The set function should return -1 on failure and 0 on success.   * Note that if this function is set, the connection will clear itself on disconnect. @@ -176,7 +176,7 @@ int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port,  int connection_status_handler(const Net_Crypto *c, int crypt_connection_id,                                connection_status_cb *connection_status_callback, void *object, int id); -/* Set function to be called when connection with crypt_connection_id receives a lossless data packet of length. +/** Set function to be called when connection with crypt_connection_id receives a lossless data packet of length.   *   * The set function should return -1 on failure and 0 on success.   * Object and id will be passed to this function untouched. @@ -188,7 +188,7 @@ int connection_data_handler(const Net_Crypto *c, int crypt_connection_id,                              connection_data_cb *connection_data_callback, void *object, int id); -/* Set function to be called when connection with crypt_connection_id receives a lossy data packet of length. +/** Set function to be called when connection with crypt_connection_id receives a lossy data packet of length.   *   * The set function should return -1 on failure and 0 on success.   * Object and id will be passed to this function untouched. @@ -196,10 +196,10 @@ int connection_data_handler(const Net_Crypto *c, int crypt_connection_id,   * return -1 on failure.   * return 0 on success.   */ -int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id, +int connection_lossy_data_handler(const Net_Crypto *c, int crypt_connection_id,                                    connection_lossy_data_cb *connection_lossy_data_callback, void *object, int id); -/* Set the function for this friend that will be callbacked with object and number if +/** Set the function for this friend that will be callbacked with object and number if   * the friend sends us a different dht public key than we have associated to him.   *   * If this function is called, the connection should be recreated with the new public key. @@ -209,19 +209,20 @@ int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id,   * return -1 on failure.   * return 0 on success.   */ -int nc_dht_pk_callback(Net_Crypto *c, int crypt_connection_id, dht_pk_cb *function, void *object, uint32_t number); +int nc_dht_pk_callback(const Net_Crypto *c, int crypt_connection_id, dht_pk_cb *function, void *object, +                       uint32_t number); -/* returns the number of packet slots left in the sendbuffer. +/** returns the number of packet slots left in the sendbuffer.   * return 0 if failure.   */  uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connection_id); -/* Return 1 if max speed was reached for this connection (no more data can be physically through the pipe). +/** Return 1 if max speed was reached for this connection (no more data can be physically through the pipe).   * Return 0 if it wasn't reached.   */  bool max_speed_reached(Net_Crypto *c, int crypt_connection_id); -/* Sends a lossless cryptopacket. +/** Sends a lossless cryptopacket.   *   * return -1 if data could not be put in packet queue.   * return positive packet number if data was put into the queue. @@ -233,16 +234,23 @@ bool max_speed_reached(Net_Crypto *c, int crypt_connection_id);  int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length,                            uint8_t congestion_control); -/* Check if packet_number was received by the other side. +/** Check if packet_number was received by the other side.   *   * packet_number must be a valid packet number of a packet sent on this connection.   *   * return -1 on failure.   * return 0 on success. + * + * Note: The condition `buffer_end - buffer_start < packet_number - buffer_start` is + * a trick which handles situations `buffer_end >= buffer_start` and + * `buffer_end < buffer_start` (when buffer_end overflowed) both correctly. + * + * It CANNOT be simplified to `packet_number < buffer_start`, as it will fail + * when `buffer_end < buffer_start`.   */ -int cryptpacket_received(Net_Crypto *c, int crypt_connection_id, uint32_t packet_number); +int cryptpacket_received(const Net_Crypto *c, int crypt_connection_id, uint32_t packet_number); -/* Sends a lossy cryptopacket. +/** Sends a lossy cryptopacket.   *   * return -1 on failure.   * return 0 on success. @@ -251,35 +259,38 @@ int cryptpacket_received(Net_Crypto *c, int crypt_connection_id, uint32_t packet   */  int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length); -/* Add a tcp relay, associating it to a crypt_connection_id. +/** Add a tcp relay, associating it to a crypt_connection_id.   *   * return 0 if it was added.   * return -1 if it wasn't.   */ -int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, const uint8_t *public_key); +int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, const IP_Port *ip_port, const uint8_t *public_key); -/* Add a tcp relay to the array. +/** Add a tcp relay to the array.   *   * return 0 if it was added.   * return -1 if it wasn't.   */ -int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, const uint8_t *public_key); +int add_tcp_relay(Net_Crypto *c, const IP_Port *ip_port, const uint8_t *public_key); -/* Return a random TCP connection number for use in send_tcp_onion_request. +/** Return a random TCP connection number for use in send_tcp_onion_request. + * + * TODO(irungentoo): This number is just the index of an array that the elements can + * change without warning.   *   * return TCP connection number on success.   * return -1 on failure.   */  int get_random_tcp_con_number(Net_Crypto *c); -/* Send an onion packet via the TCP relay corresponding to TCP_conn_number. +/** Send an onion packet via the TCP relay corresponding to tcp_connections_number.   *   * return 0 on success.   * return -1 on failure.   */  int send_tcp_onion_request(Net_Crypto *c, unsigned int tcp_connections_number, const uint8_t *data, uint16_t length); -/* Copy a maximum of num TCP relays we are connected to to tcp_relays. +/** Copy a maximum of num TCP relays we are connected to to tcp_relays.   * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6.   *   * return number of relays copied to tcp_relays on success. @@ -287,14 +298,14 @@ int send_tcp_onion_request(Net_Crypto *c, unsigned int tcp_connections_number, c   */  unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, uint16_t num); -/* Kill a crypto connection. +/** Kill a crypto connection.   *   * return -1 on failure.   * return 0 on success.   */  int crypto_kill(Net_Crypto *c, int crypt_connection_id); -/* return true if connection is valid, false otherwise +/** return true if connection is valid, false otherwise   *   * sets direct_connected to 1 if connection connects directly to other, 0 if it isn't.   * sets online_tcp_relays to the number of connected tcp relays this connection has. @@ -302,31 +313,33 @@ int crypto_kill(Net_Crypto *c, int crypt_connection_id);  bool crypto_connection_status(const Net_Crypto *c, int crypt_connection_id, bool *direct_connected,                                unsigned int *online_tcp_relays); -/* Generate our public and private keys. +/** Generate our public and private keys.   *  Only call this function the first time the program starts.   */  void new_keys(Net_Crypto *c); -/* Save the public and private keys to the keys array. +/** Save the public and private keys to the keys array.   *  Length must be CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE. + * + * TODO(irungentoo): Save only secret key.   */  void save_keys(const Net_Crypto *c, uint8_t *keys); -/* Load the secret key. +/** Load the secret key.   * Length must be CRYPTO_SECRET_KEY_SIZE.   */  void load_secret_key(Net_Crypto *c, const uint8_t *sk); -/* Create new instance of Net_Crypto. +/** Create new instance of Net_Crypto.   *  Sets all the global connection variables to their default values.   */ -Net_Crypto *new_net_crypto(const Logger *log, Mono_Time *mono_time, DHT *dht, TCP_Proxy_Info *proxy_info); +Net_Crypto *new_net_crypto(const Logger *log, Mono_Time *mono_time, DHT *dht, const TCP_Proxy_Info *proxy_info); -/* return the optimal interval in ms for running do_net_crypto. +/** return the optimal interval in ms for running do_net_crypto.   */  uint32_t crypto_run_interval(const Net_Crypto *c); -/* Main loop. */ +/** Main loop. */  void do_net_crypto(Net_Crypto *c, void *userdata);  void kill_net_crypto(Net_Crypto *c); diff --git a/protocols/Tox/libtox/src/toxcore/network.c b/protocols/Tox/libtox/src/toxcore/network.c index 88b4695a21..8569fc17e5 100644 --- a/protocols/Tox/libtox/src/toxcore/network.c +++ b/protocols/Tox/libtox/src/toxcore/network.c @@ -3,12 +3,9 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * Functions for the core networking.   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif  #ifdef __APPLE__  #define _DARWIN_C_SOURCE @@ -33,12 +30,12 @@  #define OS_WIN32  #endif -#ifdef OS_WIN32 -#ifndef WINVER +#if defined(OS_WIN32) && !defined(WINVER)  // Windows XP  #define WINVER 0x0501  #endif -#endif + +#include "network.h"  #ifdef PLAN9  #include <u.h> // Plan 9 requires this is imported first @@ -46,7 +43,7 @@  #include <libc.h>  #endif -#ifdef OS_WIN32 /* Put win32 includes here */ +#ifdef OS_WIN32 // Put win32 includes here  // The mingw32/64 Windows library warns about including winsock2.h after  // windows.h even though with the above it's a valid thing to do. So, to make  // mingw32 headers happy, we include winsock2.h first. @@ -56,15 +53,12 @@  #include <ws2tcpip.h>  #endif -#include "network.h" -  #ifdef __APPLE__  #include <mach/clock.h>  #include <mach/mach.h>  #endif  #if !defined(OS_WIN32) -  #include <arpa/inet.h>  #include <errno.h>  #include <fcntl.h> @@ -81,7 +75,50 @@  #include <sys/filio.h>  #endif -#define TOX_EWOULDBLOCK EWOULDBLOCK +#else +#ifndef IPV6_V6ONLY +#define IPV6_V6ONLY 27 +#endif +#endif + +#include <assert.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifndef VANILLA_NACL +// Used for sodium_init() +#include <sodium.h> +#endif + +#include "logger.h" +#include "mono_time.h" +#include "util.h" + +//!TOKSTYLE- +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +#include "../testing/fuzzing/fuzz_adapter.h" +#endif +//!TOKSTYLE+ + +// Disable MSG_NOSIGNAL on systems not supporting it, e.g. Windows, FreeBSD +#if !defined(MSG_NOSIGNAL) +#define MSG_NOSIGNAL 0 +#endif + +#ifndef IPV6_ADD_MEMBERSHIP +#ifdef IPV6_JOIN_GROUP +#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP +#endif +#endif + +#if !defined(OS_WIN32) + +static bool should_ignore_recv_error(int err) +{ +    return err == EWOULDBLOCK; +}  static const char *inet_ntop4(const struct in_addr *addr, char *buf, size_t bufsize)  { @@ -108,7 +145,12 @@ static int inet_pton6(const char *addrString, struct in6_addr *addrbuf)  #define IPV6_V6ONLY 27  #endif -#define TOX_EWOULDBLOCK WSAEWOULDBLOCK +static bool should_ignore_recv_error(int err) +{ +    // We ignore WSAECONNRESET as Windows helpfully* sends that error if a +    // previously sent UDP packet wasn't delivered. +    return err == WSAEWOULDBLOCK || err == WSAECONNRESET; +}  static const char *inet_ntop4(const struct in_addr *addr, char *buf, size_t bufsize)  { @@ -117,7 +159,7 @@ static const char *inet_ntop4(const struct in_addr *addr, char *buf, size_t bufs      saddr.sin_family = AF_INET;      saddr.sin_addr = *addr; -    uint32_t len = bufsize; +    DWORD len = bufsize;      if (WSAAddressToString((LPSOCKADDR)&saddr, sizeof(saddr), nullptr, buf, &len)) {          return nullptr; @@ -133,7 +175,7 @@ static const char *inet_ntop6(const struct in6_addr *addr, char *buf, size_t buf      saddr.sin6_family = AF_INET6;      saddr.sin6_addr = *addr; -    uint32_t len = bufsize; +    DWORD len = bufsize;      if (WSAAddressToString((LPSOCKADDR)&saddr, sizeof(saddr), nullptr, buf, &len)) {          return nullptr; @@ -174,34 +216,12 @@ static int inet_pton6(const char *addrString, struct in6_addr *addrbuf)  #endif -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "logger.h" -#include "mono_time.h" -#include "util.h" - -// Disable MSG_NOSIGNAL on systems not supporting it, e.g. Windows, FreeBSD -#if !defined(MSG_NOSIGNAL) -#define MSG_NOSIGNAL 0 -#endif - -#ifndef IPV6_ADD_MEMBERSHIP -#ifdef IPV6_JOIN_GROUP -#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP -#endif -#endif - -#if TOX_INET6_ADDRSTRLEN < INET6_ADDRSTRLEN -#error "TOX_INET6_ADDRSTRLEN should be greater or equal to INET6_ADDRSTRLEN (#INET6_ADDRSTRLEN)" -#endif - -#if TOX_INET_ADDRSTRLEN < INET_ADDRSTRLEN -#error "TOX_INET_ADDRSTRLEN should be greater or equal to INET_ADDRSTRLEN (#INET_ADDRSTRLEN)" -#endif +static_assert(TOX_INET6_ADDRSTRLEN >= INET6_ADDRSTRLEN, +              "TOX_INET6_ADDRSTRLEN should be greater or equal to INET6_ADDRSTRLEN (#INET6_ADDRSTRLEN)"); +static_assert(TOX_INET_ADDRSTRLEN >= INET_ADDRSTRLEN, +              "TOX_INET_ADDRSTRLEN should be greater or equal to INET_ADDRSTRLEN (#INET_ADDRSTRLEN)"); +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION  static int make_proto(int proto)  {      switch (proto) { @@ -229,6 +249,7 @@ static int make_socktype(int type)              return type;      }  } +#endif // FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION  static int make_family(Family tox_family)  { @@ -275,15 +296,15 @@ static void get_ip6(IP6 *result, const struct in6_addr *addr)      memcpy(result->uint8, addr->s6_addr, sizeof(result->uint8));  } -static void fill_addr4(IP4 ip, struct in_addr *addr) +static void fill_addr4(const IP4 *ip, struct in_addr *addr)  { -    addr->s_addr = ip.uint32; +    addr->s_addr = ip->uint32;  } -static void fill_addr6(IP6 ip, struct in6_addr *addr) +static void fill_addr6(const IP6 *ip, struct in6_addr *addr)  { -    assert(sizeof(ip.uint8) == sizeof(addr->s6_addr)); -    memcpy(addr->s6_addr, ip.uint8, sizeof(ip.uint8)); +    assert(sizeof(ip->uint8) == sizeof(addr->s6_addr)); +    memcpy(addr->s6_addr, ip->uint8, sizeof(ip->uint8));  }  #if !defined(INADDR_LOOPBACK) @@ -375,25 +396,33 @@ bool sock_valid(Socket sock)      return sock.socket != net_invalid_socket.socket;  } -/* Close the socket. +/** Close the socket.   */  void kill_sock(Socket sock)  { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    return; +#else  #ifdef OS_WIN32      closesocket(sock.socket);  #else      close(sock.socket); -#endif +#endif /* OS_WIN32 */ +#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */  }  bool set_socket_nonblock(Socket sock)  { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    return true; +#else  #ifdef OS_WIN32      u_long mode = 1;      return ioctlsocket(sock.socket, FIONBIO, &mode) == 0;  #else      return fcntl(sock.socket, F_SETFL, O_NONBLOCK, 1) == 0; -#endif +#endif /* OS_WIN32 */ +#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */  }  bool set_socket_nosigpipe(Socket sock) @@ -408,12 +437,19 @@ bool set_socket_nosigpipe(Socket sock)  bool set_socket_reuseaddr(Socket sock)  { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    return false; +#else      int set = 1;      return setsockopt(sock.socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&set, sizeof(set)) == 0; +#endif  }  bool set_socket_dualstack(Socket sock)  { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    return false; +#else      int ipv6only = 0;      socklen_t optsize = sizeof(ipv6only);      int res = getsockopt(sock.socket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, &optsize); @@ -424,6 +460,7 @@ bool set_socket_dualstack(Socket sock)      ipv6only = 0;      return setsockopt(sock.socket, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&ipv6only, sizeof(ipv6only)) == 0; +#endif  } @@ -449,28 +486,28 @@ static uint32_t data_1(uint16_t buflen, const uint8_t *buffer)  }  static void loglogdata(const Logger *log, const char *message, const uint8_t *buffer, -                       uint16_t buflen, IP_Port ip_port, int res) +                       uint16_t buflen, const IP_Port *ip_port, long res)  {      char ip_str[IP_NTOA_LEN];      if (res < 0) { /* Windows doesn't necessarily know `%zu` */          int error = net_error(); -        const char *strerror = net_new_strerror(error); -        LOGGER_TRACE(log, "[%2u] %s %3u%c %s:%u (%u: %s) | %04x%04x", +        char *strerror = net_new_strerror(error); +        LOGGER_TRACE(log, "[%2u] %s %3u%c %s:%u (%u: %s) | %08x%08x...%02x",                       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)); +                     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), buffer[buflen - 1]);          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, 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)); +        LOGGER_TRACE(log, "[%2u] %s %3u%c %s:%u (%u: %s) | %08x%08x...%02x", +                     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), buffer[buflen - 1]);      } else { /* empty or overwrite */ -        LOGGER_TRACE(log, "[%2u] %s %u%c%u %s:%u (%u: %s) | %04x%04x", -                     buffer[0], message, res, (!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)); +        LOGGER_TRACE(log, "[%2u] %s %lu%c%u %s:%u (%u: %s) | %08x%08x...%02x", +                     buffer[0], message, res, !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), buffer[buflen - 1]);      }  } @@ -500,23 +537,29 @@ uint16_t net_port(const Networking_Core *net)  }  /* Basic network functions: - * Function to send packet(data) of length length to ip_port.   */ -int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint16_t length) + +int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packet)  { +    IP_Port ipp_copy = *ip_port; +      if (net_family_is_unspec(net->family)) { /* Socket not initialized */ -        LOGGER_ERROR(net->log, "attempted to send message of length %u on uninitialised socket", (unsigned)length); +        // TODO(iphydf): Make this an error. Currently, the onion client calls +        // this via DHT getnodes. +        LOGGER_WARNING(net->log, "attempted to send message of length %u on uninitialised socket", packet.length);          return -1;      }      /* socket TOX_AF_INET, but target IP NOT: can't send */ -    if (net_family_is_ipv4(net->family) && !net_family_is_ipv4(ip_port.ip.family)) { -        LOGGER_ERROR(net->log, "attempted to send message with network family %d (probably IPv6) on IPv4 socket", -                     ip_port.ip.family.value); +    if (net_family_is_ipv4(net->family) && !net_family_is_ipv4(ipp_copy.ip.family)) { +        // TODO(iphydf): Make this an error. Occasionally we try to send to an +        // all-zero ip_port. +        LOGGER_WARNING(net->log, "attempted to send message with network family %d (probably IPv6) on IPv4 socket", +                       ipp_copy.ip.family.value);          return -1;      } -    if (net_family_is_ipv4(ip_port.ip.family) && net_family_is_ipv6(net->family)) { +    if (net_family_is_ipv4(ipp_copy.ip.family) && net_family_is_ipv6(net->family)) {          /* must convert to IPV4-in-IPV6 address */          IP6 ip6; @@ -525,46 +568,66 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint1          ip6.uint32[0] = 0;          ip6.uint32[1] = 0;          ip6.uint32[2] = net_htonl(0xFFFF); -        ip6.uint32[3] = ip_port.ip.ip.v4.uint32; +        ip6.uint32[3] = ipp_copy.ip.ip.v4.uint32; -        ip_port.ip.family = net_family_ipv6; -        ip_port.ip.ip.v6 = ip6; +        ipp_copy.ip.family = net_family_ipv6; +        ipp_copy.ip.ip.v6 = ip6;      }      struct sockaddr_storage addr;      size_t addrsize; -    if (net_family_is_ipv4(ip_port.ip.family)) { +    if (net_family_is_ipv4(ipp_copy.ip.family)) {          struct sockaddr_in *const addr4 = (struct sockaddr_in *)&addr;          addrsize = sizeof(struct sockaddr_in);          addr4->sin_family = AF_INET; -        addr4->sin_port = ip_port.port; -        fill_addr4(ip_port.ip.ip.v4, &addr4->sin_addr); -    } else if (net_family_is_ipv6(ip_port.ip.family)) { +        addr4->sin_port = ipp_copy.port; +        fill_addr4(&ipp_copy.ip.ip.v4, &addr4->sin_addr); +    } else if (net_family_is_ipv6(ipp_copy.ip.family)) {          struct sockaddr_in6 *const addr6 = (struct sockaddr_in6 *)&addr;          addrsize = sizeof(struct sockaddr_in6);          addr6->sin6_family = AF_INET6; -        addr6->sin6_port = ip_port.port; -        fill_addr6(ip_port.ip.ip.v6, &addr6->sin6_addr); +        addr6->sin6_port = ipp_copy.port; +        fill_addr6(&ipp_copy.ip.ip.v6, &addr6->sin6_addr);          addr6->sin6_flowinfo = 0;          addr6->sin6_scope_id = 0;      } else { -        LOGGER_WARNING(net->log, "unknown address type: %d", ip_port.ip.family.value); +        // TODO(iphydf): Make this an error. Currently this fails sometimes when +        // called from DHT.c:do_ping_and_sendnode_requests. +        LOGGER_WARNING(net->log, "unknown address type: %d", ipp_copy.ip.family.value);          return -1;      } -    const int res = sendto(net->sock.socket, (const char *)data, length, 0, (struct sockaddr *)&addr, addrsize); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    const long res = fuzz_sendto(net->sock.socket, (const char *)packet.data, packet.length, 0, +                                 (struct sockaddr *)&addr, addrsize); +#else +    const long res = sendto(net->sock.socket, (const char *)packet.data, packet.length, 0, +                            (struct sockaddr *)&addr, addrsize); +#endif + +    loglogdata(net->log, "O=>", packet.data, packet.length, &ipp_copy, res); -    loglogdata(net->log, "O=>", data, length, ip_port, res); +    assert(res <= INT_MAX); +    return (int)res; +} -    return res; +/** + * Function to send packet(data) of length length to ip_port. + * + * @deprecated Use send_packet instead. + */ +int sendpacket(const Networking_Core *net, const IP_Port *ip_port, const uint8_t *data, uint16_t length) +{ +    const Packet packet = {data, length}; +    return send_packet(net, ip_port, packet);  } -/* Function to receive data +/** Function to receive data   *  ip and port of sender is put into ip_port.   *  Packet data is put into data.   *  Packet length is put into length. @@ -579,13 +642,18 @@ static int receivepacket(const Logger *log, Socket sock, IP_Port *ip_port, uint8      socklen_t addrlen = sizeof(addr);  #endif      *length = 0; + +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    int fail_or_len = fuzz_recvfrom(sock.socket, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen); +#else      int fail_or_len = recvfrom(sock.socket, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen); +#endif      if (fail_or_len < 0) {          int error = net_error(); -        if (fail_or_len < 0 && error != TOX_EWOULDBLOCK) { -            const char *strerror = net_new_strerror(error); +        if (!should_ignore_recv_error(error)) { +            char *strerror = net_new_strerror(error);              LOGGER_ERROR(log, "Unexpected error reading from socket: %u, %s", error, strerror);              net_kill_strerror(strerror);          } @@ -596,7 +664,7 @@ static int receivepacket(const Logger *log, Socket sock, IP_Port *ip_port, uint8      *length = (uint32_t)fail_or_len;      if (addr.ss_family == AF_INET) { -        struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr; +        const struct sockaddr_in *addr_in = (const struct sockaddr_in *)&addr;          const Family *const family = make_tox_family(addr_in->sin_family);          assert(family != nullptr); @@ -609,7 +677,7 @@ static int receivepacket(const Logger *log, Socket sock, IP_Port *ip_port, uint8          get_ip4(&ip_port->ip.ip.v4, &addr_in->sin_addr);          ip_port->port = addr_in->sin_port;      } else if (addr.ss_family == AF_INET6) { -        struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr; +        const struct sockaddr_in6 *addr_in6 = (const struct sockaddr_in6 *)&addr;          const Family *const family = make_tox_family(addr_in6->sin6_family);          assert(family != nullptr); @@ -621,7 +689,7 @@ static int receivepacket(const Logger *log, Socket sock, IP_Port *ip_port, uint8          get_ip6(&ip_port->ip.ip.v6, &addr_in6->sin6_addr);          ip_port->port = addr_in6->sin6_port; -        if (ipv6_ipv4_in_v6(ip_port->ip.ip.v6)) { +        if (ipv6_ipv4_in_v6(&ip_port->ip.ip.v6)) {              ip_port->ip.family = net_family_ipv4;              ip_port->ip.ip.v4.uint32 = ip_port->ip.ip.v6.uint32[3];          } @@ -629,7 +697,7 @@ static int receivepacket(const Logger *log, Socket sock, IP_Port *ip_port, uint8          return -1;      } -    loglogdata(log, "=>O", data, MAX_UDP_PACKET_SIZE, *ip_port, *length); +    loglogdata(log, "=>O", data, MAX_UDP_PACKET_SIZE, ip_port, *length);      return 0;  } @@ -640,7 +708,7 @@ void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handl      net->packethandlers[byte].object = object;  } -void networking_poll(Networking_Core *net, void *userdata) +void networking_poll(const Networking_Core *net, void *userdata)  {      if (net_family_is_unspec(net->family)) {          /* Socket not initialized */ @@ -656,20 +724,18 @@ void networking_poll(Networking_Core *net, void *userdata)              continue;          } -        if (!(net->packethandlers[data[0]].function)) { +        packet_handler_cb *const cb = net->packethandlers[data[0]].function; +        void *const object = net->packethandlers[data[0]].object; + +        if (cb == nullptr) {              LOGGER_WARNING(net->log, "[%02u] -- Packet has no handler", data[0]);              continue;          } -        net->packethandlers[data[0]].function(net->packethandlers[data[0]].object, ip_port, data, length, userdata); +        cb(object, &ip_port, data, length, userdata);      }  } -#ifndef VANILLA_NACL -/* Used for sodium_init() */ -#include <sodium.h> -#endif -  //!TOKSTYLE-  // Global mutable state is not allowed in Tokstyle.  static uint8_t at_startup_ran = 0; @@ -716,15 +782,15 @@ static void at_shutdown(void)  }  #endif -/* Initialize networking. +/** Initialize networking.   * Added for reverse compatibility with old new_networking calls.   */ -Networking_Core *new_networking(const Logger *log, IP ip, uint16_t port) +Networking_Core *new_networking(const Logger *log, const IP *ip, uint16_t port)  {      return new_networking_ex(log, ip, port, port + (TOX_PORTRANGE_TO - TOX_PORTRANGE_FROM), nullptr);  } -/* Initialize networking. +/** Initialize networking.   * Bind to ip and port.   * ip must be in network order EX: 127.0.0.1 = (7F000001).   * port is in host byte order (this means don't worry about it). @@ -734,7 +800,8 @@ Networking_Core *new_networking(const Logger *log, IP ip, uint16_t port)   *   * If error is non NULL it is set to 0 if no issues, 1 if socket related error, 2 if other.   */ -Networking_Core *new_networking_ex(const Logger *log, IP ip, uint16_t port_from, uint16_t port_to, unsigned int *error) +Networking_Core *new_networking_ex(const Logger *log, const IP *ip, uint16_t port_from, uint16_t port_to, +                                   unsigned int *error)  {      /* If both from and to are 0, use default port range       * If one is 0 and the other is non-0, use the non-0 value as only port @@ -758,8 +825,8 @@ Networking_Core *new_networking_ex(const Logger *log, IP ip, uint16_t port_from,      }      /* maybe check for invalid IPs like 224+.x.y.z? if there is any IP set ever */ -    if (!net_family_is_ipv4(ip.family) && !net_family_is_ipv6(ip.family)) { -        LOGGER_ERROR(log, "invalid address family: %u", ip.family.value); +    if (!net_family_is_ipv4(ip->family) && !net_family_is_ipv6(ip->family)) { +        LOGGER_ERROR(log, "invalid address family: %u", ip->family.value);          return nullptr;      } @@ -774,7 +841,7 @@ Networking_Core *new_networking_ex(const Logger *log, IP ip, uint16_t port_from,      }      temp->log = log; -    temp->family = ip.family; +    temp->family = ip->family;      temp->port = 0;      /* Initialize our socket. */ @@ -784,7 +851,7 @@ Networking_Core *new_networking_ex(const Logger *log, IP ip, uint16_t port_from,      /* Check for socket error. */      if (!sock_valid(temp->sock)) {          int neterror = net_error(); -        const char *strerror = net_new_strerror(neterror); +        char *strerror = net_new_strerror(neterror);          LOGGER_ERROR(log, "Failed to get a socket?! %d, %s", neterror, strerror);          net_kill_strerror(strerror);          free(temp); @@ -796,15 +863,30 @@ Networking_Core *new_networking_ex(const Logger *log, IP ip, uint16_t port_from,          return nullptr;      } +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION      /* Functions to increase the size of the send and receive UDP buffers.       */      int n = 1024 * 1024 * 2; -    setsockopt(temp->sock.socket, SOL_SOCKET, SO_RCVBUF, (const char *)&n, sizeof(n)); -    setsockopt(temp->sock.socket, SOL_SOCKET, SO_SNDBUF, (const char *)&n, sizeof(n)); +    if (setsockopt(temp->sock.socket, SOL_SOCKET, SO_RCVBUF, (const char *)&n, sizeof(n)) != 0) { +        LOGGER_WARNING(log, "Failed to set socket option %d", SO_RCVBUF); +    } + +    if (setsockopt(temp->sock.socket, SOL_SOCKET, SO_SNDBUF, (const char *)&n, sizeof(n)) != 0) { +        LOGGER_WARNING(log, "Failed to set socket option %d", SO_SNDBUF); +    } + +#endif + +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION      /* Enable broadcast on socket */      int broadcast = 1; -    setsockopt(temp->sock.socket, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof(broadcast)); + +    if (setsockopt(temp->sock.socket, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof(broadcast)) != 0) { +        LOGGER_WARNING(log, "Failed to set socket option %d", SO_BROADCAST); +    } + +#endif      /* iOS UDP sockets are weird and apparently can SIGPIPE */      if (!set_socket_nosigpipe(temp->sock)) { @@ -841,7 +923,7 @@ Networking_Core *new_networking_ex(const Logger *log, IP ip, uint16_t port_from,          addrsize = sizeof(struct sockaddr_in);          addr4->sin_family = AF_INET;          addr4->sin_port = 0; -        fill_addr4(ip.ip.v4, &addr4->sin_addr); +        fill_addr4(&ip->ip.v4, &addr4->sin_addr);          portptr = &addr4->sin_port;      } else if (net_family_is_ipv6(temp->family)) { @@ -850,7 +932,7 @@ Networking_Core *new_networking_ex(const Logger *log, IP ip, uint16_t port_from,          addrsize = sizeof(struct sockaddr_in6);          addr6->sin6_family = AF_INET6;          addr6->sin6_port = 0; -        fill_addr6(ip.ip.v6, &addr6->sin6_addr); +        fill_addr6(&ip->ip.v6, &addr6->sin6_addr);          addr6->sin6_flowinfo = 0;          addr6->sin6_scope_id = 0; @@ -861,7 +943,9 @@ Networking_Core *new_networking_ex(const Logger *log, IP ip, uint16_t port_from,          return nullptr;      } -    if (net_family_is_ipv6(ip.family)) { +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + +    if (net_family_is_ipv6(ip->family)) {          const int is_dualstack = set_socket_dualstack(temp->sock);          LOGGER_DEBUG(log, "Dual-stack socket: %s",                       is_dualstack ? "enabled" : "Failed to enable, won't be able to receive from/send to IPv4 addresses"); @@ -872,10 +956,11 @@ Networking_Core *new_networking_ex(const Logger *log, IP ip, uint16_t port_from,          mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02;          mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01;          mreq.ipv6mr_interface = 0; +          const int res = setsockopt(temp->sock.socket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (const char *)&mreq, sizeof(mreq));          int neterror = net_error(); -        const char *strerror = net_new_strerror(neterror); +        char *strerror = net_new_strerror(neterror);          if (res < 0) {              LOGGER_DEBUG(log, "Failed to activate local multicast membership. (%d, %s)", neterror, strerror); @@ -886,6 +971,8 @@ Networking_Core *new_networking_ex(const Logger *log, IP ip, uint16_t port_from,          net_kill_strerror(strerror);      } +#endif +      /* A hanging program or a different user might block the standard port.       * As long as it isn't a parameter coming from the commandline,       * try a few ports after it, to see if we can find a "free" one. @@ -904,16 +991,19 @@ Networking_Core *new_networking_ex(const Logger *log, IP ip, uint16_t port_from,       */      uint16_t port_to_try = port_from;      *portptr = net_htons(port_to_try); -    int tries; -    for (tries = port_from; tries <= port_to; ++tries) { +    for (uint16_t tries = port_from; tries <= port_to; ++tries) { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +        int res = 0; +#else          int res = bind(temp->sock.socket, (struct sockaddr *)&addr, addrsize); +#endif          if (!res) {              temp->port = *portptr;              char ip_str[IP_NTOA_LEN]; -            LOGGER_DEBUG(log, "Bound successfully to %s:%u", ip_ntoa(&ip, ip_str, sizeof(ip_str)), +            LOGGER_DEBUG(log, "Bound successfully to %s:%u", ip_ntoa(ip, ip_str, sizeof(ip_str)),                           net_ntohs(temp->port));              /* errno isn't reset on success, only set on failure, the failed @@ -941,9 +1031,9 @@ Networking_Core *new_networking_ex(const Logger *log, IP ip, uint16_t port_from,      char ip_str[IP_NTOA_LEN];      int neterror = net_error(); -    const char *strerror = net_new_strerror(neterror); +    char *strerror = net_new_strerror(neterror);      LOGGER_ERROR(log, "Failed to bind socket: %d, %s IP: %s port_from: %u port_to: %u", neterror, strerror, -                 ip_ntoa(&ip, ip_str, sizeof(ip_str)), port_from, port_to); +                 ip_ntoa(ip, ip_str, sizeof(ip_str)), port_from, port_to);      net_kill_strerror(strerror);      kill_networking(temp); @@ -972,7 +1062,7 @@ Networking_Core *new_networking_no_udp(const Logger *log)      return net;  } -/* Function to cleanup networking stuff. */ +/** Function to cleanup networking stuff (doesn't do much right now). */  void kill_networking(Networking_Core *net)  {      if (!net) { @@ -999,8 +1089,8 @@ bool ip_equal(const IP *a, const IP *b)          if (net_family_is_ipv4(a->family) || net_family_is_tcp_ipv4(a->family)) {              struct in_addr addr_a;              struct in_addr addr_b; -            fill_addr4(a->ip.v4, &addr_a); -            fill_addr4(b->ip.v4, &addr_b); +            fill_addr4(&a->ip.v4, &addr_a); +            fill_addr4(&b->ip.v4, &addr_b);              return addr_a.s_addr == addr_b.s_addr;          } @@ -1014,15 +1104,15 @@ bool ip_equal(const IP *a, const IP *b)      /* different family: check on the IPv6 one if it is the IPv4 one embedded */      if (net_family_is_ipv4(a->family) && net_family_is_ipv6(b->family)) { -        if (ipv6_ipv4_in_v6(b->ip.v6)) { +        if (ipv6_ipv4_in_v6(&b->ip.v6)) {              struct in_addr addr_a; -            fill_addr4(a->ip.v4, &addr_a); +            fill_addr4(&a->ip.v4, &addr_a);              return addr_a.s_addr == b->ip.v6.uint32[3];          }      } else if (net_family_is_ipv6(a->family) && net_family_is_ipv4(b->family)) { -        if (ipv6_ipv4_in_v6(a->ip.v6)) { +        if (ipv6_ipv4_in_v6(&a->ip.v6)) {              struct in_addr addr_b; -            fill_addr4(b->ip.v4, &addr_b); +            fill_addr4(&b->ip.v4, &addr_b);              return a->ip.v6.uint32[3] == addr_b.s_addr;          }      } @@ -1043,7 +1133,7 @@ bool ipport_equal(const IP_Port *a, const IP_Port *b)      return ip_equal(&a->ip, &b->ip);  } -/* nulls out ip */ +/** nulls out ip */  void ip_reset(IP *ip)  {      if (!ip) { @@ -1053,7 +1143,17 @@ void ip_reset(IP *ip)      memset(ip, 0, sizeof(IP));  } -/* nulls out ip, sets family according to flag */ +/** nulls out ip_port */ +void ipport_reset(IP_Port *ipport) +{ +    if (!ipport) { +        return; +    } + +    memset(ipport, 0, sizeof(IP_Port)); +} + +/** nulls out ip, sets family according to flag */  void ip_init(IP *ip, bool ipv6enabled)  {      if (!ip) { @@ -1064,7 +1164,7 @@ void ip_init(IP *ip, bool ipv6enabled)      ip->family = ipv6enabled ? net_family_ipv6 : net_family_ipv4;  } -/* checks if ip is valid */ +/** checks if ip is valid */  bool ip_isset(const IP *ip)  {      if (!ip) { @@ -1074,7 +1174,7 @@ bool ip_isset(const IP *ip)      return !net_family_is_unspec(ip->family);  } -/* checks if ip is valid */ +/** checks if ip is valid */  bool ipport_isset(const IP_Port *ipport)  {      if (!ipport) { @@ -1088,7 +1188,7 @@ bool ipport_isset(const IP_Port *ipport)      return ip_isset(&ipport->ip);  } -/* copies an ip structure (careful about direction!) */ +/** copies an ip structure (careful about direction!) */  void ip_copy(IP *target, const IP *source)  {      if (!source || !target) { @@ -1098,7 +1198,7 @@ void ip_copy(IP *target, const IP *source)      *target = *source;  } -/* copies an ip_port structure (careful about direction!) */ +/** copies an ip_port structure (careful about direction!) */  void ipport_copy(IP_Port *target, const IP_Port *source)  {      if (!source || !target) { @@ -1108,11 +1208,10 @@ void ipport_copy(IP_Port *target, const IP_Port *source)      *target = *source;  } -/* ip_ntoa +/** ip_ntoa   *   converts ip into a string   *   ip_str must be of length at least IP_NTOA_LEN   * - *   IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]"   *   writes error message into the buffer on error   *   *   returns ip_str @@ -1128,22 +1227,18 @@ const char *ip_ntoa(const IP *ip, char *ip_str, size_t length)          if (net_family_is_ipv4(ip->family)) {              /* returns standard quad-dotted notation */              struct in_addr addr; -            fill_addr4(ip->ip.v4, &addr); +            fill_addr4(&ip->ip.v4, &addr); -            ip_str[0] = 0; +            ip_str[0] = '\0';              assert(make_family(ip->family) == AF_INET);              inet_ntop4(&addr, ip_str, length);          } else if (net_family_is_ipv6(ip->family)) {              /* returns hex-groups enclosed into square brackets */              struct in6_addr addr; -            fill_addr6(ip->ip.v6, &addr); +            fill_addr6(&ip->ip.v6, &addr); -            ip_str[0] = '[';              assert(make_family(ip->family) == AF_INET6); -            inet_ntop6(&addr, &ip_str[1], length - 3); -            const size_t len = strlen(ip_str); -            ip_str[len] = ']'; -            ip_str[len + 1] = 0; +            inet_ntop6(&addr, ip_str, length);          } else {              snprintf(ip_str, length, "(IP invalid, family %u)", ip->family.value);          } @@ -1152,7 +1247,7 @@ const char *ip_ntoa(const IP *ip, char *ip_str, size_t length)      }      /* brute force protection against lacking termination */ -    ip_str[length - 1] = 0; +    ip_str[length - 1] = '\0';      return ip_str;  } @@ -1204,6 +1299,10 @@ bool addr_parse_ip(const char *address, IP *to)  int addr_resolve(const char *address, IP *to, IP *extra)  { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    return false; +#else +      if (!address || !to) {          return 0;      } @@ -1211,13 +1310,7 @@ int addr_resolve(const char *address, IP *to, IP *extra)      Family tox_family = to->family;      int family = make_family(tox_family); -    struct addrinfo *server = nullptr; -    struct addrinfo *walker = nullptr; -    struct addrinfo  hints; -    int rc; -    int result = 0; -    int done = 0; - +    struct addrinfo hints;      memset(&hints, 0, sizeof(hints));      hints.ai_family   = family;      hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses. @@ -1226,7 +1319,9 @@ int addr_resolve(const char *address, IP *to, IP *extra)          return 0;      } -    rc = getaddrinfo(address, nullptr, &hints, &server); +    struct addrinfo *server = nullptr; + +    const int rc = getaddrinfo(address, nullptr, &hints, &server);      // Lookup failed.      if (rc != 0) { @@ -1238,39 +1333,44 @@ int addr_resolve(const char *address, IP *to, IP *extra)      IP ip6;      ip_init(&ip6, 1); // ipv6enabled = 1 -    for (walker = server; (walker != nullptr) && !done; walker = walker->ai_next) { +    int result = 0; +    bool done = false; + +    for (struct addrinfo *walker = server; walker != nullptr && !done; walker = walker->ai_next) {          switch (walker->ai_family) { -            case AF_INET: +            case AF_INET: {                  if (walker->ai_family == family) { /* AF_INET requested, done */ -                    struct sockaddr_in *addr = (struct sockaddr_in *)(void *)walker->ai_addr; +                    const struct sockaddr_in *addr = (const struct sockaddr_in *)(void *)walker->ai_addr;                      get_ip4(&to->ip.v4, &addr->sin_addr);                      result = TOX_ADDR_RESOLVE_INET; -                    done = 1; +                    done = true;                  } else if (!(result & TOX_ADDR_RESOLVE_INET)) { /* AF_UNSPEC requested, store away */ -                    struct sockaddr_in *addr = (struct sockaddr_in *)(void *)walker->ai_addr; +                    const struct sockaddr_in *addr = (const struct sockaddr_in *)(void *)walker->ai_addr;                      get_ip4(&ip4.ip.v4, &addr->sin_addr);                      result |= TOX_ADDR_RESOLVE_INET;                  }                  break; /* switch */ +            } -            case AF_INET6: +            case AF_INET6: {                  if (walker->ai_family == family) { /* AF_INET6 requested, done */                      if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) { -                        struct sockaddr_in6 *addr = (struct sockaddr_in6 *)(void *)walker->ai_addr; +                        const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)walker->ai_addr;                          get_ip6(&to->ip.v6, &addr->sin6_addr);                          result = TOX_ADDR_RESOLVE_INET6; -                        done = 1; +                        done = true;                      }                  } else if (!(result & TOX_ADDR_RESOLVE_INET6)) { /* AF_UNSPEC requested, store away */                      if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) { -                        struct sockaddr_in6 *addr = (struct sockaddr_in6 *)(void *)walker->ai_addr; +                        const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)walker->ai_addr;                          get_ip6(&ip6.ip.v6, &addr->sin6_addr);                          result |= TOX_ADDR_RESOLVE_INET6;                      }                  }                  break; /* switch */ +            }          }      } @@ -1290,6 +1390,7 @@ int addr_resolve(const char *address, IP *to, IP *extra)      freeaddrinfo(server);      return result; +#endif  }  bool addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra) @@ -1303,49 +1404,78 @@ bool addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra)      return true;  } -int net_connect(Socket sock, IP_Port ip_port) +int net_connect(const Logger *log, Socket sock, const IP_Port *ip_port)  {      struct sockaddr_storage addr = {0};      size_t addrsize; -    if (net_family_is_ipv4(ip_port.ip.family)) { +    if (net_family_is_ipv4(ip_port->ip.family)) {          struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;          addrsize = sizeof(struct sockaddr_in);          addr4->sin_family = AF_INET; -        fill_addr4(ip_port.ip.ip.v4, &addr4->sin_addr); -        addr4->sin_port = ip_port.port; -    } else if (net_family_is_ipv6(ip_port.ip.family)) { +        fill_addr4(&ip_port->ip.ip.v4, &addr4->sin_addr); +        addr4->sin_port = ip_port->port; +    } else if (net_family_is_ipv6(ip_port->ip.family)) {          struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;          addrsize = sizeof(struct sockaddr_in6);          addr6->sin6_family = AF_INET6; -        fill_addr6(ip_port.ip.ip.v6, &addr6->sin6_addr); -        addr6->sin6_port = ip_port.port; +        fill_addr6(&ip_port->ip.ip.v6, &addr6->sin6_addr); +        addr6->sin6_port = ip_port->port;      } else {          return 0;      } +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    return 0; +#else +    LOGGER_DEBUG(log, "connecting socket %d", (int)sock.socket);      return connect(sock.socket, (struct sockaddr *)&addr, addrsize); +#endif  }  int32_t net_getipport(const char *node, IP_Port **res, int tox_type)  { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    *res = (IP_Port *)calloc(1, sizeof(IP_Port)); +    assert(*res != nullptr); +    IP_Port *ip_port = *res; +    ip_port->ip.ip.v4.uint32 = 0x7F000003; // 127.0.0.3 +    ip_port->ip.family = *make_tox_family(AF_INET); + +    return 1; +#else +    // Try parsing as IP address first. +    IP_Port parsed = {0}; + +    if (addr_parse_ip(node, &parsed.ip)) { +        IP_Port *tmp = (IP_Port *)calloc(1, sizeof(IP_Port)); + +        if (tmp == nullptr) { +            return -1; +        } + +        tmp[0] = parsed; +        *res = tmp; +        return 1; +    } + +    // It's not an IP address, so now we try doing a DNS lookup.      struct addrinfo *infos; -    int ret = getaddrinfo(node, nullptr, nullptr, &infos); +    const int ret = getaddrinfo(node, nullptr, nullptr, &infos);      *res = nullptr;      if (ret != 0) {          return -1;      } -    // Used to avoid malloc parameter overflow +    // Used to avoid calloc parameter overflow      const size_t max_count = min_u64(SIZE_MAX, INT32_MAX) / sizeof(IP_Port); -    int type = make_socktype(tox_type); -    struct addrinfo *cur; +    const int type = make_socktype(tox_type);      size_t count = 0; -    for (cur = infos; count < max_count && cur != nullptr; cur = cur->ai_next) { +    for (struct addrinfo *cur = infos; count < max_count && cur != nullptr; cur = cur->ai_next) {          if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {              continue;          } @@ -1364,7 +1494,7 @@ int32_t net_getipport(const char *node, IP_Port **res, int tox_type)          return 0;      } -    *res = (IP_Port *)malloc(sizeof(IP_Port) * count); +    *res = (IP_Port *)calloc(count, sizeof(IP_Port));      if (*res == nullptr) {          freeaddrinfo(infos); @@ -1373,16 +1503,16 @@ int32_t net_getipport(const char *node, IP_Port **res, int tox_type)      IP_Port *ip_port = *res; -    for (cur = infos; cur != nullptr; cur = cur->ai_next) { +    for (struct addrinfo *cur = infos; cur != nullptr; cur = cur->ai_next) {          if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {              continue;          }          if (cur->ai_family == AF_INET) { -            struct sockaddr_in *addr = (struct sockaddr_in *)(void *)cur->ai_addr; +            const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)cur->ai_addr;              memcpy(&ip_port->ip.ip.v4, &addr->sin_addr, sizeof(IP4));          } else if (cur->ai_family == AF_INET6) { -            struct sockaddr_in6 *addr = (struct sockaddr_in6 *)(void *)cur->ai_addr; +            const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(const void *)cur->ai_addr;              memcpy(&ip_port->ip.ip.v6, &addr->sin6_addr, sizeof(IP6));          } else {              continue; @@ -1404,6 +1534,7 @@ int32_t net_getipport(const char *node, IP_Port **res, int tox_type)      freeaddrinfo(infos);      return count; +#endif  }  void net_freeipport(IP_Port *ip_ports) @@ -1432,50 +1563,85 @@ bool bind_to_port(Socket sock, Family family, uint16_t port)          return false;      } +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    return true; +#else      return bind(sock.socket, (struct sockaddr *)&addr, addrsize) == 0; +#endif  }  Socket net_socket(Family domain, int type, int protocol)  { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    const Socket sock = {1}; +    return sock; +#else      const int platform_domain = make_family(domain);      const int platform_type = make_socktype(type);      const int platform_prot = make_proto(protocol);      const Socket sock = {(int)socket(platform_domain, platform_type, platform_prot)};      return sock; +#endif  } -int net_send(Socket sock, const void *buf, size_t len) +int net_send(const Logger *log, Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port)  { -    return send(sock.socket, (const char *)buf, len, MSG_NOSIGNAL); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    int res = fuzz_send(sock.socket, (const char *)buf, len, MSG_NOSIGNAL); +#else +    int res = send(sock.socket, (const char *)buf, len, MSG_NOSIGNAL); +#endif +    loglogdata(log, "T=>", buf, len, ip_port, res); +    return res;  } -int net_recv(Socket sock, void *buf, size_t len) +int net_recv(const Logger *log, Socket sock, uint8_t *buf, size_t len, const IP_Port *ip_port)  { -    return recv(sock.socket, (char *)buf, len, MSG_NOSIGNAL); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    int res = fuzz_recv(sock.socket, (char *)buf, len, MSG_NOSIGNAL); +#else +    int res = recv(sock.socket, (char *)buf, len, MSG_NOSIGNAL); +#endif +    loglogdata(log, "=>T", buf, len, ip_port, res); +    return res;  }  int net_listen(Socket sock, int backlog)  { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    return 0; +#else      return listen(sock.socket, backlog); +#endif  }  Socket net_accept(Socket sock)  { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    const Socket newsock = {2}; +    return newsock; +#else      const Socket newsock = {accept(sock.socket, nullptr, nullptr)};      return newsock; +#endif  } -size_t net_socket_data_recv_buffer(Socket sock) +uint16_t net_socket_data_recv_buffer(Socket sock)  { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +    return 0; +#else +  #ifdef OS_WIN32 -    unsigned long count = 0; +    u_long count = 0;      ioctlsocket(sock.socket, FIONREAD, &count);  #else      int count = 0;      ioctl(sock.socket, FIONREAD, &count);  #endif -    return count; +    return (uint16_t)count; +#endif  }  uint32_t net_htonl(uint32_t hostlong) @@ -1551,9 +1717,9 @@ size_t net_unpack_u64(const uint8_t *bytes, uint64_t *v)      return p - bytes;  } -bool ipv6_ipv4_in_v6(IP6 a) +bool ipv6_ipv4_in_v6(const IP6 *a)  { -    return a.uint64[0] == 0 && a.uint32[2] == net_htonl(0xffff); +    return a->uint64[0] == 0 && a->uint32[2] == net_htonl(0xffff);  }  int net_error(void) @@ -1565,7 +1731,7 @@ int net_error(void)  #endif  } -const char *net_new_strerror(int error) +char *net_new_strerror(int error)  {  #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)      char *str = nullptr; @@ -1580,13 +1746,45 @@ const char *net_new_strerror(int error)                     error, 0, (char *)&str, 0, nullptr);      return str;  #else -    return strerror(error); +    char tmp[256]; + +    errno = 0; + +#ifdef _GNU_SOURCE +    const char *retstr = strerror_r(error, tmp, sizeof(tmp)); + +    if (errno != 0) { +        snprintf(tmp, sizeof(tmp), "error %d (strerror_r failed with errno %d)", error, errno); +    } + +#else +    const int fmt_error = strerror_r(error, tmp, sizeof(tmp)); + +    if (fmt_error != 0) { +        snprintf(tmp, sizeof(tmp), "error %d (strerror_r failed with error %d, errno %d)", error, fmt_error, errno); +    } + +    const char *retstr = tmp; +#endif + +    const size_t retstr_len = strlen(retstr); +    char *str = (char *)malloc(retstr_len + 1); + +    if (str == nullptr) { +        return nullptr; +    } + +    memcpy(str, retstr, retstr_len + 1); + +    return str;  #endif  } -void net_kill_strerror(const char *strerror) +void net_kill_strerror(char *strerror)  {  #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)      LocalFree((char *)strerror); +#else +    free(strerror);  #endif  } diff --git a/protocols/Tox/libtox/src/toxcore/network.h b/protocols/Tox/libtox/src/toxcore/network.h index b7e8ede2b9..47a93bf0fa 100644 --- a/protocols/Tox/libtox/src/toxcore/network.h +++ b/protocols/Tox/libtox/src/toxcore/network.h @@ -3,18 +3,18 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * Datatypes, functions and includes for the core networking.   */  #ifndef C_TOXCORE_TOXCORE_NETWORK_H  #define C_TOXCORE_TOXCORE_NETWORK_H -#include "logger.h" -  #include <stdbool.h>    // bool  #include <stddef.h>     // size_t  #include <stdint.h>     // uint*_t +#include "logger.h" +  #ifdef __cplusplus  extern "C" {  #endif @@ -43,44 +43,6 @@ extern const Family net_family_tcp_ipv6;  extern const Family net_family_tox_tcp_ipv4;  extern const Family net_family_tox_tcp_ipv6; -typedef struct Socket { -    int socket; -} Socket; - -Socket net_socket(Family domain, int type, int protocol); - -/** - * Check if socket is valid. - * - * @return true if valid, false otherwise. - */ -bool sock_valid(Socket sock); - -extern const Socket net_invalid_socket; - -/** - * Calls send(sockfd, buf, len, MSG_NOSIGNAL). - */ -int net_send(Socket sock, const void *buf, size_t len); -/** - * Calls recv(sockfd, buf, len, MSG_NOSIGNAL). - */ -int net_recv(Socket sock, void *buf, size_t len); -/** - * Calls listen(sockfd, backlog). - */ -int net_listen(Socket sock, int backlog); -/** - * Calls accept(sockfd, nullptr, nullptr). - */ -Socket net_accept(Socket sock); - -/** - * return the amount of data in the tcp recv buffer. - * return 0 on failure. - */ -size_t net_socket_data_recv_buffer(Socket sock); -  #define MAX_UDP_PACKET_SIZE 2048  typedef enum Net_Packet_Type { @@ -119,7 +81,7 @@ typedef enum Net_Packet_Type {  #define TOX_PORTRANGE_TO   33545  #define TOX_PORT_DEFAULT   TOX_PORTRANGE_FROM -/* Redefinitions of variables for safe transfer over wire. */ +/** Redefinitions of variables for safe transfer over wire. */  #define TOX_AF_UNSPEC 0  #define TOX_AF_INET 2  #define TOX_AF_INET6 10 @@ -132,18 +94,26 @@ typedef enum Net_Packet_Type {  #define TOX_PROTO_TCP 1  #define TOX_PROTO_UDP 2 -/* TCP related */ +/** TCP related */  #define TCP_ONION_FAMILY (TOX_AF_INET6 + 1)  #define TCP_INET (TOX_AF_INET6 + 2)  #define TCP_INET6 (TOX_AF_INET6 + 3)  #define TCP_FAMILY (TOX_AF_INET6 + 4) +#define SIZE_IP4 4 +#define SIZE_IP6 16 +#define SIZE_IP (1 + SIZE_IP6) +#define SIZE_PORT 2 +#define SIZE_IPPORT (SIZE_IP + SIZE_PORT) +  typedef union IP4 {      uint32_t uint32;      uint16_t uint16[2];      uint8_t uint8[4];  } IP4; +static_assert(sizeof(IP4) == SIZE_IP4, "IP4 size must be 4"); +  IP4 get_ip4_loopback(void);  extern const IP4 ip4_broadcast; @@ -154,6 +124,10 @@ typedef union IP6 {      uint64_t uint64[2];  } IP6; +// TODO(iphydf): Stop relying on this. We memcpy this struct (and IP4 above) +// into packets but really should be serialising it properly. +static_assert(sizeof(IP6) == SIZE_IP6, "IP6 size must be 16"); +  IP6 get_ip6_loopback(void);  extern const IP6 ip6_broadcast; @@ -162,19 +136,55 @@ typedef union IP_Union {      IP6 v6;  } IP_Union; -#define IP_DEFINED  typedef struct IP {      Family family;      IP_Union ip;  } IP; -#define IP_PORT_DEFINED  typedef struct IP_Port {      IP ip;      uint16_t port;  } IP_Port; -/* Convert values between host and network byte order. +typedef struct Socket { +    int socket; +} Socket; + +Socket net_socket(Family domain, int type, int protocol); + +/** + * Check if socket is valid. + * + * @return true if valid, false otherwise. + */ +bool sock_valid(Socket sock); + +extern const Socket net_invalid_socket; + +/** + * Calls send(sockfd, buf, len, MSG_NOSIGNAL). + */ +int net_send(const Logger *log, Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port); +/** + * Calls recv(sockfd, buf, len, MSG_NOSIGNAL). + */ +int net_recv(const Logger *log, Socket sock, uint8_t *buf, size_t len, const IP_Port *ip_port); +/** + * Calls listen(sockfd, backlog). + */ +int net_listen(Socket sock, int backlog); +/** + * Calls accept(sockfd, nullptr, nullptr). + */ +Socket net_accept(Socket sock); + +/** + * return the size of data in the tcp recv buffer. + * return 0 on failure. + */ +uint16_t net_socket_data_recv_buffer(Socket sock); + +/** Convert values between host and network byte order.   */  uint32_t net_htonl(uint32_t hostlong);  uint16_t net_htons(uint16_t hostshort); @@ -189,35 +199,28 @@ size_t net_unpack_u16(const uint8_t *bytes, uint16_t *v);  size_t net_unpack_u32(const uint8_t *bytes, uint32_t *v);  size_t net_unpack_u64(const uint8_t *bytes, uint64_t *v); -/* Does the IP6 struct a contain an IPv4 address in an IPv6 one? */ -bool ipv6_ipv4_in_v6(IP6 a); - -#define SIZE_IP4 4 -#define SIZE_IP6 16 -#define SIZE_IP (1 + SIZE_IP6) -#define SIZE_PORT 2 -#define SIZE_IPPORT (SIZE_IP + SIZE_PORT) +/** Does the IP6 struct a contain an IPv4 address in an IPv6 one? */ +bool ipv6_ipv4_in_v6(const IP6 *a);  #define TOX_ENABLE_IPV6_DEFAULT true -/* addr_resolve return values */ +/** addr_resolve return values */  #define TOX_ADDR_RESOLVE_INET  1  #define TOX_ADDR_RESOLVE_INET6 2  #define TOX_INET6_ADDRSTRLEN 66  #define TOX_INET_ADDRSTRLEN 22 -/* ip_ntoa +/** this would be TOX_INET6_ADDRSTRLEN, but it might be too short for the error message */ +#define IP_NTOA_LEN 96 // TODO(irungentoo): magic number. Why not INET6_ADDRSTRLEN ? +/** ip_ntoa   *   converts ip into a string   *   ip_str must be of length at least IP_NTOA_LEN   * - *   IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]"   *   writes error message into the buffer on error   *   *   returns ip_str   */ -/* this would be TOX_INET6_ADDRSTRLEN, but it might be too short for the error message */ -#define IP_NTOA_LEN 96 // TODO(irungentoo): magic number. Why not INET6_ADDRSTRLEN ?  const char *ip_ntoa(const IP *ip, char *ip_str, size_t length);  /** @@ -264,17 +267,19 @@ bool ip_equal(const IP *a, const IP *b);   */  bool ipport_equal(const IP_Port *a, const IP_Port *b); -/* nulls out ip */ +/** nulls out ip */  void ip_reset(IP *ip); -/* nulls out ip, sets family according to flag */ +/** nulls out ip_port */ +void ipport_reset(IP_Port *ipport); +/** nulls out ip, sets family according to flag */  void ip_init(IP *ip, bool ipv6enabled); -/* checks if ip is valid */ +/** checks if ip is valid */  bool ip_isset(const IP *ip); -/* checks if ip is valid */ +/** checks if ip is valid */  bool ipport_isset(const IP_Port *ipport); -/* copies an ip structure */ +/** copies an ip structure (careful about direction!) */  void ip_copy(IP *target, const IP *source); -/* copies an ip_port structure */ +/** copies an ip_port structure (careful about direction!) */  void ipport_copy(IP_Port *target, const IP_Port *source);  /** @@ -312,25 +317,25 @@ int addr_resolve(const char *address, IP *to, IP *extra);   */  bool addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra); -/* Function to receive data, ip and port of sender is put into ip_port. +/** Function to receive data, ip and port of sender is put into ip_port.   * Packet data is put into data.   * Packet length is put into length.   */ -typedef int packet_handler_cb(void *object, IP_Port ip_port, const uint8_t *data, uint16_t len, void *userdata); +typedef int packet_handler_cb(void *object, const IP_Port *ip_port, const uint8_t *data, uint16_t len, void *userdata);  typedef struct Networking_Core Networking_Core;  Family net_family(const Networking_Core *net);  uint16_t net_port(const Networking_Core *net); -/* Run this before creating sockets. +/** Run this before creating sockets.   *   * return 0 on success   * return -1 on failure   */  int networking_at_startup(void); -/* Close the socket. +/** Close the socket.   */  void kill_sock(Socket sock); @@ -364,19 +369,42 @@ bool set_socket_dualstack(Socket sock);  /* Basic network functions: */ -/* Function to send packet(data) of length length to ip_port. */ -int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint16_t length); +/** + * An outgoing network packet. + * + * Use `send_packet` to send it to an IP/port endpoint. + */ +typedef struct Packet { +    const uint8_t *data; +    uint16_t length; +} Packet; + +/** + * Function to send a network packet to a given IP/port. + */ +int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packet); + +/** + * Function to send packet(data) of length length to ip_port. + * + * @deprecated Use send_packet instead. + */ +int sendpacket(const Networking_Core *net, const IP_Port *ip_port, const uint8_t *data, uint16_t length); -/* Function to call when packet beginning with byte is received. */ +/** Function to call when packet beginning with byte is received. */  void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_cb *cb, void *object); -/* Call this several times a second. */ -void networking_poll(Networking_Core *net, void *userdata); +/** Call this several times a second. */ +void networking_poll(const Networking_Core *net, void *userdata); -/* Connect a socket to the address specified by the ip_port. */ -int net_connect(Socket sock, IP_Port ip_port); +/** Connect a socket to the address specified by the ip_port. + * + * Return 0 on success. + * Return -1 on failure. + */ +int net_connect(const Logger *log, Socket sock, const IP_Port *ip_port); -/* High-level getaddrinfo implementation. +/** High-level getaddrinfo implementation.   * Given node, which identifies an Internet host, net_getipport() fills an array   * with one or more IP_Port structures, each of which contains an Internet   * address that can be specified by calling net_connect(), the port is ignored. @@ -389,7 +417,7 @@ int net_connect(Socket sock, IP_Port ip_port);   */  int32_t net_getipport(const char *node, IP_Port **res, int tox_type); -/* Deallocates memory allocated by net_getipport +/** Deallocates memory allocated by net_getipport   */  void net_freeipport(IP_Port *ip_ports); @@ -398,7 +426,7 @@ void net_freeipport(IP_Port *ip_ports);   */  bool bind_to_port(Socket sock, Family family, uint16_t port); -/* Get the last networking error code. +/** Get the last networking error code.   *   * Similar to Unix's errno, but cross-platform, as not all platforms use errno   * to indicate networking errors. @@ -412,35 +440,39 @@ bool bind_to_port(Socket sock, Family family, uint16_t port);   */  int net_error(void); -/* Get a text explanation for the error code from net_error(). +/** Get a text explanation for the error code from net_error().   *   * return NULL on failure.   * return pointer to a NULL-terminated string describing the error code on   * success. The returned string must be freed using net_kill_strerror().   */ -const char *net_new_strerror(int error); +char *net_new_strerror(int error); -/* Frees the string returned by net_new_strerror(). +/** Frees the string returned by net_new_strerror().   * It's valid to pass NULL as the argument, the function does nothing in this   * case.   */ -void net_kill_strerror(const char *strerror); +void net_kill_strerror(char *strerror); -/* Initialize networking. - * bind to ip and port. +/** Initialize networking. + * Added for reverse compatibility with old new_networking calls. + */ +Networking_Core *new_networking(const Logger *log, const IP *ip, uint16_t port); +/** Initialize networking. + * Bind to ip and port.   * ip must be in network order EX: 127.0.0.1 = (7F000001).   * port is in host byte order (this means don't worry about it).   * - * return Networking_Core object if no problems - * return NULL if there are problems. + *  return Networking_Core object if no problems + *  return NULL if there are problems.   *   * If error is non NULL it is set to 0 if no issues, 1 if socket related error, 2 if other.   */ -Networking_Core *new_networking(const Logger *log, IP ip, uint16_t port); -Networking_Core *new_networking_ex(const Logger *log, IP ip, uint16_t port_from, uint16_t port_to, unsigned int *error); +Networking_Core *new_networking_ex(const Logger *log, const IP *ip, uint16_t port_from, uint16_t port_to, +                                   unsigned int *error);  Networking_Core *new_networking_no_udp(const Logger *log); -/* Function to cleanup networking stuff (doesn't do much right now). */ +/** Function to cleanup networking stuff (doesn't do much right now). */  void kill_networking(Networking_Core *net);  #ifdef __cplusplus diff --git a/protocols/Tox/libtox/src/toxcore/onion.c b/protocols/Tox/libtox/src/toxcore/onion.c index 32a3e88d6e..663c7b1b5c 100644 --- a/protocols/Tox/libtox/src/toxcore/onion.c +++ b/protocols/Tox/libtox/src/toxcore/onion.c @@ -3,13 +3,9 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * Implementation of the onion part of docs/Prevent_Tracking.txt   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -  #include "onion.h"  #include <stdlib.h> @@ -27,8 +23,8 @@  #define SEND_2 ONION_SEND_2  #define SEND_1 ONION_SEND_1 -/* Change symmetric keys every 2 hours to make paths expire eventually. */  #define KEY_REFRESH_INTERVAL (2 * 60 * 60) +/** Change symmetric keys every 2 hours to make paths expire eventually. */  static void change_symmetric_key(Onion *onion)  {      if (mono_time_is_timeout(onion->mono_time, onion->timestamp, KEY_REFRESH_INTERVAL)) { @@ -37,20 +33,20 @@ static void change_symmetric_key(Onion *onion)      }  } -/* packing and unpacking functions */ -static void ip_pack(uint8_t *data, IP source) +/** packing and unpacking functions */ +static void ip_pack(uint8_t *data, const IP *source)  { -    data[0] = source.family.value; +    data[0] = source->family.value; -    if (net_family_is_ipv4(source.family) || net_family_is_tox_tcp_ipv4(source.family)) { +    if (net_family_is_ipv4(source->family) || net_family_is_tox_tcp_ipv4(source->family)) {          memset(data + 1, 0, SIZE_IP6); -        memcpy(data + 1, source.ip.v4.uint8, SIZE_IP4); +        memcpy(data + 1, source->ip.v4.uint8, SIZE_IP4);      } else { -        memcpy(data + 1, source.ip.v6.uint8, SIZE_IP6); +        memcpy(data + 1, source->ip.v6.uint8, SIZE_IP6);      }  } -/* return 0 on success, -1 on failure. */ +/** return 0 on success, -1 on failure. */  static int ip_unpack(IP *target, const uint8_t *data, unsigned int data_size, bool disable_family_check)  {      if (data_size < (1 + SIZE_IP6)) { @@ -75,11 +71,11 @@ static int ip_unpack(IP *target, const uint8_t *data, unsigned int data_size, bo  static void ipport_pack(uint8_t *data, const IP_Port *source)  { -    ip_pack(data, source->ip); +    ip_pack(data, &source->ip);      memcpy(data + SIZE_IP, &source->port, SIZE_PORT);  } -/* return 0 on success, -1 on failure. */ +/** return 0 on success, -1 on failure. */  static int ipport_unpack(IP_Port *target, const uint8_t *data, unsigned int data_size, bool disable_family_check)  {      if (data_size < (SIZE_IP + SIZE_PORT)) { @@ -95,7 +91,7 @@ static int ipport_unpack(IP_Port *target, const uint8_t *data, unsigned int data  } -/* Create a new onion path. +/** Create a new onion path.   *   * Create a new onion path out of nodes (nodes is a list of ONION_PATH_LENGTH nodes)   * @@ -124,6 +120,8 @@ int create_onion_path(const DHT *dht, Onion_Path *new_path, const Node_format *n      encrypt_precompute(nodes[2].public_key, random_secret_key, new_path->shared_key3);      memcpy(new_path->public_key3, random_public_key, CRYPTO_PUBLIC_KEY_SIZE); +    crypto_memzero(random_secret_key, sizeof(random_secret_key)); +      new_path->ip_port1 = nodes[0].ip_port;      new_path->ip_port2 = nodes[1].ip_port;      new_path->ip_port3 = nodes[2].ip_port; @@ -135,7 +133,7 @@ int create_onion_path(const DHT *dht, Onion_Path *new_path, const Node_format *n      return 0;  } -/* Dump nodes in onion path to nodes of length num_nodes. +/** Dump nodes in onion path to nodes of length num_nodes.   *   * return -1 on failure.   * return 0 on success. @@ -156,7 +154,7 @@ int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_      return 0;  } -/* Create a onion packet. +/** Create a onion packet.   *   * Use Onion_Path path to create packet for data of length to dest.   * Maximum length of data is ONION_MAX_DATA_SIZE. @@ -165,7 +163,7 @@ int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_   * return -1 on failure.   * return length of created packet on success.   */ -int create_onion_packet(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, IP_Port dest, +int create_onion_packet(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, const IP_Port *dest,                          const uint8_t *data, uint16_t length)  {      if (1 + length + SEND_1 > max_packet_length || length == 0) { @@ -174,7 +172,7 @@ int create_onion_packet(uint8_t *packet, uint16_t max_packet_length, const Onion      VLA(uint8_t, step1, SIZE_IPPORT + length); -    ipport_pack(step1, &dest); +    ipport_pack(step1, dest);      memcpy(step1 + SIZE_IPPORT, data, length);      uint8_t nonce[CRYPTO_NONCE_SIZE]; @@ -215,7 +213,7 @@ int create_onion_packet(uint8_t *packet, uint16_t max_packet_length, const Onion      return 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + len;  } -/* Create a onion packet to be sent over tcp. +/** Create a onion packet to be sent over tcp.   *   * Use Onion_Path path to create packet for data of length to dest.   * Maximum length of data is ONION_MAX_DATA_SIZE. @@ -224,7 +222,7 @@ int create_onion_packet(uint8_t *packet, uint16_t max_packet_length, const Onion   * return -1 on failure.   * return length of created packet on success.   */ -int create_onion_packet_tcp(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, IP_Port dest, +int create_onion_packet_tcp(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, const IP_Port *dest,                              const uint8_t *data, uint16_t length)  {      if (CRYPTO_NONCE_SIZE + SIZE_IPPORT + SEND_BASE * 2 + length > max_packet_length || length == 0) { @@ -233,7 +231,7 @@ int create_onion_packet_tcp(uint8_t *packet, uint16_t max_packet_length, const O      VLA(uint8_t, step1, SIZE_IPPORT + length); -    ipport_pack(step1, &dest); +    ipport_pack(step1, dest);      memcpy(step1 + SIZE_IPPORT, data, length);      uint8_t nonce[CRYPTO_NONCE_SIZE]; @@ -264,7 +262,7 @@ int create_onion_packet_tcp(uint8_t *packet, uint16_t max_packet_length, const O      return CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE + len;  } -/* Create and send a onion packet. +/** Create and send a onion packet.   *   * Use Onion_Path path to send data of length to dest.   * Maximum length of data is ONION_MAX_DATA_SIZE. @@ -272,7 +270,8 @@ int create_onion_packet_tcp(uint8_t *packet, uint16_t max_packet_length, const O   * return -1 on failure.   * return 0 on success.   */ -int send_onion_packet(Networking_Core *net, const Onion_Path *path, IP_Port dest, const uint8_t *data, uint16_t length) +int send_onion_packet(const Networking_Core *net, const Onion_Path *path, const IP_Port *dest, const uint8_t *data, +                      uint16_t length)  {      uint8_t packet[ONION_MAX_PACKET_SIZE];      int len = create_onion_packet(packet, sizeof(packet), path, dest, data, length); @@ -281,20 +280,21 @@ int send_onion_packet(Networking_Core *net, const Onion_Path *path, IP_Port dest          return -1;      } -    if (sendpacket(net, path->ip_port1, packet, len) != len) { +    if (sendpacket(net, &path->ip_port1, packet, len) != len) {          return -1;      }      return 0;  } -/* Create and send a onion response sent initially to dest with. +/** Create and send a onion response sent initially to dest with.   * Maximum length of data is ONION_RESPONSE_MAX_DATA_SIZE.   *   * return -1 on failure.   * return 0 on success.   */ -int send_onion_response(Networking_Core *net, IP_Port dest, const uint8_t *data, uint16_t length, const uint8_t *ret) +int send_onion_response(const Networking_Core *net, const IP_Port *dest, const uint8_t *data, uint16_t length, +                        const uint8_t *ret)  {      if (length > ONION_RESPONSE_MAX_DATA_SIZE || length == 0) {          return -1; @@ -312,7 +312,8 @@ int send_onion_response(Networking_Core *net, IP_Port dest, const uint8_t *data,      return 0;  } -static int handle_send_initial(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) +static int handle_send_initial(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, +                               void *userdata)  {      Onion *onion = (Onion *)object; @@ -340,7 +341,7 @@ static int handle_send_initial(void *object, IP_Port source, const uint8_t *pack      return onion_send_1(onion, plain, len, source, packet + 1);  } -int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, IP_Port source, const uint8_t *nonce) +int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, const IP_Port *source, const uint8_t *nonce)  {      if (len > ONION_MAX_PACKET_SIZE + SIZE_IPPORT - (1 + CRYPTO_NONCE_SIZE + ONION_RETURN_1)) {          return 1; @@ -357,9 +358,9 @@ int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, IP_Port      }      uint8_t ip_port[SIZE_IPPORT]; -    ipport_pack(ip_port, &source); +    ipport_pack(ip_port, source); -    uint8_t data[ONION_MAX_PACKET_SIZE]; +    uint8_t data[ONION_MAX_PACKET_SIZE] = {0};      data[0] = NET_PACKET_ONION_SEND_1;      memcpy(data + 1, nonce, CRYPTO_NONCE_SIZE);      memcpy(data + 1 + CRYPTO_NONCE_SIZE, plain + SIZE_IPPORT, len - SIZE_IPPORT); @@ -375,14 +376,14 @@ int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, IP_Port      data_len += CRYPTO_NONCE_SIZE + len; -    if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) { +    if ((uint32_t)sendpacket(onion->net, &send_to, data, data_len) != data_len) {          return 1;      }      return 0;  } -static int handle_send_1(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) +static int handle_send_1(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)  {      Onion *onion = (Onion *)object; @@ -413,7 +414,7 @@ static int handle_send_1(void *object, IP_Port source, const uint8_t *packet, ui          return 1;      } -    uint8_t data[ONION_MAX_PACKET_SIZE]; +    uint8_t data[ONION_MAX_PACKET_SIZE] = {0};      data[0] = NET_PACKET_ONION_SEND_2;      memcpy(data + 1, packet + 1, CRYPTO_NONCE_SIZE);      memcpy(data + 1 + CRYPTO_NONCE_SIZE, plain + SIZE_IPPORT, len - SIZE_IPPORT); @@ -421,7 +422,7 @@ static int handle_send_1(void *object, IP_Port source, const uint8_t *packet, ui      uint8_t *ret_part = data + data_len;      random_nonce(ret_part);      uint8_t ret_data[RETURN_1 + SIZE_IPPORT]; -    ipport_pack(ret_data, &source); +    ipport_pack(ret_data, source);      memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_1), RETURN_1);      len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),                                   ret_part + CRYPTO_NONCE_SIZE); @@ -432,14 +433,14 @@ static int handle_send_1(void *object, IP_Port source, const uint8_t *packet, ui      data_len += CRYPTO_NONCE_SIZE + len; -    if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) { +    if ((uint32_t)sendpacket(onion->net, &send_to, data, data_len) != data_len) {          return 1;      }      return 0;  } -static int handle_send_2(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) +static int handle_send_2(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)  {      Onion *onion = (Onion *)object; @@ -468,8 +469,9 @@ static int handle_send_2(void *object, IP_Port source, const uint8_t *packet, ui          return 1;      } -    if (plain[SIZE_IPPORT] != NET_PACKET_ANNOUNCE_REQUEST && -            plain[SIZE_IPPORT] != NET_PACKET_ONION_DATA_REQUEST) { +    const uint8_t packet_id = plain[SIZE_IPPORT]; + +    if (packet_id != NET_PACKET_ANNOUNCE_REQUEST && packet_id != NET_PACKET_ONION_DATA_REQUEST) {          return 1;      } @@ -479,13 +481,13 @@ static int handle_send_2(void *object, IP_Port source, const uint8_t *packet, ui          return 1;      } -    uint8_t data[ONION_MAX_PACKET_SIZE]; +    uint8_t data[ONION_MAX_PACKET_SIZE] = {0};      memcpy(data, plain + SIZE_IPPORT, len - SIZE_IPPORT); -    uint16_t data_len = (len - SIZE_IPPORT); +    uint16_t data_len = len - SIZE_IPPORT;      uint8_t *ret_part = data + (len - SIZE_IPPORT);      random_nonce(ret_part);      uint8_t ret_data[RETURN_2 + SIZE_IPPORT]; -    ipport_pack(ret_data, &source); +    ipport_pack(ret_data, source);      memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_2), RETURN_2);      len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),                                   ret_part + CRYPTO_NONCE_SIZE); @@ -496,7 +498,7 @@ static int handle_send_2(void *object, IP_Port source, const uint8_t *packet, ui      data_len += RETURN_3; -    if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) { +    if ((uint32_t)sendpacket(onion->net, &send_to, data, data_len) != data_len) {          return 1;      } @@ -504,7 +506,7 @@ static int handle_send_2(void *object, IP_Port source, const uint8_t *packet, ui  } -static int handle_recv_3(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) +static int handle_recv_3(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)  {      Onion *onion = (Onion *)object; @@ -516,8 +518,9 @@ static int handle_recv_3(void *object, IP_Port source, const uint8_t *packet, ui          return 1;      } -    if (packet[1 + RETURN_3] != NET_PACKET_ANNOUNCE_RESPONSE && -            packet[1 + RETURN_3] != NET_PACKET_ONION_DATA_RESPONSE) { +    const uint8_t packet_id = packet[1 + RETURN_3]; + +    if (packet_id != NET_PACKET_ANNOUNCE_RESPONSE && packet_id != NET_PACKET_ONION_DATA_RESPONSE) {          return 1;      } @@ -537,20 +540,20 @@ static int handle_recv_3(void *object, IP_Port source, const uint8_t *packet, ui          return 1;      } -    uint8_t data[ONION_MAX_PACKET_SIZE]; +    uint8_t data[ONION_MAX_PACKET_SIZE] = {0};      data[0] = NET_PACKET_ONION_RECV_2;      memcpy(data + 1, plain + SIZE_IPPORT, RETURN_2);      memcpy(data + 1 + RETURN_2, packet + 1 + RETURN_3, length - (1 + RETURN_3));      uint16_t data_len = 1 + RETURN_2 + (length - (1 + RETURN_3)); -    if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) { +    if ((uint32_t)sendpacket(onion->net, &send_to, data, data_len) != data_len) {          return 1;      }      return 0;  } -static int handle_recv_2(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) +static int handle_recv_2(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)  {      Onion *onion = (Onion *)object; @@ -562,8 +565,9 @@ static int handle_recv_2(void *object, IP_Port source, const uint8_t *packet, ui          return 1;      } -    if (packet[1 + RETURN_2] != NET_PACKET_ANNOUNCE_RESPONSE && -            packet[1 + RETURN_2] != NET_PACKET_ONION_DATA_RESPONSE) { +    const uint8_t packet_id = packet[1 + RETURN_2]; + +    if (packet_id != NET_PACKET_ANNOUNCE_RESPONSE && packet_id != NET_PACKET_ONION_DATA_RESPONSE) {          return 1;      } @@ -583,20 +587,20 @@ static int handle_recv_2(void *object, IP_Port source, const uint8_t *packet, ui          return 1;      } -    uint8_t data[ONION_MAX_PACKET_SIZE]; +    uint8_t data[ONION_MAX_PACKET_SIZE] = {0};      data[0] = NET_PACKET_ONION_RECV_1;      memcpy(data + 1, plain + SIZE_IPPORT, RETURN_1);      memcpy(data + 1 + RETURN_1, packet + 1 + RETURN_2, length - (1 + RETURN_2));      uint16_t data_len = 1 + RETURN_1 + (length - (1 + RETURN_2)); -    if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) { +    if ((uint32_t)sendpacket(onion->net, &send_to, data, data_len) != data_len) {          return 1;      }      return 0;  } -static int handle_recv_1(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) +static int handle_recv_1(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)  {      Onion *onion = (Onion *)object; @@ -608,8 +612,9 @@ static int handle_recv_1(void *object, IP_Port source, const uint8_t *packet, ui          return 1;      } -    if (packet[1 + RETURN_1] != NET_PACKET_ANNOUNCE_RESPONSE && -            packet[1 + RETURN_1] != NET_PACKET_ONION_DATA_RESPONSE) { +    const uint8_t packet_id = packet[1 + RETURN_1]; + +    if (packet_id != NET_PACKET_ANNOUNCE_RESPONSE && packet_id != NET_PACKET_ONION_DATA_RESPONSE) {          return 1;      } @@ -634,10 +639,10 @@ static int handle_recv_1(void *object, IP_Port source, const uint8_t *packet, ui      if (onion->recv_1_function &&              !net_family_is_ipv4(send_to.ip.family) &&              !net_family_is_ipv6(send_to.ip.family)) { -        return onion->recv_1_function(onion->callback_object, send_to, packet + (1 + RETURN_1), data_len); +        return onion->recv_1_function(onion->callback_object, &send_to, packet + (1 + RETURN_1), data_len);      } -    if ((uint32_t)sendpacket(onion->net, send_to, packet + (1 + RETURN_1), data_len) != data_len) { +    if ((uint32_t)sendpacket(onion->net, &send_to, packet + (1 + RETURN_1), data_len) != data_len) {          return 1;      } @@ -650,7 +655,7 @@ void set_callback_handle_recv_1(Onion *onion, onion_recv_1_cb *function, void *o      onion->callback_object = object;  } -Onion *new_onion(Mono_Time *mono_time, DHT *dht) +Onion *new_onion(const Logger *log, Mono_Time *mono_time, DHT *dht)  {      if (dht == nullptr) {          return nullptr; @@ -662,6 +667,7 @@ Onion *new_onion(Mono_Time *mono_time, DHT *dht)          return nullptr;      } +    onion->log = log;      onion->dht = dht;      onion->net = dht_get_net(dht);      onion->mono_time = mono_time; @@ -693,5 +699,7 @@ void kill_onion(Onion *onion)      networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_2, nullptr, nullptr);      networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_1, nullptr, nullptr); +    crypto_memzero(onion->secret_symmetric_key, sizeof(onion->secret_symmetric_key)); +      free(onion);  } diff --git a/protocols/Tox/libtox/src/toxcore/onion.h b/protocols/Tox/libtox/src/toxcore/onion.h index da1450818f..970ef5b139 100644 --- a/protocols/Tox/libtox/src/toxcore/onion.h +++ b/protocols/Tox/libtox/src/toxcore/onion.h @@ -3,18 +3,20 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * Implementation of the onion part of docs/Prevent_Tracking.txt   */  #ifndef C_TOXCORE_TOXCORE_ONION_H  #define C_TOXCORE_TOXCORE_ONION_H  #include "DHT.h" +#include "logger.h"  #include "mono_time.h" -typedef int onion_recv_1_cb(void *object, IP_Port dest, const uint8_t *data, uint16_t length); +typedef int onion_recv_1_cb(void *object, const IP_Port *dest, const uint8_t *data, uint16_t length);  typedef struct Onion { +    const Logger *log;      Mono_Time *mono_time;      DHT *dht;      Networking_Core *net; @@ -66,7 +68,7 @@ typedef struct Onion_Path {      uint32_t path_num;  } Onion_Path; -/* Create a new onion path. +/** Create a new onion path.   *   * Create a new onion path out of nodes (nodes is a list of ONION_PATH_LENGTH nodes)   * @@ -77,14 +79,14 @@ typedef struct Onion_Path {   */  int create_onion_path(const DHT *dht, Onion_Path *new_path, const Node_format *nodes); -/* Dump nodes in onion path to nodes of length num_nodes; +/** Dump nodes in onion path to nodes of length num_nodes.   *   * return -1 on failure.   * return 0 on success.   */  int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_Path *path); -/* Create a onion packet. +/** Create a onion packet.   *   * Use Onion_Path path to create packet for data of length to dest.   * Maximum length of data is ONION_MAX_DATA_SIZE. @@ -93,11 +95,11 @@ int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_   * return -1 on failure.   * return length of created packet on success.   */ -int create_onion_packet(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, IP_Port dest, +int create_onion_packet(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, const IP_Port *dest,                          const uint8_t *data, uint16_t length); -/* Create a onion packet to be sent over tcp. +/** Create a onion packet to be sent over tcp.   *   * Use Onion_Path path to create packet for data of length to dest.   * Maximum length of data is ONION_MAX_DATA_SIZE. @@ -106,10 +108,10 @@ int create_onion_packet(uint8_t *packet, uint16_t max_packet_length, const Onion   * return -1 on failure.   * return length of created packet on success.   */ -int create_onion_packet_tcp(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, IP_Port dest, +int create_onion_packet_tcp(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, const IP_Port *dest,                              const uint8_t *data, uint16_t length); -/* Create and send a onion packet. +/** Create and send a onion packet.   *   * Use Onion_Path path to send data of length to dest.   * Maximum length of data is ONION_MAX_DATA_SIZE. @@ -117,17 +119,19 @@ int create_onion_packet_tcp(uint8_t *packet, uint16_t max_packet_length, const O   * return -1 on failure.   * return 0 on success.   */ -int send_onion_packet(Networking_Core *net, const Onion_Path *path, IP_Port dest, const uint8_t *data, uint16_t length); +int send_onion_packet(const Networking_Core *net, const Onion_Path *path, const IP_Port *dest, const uint8_t *data, +                      uint16_t length); -/* Create and send a onion response sent initially to dest with. +/** Create and send a onion response sent initially to dest with.   * Maximum length of data is ONION_RESPONSE_MAX_DATA_SIZE.   *   * return -1 on failure.   * return 0 on success.   */ -int send_onion_response(Networking_Core *net, IP_Port dest, const uint8_t *data, uint16_t length, const uint8_t *ret); +int send_onion_response(const Networking_Core *net, const IP_Port *dest, const uint8_t *data, uint16_t length, +                        const uint8_t *ret); -/* Function to handle/send received decrypted versions of the packet sent with send_onion_packet. +/** Function to handle/send received decrypted versions of the packet sent with send_onion_packet.   *   * return 0 on success.   * return 1 on failure. @@ -137,13 +141,13 @@ int send_onion_response(Networking_Core *net, IP_Port dest, const uint8_t *data,   * Source family must be set to something else than TOX_AF_INET6 or TOX_AF_INET so that the callback gets called   * when the response is received.   */ -int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, IP_Port source, const uint8_t *nonce); +int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, const IP_Port *source, const uint8_t *nonce); -/* Set the callback to be called when the dest ip_port doesn't have TOX_AF_INET6 or TOX_AF_INET as the family. +/** Set the callback to be called when the dest ip_port doesn't have TOX_AF_INET6 or TOX_AF_INET as the family.   */  void set_callback_handle_recv_1(Onion *onion, onion_recv_1_cb *function, void *object); -Onion *new_onion(Mono_Time *mono_time, DHT *dht); +Onion *new_onion(const Logger *log, Mono_Time *mono_time, DHT *dht);  void kill_onion(Onion *onion); diff --git a/protocols/Tox/libtox/src/toxcore/onion_announce.c b/protocols/Tox/libtox/src/toxcore/onion_announce.c index 0a04a4b834..5c37fbe18c 100644 --- a/protocols/Tox/libtox/src/toxcore/onion_announce.c +++ b/protocols/Tox/libtox/src/toxcore/onion_announce.c @@ -3,13 +3,9 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * Implementation of the announce part of docs/Prevent_Tracking.txt   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -  #include "onion_announce.h"  #include <stdlib.h> @@ -26,6 +22,9 @@  #define DATA_REQUEST_MIN_SIZE ONION_DATA_REQUEST_MIN_SIZE  #define DATA_REQUEST_MIN_SIZE_RECV (DATA_REQUEST_MIN_SIZE + ONION_RETURN_3) +static_assert(ONION_PING_ID_SIZE == CRYPTO_PUBLIC_KEY_SIZE, +              "announce response packets assume that ONION_PING_ID_SIZE is equal to CRYPTO_PUBLIC_KEY_SIZE"); +  typedef struct Onion_Announce_Entry {      uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];      IP_Port ret_ip_port; @@ -35,6 +34,7 @@ typedef struct Onion_Announce_Entry {  } Onion_Announce_Entry;  struct Onion_Announce { +    const Logger *log;      Mono_Time *mono_time;      DHT     *dht;      Networking_Core *net; @@ -45,6 +45,11 @@ struct Onion_Announce {      Shared_Keys shared_keys_recv;  }; +static bool onion_ping_id_eq(const uint8_t *a, const uint8_t *b) +{ +    return public_key_cmp(a, b) == 0; +} +  uint8_t *onion_announce_entry_public_key(Onion_Announce *onion_a, uint32_t entry)  {      return onion_a->entries[entry].public_key; @@ -55,7 +60,7 @@ void onion_announce_entry_set_time(Onion_Announce *onion_a, uint32_t entry, uint      onion_a->entries[entry].time = time;  } -/* Create an onion announce request packet in packet of max_packet_length (recommended size ONION_ANNOUNCE_REQUEST_SIZE). +/** Create an onion announce request packet in packet of max_packet_length (recommended size ONION_ANNOUNCE_REQUEST_SIZE).   *   * dest_client_id is the public key of the node the packet will be sent to.   * public_key and secret_key is the kepair which will be used to encrypt the request. @@ -99,7 +104,7 @@ int create_announce_request(uint8_t *packet, uint16_t max_packet_length, const u      return ONION_ANNOUNCE_REQUEST_SIZE;  } -/* Create an onion data request packet in packet of max_packet_length (recommended size ONION_MAX_PACKET_SIZE). +/** Create an onion data request packet in packet of max_packet_length (recommended size ONION_MAX_PACKET_SIZE).   *   * public_key is the real public key of the node which we want to send the data of length length to.   * encrypt_public_key is the public key used to encrypt the data packet. @@ -141,7 +146,7 @@ int create_data_request(uint8_t *packet, uint16_t max_packet_length, const uint8      return DATA_REQUEST_MIN_SIZE + length;  } -/* Create and send an onion announce request packet. +/** Create and send an onion announce request packet.   *   * path is the path the request will take before it is sent to dest.   * @@ -155,9 +160,10 @@ int create_data_request(uint8_t *packet, uint16_t max_packet_length, const uint8   * return -1 on failure.   * return 0 on success.   */ -int send_announce_request(Networking_Core *net, const Onion_Path *path, Node_format dest, const uint8_t *public_key, -                          const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id, const uint8_t *data_public_key, -                          uint64_t sendback_data) +int send_announce_request(const Networking_Core *net, const Onion_Path *path, Node_format dest, +                          const uint8_t *public_key, const uint8_t *secret_key, +                          const uint8_t *ping_id, const uint8_t *client_id, +                          const uint8_t *data_public_key, uint64_t sendback_data)  {      uint8_t request[ONION_ANNOUNCE_REQUEST_SIZE];      int len = create_announce_request(request, sizeof(request), dest.public_key, public_key, secret_key, ping_id, client_id, @@ -168,20 +174,20 @@ int send_announce_request(Networking_Core *net, const Onion_Path *path, Node_for      }      uint8_t packet[ONION_MAX_PACKET_SIZE]; -    len = create_onion_packet(packet, sizeof(packet), path, dest.ip_port, request, sizeof(request)); +    len = create_onion_packet(packet, sizeof(packet), path, &dest.ip_port, request, sizeof(request));      if (len == -1) {          return -1;      } -    if (sendpacket(net, path->ip_port1, packet, len) != len) { +    if (sendpacket(net, &path->ip_port1, packet, len) != len) {          return -1;      }      return 0;  } -/* Create and send an onion data request packet. +/** Create and send an onion data request packet.   *   * path is the path the request will take before it is sent to dest.   * (if dest knows the person with the public_key they should @@ -192,10 +198,13 @@ int send_announce_request(Networking_Core *net, const Onion_Path *path, Node_for   *   * nonce is the nonce to encrypt this packet with   * + * The maximum length of data is MAX_DATA_REQUEST_SIZE. + *   * return -1 on failure.   * return 0 on success.   */ -int send_data_request(Networking_Core *net, const Onion_Path *path, IP_Port dest, const uint8_t *public_key, +int send_data_request(const Networking_Core *net, const Onion_Path *path, const IP_Port *dest, +                      const uint8_t *public_key,                        const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length)  {      uint8_t request[ONION_MAX_DATA_SIZE]; @@ -212,36 +221,34 @@ int send_data_request(Networking_Core *net, const Onion_Path *path, IP_Port dest          return -1;      } -    if (sendpacket(net, path->ip_port1, packet, len) != len) { +    if (sendpacket(net, &path->ip_port1, packet, len) != len) {          return -1;      }      return 0;  } -/* Generate a ping_id and put it in ping_id */ +/** Generate a ping_id and put it in ping_id */  static void generate_ping_id(const Onion_Announce *onion_a, uint64_t time, const uint8_t *public_key, -                             IP_Port ret_ip_port, uint8_t *ping_id) +                             const IP_Port *ret_ip_port, uint8_t *ping_id)  {      time /= PING_ID_TIMEOUT; -    uint8_t data[CRYPTO_SYMMETRIC_KEY_SIZE + sizeof(time) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(ret_ip_port)]; +    uint8_t data[CRYPTO_SYMMETRIC_KEY_SIZE + sizeof(time) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port)];      memcpy(data, onion_a->secret_bytes, CRYPTO_SYMMETRIC_KEY_SIZE);      memcpy(data + CRYPTO_SYMMETRIC_KEY_SIZE, &time, sizeof(time));      memcpy(data + CRYPTO_SYMMETRIC_KEY_SIZE + sizeof(time), public_key, CRYPTO_PUBLIC_KEY_SIZE); -    memcpy(data + CRYPTO_SYMMETRIC_KEY_SIZE + sizeof(time) + CRYPTO_PUBLIC_KEY_SIZE, &ret_ip_port, sizeof(ret_ip_port)); +    memcpy(data + CRYPTO_SYMMETRIC_KEY_SIZE + sizeof(time) + CRYPTO_PUBLIC_KEY_SIZE, ret_ip_port, sizeof(IP_Port));      crypto_sha256(ping_id, data, sizeof(data));  } -/* check if public key is in entries list +/** check if public key is in entries list   *   * return -1 if no   * return position in list if yes   */  static int in_entries(const Onion_Announce *onion_a, const uint8_t *public_key)  { -    unsigned int i; - -    for (i = 0; i < ONION_ANNOUNCE_MAX_ENTRIES; ++i) { +    for (unsigned int i = 0; i < ONION_ANNOUNCE_MAX_ENTRIES; ++i) {          if (!mono_time_is_timeout(onion_a->mono_time, onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT)                  && public_key_cmp(onion_a->entries[i].public_key, public_key) == 0) {              return i; @@ -251,24 +258,22 @@ static int in_entries(const Onion_Announce *onion_a, const uint8_t *public_key)      return -1;  } -typedef struct Cmp_data { +typedef struct Cmp_Data {      const Mono_Time *mono_time;      const uint8_t *base_public_key;      Onion_Announce_Entry entry; -} Cmp_data; +} Cmp_Data;  static int cmp_entry(const void *a, const void *b)  { -    Cmp_data cmp1; -    Cmp_data cmp2; -    memcpy(&cmp1, a, sizeof(Cmp_data)); -    memcpy(&cmp2, b, sizeof(Cmp_data)); -    Onion_Announce_Entry entry1 = cmp1.entry; -    Onion_Announce_Entry entry2 = cmp2.entry; -    const uint8_t *cmp_public_key = cmp1.base_public_key; +    const Cmp_Data *cmp1 = (const Cmp_Data *)a; +    const Cmp_Data *cmp2 = (const Cmp_Data *)b; +    const Onion_Announce_Entry entry1 = cmp1->entry; +    const Onion_Announce_Entry entry2 = cmp2->entry; +    const uint8_t *cmp_public_key = cmp1->base_public_key; -    int t1 = mono_time_is_timeout(cmp1.mono_time, entry1.time, ONION_ANNOUNCE_TIMEOUT); -    int t2 = mono_time_is_timeout(cmp1.mono_time, entry2.time, ONION_ANNOUNCE_TIMEOUT); +    const int t1 = mono_time_is_timeout(cmp1->mono_time, entry1.time, ONION_ANNOUNCE_TIMEOUT); +    const int t2 = mono_time_is_timeout(cmp1->mono_time, entry2.time, ONION_ANNOUNCE_TIMEOUT);      if (t1 && t2) {          return 0; @@ -282,7 +287,7 @@ static int cmp_entry(const void *a, const void *b)          return 1;      } -    int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key); +    const int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key);      if (close == 1) {          return 1; @@ -300,7 +305,7 @@ static void sort_onion_announce_list(Onion_Announce_Entry *list, unsigned int le  {      // Pass comp_public_key to qsort with each Client_data entry, so the      // comparison function can use it as the base of comparison. -    VLA(Cmp_data, cmp_list, length); +    VLA(Cmp_Data, cmp_list, length);      for (uint32_t i = 0; i < length; ++i) {          cmp_list[i].mono_time = mono_time; @@ -308,19 +313,19 @@ static void sort_onion_announce_list(Onion_Announce_Entry *list, unsigned int le          cmp_list[i].entry = list[i];      } -    qsort(cmp_list, length, sizeof(Cmp_data), cmp_entry); +    qsort(cmp_list, length, sizeof(Cmp_Data), cmp_entry);      for (uint32_t i = 0; i < length; ++i) {          list[i] = cmp_list[i].entry;      }  } -/* add entry to entries list +/** add entry to entries list   *   * return -1 if failure   * return position if added   */ -static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, const uint8_t *public_key, +static int add_to_entries(Onion_Announce *onion_a, const IP_Port *ret_ip_port, const uint8_t *public_key,                            const uint8_t *data_public_key, const uint8_t *ret)  { @@ -345,7 +350,7 @@ static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, const ui      }      memcpy(onion_a->entries[pos].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); -    onion_a->entries[pos].ret_ip_port = ret_ip_port; +    onion_a->entries[pos].ret_ip_port = *ret_ip_port;      memcpy(onion_a->entries[pos].ret, ret, ONION_RETURN_3);      memcpy(onion_a->entries[pos].data_public_key, data_public_key, CRYPTO_PUBLIC_KEY_SIZE);      onion_a->entries[pos].time = mono_time_get(onion_a->mono_time); @@ -355,7 +360,8 @@ static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, const ui      return in_entries(onion_a, public_key);  } -static int handle_announce_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) +static int handle_announce_request(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, +                                   void *userdata)  {      Onion_Announce *onion_a = (Onion_Announce *)object; @@ -386,10 +392,10 @@ static int handle_announce_request(void *object, IP_Port source, const uint8_t *      int index; -    uint8_t *data_public_key = plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE; +    const uint8_t *data_public_key = plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE; -    if (crypto_memcmp(ping_id1, plain, ONION_PING_ID_SIZE) == 0 -            || crypto_memcmp(ping_id2, plain, ONION_PING_ID_SIZE) == 0) { +    if (onion_ping_id_eq(ping_id1, plain) +            || onion_ping_id_eq(ping_id2, plain)) {          index = add_to_entries(onion_a, source, packet_public_key, data_public_key,                                 packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3));      } else { @@ -399,7 +405,7 @@ static int handle_announce_request(void *object, IP_Port source, const uint8_t *      /*Respond with a announce response packet*/      Node_format nodes_list[MAX_SENT_NODES];      unsigned int num_nodes = -        get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, net_family_unspec, ip_is_lan(source.ip), 1); +        get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, net_family_unspec, ip_is_lan(&source->ip));      uint8_t nonce[CRYPTO_NONCE_SIZE];      random_nonce(nonce); @@ -455,9 +461,10 @@ static int handle_announce_request(void *object, IP_Port source, const uint8_t *      return 0;  } -static int handle_data_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) +static int handle_data_request(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, +                               void *userdata)  { -    Onion_Announce *onion_a = (Onion_Announce *)object; +    const Onion_Announce *onion_a = (const Onion_Announce *)object;      if (length <= DATA_REQUEST_MIN_SIZE_RECV) {          return 1; @@ -477,7 +484,7 @@ static int handle_data_request(void *object, IP_Port source, const uint8_t *pack      data[0] = NET_PACKET_ONION_DATA_RESPONSE;      memcpy(data + 1, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, length - (1 + CRYPTO_PUBLIC_KEY_SIZE + ONION_RETURN_3)); -    if (send_onion_response(onion_a->net, onion_a->entries[index].ret_ip_port, data, SIZEOF_VLA(data), +    if (send_onion_response(onion_a->net, &onion_a->entries[index].ret_ip_port, data, SIZEOF_VLA(data),                              onion_a->entries[index].ret) == -1) {          return 1;      } @@ -485,7 +492,7 @@ static int handle_data_request(void *object, IP_Port source, const uint8_t *pack      return 0;  } -Onion_Announce *new_onion_announce(Mono_Time *mono_time, DHT *dht) +Onion_Announce *new_onion_announce(const Logger *log, Mono_Time *mono_time, DHT *dht)  {      if (dht == nullptr) {          return nullptr; @@ -497,6 +504,7 @@ Onion_Announce *new_onion_announce(Mono_Time *mono_time, DHT *dht)          return nullptr;      } +    onion_a->log = log;      onion_a->mono_time = mono_time;      onion_a->dht = dht;      onion_a->net = dht_get_net(dht); diff --git a/protocols/Tox/libtox/src/toxcore/onion_announce.h b/protocols/Tox/libtox/src/toxcore/onion_announce.h index 3145803c15..c4159d2bf6 100644 --- a/protocols/Tox/libtox/src/toxcore/onion_announce.h +++ b/protocols/Tox/libtox/src/toxcore/onion_announce.h @@ -3,12 +3,13 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * Implementation of the announce part of docs/Prevent_Tracking.txt   */  #ifndef C_TOXCORE_TOXCORE_ONION_ANNOUNCE_H  #define C_TOXCORE_TOXCORE_ONION_ANNOUNCE_H +#include "logger.h"  #include "onion.h"  #define ONION_ANNOUNCE_MAX_ENTRIES 160 @@ -24,20 +25,16 @@  #define ONION_DATA_RESPONSE_MIN_SIZE (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE) -#if ONION_PING_ID_SIZE != CRYPTO_PUBLIC_KEY_SIZE -#error "announce response packets assume that ONION_PING_ID_SIZE is equal to CRYPTO_PUBLIC_KEY_SIZE" -#endif -  #define ONION_DATA_REQUEST_MIN_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE)  #define MAX_DATA_REQUEST_SIZE (ONION_MAX_DATA_SIZE - ONION_DATA_REQUEST_MIN_SIZE)  typedef struct Onion_Announce Onion_Announce; -/* These two are not public; they are for tests only! */ +/** These two are not public; they are for tests only! */  uint8_t *onion_announce_entry_public_key(Onion_Announce *onion_a, uint32_t entry);  void onion_announce_entry_set_time(Onion_Announce *onion_a, uint32_t entry, uint64_t time); -/* Create an onion announce request packet in packet of max_packet_length (recommended size ONION_ANNOUNCE_REQUEST_SIZE). +/** Create an onion announce request packet in packet of max_packet_length (recommended size ONION_ANNOUNCE_REQUEST_SIZE).   *   * dest_client_id is the public key of the node the packet will be sent to.   * public_key and secret_key is the kepair which will be used to encrypt the request. @@ -54,7 +51,7 @@ int create_announce_request(uint8_t *packet, uint16_t max_packet_length, const u                              const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id,                              const uint8_t *data_public_key, uint64_t sendback_data); -/* Create an onion data request packet in packet of max_packet_length (recommended size ONION_MAX_PACKET_SIZE). +/** Create an onion data request packet in packet of max_packet_length (recommended size ONION_MAX_PACKET_SIZE).   *   * public_key is the real public key of the node which we want to send the data of length length to.   * encrypt_public_key is the public key used to encrypt the data packet. @@ -67,7 +64,7 @@ int create_announce_request(uint8_t *packet, uint16_t max_packet_length, const u  int create_data_request(uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key,                          const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length); -/* Create and send an onion announce request packet. +/** Create and send an onion announce request packet.   *   * path is the path the request will take before it is sent to dest.   * @@ -81,11 +78,12 @@ int create_data_request(uint8_t *packet, uint16_t max_packet_length, const uint8   * return -1 on failure.   * return 0 on success.   */ -int send_announce_request(Networking_Core *net, const Onion_Path *path, Node_format dest, const uint8_t *public_key, -                          const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id, const uint8_t *data_public_key, -                          uint64_t sendback_data); +int send_announce_request(const Networking_Core *net, const Onion_Path *path, Node_format dest, +                          const uint8_t *public_key, const uint8_t *secret_key, +                          const uint8_t *ping_id, const uint8_t *client_id, +                          const uint8_t *data_public_key,  uint64_t sendback_data); -/* Create and send an onion data request packet. +/** Create and send an onion data request packet.   *   * path is the path the request will take before it is sent to dest.   * (if dest knows the person with the public_key they should @@ -101,11 +99,12 @@ int send_announce_request(Networking_Core *net, const Onion_Path *path, Node_for   * return -1 on failure.   * return 0 on success.   */ -int send_data_request(Networking_Core *net, const Onion_Path *path, IP_Port dest, const uint8_t *public_key, +int send_data_request(const Networking_Core *net, const Onion_Path *path, const IP_Port *dest, +                      const uint8_t *public_key,                        const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length); -Onion_Announce *new_onion_announce(Mono_Time *mono_time, DHT *dht); +Onion_Announce *new_onion_announce(const Logger *log, Mono_Time *mono_time, DHT *dht);  void kill_onion_announce(Onion_Announce *onion_a); diff --git a/protocols/Tox/libtox/src/toxcore/onion_client.c b/protocols/Tox/libtox/src/toxcore/onion_client.c index d3a56af73b..592cb4f57d 100644 --- a/protocols/Tox/libtox/src/toxcore/onion_client.c +++ b/protocols/Tox/libtox/src/toxcore/onion_client.c @@ -3,16 +3,13 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * Implementation of the client part of docs/Prevent_Tracking.txt (The part that   * uses the onion stuff to connect to the friend)   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -  #include "onion_client.h" +#include <assert.h>  #include <stdlib.h>  #include <string.h> @@ -20,7 +17,7 @@  #include "mono_time.h"  #include "util.h" -/* defines for the array size and +/** defines for the array size and   * timeout for onion announce packets. */  #define ANNOUNCE_ARRAY_SIZE 256  #define ANNOUNCE_TIMEOUT 10 @@ -146,26 +143,24 @@ Net_Crypto *onion_get_net_crypto(const Onion_Client *onion_c)      return onion_c->c;  } -/* Add a node to the path_nodes bootstrap array. +/** Add a node to the path_nodes bootstrap array.   *   * return -1 on failure   * return 0 on success   */ -int onion_add_bs_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *public_key) +int onion_add_bs_path_node(Onion_Client *onion_c, const IP_Port *ip_port, const uint8_t *public_key)  { -    if (!net_family_is_ipv4(ip_port.ip.family) && !net_family_is_ipv6(ip_port.ip.family)) { +    if (!net_family_is_ipv4(ip_port->ip.family) && !net_family_is_ipv6(ip_port->ip.family)) {          return -1;      } -    unsigned int i; - -    for (i = 0; i < MAX_PATH_NODES; ++i) { +    for (unsigned int i = 0; i < MAX_PATH_NODES; ++i) {          if (public_key_cmp(public_key, onion_c->path_nodes_bs[i].public_key) == 0) {              return -1;          }      } -    onion_c->path_nodes_bs[onion_c->path_nodes_index_bs % MAX_PATH_NODES].ip_port = ip_port; +    onion_c->path_nodes_bs[onion_c->path_nodes_index_bs % MAX_PATH_NODES].ip_port = *ip_port;      memcpy(onion_c->path_nodes_bs[onion_c->path_nodes_index_bs % MAX_PATH_NODES].public_key, public_key,             CRYPTO_PUBLIC_KEY_SIZE); @@ -179,26 +174,24 @@ int onion_add_bs_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t      return 0;  } -/* Add a node to the path_nodes array. +/** Add a node to the path_nodes array.   *   * return -1 on failure   * return 0 on success   */ -static int onion_add_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *public_key) +static int onion_add_path_node(Onion_Client *onion_c, const IP_Port *ip_port, const uint8_t *public_key)  { -    if (!net_family_is_ipv4(ip_port.ip.family) && !net_family_is_ipv6(ip_port.ip.family)) { +    if (!net_family_is_ipv4(ip_port->ip.family) && !net_family_is_ipv6(ip_port->ip.family)) {          return -1;      } -    unsigned int i; - -    for (i = 0; i < MAX_PATH_NODES; ++i) { +    for (unsigned int i = 0; i < MAX_PATH_NODES; ++i) {          if (public_key_cmp(public_key, onion_c->path_nodes[i].public_key) == 0) {              return -1;          }      } -    onion_c->path_nodes[onion_c->path_nodes_index % MAX_PATH_NODES].ip_port = ip_port; +    onion_c->path_nodes[onion_c->path_nodes_index % MAX_PATH_NODES].ip_port = *ip_port;      memcpy(onion_c->path_nodes[onion_c->path_nodes_index % MAX_PATH_NODES].public_key, public_key,             CRYPTO_PUBLIC_KEY_SIZE); @@ -212,7 +205,7 @@ static int onion_add_path_node(Onion_Client *onion_c, IP_Port ip_port, const uin      return 0;  } -/* Put up to max_num nodes in nodes. +/** Put up to max_num nodes in nodes.   *   * return the number of nodes.   */ @@ -249,14 +242,12 @@ uint16_t onion_backup_nodes(const Onion_Client *onion_c, Node_format *nodes, uin      return i;  } -/* Put up to max_num random nodes in nodes. +/** Put up to max_num random nodes in nodes.   *   * return the number of nodes.   */  static uint16_t random_nodes_path_onion(const Onion_Client *onion_c, Node_format *nodes, uint16_t max_num)  { -    unsigned int i; -      if (!max_num) {          return 0;      } @@ -269,8 +260,9 @@ static uint16_t random_nodes_path_onion(const Onion_Client *onion_c, Node_format              return 0;          } -        for (i = 0; i < max_num; ++i) { -            nodes[i] = onion_c->path_nodes[random_u32() % num_nodes]; +        for (unsigned int i = 0; i < max_num; ++i) { +            const uint32_t rand_idx = random_range_u32(num_nodes); +            nodes[i] = onion_c->path_nodes[rand_idx];          }      } else {          int random_tcp = get_random_tcp_con_number(onion_c->c); @@ -280,11 +272,15 @@ static uint16_t random_nodes_path_onion(const Onion_Client *onion_c, Node_format          }          if (num_nodes >= 2) { +            nodes[0] = (Node_format) { +                0 +            };              nodes[0].ip_port.ip.family = net_family_tcp_family;              nodes[0].ip_port.ip.ip.v4.uint32 = random_tcp; -            for (i = 1; i < max_num; ++i) { -                nodes[i] = onion_c->path_nodes[random_u32() % num_nodes]; +            for (unsigned int i = 1; i < max_num; ++i) { +                const uint32_t rand_idx = random_range_u32(num_nodes); +                nodes[i] = onion_c->path_nodes[rand_idx];              }          } else {              const uint16_t num_nodes_bs = min_u16(onion_c->path_nodes_index_bs, MAX_PATH_NODES); @@ -293,11 +289,15 @@ static uint16_t random_nodes_path_onion(const Onion_Client *onion_c, Node_format                  return 0;              } +            nodes[0] = (Node_format) { +                0 +            };              nodes[0].ip_port.ip.family = net_family_tcp_family;              nodes[0].ip_port.ip.ip.v4.uint32 = random_tcp; -            for (i = 1; i < max_num; ++i) { -                nodes[i] = onion_c->path_nodes_bs[random_u32() % num_nodes_bs]; +            for (unsigned int i = 1; i < max_num; ++i) { +                const uint32_t rand_idx = random_range_u32(num_nodes_bs); +                nodes[i] = onion_c->path_nodes_bs[rand_idx];              }          }      } @@ -305,15 +305,13 @@ static uint16_t random_nodes_path_onion(const Onion_Client *onion_c, Node_format      return max_num;  } -/* +/**   * return -1 if nodes are suitable for creating a new path.   * return path number of already existing similar path if one already exists.   */  static int is_path_used(const Mono_Time *mono_time, const Onion_Client_Paths *onion_paths, const Node_format *nodes)  { -    unsigned int i; - -    for (i = 0; i < NUMBER_ONION_PATHS; ++i) { +    for (unsigned int i = 0; i < NUMBER_ONION_PATHS; ++i) {          if (mono_time_is_timeout(mono_time, onion_paths->last_path_success[i], ONION_PATH_TIMEOUT)) {              continue;          } @@ -331,8 +329,8 @@ static int is_path_used(const Mono_Time *mono_time, const Onion_Client_Paths *on      return -1;  } -/* is path timed out */ -static bool path_timed_out(const Mono_Time *mono_time, Onion_Client_Paths *onion_paths, uint32_t pathnum) +/** is path timed out */ +static bool path_timed_out(const Mono_Time *mono_time, const Onion_Client_Paths *onion_paths, uint32_t pathnum)  {      pathnum = pathnum % NUMBER_ONION_PATHS; @@ -344,7 +342,7 @@ static bool path_timed_out(const Mono_Time *mono_time, Onion_Client_Paths *onion              || mono_time_is_timeout(mono_time, onion_paths->path_creation_time[pathnum], ONION_PATH_MAX_LIFETIME));  } -/* should node be considered to have timed out */ +/** should node be considered to have timed out */  static bool onion_node_timed_out(const Onion_Node *node, const Mono_Time *mono_time)  {      return (node->timestamp == 0 @@ -352,7 +350,7 @@ static bool onion_node_timed_out(const Onion_Node *node, const Mono_Time *mono_t                  && mono_time_is_timeout(mono_time, node->last_pinged, ONION_NODE_TIMEOUT)));  } -/* Create a new path or use an old suitable one (if pathnum is valid) +/** Create a new path or use an old suitable one (if pathnum is valid)   * or a random one from onion_paths.   *   * return -1 on failure @@ -364,7 +362,7 @@ static bool onion_node_timed_out(const Onion_Node *node, const Mono_Time *mono_t  static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_paths, uint32_t pathnum, Onion_Path *path)  {      if (pathnum == UINT32_MAX) { -        pathnum = random_u32() % NUMBER_ONION_PATHS; +        pathnum = random_range_u32(NUMBER_ONION_PATHS);      } else {          pathnum = pathnum % NUMBER_ONION_PATHS;      } @@ -403,12 +401,12 @@ static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_pa      }      ++onion_paths->last_path_used_times[pathnum]; -    memcpy(path, &onion_paths->paths[pathnum], sizeof(Onion_Path)); +    *path = onion_paths->paths[pathnum];      return 0;  } -/* Does path with path_num exist. */ -static bool path_exists(const Mono_Time *mono_time, Onion_Client_Paths *onion_paths, uint32_t path_num) +/** Does path with path_num exist. */ +static bool path_exists(const Mono_Time *mono_time, const Onion_Client_Paths *onion_paths, uint32_t path_num)  {      if (path_timed_out(mono_time, onion_paths, path_num)) {          return 0; @@ -417,7 +415,7 @@ static bool path_exists(const Mono_Time *mono_time, Onion_Client_Paths *onion_pa      return onion_paths->paths[path_num % NUMBER_ONION_PATHS].path_num == path_num;  } -/* Set path timeouts, return the path number. +/** Set path timeouts, return the path number.   *   */  static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, uint32_t path_num) @@ -441,10 +439,8 @@ static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, uint32_t          Node_format nodes[ONION_PATH_LENGTH];          if (onion_path_to_nodes(nodes, ONION_PATH_LENGTH, &onion_paths->paths[path_num % NUMBER_ONION_PATHS]) == 0) { -            unsigned int i; - -            for (i = 0; i < ONION_PATH_LENGTH; ++i) { -                onion_add_path_node(onion_c, nodes[i].ip_port, nodes[i].public_key); +            for (unsigned int i = 0; i < ONION_PATH_LENGTH; ++i) { +                onion_add_path_node(onion_c, &nodes[i].ip_port, nodes[i].public_key);              }          } @@ -454,12 +450,12 @@ static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, uint32_t      return -1;  } -/* Function to send onion packet via TCP and UDP. +/** Function to send onion packet via TCP and UDP.   *   * return -1 on failure.   * return 0 on success.   */ -static int send_onion_packet_tcp_udp(const Onion_Client *onion_c, const Onion_Path *path, IP_Port dest, +static int send_onion_packet_tcp_udp(const Onion_Client *onion_c, const Onion_Path *path, const IP_Port *dest,                                       const uint8_t *data, uint16_t length)  {      if (net_family_is_ipv4(path->ip_port1.ip.family) || net_family_is_ipv6(path->ip_port1.ip.family)) { @@ -470,7 +466,7 @@ static int send_onion_packet_tcp_udp(const Onion_Client *onion_c, const Onion_Pa              return -1;          } -        if (sendpacket(onion_c->net, path->ip_port1, packet, len) != len) { +        if (sendpacket(onion_c->net, &path->ip_port1, packet, len) != len) {              return -1;          } @@ -491,7 +487,7 @@ static int send_onion_packet_tcp_udp(const Onion_Client *onion_c, const Onion_Pa      return -1;  } -/* Creates a sendback for use in an announce request. +/** Creates a sendback for use in an announce request.   *   * num is 0 if we used our secret public key for the announce   * num is 1 + friendnum if we use a temporary one. @@ -506,13 +502,13 @@ static int send_onion_packet_tcp_udp(const Onion_Client *onion_c, const Onion_Pa   * return 0 on success   *   */ -static int new_sendback(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, IP_Port ip_port, +static int new_sendback(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, const IP_Port *ip_port,                          uint32_t path_num, uint64_t *sendback)  {      uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)];      memcpy(data, &num, sizeof(uint32_t));      memcpy(data + sizeof(uint32_t), public_key, CRYPTO_PUBLIC_KEY_SIZE); -    memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, &ip_port, sizeof(IP_Port)); +    memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, ip_port, sizeof(IP_Port));      memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), &path_num, sizeof(uint32_t));      *sendback = ping_array_add(onion_c->announce_ping_array, onion_c->mono_time, data, sizeof(data)); @@ -523,7 +519,7 @@ static int new_sendback(Onion_Client *onion_c, uint32_t num, const uint8_t *publ      return 0;  } -/* Checks if the sendback is valid and returns the public key contained in it in ret_pubkey and the +/** Checks if the sendback is valid and returns the public key contained in it in ret_pubkey and the   * ip contained in it in ret_ip_port   *   * sendback is the sendback ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big @@ -553,8 +549,8 @@ static uint32_t check_sendback(Onion_Client *onion_c, const uint8_t *sendback, u      return num;  } -static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, const uint8_t *dest_pubkey, -                                        const uint8_t *ping_id, uint32_t pathnum) +static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, const IP_Port *dest, +                                        const uint8_t *dest_pubkey, const uint8_t *ping_id, uint32_t pathnum)  {      if (num > onion_c->num_friends) {          return -1; @@ -603,24 +599,22 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_      return send_onion_packet_tcp_udp(onion_c, &path, dest, request, len);  } -typedef struct Onion_Client_Cmp_data { +typedef struct Onion_Client_Cmp_Data {      const Mono_Time *mono_time;      const uint8_t *base_public_key;      Onion_Node entry; -} Onion_Client_Cmp_data; +} Onion_Client_Cmp_Data;  static int onion_client_cmp_entry(const void *a, const void *b)  { -    Onion_Client_Cmp_data cmp1; -    Onion_Client_Cmp_data cmp2; -    memcpy(&cmp1, a, sizeof(Onion_Client_Cmp_data)); -    memcpy(&cmp2, b, sizeof(Onion_Client_Cmp_data)); -    Onion_Node entry1 = cmp1.entry; -    Onion_Node entry2 = cmp2.entry; -    const uint8_t *cmp_public_key = cmp1.base_public_key; +    const Onion_Client_Cmp_Data *cmp1 = (const Onion_Client_Cmp_Data *)a; +    const Onion_Client_Cmp_Data *cmp2 = (const Onion_Client_Cmp_Data *)b; +    const Onion_Node entry1 = cmp1->entry; +    const Onion_Node entry2 = cmp2->entry; +    const uint8_t *cmp_public_key = cmp1->base_public_key; -    int t1 = onion_node_timed_out(&entry1, cmp1.mono_time); -    int t2 = onion_node_timed_out(&entry2, cmp2.mono_time); +    const int t1 = onion_node_timed_out(&entry1, cmp1->mono_time); +    const int t2 = onion_node_timed_out(&entry2, cmp2->mono_time);      if (t1 && t2) {          return 0; @@ -634,7 +628,7 @@ static int onion_client_cmp_entry(const void *a, const void *b)          return 1;      } -    int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key); +    const int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key);      if (close == 1) {          return 1; @@ -652,7 +646,7 @@ static void sort_onion_node_list(Onion_Node *list, unsigned int length, const Mo  {      // Pass comp_public_key to qsort with each Client_data entry, so the      // comparison function can use it as the base of comparison. -    VLA(Onion_Client_Cmp_data, cmp_list, length); +    VLA(Onion_Client_Cmp_Data, cmp_list, length);      for (uint32_t i = 0; i < length; ++i) {          cmp_list[i].mono_time = mono_time; @@ -660,14 +654,14 @@ static void sort_onion_node_list(Onion_Node *list, unsigned int length, const Mo          cmp_list[i].entry = list[i];      } -    qsort(cmp_list, length, sizeof(Onion_Client_Cmp_data), onion_client_cmp_entry); +    qsort(cmp_list, length, sizeof(Onion_Client_Cmp_Data), onion_client_cmp_entry);      for (uint32_t i = 0; i < length; ++i) {          list[i] = cmp_list[i].entry;      }  } -static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, IP_Port ip_port, +static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, const IP_Port *ip_port,                                uint8_t is_stored, const uint8_t *pingid_or_key, uint32_t path_used)  {      if (num > onion_c->num_friends) { @@ -704,14 +698,13 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t      int index = -1;      int stored = 0; -    unsigned int i;      if (onion_node_timed_out(&list_nodes[0], onion_c->mono_time)              || id_closest(reference_id, list_nodes[0].public_key, public_key) == 2) {          index = 0;      } -    for (i = 0; i < list_length; ++i) { +    for (unsigned int i = 0; i < list_length; ++i) {          if (public_key_cmp(list_nodes[i].public_key, public_key) == 0) {              index = i;              stored = 1; @@ -724,7 +717,7 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t      }      memcpy(list_nodes[index].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); -    list_nodes[index].ip_port = ip_port; +    list_nodes[index].ip_port = *ip_port;      // TODO(irungentoo): remove this and find a better source of nodes to use for paths.      onion_add_path_node(onion_c, ip_port, public_key); @@ -748,12 +741,10 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t      return 0;  } -static int good_to_ping(Mono_Time *mono_time, Last_Pinged *last_pinged, uint8_t *last_pinged_index, +static int good_to_ping(const Mono_Time *mono_time, Last_Pinged *last_pinged, uint8_t *last_pinged_index,                          const uint8_t *public_key)  { -    unsigned int i; - -    for (i = 0; i < MAX_STORED_PINGED_NODES; ++i) { +    for (unsigned int i = 0; i < MAX_STORED_PINGED_NODES; ++i) {          if (!mono_time_is_timeout(mono_time, last_pinged[i].timestamp, MIN_NODE_PING_TIME)) {              if (public_key_cmp(last_pinged[i].public_key, public_key) == 0) {                  return 0; @@ -768,7 +759,7 @@ static int good_to_ping(Mono_Time *mono_time, Last_Pinged *last_pinged, uint8_t  }  static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_format *nodes, uint16_t num_nodes, -                             IP_Port source) +                             const IP_Port *source)  {      if (num > onion_c->num_friends) {          return -1; @@ -778,7 +769,7 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_for          return 0;      } -    Onion_Node *list_nodes = nullptr; +    const Onion_Node *list_nodes = nullptr;      const uint8_t *reference_id = nullptr;      unsigned int list_length; @@ -799,11 +790,11 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_for          last_pinged_index = &onion_c->friends_list[num - 1].last_pinged_index;      } -    const bool lan_ips_accepted = ip_is_lan(source.ip); +    const bool lan_ips_accepted = ip_is_lan(&source->ip);      for (uint32_t i = 0; i < num_nodes; ++i) {          if (!lan_ips_accepted) { -            if (ip_is_lan(nodes[i].ip_port.ip)) { +            if (ip_is_lan(&nodes[i].ip_port.ip)) {                  continue;              }          } @@ -822,7 +813,7 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_for              }              if (j == list_length && good_to_ping(onion_c->mono_time, last_pinged, last_pinged_index, nodes[i].public_key)) { -                client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].public_key, nullptr, -1); +                client_send_announce_request(onion_c, num, &nodes[i].ip_port, nodes[i].public_key, nullptr, -1);              }          }      } @@ -830,7 +821,7 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_for      return 0;  } -static int handle_announce_response(void *object, IP_Port source, const uint8_t *packet, uint16_t length, +static int handle_announce_response(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length,                                      void *userdata)  {      Onion_Client *onion_c = (Onion_Client *)object; @@ -875,7 +866,7 @@ static int handle_announce_response(void *object, IP_Port source, const uint8_t      uint32_t path_used = set_path_timeouts(onion_c, num, path_num); -    if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, path_used) == -1) { +    if (client_add_to_list(onion_c, num, public_key, &ip_port, plain[0], plain + 1, path_used) == -1) {          return 1;      } @@ -899,7 +890,8 @@ static int handle_announce_response(void *object, IP_Port source, const uint8_t  #define DATA_IN_RESPONSE_MIN_SIZE ONION_DATA_IN_RESPONSE_MIN_SIZE -static int handle_data_response(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) +static int handle_data_response(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, +                                void *userdata)  {      Onion_Client *onion_c = (Onion_Client *)object; @@ -986,9 +978,7 @@ static int handle_dhtpk_announce(void *object, const uint8_t *source_pubkey, con              return 1;          } -        int i; - -        for (i = 0; i < num_nodes; ++i) { +        for (int i = 0; i < num_nodes; ++i) {              const Family family = nodes[i].ip_port.ip.family;              if (net_family_is_ipv4(family) || net_family_is_ipv6(family)) { @@ -997,7 +987,7 @@ static int handle_dhtpk_announce(void *object, const uint8_t *source_pubkey, con                  if (onion_c->friends_list[friend_num].tcp_relay_node_callback) {                      void *obj = onion_c->friends_list[friend_num].tcp_relay_node_callback_object;                      uint32_t number = onion_c->friends_list[friend_num].tcp_relay_node_callback_number; -                    onion_c->friends_list[friend_num].tcp_relay_node_callback(obj, number, nodes[i].ip_port, nodes[i].public_key); +                    onion_c->friends_list[friend_num].tcp_relay_node_callback(obj, number, &nodes[i].ip_port, nodes[i].public_key);                  }              }          } @@ -1012,22 +1002,23 @@ static int handle_tcp_onion(void *object, const uint8_t *data, uint16_t length,          return 1;      } -    IP_Port ip_port = {{{0}}}; +    IP_Port ip_port = {0};      ip_port.ip.family = net_family_tcp_family;      if (data[0] == NET_PACKET_ANNOUNCE_RESPONSE) { -        return handle_announce_response(object, ip_port, data, length, userdata); +        return handle_announce_response(object, &ip_port, data, length, userdata);      }      if (data[0] == NET_PACKET_ONION_DATA_RESPONSE) { -        return handle_data_response(object, ip_port, data, length, userdata); +        return handle_data_response(object, &ip_port, data, length, userdata);      }      return 1;  } -/* Send data of length length to friendnum. - * This data will be received by the friend using the onion_data_handlers callbacks. +/** Send data of length length to friendnum. + * Maximum length of data is ONION_CLIENT_MAX_DATA_SIZE. + * This data will be received by the friend using the Onion_Data_Handlers callbacks.   *   * Even if this function succeeds, the friend might not receive any data.   * @@ -1051,7 +1042,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data,      unsigned int good_nodes[MAX_ONION_CLIENTS];      unsigned int num_good = 0;      unsigned int num_nodes = 0; -    Onion_Node *list_nodes = onion_c->friends_list[friend_num].clients_list; +    const Onion_Node *list_nodes = onion_c->friends_list[friend_num].clients_list;      for (unsigned int i = 0; i < MAX_ONION_CLIENTS; ++i) {          if (onion_node_timed_out(&list_nodes[i], onion_c->mono_time)) { @@ -1100,7 +1091,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data,              continue;          } -        if (send_onion_packet_tcp_udp(onion_c, &path, list_nodes[good_nodes[i]].ip_port, o_packet, len) == 0) { +        if (send_onion_packet_tcp_udp(onion_c, &path, &list_nodes[good_nodes[i]].ip_port, o_packet, len) == 0) {              ++good;          }      } @@ -1108,7 +1099,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data,      return good;  } -/* Try to send the dht public key via the DHT instead of onion +/** Try to send the dht public key via the DHT instead of onion   *   * Even if this function succeeds, the friend might not receive any data.   * @@ -1139,18 +1130,20 @@ static int send_dht_dhtpk(const Onion_Client *onion_c, int friend_num, const uin          return -1;      } -    uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; -    len = create_request(dht_get_self_public_key(onion_c->dht), dht_get_self_secret_key(onion_c->dht), packet, +    uint8_t packet_data[MAX_CRYPTO_REQUEST_SIZE]; +    len = create_request(dht_get_self_public_key(onion_c->dht), dht_get_self_secret_key(onion_c->dht), packet_data,                           onion_c->friends_list[friend_num].dht_public_key, temp, SIZEOF_VLA(temp), CRYPTO_PACKET_DHTPK); +    assert(len <= UINT16_MAX); +    const Packet packet = {packet_data, (uint16_t)len};      if (len == -1) {          return -1;      } -    return route_tofriend(onion_c->dht, onion_c->friends_list[friend_num].dht_public_key, packet, len); +    return route_to_friend(onion_c->dht, onion_c->friends_list[friend_num].dht_public_key, &packet);  } -static int handle_dht_dhtpk(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet, +static int handle_dht_dhtpk(void *object, const IP_Port *source, const uint8_t *source_pubkey, const uint8_t *packet,                              uint16_t length, void *userdata)  {      Onion_Client *onion_c = (Onion_Client *)object; @@ -1179,7 +1172,7 @@ static int handle_dht_dhtpk(void *object, IP_Port source, const uint8_t *source_      return handle_dhtpk_announce(onion_c, packet, plain, len, userdata);  } -/* Send the packets to tell our friends what our DHT public key is. +/** Send the packets to tell our friends what our DHT public key is.   *   * if onion_dht_both is 0, use only the onion to send the packet.   * if it is 1, use only the dht. @@ -1200,7 +1193,7 @@ static int send_dhtpk_announce(Onion_Client *onion_c, uint16_t friend_num, uint8      net_pack_u64(data + 1, no_replay);      memcpy(data + 1 + sizeof(uint64_t), dht_get_self_public_key(onion_c->dht), CRYPTO_PUBLIC_KEY_SIZE);      Node_format nodes[MAX_SENT_NODES]; -    uint16_t num_relays = copy_connected_tcp_relays(onion_c->c, nodes, (MAX_SENT_NODES / 2)); +    uint16_t num_relays = copy_connected_tcp_relays(onion_c->c, nodes, MAX_SENT_NODES / 2);      uint16_t num_nodes = closelist_nodes(onion_c->dht, &nodes[num_relays], MAX_SENT_NODES - num_relays);      num_nodes += num_relays;      int nodes_len = 0; @@ -1236,16 +1229,14 @@ static int send_dhtpk_announce(Onion_Client *onion_c, uint16_t friend_num, uint8      return num1 + num2;  } -/* Get the friend_num of a friend. +/** Get the friend_num of a friend.   *   * return -1 on failure.   * return friend number on success.   */  int onion_friend_num(const Onion_Client *onion_c, const uint8_t *public_key)  { -    unsigned int i; - -    for (i = 0; i < onion_c->num_friends; ++i) { +    for (unsigned int i = 0; i < onion_c->num_friends; ++i) {          if (onion_c->friends_list[i].status == 0) {              continue;          } @@ -1258,7 +1249,7 @@ int onion_friend_num(const Onion_Client *onion_c, const uint8_t *public_key)      return -1;  } -/* Set the size of the friend list to num. +/** Set the size of the friend list to num.   *   *  return -1 if realloc fails.   *  return 0 if it succeeds. @@ -1281,7 +1272,7 @@ static int realloc_onion_friends(Onion_Client *onion_c, uint32_t num)      return 0;  } -/* Add a friend who we want to connect to. +/** Add a friend who we want to connect to.   *   * return -1 on failure.   * return the friend number on success or if the friend was already added. @@ -1319,7 +1310,7 @@ int onion_addfriend(Onion_Client *onion_c, const uint8_t *public_key)      return index;  } -/* Delete a friend. +/** Delete a friend.   *   * return -1 on failure.   * return the deleted friend number on success. @@ -1355,7 +1346,7 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num)      return friend_num;  } -/* Set the function for this friend that will be callbacked with object and number +/** Set the function for this friend that will be callbacked with object and number   * when that friends gives us one of the TCP relays he is connected to.   *   * object and number will be passed as argument to this function. @@ -1376,7 +1367,7 @@ int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num,      return 0;  } -/* Set the function for this friend that will be callbacked with object and number +/** Set the function for this friend that will be callbacked with object and number   * when that friend gives us his DHT temporary public key.   *   * object and number will be passed as argument to this function. @@ -1397,7 +1388,7 @@ int onion_dht_pk_callback(Onion_Client *onion_c, int friend_num,      return 0;  } -/* Set a friend's DHT public key. +/** Set a friend's DHT public key.   *   * return -1 on failure.   * return 0 on success. @@ -1425,7 +1416,7 @@ int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uin      return 0;  } -/* Copy friends DHT public key into dht_key. +/** Copy friends DHT public key into dht_key.   *   * return 0 on failure (no key copied).   * return 1 on success (key copied). @@ -1448,7 +1439,7 @@ unsigned int onion_getfriend_DHT_pubkey(const Onion_Client *onion_c, int friend_      return 1;  } -/* Get the ip of friend friendnum and put it in ip_port +/** Get the ip of friend friendnum and put it in ip_port   *   *  return -1, -- if public_key does NOT refer to a friend   *  return  0, -- if public_key refers to a friend and we failed to find the friend (yet) @@ -1467,7 +1458,7 @@ int onion_getfriendip(const Onion_Client *onion_c, int friend_num, IP_Port *ip_p  } -/* Set if friend is online or not. +/** Set if friend is online or not.   * NOTE: This function is there and should be used so that we don't send useless packets to the friend if he is online.   *   * is_online 1 means friend is online. @@ -1503,10 +1494,8 @@ static void populate_path_nodes(Onion_Client *onion_c)      unsigned int num_nodes = randfriends_nodes(onion_c->dht, nodes_list, MAX_FRIEND_CLIENTS); -    unsigned int i; - -    for (i = 0; i < num_nodes; ++i) { -        onion_add_path_node(onion_c, nodes_list[i].ip_port, nodes_list[i].public_key); +    for (unsigned int i = 0; i < num_nodes; ++i) { +        onion_add_path_node(onion_c, &nodes_list[i].ip_port, nodes_list[i].public_key);      }  } @@ -1515,10 +1504,9 @@ static void populate_path_nodes_tcp(Onion_Client *onion_c)      Node_format nodes_list[MAX_SENT_NODES];      unsigned int num_nodes = copy_connected_tcp_relays(onion_c->c, nodes_list, MAX_SENT_NODES); -    unsigned int i; -    for (i = 0; i < num_nodes; ++i) { -        onion_add_bs_path_node(onion_c, nodes_list[i].ip_port, nodes_list[i].public_key); +    for (unsigned int i = 0; i < num_nodes; ++i) { +        onion_add_bs_path_node(onion_c, &nodes_list[i].ip_port, nodes_list[i].public_key);      }  } @@ -1596,8 +1584,8 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)              }              if (mono_time_is_timeout(onion_c->mono_time, list_nodes[i].last_pinged, interval) -                    || (ping_random && random_u32() % (MAX_ONION_CLIENTS - i) == 0)) { -                if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, +                    || (ping_random && random_range_u32(MAX_ONION_CLIENTS - i) == 0)) { +                if (client_send_announce_request(onion_c, friendnum + 1, &list_nodes[i].ip_port,                                                   list_nodes[i].public_key, nullptr, -1) == 0) {                      list_nodes[i].last_pinged = mono_time_get(onion_c->mono_time);                      ++list_nodes[i].unsuccessful_pings; @@ -1614,13 +1602,11 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)                  n = (MAX_ONION_CLIENTS / 2);              } -            if (count <= random_u32() % MAX_ONION_CLIENTS) { +            if (count <= random_range_u32(MAX_ONION_CLIENTS)) {                  if (num_nodes != 0) { -                    unsigned int j; - -                    for (j = 0; j < n; ++j) { -                        const uint32_t num = random_u32() % num_nodes; -                        client_send_announce_request(onion_c, friendnum + 1, onion_c->path_nodes[num].ip_port, +                    for (unsigned int j = 0; j < n; ++j) { +                        const uint32_t num = random_range_u32(num_nodes); +                        client_send_announce_request(onion_c, friendnum + 1, &onion_c->path_nodes[num].ip_port,                                                       onion_c->path_nodes[num].public_key, nullptr, -1);                      } @@ -1649,7 +1635,7 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)  } -/* Function to call when onion data packet with contents beginning with byte is received. */ +/** Function to call when onion data packet with contents beginning with byte is received. */  void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_cb *cb, void *object)  {      onion_c->onion_data_handlers[byte].function = cb; @@ -1708,7 +1694,7 @@ static void do_announce(Onion_Client *onion_c)          if (mono_time_is_timeout(onion_c->mono_time, list_nodes[i].last_pinged, interval)                  || (mono_time_is_timeout(onion_c->mono_time, onion_c->last_announce, ONION_NODE_PING_INTERVAL) -                    && random_u32() % (MAX_ONION_CLIENTS_ANNOUNCE - i) == 0)) { +                    && random_range_u32(MAX_ONION_CLIENTS_ANNOUNCE - i) == 0)) {              uint32_t path_to_use = list_nodes[i].path_used;              if (list_nodes[i].unsuccessful_pings == ONION_NODE_MAX_PINGS - 1 @@ -1717,7 +1703,7 @@ static void do_announce(Onion_Client *onion_c)                  path_to_use = -1;              } -            if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].public_key, +            if (client_send_announce_request(onion_c, 0, &list_nodes[i].ip_port, list_nodes[i].public_key,                                               list_nodes[i].ping_id, path_to_use) == 0) {                  list_nodes[i].last_pinged = mono_time_get(onion_c->mono_time);                  ++list_nodes[i].unsuccessful_pings; @@ -1728,7 +1714,7 @@ static void do_announce(Onion_Client *onion_c)      if (count != MAX_ONION_CLIENTS_ANNOUNCE) {          uint16_t num_nodes; -        Node_format *path_nodes; +        const Node_format *path_nodes;          if (random_u08() % 2 == 0 || onion_c->path_nodes_index == 0) {              num_nodes = min_u16(onion_c->path_nodes_index_bs, MAX_PATH_NODES); @@ -1738,18 +1724,18 @@ static void do_announce(Onion_Client *onion_c)              path_nodes = onion_c->path_nodes;          } -        if (count <= random_u32() % MAX_ONION_CLIENTS_ANNOUNCE) { +        if (count <= random_range_u32(MAX_ONION_CLIENTS_ANNOUNCE)) {              if (num_nodes != 0) {                  for (unsigned int i = 0; i < (MAX_ONION_CLIENTS_ANNOUNCE / 2); ++i) { -                    const uint32_t num = random_u32() % num_nodes; -                    client_send_announce_request(onion_c, 0, path_nodes[num].ip_port, path_nodes[num].public_key, nullptr, -1); +                    const uint32_t num = random_range_u32(num_nodes); +                    client_send_announce_request(onion_c, 0, &path_nodes[num].ip_port, path_nodes[num].public_key, nullptr, -1);                  }              }          }      }  } -/*  return 0 if we are not connected to the network. +/**  return 0 if we are not connected to the network.   *  return 1 if we are.   */  static int onion_isconnected(const Onion_Client *onion_c) @@ -1794,7 +1780,7 @@ static int onion_isconnected(const Onion_Client *onion_c)  #define ONION_CONNECTION_SECONDS 3 -/*  return 0 if we are not connected to the network. +/**  return 0 if we are not connected to the network.   *  return 1 if we are connected with TCP only.   *  return 2 if we are also connected with UDP.   */ diff --git a/protocols/Tox/libtox/src/toxcore/onion_client.h b/protocols/Tox/libtox/src/toxcore/onion_client.h index c0f8f52c8b..c724e97344 100644 --- a/protocols/Tox/libtox/src/toxcore/onion_client.h +++ b/protocols/Tox/libtox/src/toxcore/onion_client.h @@ -3,7 +3,7 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * Implementation of the client part of docs/Prevent_Tracking.txt (The part that   * uses the onion stuff to connect to the friend)   */ @@ -19,13 +19,13 @@  #define ONION_NODE_PING_INTERVAL 15  #define ONION_NODE_TIMEOUT ONION_NODE_PING_INTERVAL -/* The interval in seconds at which to tell our friends where we are */ +/** The interval in seconds at which to tell our friends where we are */  #define ONION_DHTPK_SEND_INTERVAL 30  #define DHT_DHTPK_SEND_INTERVAL 20  #define NUMBER_ONION_PATHS 6 -/* The timeout the first time the path is added and +/** The timeout the first time the path is added and   * then for all the next consecutive times */  #define ONION_PATH_FIRST_TIMEOUT 4  #define ONION_PATH_TIMEOUT 10 @@ -39,14 +39,14 @@  #define MAX_PATH_NODES 32 -/* If no announce response packets are received within this interval tox will +/** If no announce response packets are received within this interval tox will   * be considered offline. We give time for a node to be pinged often enough   * that it times out, which leads to the network being thoroughly tested as it   * is replaced.   */  #define ONION_OFFLINE_TIMEOUT (ONION_NODE_PING_INTERVAL * (ONION_NODE_MAX_PINGS+2)) -/* Onion data packet ids. */ +/** Onion data packet ids. */  #define ONION_DATA_FRIEND_REQ CRYPTO_PACKET_FRIEND_REQ  #define ONION_DATA_DHTPK CRYPTO_PACKET_DHTPK @@ -55,41 +55,41 @@ typedef struct Onion_Client Onion_Client;  DHT *onion_get_dht(const Onion_Client *onion_c);  Net_Crypto *onion_get_net_crypto(const Onion_Client *onion_c); -/* Add a node to the path_nodes bootstrap array. +/** Add a node to the path_nodes bootstrap array.   *   * return -1 on failure   * return 0 on success   */ -int onion_add_bs_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *public_key); +int onion_add_bs_path_node(Onion_Client *onion_c, const IP_Port *ip_port, const uint8_t *public_key); -/* Put up to max_num nodes in nodes. +/** Put up to max_num nodes in nodes.   *   * return the number of nodes.   */  uint16_t onion_backup_nodes(const Onion_Client *onion_c, Node_format *nodes, uint16_t max_num); -/* Add a friend who we want to connect to. +/** Get the friend_num of a friend.   *   * return -1 on failure. - * return the friend number on success or if the friend was already added. + * return friend number on success.   */  int onion_friend_num(const Onion_Client *onion_c, const uint8_t *public_key); -/* Add a friend who we want to connect to. +/** Add a friend who we want to connect to.   *   * return -1 on failure. - * return the friend number on success. + * return the friend number on success or if the friend was already added.   */  int onion_addfriend(Onion_Client *onion_c, const uint8_t *public_key); -/* Delete a friend. +/** Delete a friend.   *   * return -1 on failure.   * return the deleted friend number on success.   */  int onion_delfriend(Onion_Client *onion_c, int friend_num); -/* Set if friend is online or not. +/** Set if friend is online or not.   * NOTE: This function is there and should be used so that we don't send useless packets to the friend if he is online.   *   * is_online 1 means friend is online. @@ -100,7 +100,7 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num);   */  int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_online); -/* Get the ip of friend friendnum and put it in ip_port +/** Get the ip of friend friendnum and put it in ip_port   *   *  return -1, -- if public_key does NOT refer to a friend   *  return  0, -- if public_key refers to a friend and we failed to find the friend (yet) @@ -109,9 +109,9 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on   */  int onion_getfriendip(const Onion_Client *onion_c, int friend_num, IP_Port *ip_port); -typedef int recv_tcp_relay_cb(void *object, uint32_t number, IP_Port ip_port, const uint8_t *public_key); +typedef int recv_tcp_relay_cb(void *object, uint32_t number, const IP_Port *ip_port, const uint8_t *public_key); -/* Set the function for this friend that will be callbacked with object and number +/** Set the function for this friend that will be callbacked with object and number   * when that friends gives us one of the TCP relays he is connected to.   *   * object and number will be passed as argument to this function. @@ -124,7 +124,7 @@ int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num,  typedef void onion_dht_pk_cb(void *data, int32_t number, const uint8_t *dht_public_key, void *userdata); -/* Set the function for this friend that will be callbacked with object and number +/** Set the function for this friend that will be callbacked with object and number   * when that friend gives us his DHT temporary public key.   *   * object and number will be passed as argument to this function. @@ -135,14 +135,14 @@ typedef void onion_dht_pk_cb(void *data, int32_t number, const uint8_t *dht_publ  int onion_dht_pk_callback(Onion_Client *onion_c, int friend_num, onion_dht_pk_cb *function, void *object,                            uint32_t number); -/* Set a friends DHT public key. +/** Set a friend's DHT public key.   *   * return -1 on failure.   * return 0 on success.   */  int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uint8_t *dht_key); -/* Copy friends DHT public key into dht_key. +/** Copy friends DHT public key into dht_key.   *   * return 0 on failure (no key copied).   * return 1 on success (key copied). @@ -152,7 +152,7 @@ unsigned int onion_getfriend_DHT_pubkey(const Onion_Client *onion_c, int friend_  #define ONION_DATA_IN_RESPONSE_MIN_SIZE (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE)  #define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE) -/* Send data of length length to friendnum. +/** Send data of length length to friendnum.   * Maximum length of data is ONION_CLIENT_MAX_DATA_SIZE.   * This data will be received by the friend using the Onion_Data_Handlers callbacks.   * @@ -166,7 +166,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data,  typedef int oniondata_handler_cb(void *object, const uint8_t *source_pubkey, const uint8_t *data,                                   uint16_t len, void *userdata); -/* Function to call when onion data packet with contents beginning with byte is received. */ +/** Function to call when onion data packet with contents beginning with byte is received. */  void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_cb *cb, void *object);  void do_onion_client(Onion_Client *onion_c); @@ -176,7 +176,7 @@ Onion_Client *new_onion_client(const Logger *logger, Mono_Time *mono_time, Net_C  void kill_onion_client(Onion_Client *onion_c); -/*  return 0 if we are not connected to the network. +/**  return 0 if we are not connected to the network.   *  return 1 if we are connected with TCP only.   *  return 2 if we are also connected with UDP.   */ diff --git a/protocols/Tox/libtox/src/toxcore/ping.api.h b/protocols/Tox/libtox/src/toxcore/ping.api.h deleted file mode 100644 index d4d071b11d..0000000000 --- a/protocols/Tox/libtox/src/toxcore/ping.api.h +++ /dev/null @@ -1,50 +0,0 @@ -%{ -/* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. - * Copyright © 2013 Tox project. - * Copyright © 2013 plutooo - */ - -/* - * Buffered pinging using cyclic arrays. - */ -#ifndef C_TOXCORE_TOXCORE_PING_H -#define C_TOXCORE_TOXCORE_PING_H - -#include "DHT.h" -#include "network.h" - -#include <stdint.h> -%} - -class iP_Port { struct this; } -class dHT { struct this; } -class mono_Time { struct this; } - -class ping { - -struct this; - -static this new(const mono_Time::this *mono_time, dHT::this *dht); -void kill(); - -/** Add nodes to the to_ping list. - * All nodes in this list are pinged every TIME_TOPING seconds - * and are then removed from the list. - * If the list is full the nodes farthest from our public_key are replaced. - * The purpose of this list is to enable quick integration of new nodes into the - * network while preventing amplification attacks. - * - *  return 0 if node was added. - *  return -1 if node was not added. - */ -int32_t add(const uint8_t *public_key, iP_Port::this ip_port); -void iterate(); - -int32_t send_request(iP_Port::this ipp, const uint8_t *public_key); - -} - -%{ -#endif // C_TOXCORE_TOXCORE_PING_H -%} diff --git a/protocols/Tox/libtox/src/toxcore/ping.c b/protocols/Tox/libtox/src/toxcore/ping.c index 305cce47c4..249d4a0647 100644 --- a/protocols/Tox/libtox/src/toxcore/ping.c +++ b/protocols/Tox/libtox/src/toxcore/ping.c @@ -4,13 +4,9 @@   * Copyright © 2013 plutooo   */ -/* +/**   * Buffered pinging using cyclic arrays.   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -  #include "ping.h"  #include <stdlib.h> @@ -24,10 +20,10 @@  #define PING_NUM_MAX 512 -/* Maximum newly announced nodes to ping per TIME_TO_PING seconds. */ +/** Maximum newly announced nodes to ping per TIME_TO_PING seconds. */  #define MAX_TO_PING 32 -/* Ping newly announced nodes to ping per TIME_TO_PING seconds*/ +/** Ping newly announced nodes to ping per TIME_TO_PING seconds*/  #define TIME_TO_PING 2 @@ -45,14 +41,14 @@ struct Ping {  #define DHT_PING_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + PING_PLAIN_SIZE + CRYPTO_MAC_SIZE)  #define PING_DATA_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port)) -int32_t ping_send_request(Ping *ping, IP_Port ipp, const uint8_t *public_key) +void ping_send_request(Ping *ping, const IP_Port *ipp, const uint8_t *public_key)  {      uint8_t   pk[DHT_PING_SIZE];      int       rc;      uint64_t  ping_id;      if (id_equal(public_key, dht_get_self_public_key(ping->dht))) { -        return 1; +        return;      }      uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; @@ -62,11 +58,12 @@ int32_t ping_send_request(Ping *ping, IP_Port ipp, const uint8_t *public_key)      // Generate random ping_id.      uint8_t data[PING_DATA_SIZE];      id_copy(data, public_key); -    memcpy(data + CRYPTO_PUBLIC_KEY_SIZE, &ipp, sizeof(IP_Port)); +    memcpy(data + CRYPTO_PUBLIC_KEY_SIZE, ipp, sizeof(IP_Port));      ping_id = ping_array_add(ping->ping_array, ping->mono_time, data, sizeof(data));      if (ping_id == 0) { -        return 1; +        crypto_memzero(shared_key, sizeof(shared_key)); +        return;      }      uint8_t ping_plain[PING_PLAIN_SIZE]; @@ -83,18 +80,20 @@ int32_t ping_send_request(Ping *ping, IP_Port ipp, const uint8_t *public_key)                                  ping_plain, sizeof(ping_plain),                                  pk + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); +    crypto_memzero(shared_key, sizeof(shared_key)); +      if (rc != PING_PLAIN_SIZE + CRYPTO_MAC_SIZE) { -        return 1; +        return;      } -    return sendpacket(dht_get_net(ping->dht), ipp, pk, sizeof(pk)); +    // We never check this return value and failures in sendpacket are already logged +    sendpacket(dht_get_net(ping->dht), ipp, pk, sizeof(pk));  } -static int ping_send_response(Ping *ping, IP_Port ipp, const uint8_t *public_key, uint64_t ping_id, -                              uint8_t *shared_encryption_key) +static int ping_send_response(const Ping *ping, const IP_Port *ipp, const uint8_t *public_key, +                              uint64_t ping_id, const uint8_t *shared_encryption_key)  { -    uint8_t   pk[DHT_PING_SIZE]; -    int       rc; +    uint8_t pk[DHT_PING_SIZE];      if (id_equal(public_key, dht_get_self_public_key(ping->dht))) {          return 1; @@ -109,10 +108,10 @@ static int ping_send_response(Ping *ping, IP_Port ipp, const uint8_t *public_key      random_nonce(pk + 1 + CRYPTO_PUBLIC_KEY_SIZE); // Generate new nonce      // Encrypt ping_id using recipient privkey -    rc = encrypt_data_symmetric(shared_encryption_key, -                                pk + 1 + CRYPTO_PUBLIC_KEY_SIZE, -                                ping_plain, sizeof(ping_plain), -                                pk + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); +    const int rc = encrypt_data_symmetric(shared_encryption_key, +                                          pk + 1 + CRYPTO_PUBLIC_KEY_SIZE, +                                          ping_plain, sizeof(ping_plain), +                                          pk + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);      if (rc != PING_PLAIN_SIZE + CRYPTO_MAC_SIZE) {          return 1; @@ -121,10 +120,10 @@ static int ping_send_response(Ping *ping, IP_Port ipp, const uint8_t *public_key      return sendpacket(dht_get_net(ping->dht), ipp, pk, sizeof(pk));  } -static int handle_ping_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) +static int handle_ping_request(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, +                               void *userdata)  { -    DHT       *dht = (DHT *)object; -    int        rc; +    DHT *dht = (DHT *)object;      if (length != DHT_PING_SIZE) {          return 1; @@ -137,34 +136,39 @@ static int handle_ping_request(void *object, IP_Port source, const uint8_t *pack      }      uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; -      uint8_t ping_plain[PING_PLAIN_SIZE]; +      // Decrypt ping_id      dht_get_shared_key_recv(dht, shared_key, packet + 1); -    rc = decrypt_data_symmetric(shared_key, -                                packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, -                                packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, -                                PING_PLAIN_SIZE + CRYPTO_MAC_SIZE, -                                ping_plain); +    const int rc = decrypt_data_symmetric(shared_key, +                                          packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, +                                          packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, +                                          PING_PLAIN_SIZE + CRYPTO_MAC_SIZE, +                                          ping_plain);      if (rc != sizeof(ping_plain)) { +        crypto_memzero(shared_key, sizeof(shared_key));          return 1;      }      if (ping_plain[0] != NET_PACKET_PING_REQUEST) { +        crypto_memzero(shared_key, sizeof(shared_key));          return 1;      } -    uint64_t   ping_id; +    uint64_t ping_id;      memcpy(&ping_id, ping_plain + 1, sizeof(ping_id));      // Send response      ping_send_response(ping, source, packet + 1, ping_id, shared_key);      ping_add(ping, packet + 1, source); +    crypto_memzero(shared_key, sizeof(shared_key)); +      return 0;  } -static int handle_ping_response(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) +static int handle_ping_response(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, +                                void *userdata)  {      DHT      *dht = (DHT *)object;      int       rc; @@ -192,6 +196,8 @@ static int handle_ping_response(void *object, IP_Port source, const uint8_t *pac                                  PING_PLAIN_SIZE + CRYPTO_MAC_SIZE,                                  ping_plain); +    crypto_memzero(shared_key, sizeof(shared_key)); +      if (rc != sizeof(ping_plain)) {          return 1;      } @@ -215,7 +221,7 @@ static int handle_ping_response(void *object, IP_Port source, const uint8_t *pac      IP_Port ipp;      memcpy(&ipp, data + CRYPTO_PUBLIC_KEY_SIZE, sizeof(IP_Port)); -    if (!ipport_equal(&ipp, &source)) { +    if (!ipport_equal(&ipp, source)) {          return 1;      } @@ -223,27 +229,26 @@ static int handle_ping_response(void *object, IP_Port source, const uint8_t *pac      return 0;  } -/* Check if public_key with ip_port is in the list. +/** Check if public_key with ip_port is in the list.   *   * return 1 if it is.   * return 0 if it isn't.   */  static int in_list(const Client_data *list, uint16_t length, const Mono_Time *mono_time, const uint8_t *public_key, -                   IP_Port ip_port) +                   const IP_Port *ip_port)  { -    unsigned int i; - -    for (i = 0; i < length; ++i) { +    for (unsigned int i = 0; i < length; ++i) {          if (id_equal(list[i].public_key, public_key)) {              const IPPTsPng *ipptp; -            if (net_family_is_ipv4(ip_port.ip.family)) { +            if (net_family_is_ipv4(ip_port->ip.family)) {                  ipptp = &list[i].assoc4;              } else {                  ipptp = &list[i].assoc6;              } -            if (!mono_time_is_timeout(mono_time, ipptp->timestamp, BAD_NODE_TIMEOUT) && ipport_equal(&ipptp->ip_port, &ip_port)) { +            if (!mono_time_is_timeout(mono_time, ipptp->timestamp, BAD_NODE_TIMEOUT) +                    && ipport_equal(&ipptp->ip_port, ip_port)) {                  return 1;              }          } @@ -252,7 +257,7 @@ static int in_list(const Client_data *list, uint16_t length, const Mono_Time *mo      return 0;  } -/* Add nodes to the to_ping list. +/** Add nodes to the to_ping list.   * All nodes in this list are pinged every TIME_TO_PING seconds   * and are then removed from the list.   * If the list is full the nodes farthest from our public_key are replaced. @@ -262,9 +267,9 @@ static int in_list(const Client_data *list, uint16_t length, const Mono_Time *mo   *  return 0 if node was added.   *  return -1 if node was not added.   */ -int32_t ping_add(Ping *ping, const uint8_t *public_key, IP_Port ip_port) +int32_t ping_add(Ping *ping, const uint8_t *public_key, const IP_Port *ip_port)  { -    if (!ip_isset(&ip_port.ip)) { +    if (!ip_isset(&ip_port->ip)) {          return -1;      } @@ -283,12 +288,10 @@ int32_t ping_add(Ping *ping, const uint8_t *public_key, IP_Port ip_port)          return -1;      } -    unsigned int i; - -    for (i = 0; i < MAX_TO_PING; ++i) { +    for (unsigned int i = 0; i < MAX_TO_PING; ++i) {          if (!ip_isset(&ping->to_ping[i].ip_port.ip)) {              memcpy(ping->to_ping[i].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); -            ipport_copy(&ping->to_ping[i].ip_port, &ip_port); +            ipport_copy(&ping->to_ping[i].ip_port, ip_port);              return 0;          } @@ -305,7 +308,7 @@ int32_t ping_add(Ping *ping, const uint8_t *public_key, IP_Port ip_port)  } -/* Ping all the valid nodes in the to_ping list every TIME_TO_PING seconds. +/** Ping all the valid nodes in the to_ping list every TIME_TO_PING seconds.   * This function must be run at least once every TIME_TO_PING seconds.   */  void ping_iterate(Ping *ping) @@ -325,11 +328,11 @@ void ping_iterate(Ping *ping)              break;          } -        if (!node_addable_to_close_list(ping->dht, ping->to_ping[i].public_key, ping->to_ping[i].ip_port)) { +        if (!node_addable_to_close_list(ping->dht, ping->to_ping[i].public_key, &ping->to_ping[i].ip_port)) {              continue;          } -        ping_send_request(ping, ping->to_ping[i].ip_port, ping->to_ping[i].public_key); +        ping_send_request(ping, &ping->to_ping[i].ip_port, ping->to_ping[i].public_key);          ip_reset(&ping->to_ping[i].ip_port.ip);      } diff --git a/protocols/Tox/libtox/src/toxcore/ping.h b/protocols/Tox/libtox/src/toxcore/ping.h index 9badd5aa1b..4e8192323a 100644 --- a/protocols/Tox/libtox/src/toxcore/ping.h +++ b/protocols/Tox/libtox/src/toxcore/ping.h @@ -4,43 +4,25 @@   * Copyright © 2013 plutooo   */ -/* +/**   * Buffered pinging using cyclic arrays.   */  #ifndef C_TOXCORE_TOXCORE_PING_H  #define C_TOXCORE_TOXCORE_PING_H -#include "DHT.h" -#include "network.h" -  #include <stdint.h> -#ifndef IP_PORT_DEFINED -#define IP_PORT_DEFINED -typedef struct IP_Port IP_Port; -#endif /* IP_PORT_DEFINED */ - -#ifndef DHT_DEFINED -#define DHT_DEFINED -typedef struct DHT DHT; -#endif /* DHT_DEFINED */ - -#ifndef MONO_TIME_DEFINED -#define MONO_TIME_DEFINED -typedef struct Mono_Time Mono_Time; -#endif /* MONO_TIME_DEFINED */ +#include "DHT.h" +#include "network.h" -#ifndef PING_DEFINED -#define PING_DEFINED  typedef struct Ping Ping; -#endif /* PING_DEFINED */  Ping *ping_new(const struct Mono_Time *mono_time, DHT *dht);  void ping_kill(Ping *ping);  /** Add nodes to the to_ping list. - * All nodes in this list are pinged every TIME_TOPING seconds + * All nodes in this list are pinged every TIME_TO_PING seconds   * and are then removed from the list.   * If the list is full the nodes farthest from our public_key are replaced.   * The purpose of this list is to enable quick integration of new nodes into the @@ -49,10 +31,10 @@ void ping_kill(Ping *ping);   *  return 0 if node was added.   *  return -1 if node was not added.   */ -int32_t ping_add(Ping *ping, const uint8_t *public_key, struct IP_Port ip_port); +int32_t ping_add(Ping *ping, const uint8_t *public_key, const IP_Port *ip_port);  void ping_iterate(Ping *ping); -int32_t ping_send_request(Ping *ping, struct IP_Port ipp, const uint8_t *public_key); +void ping_send_request(Ping *ping, const IP_Port *ipp, const uint8_t *public_key);  #endif // C_TOXCORE_TOXCORE_PING_H diff --git a/protocols/Tox/libtox/src/toxcore/ping_array.api.h b/protocols/Tox/libtox/src/toxcore/ping_array.api.h deleted file mode 100644 index d36e56dcf6..0000000000 --- a/protocols/Tox/libtox/src/toxcore/ping_array.api.h +++ /dev/null @@ -1,66 +0,0 @@ -%{ -/* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. - * Copyright © 2013 Tox project. - */ - -/* - * Implementation of an efficient array to store that we pinged something. - */ -#ifndef C_TOXCORE_TOXCORE_PING_ARRAY_H -#define C_TOXCORE_TOXCORE_PING_ARRAY_H - -#include <stddef.h> -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif -%} - -class mono_Time { struct this; } - -class ping { class array { - -struct this; - -/** - * Initialize a Ping_Array. - * - * @param size represents the total size of the array and should be a power of 2. - * @param timeout represents the maximum timeout in seconds for the entry. - * - * @return 0 on success, -1 on failure. - */ -static this new(uint32_t size, uint32_t timeout); - -/** - * Free all the allocated memory in a Ping_Array. - */ -void kill(); - -/** - * Add a data with length to the Ping_Array list and return a ping_id. - * - * @return ping_id on success, 0 on failure. - */ -uint64_t add(const mono_Time::this *mono_time, const uint8_t *data, uint32_t length); - -/** - * Check if ping_id is valid and not timed out. - * - * On success, copies the data into data of length, - * - * @return length of data copied on success, -1 on failure. - */ -int32_t check(const mono_Time::this *mono_time, uint8_t[length] data, uint64_t ping_id); - -} } - -%{ -#ifdef __cplusplus -}  // extern "C" -#endif - -#endif // C_TOXCORE_TOXCORE_PING_ARRAY_H -%} diff --git a/protocols/Tox/libtox/src/toxcore/ping_array.c b/protocols/Tox/libtox/src/toxcore/ping_array.c index 201b507d4c..fe067d2b29 100644 --- a/protocols/Tox/libtox/src/toxcore/ping_array.c +++ b/protocols/Tox/libtox/src/toxcore/ping_array.c @@ -3,13 +3,9 @@   * Copyright © 2014 Tox project.   */ -/* +/**   * Implementation of an efficient array to store that we pinged something.   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -  #include "ping_array.h"  #include <stdlib.h> @@ -20,7 +16,7 @@  #include "util.h"  typedef struct Ping_Array_Entry { -    void *data; +    uint8_t *data;      uint32_t length;      uint64_t time;      uint64_t ping_id; @@ -89,7 +85,7 @@ void ping_array_kill(Ping_Array *array)      free(array);  } -/* Clear timed out entries. +/** Clear timed out entries.   */  static void ping_array_clear_timedout(Ping_Array *array, const Mono_Time *mono_time)  { @@ -116,7 +112,7 @@ uint64_t ping_array_add(Ping_Array *array, const Mono_Time *mono_time, const uin          clear_entry(array, index);      } -    array->entries[index].data = malloc(length); +    array->entries[index].data = (uint8_t *)malloc(length);      if (array->entries[index].data == nullptr) {          return 0; diff --git a/protocols/Tox/libtox/src/toxcore/ping_array.h b/protocols/Tox/libtox/src/toxcore/ping_array.h index 70c517de9e..98dceaba0c 100644 --- a/protocols/Tox/libtox/src/toxcore/ping_array.h +++ b/protocols/Tox/libtox/src/toxcore/ping_array.h @@ -3,8 +3,8 @@   * Copyright © 2013 Tox project.   */ -/* - * Implementation of an efficient array to store that we pinged something. +/** @file + * @brief Implementation of an efficient array to store that we pinged something.   */  #ifndef C_TOXCORE_TOXCORE_PING_ARRAY_H  #define C_TOXCORE_TOXCORE_PING_ARRAY_H @@ -12,22 +12,16 @@  #include <stddef.h>  #include <stdint.h> +#include "mono_time.h" +  #ifdef __cplusplus  extern "C" {  #endif -#ifndef MONO_TIME_DEFINED -#define MONO_TIME_DEFINED -typedef struct Mono_Time Mono_Time; -#endif /* MONO_TIME_DEFINED */ - -#ifndef PING_ARRAY_DEFINED -#define PING_ARRAY_DEFINED  typedef struct Ping_Array Ping_Array; -#endif /* PING_ARRAY_DEFINED */  /** - * Initialize a Ping_Array. + * @brief Initialize a Ping_Array.   *   * @param size represents the total size of the array and should be a power of 2.   * @param timeout represents the maximum timeout in seconds for the entry. @@ -37,12 +31,12 @@ typedef struct Ping_Array Ping_Array;  struct Ping_Array *ping_array_new(uint32_t size, uint32_t timeout);  /** - * Free all the allocated memory in a Ping_Array. + * @brief Free all the allocated memory in a @ref Ping_Array.   */  void ping_array_kill(struct Ping_Array *array);  /** - * Add a data with length to the Ping_Array list and return a ping_id. + * @brief Add a data with length to the @ref Ping_Array list and return a ping_id.   *   * @return ping_id on success, 0 on failure.   */ @@ -50,7 +44,7 @@ uint64_t ping_array_add(struct Ping_Array *array, const struct Mono_Time *mono_t                          uint32_t length);  /** - * Check if ping_id is valid and not timed out. + * @brief Check if @p ping_id is valid and not timed out.   *   * On success, copies the data into data of length,   * diff --git a/protocols/Tox/libtox/src/toxcore/state.c b/protocols/Tox/libtox/src/toxcore/state.c index 13ae8e7189..a31768131a 100644 --- a/protocols/Tox/libtox/src/toxcore/state.c +++ b/protocols/Tox/libtox/src/toxcore/state.c @@ -6,7 +6,7 @@  #include <string.h> -/* state load/save */ +/** state load/save */  int state_load(const Logger *log, state_load_cb *state_load_callback, void *outer,                 const uint8_t *data, uint32_t length, uint16_t cookie_inner)  { @@ -34,7 +34,7 @@ int state_load(const Logger *log, state_load_cb *state_load_callback, void *oute              return -1;          } -        if (lendian_to_host16((cookie_type >> 16)) != cookie_inner) { +        if (lendian_to_host16(cookie_type >> 16) != cookie_inner) {              /* something is not matching up in a bad way, give up */              LOGGER_ERROR(log, "state file garbled: %04x != %04x", cookie_type >> 16, cookie_inner);              return -1; @@ -43,17 +43,20 @@ int state_load(const Logger *log, state_load_cb *state_load_callback, void *oute          const uint16_t type = lendian_to_host16(cookie_type & 0xFFFF);          switch (state_load_callback(outer, data, length_sub, type)) { -            case STATE_LOAD_STATUS_CONTINUE: +            case STATE_LOAD_STATUS_CONTINUE: {                  data += length_sub;                  length -= length_sub;                  break; +            } -            case STATE_LOAD_STATUS_ERROR: +            case STATE_LOAD_STATUS_ERROR: {                  LOGGER_ERROR(log, "Error occcured in state file (type: %u).", type);                  return -1; +            } -            case STATE_LOAD_STATUS_END: +            case STATE_LOAD_STATUS_END: {                  return 0; +            }          }      } diff --git a/protocols/Tox/libtox/src/toxcore/state.h b/protocols/Tox/libtox/src/toxcore/state.h index cbe97b49da..c539828b11 100644 --- a/protocols/Tox/libtox/src/toxcore/state.h +++ b/protocols/Tox/libtox/src/toxcore/state.h @@ -52,7 +52,7 @@ typedef enum State_Load_Status {  typedef State_Load_Status state_load_cb(void *outer, const uint8_t *data, uint32_t len, uint16_t type); -// state load/save +/** state load/save */  int state_load(const Logger *log, state_load_cb *state_load_callback, void *outer,                 const uint8_t *data, uint32_t length, uint16_t cookie_inner); diff --git a/protocols/Tox/libtox/src/toxcore/tox.api.h b/protocols/Tox/libtox/src/toxcore/tox.api.h deleted file mode 100644 index 90a6ffc8f8..0000000000 --- a/protocols/Tox/libtox/src/toxcore/tox.api.h +++ /dev/null @@ -1,2862 +0,0 @@ -%{ -/* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. - * Copyright © 2013 Tox project. - */ - -/* - * The Tox public API. - */ -#ifndef C_TOXCORE_TOXCORE_TOX_H -#define C_TOXCORE_TOXCORE_TOX_H - -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -//!TOKSTYLE- - -#ifdef __cplusplus -extern "C" { -#endif -%} - - -/***************************************************************************** - * `tox.h` SHOULD *NOT* BE EDITED MANUALLY – any changes should be made to   * - * `tox.api.h`, located in `toxcore/`. For instructions on how to            * - * generate `tox.h` from `tox.api.h` please refer to `docs/apidsl.md`        * - *****************************************************************************/ - - -/** - * @page core Public core API for Tox clients. - * - * Every function that can fail takes a function-specific error code pointer - * that can be used to diagnose problems with the Tox state or the function - * arguments. The error code pointer can be NULL, which does not influence the - * function's behaviour, but can be done if the reason for failure is irrelevant - * to the client. - * - * The exception to this rule are simple allocation functions whose only failure - * mode is allocation failure. They return NULL in that case, and do not set an - * error code. - * - * Every error code type has an OK value to which functions will set their error - * code value on success. Clients can keep their error code uninitialised before - * passing it to a function. The library guarantees that after returning, the - * value pointed to by the error code pointer has been initialised. - * - * Functions with pointer parameters often have a NULL error code, meaning they - * could not perform any operation, because one of the required parameters was - * NULL. Some functions operate correctly or are defined as effectless on NULL. - * - * Some functions additionally return a value outside their - * return type domain, or a bool containing true on success and false on - * failure. - * - * All functions that take a Tox instance pointer will cause undefined behaviour - * when passed a NULL Tox pointer. - * - * All integer values are expected in host byte order. - * - * Functions with parameters with enum types cause unspecified behaviour if the - * enumeration value is outside the valid range of the type. If possible, the - * function will try to use a sane default, but there will be no error code, - * and one possible action for the function to take is to have no effect. - * - * Integer constants and the memory layout of publicly exposed structs are not - * part of the ABI. - */ - -/** - * @subsection events Events and callbacks - * - * Events are handled by callbacks. One callback can be registered per event. - * All events have a callback function type named `tox_{event}_cb` and a - * function to register it named `tox_callback_{event}`. Passing a NULL - * callback will result in no callback being registered for that event. Only - * one callback per event can be registered, so if a client needs multiple - * event listeners, it needs to implement the dispatch functionality itself. - * - * The last argument to a callback is the user data pointer. It is passed from - * ${tox.iterate} to each callback in sequence. - * - * The user data pointer is never stored or dereferenced by any library code, so - * can be any pointer, including NULL. Callbacks must all operate on the same - * object type. In the apidsl code (tox.in.h), this is denoted with `any`. The - * `any` in ${tox.iterate} must be the same `any` as in all callbacks. In C, - * lacking parametric polymorphism, this is a pointer to void. - * - * Old style callbacks that are registered together with a user data pointer - * receive that pointer as argument when they are called. They can each have - * their own user data pointer of their own type. - */ - -/** - * @subsection threading Threading implications - * - * It is possible to run multiple concurrent threads with a Tox instance for - * each thread. It is also possible to run all Tox instances in the same thread. - * A common way to run Tox (multiple or single instance) is to have one thread - * running a simple ${tox.iterate} loop, sleeping for ${tox.iteration_interval} - * milliseconds on each iteration. - * - * If you want to access a single Tox instance from multiple threads, access - * to the instance must be synchronised. While multiple threads can concurrently - * access multiple different Tox instances, no more than one API function can - * operate on a single instance at any given time. - * - * Functions that write to variable length byte arrays will always have a size - * function associated with them. The result of this size function is only valid - * until another mutating function (one that takes a pointer to non-const Tox) - * is called. Thus, clients must ensure that no other thread calls a mutating - * function between the call to the size function and the call to the retrieval - * function. - * - * E.g. to get the current nickname, one would write - * - * @code - * size_t length = ${tox.self.name.size}(tox); - * uint8_t *name = malloc(length); - * if (!name) abort(); - * ${tox.self.name.get}(tox, name); - * @endcode - * - * If any other thread calls ${tox.self.name.set} while this thread is allocating - * memory, the length may have become invalid, and the call to - * ${tox.self.name.get} may cause undefined behaviour. - */ - -// The rest of this file is in class tox. -class tox { - -/** - * The Tox instance type. All the state associated with a connection is held - * within the instance. Multiple instances can exist and operate concurrently. - * The maximum number of Tox instances that can exist on a single network - * device is limited. Note that this is not just a per-process limit, since the - * limiting factor is the number of usable ports on a device. - */ -struct this; - - -/******************************************************************************* - * - * :: API version - * - ******************************************************************************/ - - -/** - * The major version number. Incremented when the API or ABI changes in an - * incompatible way. - * - * The function variants of these constants return the version number of the - * library. They can be used to display the Tox library version or to check - * whether the client is compatible with the dynamically linked version of Tox. - */ -const VERSION_MAJOR                = 0; - -/** - * The minor version number. Incremented when functionality is added without - * breaking the API or ABI. Set to 0 when the major version number is - * incremented. - */ -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                = 13; - -/** - * A macro to check at preprocessing time whether the client code is compatible - * with the installed version of Tox. Leading zeros in the version number are - * ignored. E.g. 0.1.5 is to 0.1.4 what 1.5 is to 1.4, that is: it can add new - * features, but can't break the API. - */ -#define TOX_VERSION_IS_API_COMPATIBLE(MAJOR, MINOR, PATCH)              \ -  ((TOX_VERSION_MAJOR > 0 && TOX_VERSION_MAJOR == MAJOR) && (           \ -    /* 1.x.x, 2.x.x, etc. with matching major version. */               \ -    TOX_VERSION_MINOR > MINOR ||                                        \ -    (TOX_VERSION_MINOR == MINOR && TOX_VERSION_PATCH >= PATCH)          \ -  )) || ((TOX_VERSION_MAJOR == 0 && MAJOR == 0) && (                    \ -    /* 0.x.x makes minor behave like major above. */                    \ -    ((TOX_VERSION_MINOR > 0 && TOX_VERSION_MINOR == MINOR) && (         \ -      TOX_VERSION_PATCH >= PATCH                                        \ -    )) || ((TOX_VERSION_MINOR == 0 && MINOR == 0) && (                  \ -      /* 0.0.x and 0.0.y are only compatible if x == y. */              \ -      TOX_VERSION_PATCH == PATCH                                        \ -    ))                                                                  \ -  )) - -static namespace version { - -  /** -   * Return whether the compiled library version is compatible with the passed -   * version numbers. -   */ -  bool is_compatible(uint32_t major, uint32_t minor, uint32_t patch); - -} - -/** - * A convenience macro to call tox_version_is_compatible with the currently - * compiling API version. - */ -#define TOX_VERSION_IS_ABI_COMPATIBLE()                         \ -  tox_version_is_compatible(TOX_VERSION_MAJOR, TOX_VERSION_MINOR, TOX_VERSION_PATCH) - -/******************************************************************************* - * - * :: Numeric constants - * - * The values of these are not part of the ABI. Prefer to use the function - * versions of them for code that should remain compatible with future versions - * of toxcore. - * - ******************************************************************************/ - - -/** - * The size of a Tox Public Key in bytes. - */ -const PUBLIC_KEY_SIZE              = 32; - -/** - * The size of a Tox Secret Key in bytes. - */ -const SECRET_KEY_SIZE              = 32; - -/** - * The size of a Tox Conference unique id in bytes. - * - * @deprecated Use $CONFERENCE_ID_SIZE instead. - */ -const CONFERENCE_UID_SIZE          = 32; - -/** - * The size of a Tox Conference unique id in bytes. - */ -const CONFERENCE_ID_SIZE           = 32; - -/** - * The size of the nospam in bytes when written in a Tox address. - */ -const NOSPAM_SIZE                  = sizeof(uint32_t); - -/** - * The size of a Tox address in bytes. Tox addresses are in the format - * [Public Key ($PUBLIC_KEY_SIZE bytes)][nospam (4 bytes)][checksum (2 bytes)]. - * - * The checksum is computed over the Public Key and the nospam value. The first - * byte is an XOR of all the even bytes (0, 2, 4, ...), the second byte is an - * XOR of all the odd bytes (1, 3, 5, ...) of the Public Key and nospam. - */ -const ADDRESS_SIZE                = PUBLIC_KEY_SIZE + NOSPAM_SIZE + sizeof(uint16_t); - -/** - * Maximum length of a nickname in bytes. - * - * @deprecated The macro will be removed in 0.3.0. Use the function instead. - */ -const MAX_NAME_LENGTH             = 128; - -/** - * Maximum length of a status message in bytes. - * - * @deprecated The macro will be removed in 0.3.0. Use the function instead. - */ -const MAX_STATUS_MESSAGE_LENGTH   = 1007; - -/** - * Maximum length of a friend request message in bytes. - * - * @deprecated The macro will be removed in 0.3.0. Use the function instead. - */ -const MAX_FRIEND_REQUEST_LENGTH   = 1016; - -/** - * Maximum length of a single message after which it should be split. - * - * @deprecated The macro will be removed in 0.3.0. Use the function instead. - */ -const MAX_MESSAGE_LENGTH          = 1372; - -/** - * Maximum size of custom packets. TODO(iphydf): should be LENGTH? - * - * @deprecated The macro will be removed in 0.3.0. Use the function instead. - */ -const MAX_CUSTOM_PACKET_SIZE      = 1373; - -/** - * The number of bytes in a hash generated by $hash. - */ -const HASH_LENGTH                 = 32; - -/** - * The number of bytes in a file id. - */ -const FILE_ID_LENGTH              = 32; - -/** - * Maximum file name length for file transfers. - * - * @deprecated The macro will be removed in 0.3.0. Use the function instead. - */ -const MAX_FILENAME_LENGTH         = 255; - -/** - * Maximum length of a hostname, e.g. proxy or bootstrap node names. - * - * This length does not include the NUL byte. Hostnames are NUL-terminated C - * strings, so they are 255 characters plus one NUL byte. - * - * @deprecated The macro will be removed in 0.3.0. Use the function instead. - */ -const MAX_HOSTNAME_LENGTH         = 255; - - -/******************************************************************************* - * - * :: Global enumerations - * - ******************************************************************************/ - - -/** - * Represents the possible statuses a client can have. - * - * @deprecated All UPPER_CASE enum type names are deprecated. Use the - *   Camel_Snake_Case versions, instead. - */ -enum class USER_STATUS { -  /** -   * User is online and available. -   */ -  NONE, -  /** -   * User is away. Clients can set this e.g. after a user defined -   * inactivity time. -   */ -  AWAY, -  /** -   * User is busy. Signals to other clients that this client does not -   * currently wish to communicate. -   */ -  BUSY, -} - - -/** - * Represents message types for ${tox.friend.send.message} and conference - * messages. - * - * @deprecated All UPPER_CASE enum type names are deprecated. Use the - *   Camel_Snake_Case versions, instead. - */ -enum class MESSAGE_TYPE { -  /** -   * Normal text message. Similar to PRIVMSG on IRC. -   */ -  NORMAL, -  /** -   * A message describing an user action. This is similar to /me (CTCP ACTION) -   * on IRC. -   */ -  ACTION, -} - - -/******************************************************************************* - * - * :: Startup options - * - ******************************************************************************/ - - -/** - * Type of proxy used to connect to TCP relays. - * - * @deprecated All UPPER_CASE enum type names are deprecated. Use the - *   Camel_Snake_Case versions, instead. - */ -enum class PROXY_TYPE { -  /** -   * Don't use a proxy. -   */ -  NONE, -  /** -   * HTTP proxy using CONNECT. -   */ -  HTTP, -  /** -   * SOCKS proxy for simple socket pipes. -   */ -  SOCKS5, -} - -/** - * Type of savedata to create the Tox instance from. - * - * @deprecated All UPPER_CASE enum type names are deprecated. Use the - *   Camel_Snake_Case versions, instead. - */ -enum class SAVEDATA_TYPE { -  /** -   * No savedata. -   */ -  NONE, -  /** -   * Savedata is one that was obtained from ${savedata.get}. -   */ -  TOX_SAVE, -  /** -   * Savedata is a secret key of length $SECRET_KEY_SIZE. -   */ -  SECRET_KEY, -} - - -/** - * Severity level of log messages. - * - * @deprecated All UPPER_CASE enum type names are deprecated. Use the - *   Camel_Snake_Case versions, instead. - */ -enum class LOG_LEVEL { -  /** -   * Very detailed traces including all network activity. -   */ -  TRACE, -  /** -   * Debug messages such as which port we bind to. -   */ -  DEBUG, -  /** -   * Informational log messages such as video call status changes. -   */ -  INFO, -  /** -   * Warnings about internal inconsistency or logic errors. -   */ -  WARNING, -  /** -   * Severe unexpected errors caused by external or internal inconsistency. -   */ -  ERROR, -} - -/** - * This event is triggered when the toxcore library logs an internal message. - * This is mostly useful for debugging. This callback can be called from any - * function, not just $iterate. This means the user data lifetime must at - * least extend between registering and unregistering it or $kill. - * - * Other toxcore modules such as toxav may concurrently call this callback at - * any time. Thus, user code must make sure it is equipped to handle concurrent - * execution, e.g. by employing appropriate mutex locking. - * - * @param level The severity of the log message. - * @param file The source file from which the message originated. - * @param line The source line from which the message originated. - * @param func The function from which the message originated. - * @param message The log message. - * @param user_data The user data pointer passed to $new in options. - */ -typedef void log_cb(LOG_LEVEL level, string file, uint32_t line, string func, string message, any user_data); - - -static class options { -  /** -   * This struct contains all the startup options for Tox. You must $new to -   * allocate an object of this type. -   * -   * WARNING: Although this struct happens to be visible in the API, it is -   * effectively private. Do not allocate this yourself or access members -   * directly, as it *will* break binary compatibility frequently. -   * -   * @deprecated The memory layout of this struct (size, alignment, and field -   * order) is not part of the ABI. To remain compatible, prefer to use $new to -   * allocate the object and accessor functions to set the members. The struct -   * will become opaque (i.e. the definition will become private) in v0.3.0. -   */ -  struct this [get, set] { -    /** -     * The type of socket to create. -     * -     * If this is set to false, an IPv4 socket is created, which subsequently -     * only allows IPv4 communication. -     * If it is set to true, an IPv6 socket is created, allowing both IPv4 and -     * IPv6 communication. -     */ -    bool ipv6_enabled; - -    /** -     * Enable the use of UDP communication when available. -     * -     * Setting this to false will force Tox to use TCP only. Communications will -     * need to be relayed through a TCP relay node, potentially slowing them down. -     * -     * If a proxy is enabled, UDP will be disabled if either toxcore or the -     * proxy don't support proxying UDP messages. -     */ -    bool udp_enabled; - -    /** -     * Enable local network peer discovery. -     * -     * Disabling this will cause Tox to not look for peers on the local network. -     */ -    bool local_discovery_enabled; - -    namespace proxy { -      /** -       * Pass communications through a proxy. -       */ -      PROXY_TYPE type; - -      /** -       * The IP address or DNS name of the proxy to be used. -       * -       * If used, this must be non-NULL and be a valid DNS name. The name must not -       * exceed $MAX_HOSTNAME_LENGTH characters, and be in a NUL-terminated C string -       * format ($MAX_HOSTNAME_LENGTH includes the NUL byte). -       * -       * This member is ignored (it can be NULL) if proxy_type is ${PROXY_TYPE.NONE}. -       * -       * The data pointed at by this member is owned by the user, so must -       * outlive the options object. -       */ -      string host; - -      /** -       * The port to use to connect to the proxy server. -       * -       * Ports must be in the range (1, 65535). The value is ignored if -       * proxy_type is ${PROXY_TYPE.NONE}. -       */ -      uint16_t port; -    } - -    /** -     * The start port of the inclusive port range to attempt to use. -     * -     * If both start_port and end_port are 0, the default port range will be -     * used: [33445, 33545]. -     * -     * If either start_port or end_port is 0 while the other is non-zero, the -     * non-zero port will be the only port in the range. -     * -     * Having start_port > end_port will yield the same behavior as if start_port -     * and end_port were swapped. -     */ -    uint16_t start_port; - -    /** -     * The end port of the inclusive port range to attempt to use. -     */ -    uint16_t end_port; - -    /** -     * The port to use for the TCP server (relay). If 0, the TCP server is -     * disabled. -     * -     * Enabling it is not required for Tox to function properly. -     * -     * When enabled, your Tox instance can act as a TCP relay for other Tox -     * instance. This leads to increased traffic, thus when writing a client -     * it is recommended to enable TCP server only if the user has an option -     * to disable it. -     */ -    uint16_t tcp_port; - -    /** -     * Enables or disables UDP hole-punching in toxcore. (Default: enabled). -     */ -    bool hole_punching_enabled; - -    namespace savedata { -      /** -       * The type of savedata to load from. -       */ -      SAVEDATA_TYPE type; - -      /** -       * The savedata. -       * -       * The data pointed at by this member is owned by the user, so must -       * outlive the options object. -       */ -      const uint8_t[length] data; - -      /** -       * The length of the savedata. -       */ -      size_t length; -    } - -    namespace log { -      /** -       * Logging callback for the new tox instance. -       */ -      log_cb *callback; - -      /** -       * User data pointer passed to the logging callback. -       */ -      any user_data; -    } - -    /** -     * These options are experimental, so avoid writing code that depends on -     * them. Options marked "experimental" may change their behaviour or go away -     * entirely in the future, or may be renamed to something non-experimental -     * if they become part of the supported API. -     */ -    namespace experimental { -      /** -       * Make public API functions thread-safe using a per-instance lock. -       * -       * Default: false. -       */ -      bool thread_safety; -    } -  } - - -  /** -   * Initialises a $this object with the default options. -   * -   * The result of this function is independent of the original options. All -   * values will be overwritten, no values will be read (so it is permissible -   * to pass an uninitialised object). -   * -   * If options is NULL, this function has no effect. -   * -   * @param options An options object to be filled with default options. -   */ -  void default(); - - -  /** -   * Allocates a new $this object and initialises it with the default -   * options. This function can be used to preserve long term ABI compatibility by -   * giving the responsibility of allocation and deallocation to the Tox library. -   * -   * Objects returned from this function must be freed using the $free -   * function. -   * -   * @return A new $this object with default options or NULL on failure. -   */ -  static this new() { -    /** -     * The function failed to allocate enough memory for the options struct. -     */ -    MALLOC, -  } - - -  /** -   * Releases all resources associated with an options objects. -   * -   * Passing a pointer that was not returned by $new results in -   * undefined behaviour. -   */ -  void free(); -} - - -/******************************************************************************* - * - * :: Creation and destruction - * - ******************************************************************************/ - - -/** - * @brief Creates and initialises a new Tox instance with the options passed. - * - * This function will bring the instance into a valid state. Running the event - * loop with a new instance will operate correctly. - * - * If loading failed or succeeded only partially, the new or partially loaded - * instance is returned and an error code is set. - * - * @param options An options object as described above. If this parameter is - *   NULL, the default options are used. - * - * @see $iterate for the event loop. - * - * @return A new Tox instance pointer on success or NULL on failure. - */ -static this new(const options_t *options) { -  NULL, -  /** -   * The function was unable to allocate enough memory to store the internal -   * structures for the Tox object. -   */ -  MALLOC, -  /** -   * The function was unable to bind to a port. This may mean that all ports -   * have already been bound, e.g. by other Tox instances, or it may mean -   * a permission error. You may be able to gather more information from errno. -   */ -  PORT_ALLOC, - -  namespace PROXY { -    /** -     * proxy_type was invalid. -     */ -    BAD_TYPE, -    /** -     * proxy_type was valid but the proxy_host passed had an invalid format -     * or was NULL. -     */ -    BAD_HOST, -    /** -     * proxy_type was valid, but the proxy_port was invalid. -     */ -    BAD_PORT, -    /** -     * The proxy address passed could not be resolved. -     */ -    NOT_FOUND, -  } - -  namespace LOAD { -    /** -     * The byte array to be loaded contained an encrypted save. -     */ -    ENCRYPTED, -    /** -     * The data format was invalid. This can happen when loading data that was -     * saved by an older version of Tox, or when the data has been corrupted. -     * When loading from badly formatted data, some data may have been loaded, -     * and the rest is discarded. Passing an invalid length parameter also -     * causes this error. -     */ -    BAD_FORMAT, -  } -} - - -/** - * Releases all resources associated with the Tox instance and disconnects from - * the network. - * - * After calling this function, the Tox pointer becomes invalid. No other - * functions can be called, and the pointer value can no longer be read. - */ -void kill(); - - -uint8_t[size] savedata { -  /** -   * Calculates the number of bytes required to store the tox instance with -   * $get. This function cannot fail. The result is always greater than 0. -   * -   * @see threading for concurrency implications. -   */ -  size(); - -  /** -   * Store all information associated with the tox instance to a byte array. -   * -   * @param savedata A memory region large enough to store the tox instance -   *   data. Call $size to find the number of bytes required. If this parameter -   *   is NULL, this function has no effect. -   */ -  get(); -} - - -/******************************************************************************* - * - * :: Connection lifecycle and event loop - * - ******************************************************************************/ - - -/** - * Sends a "get nodes" request to the given bootstrap node with IP, port, and - * public key to setup connections. - * - * This function will attempt to connect to the node using UDP. You must use - * this function even if ${options.this.udp_enabled} was set to false. - * - * @param host The hostname or IP address (IPv4 or IPv6) of the node. Must be - *   at most $MAX_HOSTNAME_LENGTH chars, including the NUL byte. - * @param port The port on the host on which the bootstrap Tox instance is - *   listening. - * @param public_key The long term public key of the bootstrap node - *   ($PUBLIC_KEY_SIZE bytes). - * @return true on success. - */ -bool bootstrap(string host, uint16_t port, const uint8_t[PUBLIC_KEY_SIZE] public_key) { -  NULL, -  /** -   * The hostname could not be resolved to an IP address, or the IP address -   * passed was invalid. -   */ -  BAD_HOST, -  /** -   * The port passed was invalid. The valid port range is (1, 65535). -   */ -  BAD_PORT, -} - - -/** - * Adds additional host:port pair as TCP relay. - * - * This function can be used to initiate TCP connections to different ports on - * the same bootstrap node, or to add TCP relays without using them as - * bootstrap nodes. - * - * @param host The hostname or IP address (IPv4 or IPv6) of the TCP relay. - *   Must be at most $MAX_HOSTNAME_LENGTH chars, including the NUL byte. - * @param port The port on the host on which the TCP relay is listening. - * @param public_key The long term public key of the TCP relay - *   ($PUBLIC_KEY_SIZE bytes). - * @return true on success. - */ -bool add_tcp_relay(string host, uint16_t port, const uint8_t[PUBLIC_KEY_SIZE] public_key) -    with error for bootstrap; - - -/** - * Protocols that can be used to connect to the network or friends. - * - * @deprecated All UPPER_CASE enum type names are deprecated. Use the - *   Camel_Snake_Case versions, instead. - */ -enum class CONNECTION { -  /** -   * There is no connection. This instance, or the friend the state change is -   * about, is now offline. -   */ -  NONE, -  /** -   * A TCP connection has been established. For the own instance, this means it -   * is connected through a TCP relay, only. For a friend, this means that the -   * connection to that particular friend goes through a TCP relay. -   */ -  TCP, -  /** -   * A UDP connection has been established. For the own instance, this means it -   * is able to send UDP packets to DHT nodes, but may still be connected to -   * a TCP relay. For a friend, this means that the connection to that -   * particular friend was built using direct UDP packets. -   */ -  UDP, -} - - -namespace self { - -  CONNECTION connection_status { -    /** -     * Return whether we are connected to the DHT. The return value is equal to the -     * last value received through the `${event connection_status}` callback. -     * -     * @deprecated This getter is deprecated. Use the event and store the status -     * in the client state. -     */ -    get(); -  } - - -  /** -   * This event is triggered whenever there is a change in the DHT connection -   * state. When disconnected, a client may choose to call $bootstrap again, to -   * reconnect to the DHT. Note that this state may frequently change for short -   * amounts of time. Clients should therefore not immediately bootstrap on -   * receiving a disconnect. -   * -   * TODO(iphydf): how long should a client wait before bootstrapping again? -   */ -  event connection_status const { -    /** -     * @param connection_status Whether we are connected to the DHT. -     */ -    typedef void(CONNECTION connection_status); -  } - -} - - -/** - * Return the time in milliseconds before $iterate() should be called again - * for optimal performance. - */ -const uint32_t iteration_interval(); - - -/** - * The main loop that needs to be run in intervals of $iteration_interval() - * milliseconds. - */ -void iterate(any user_data); - - -/******************************************************************************* - * - * :: Internal client information (Tox address/id) - * - ******************************************************************************/ - - -namespace self { - -  uint8_t[ADDRESS_SIZE] address { -    /** -     * Writes the Tox friend address of the client to a byte array. The address is -     * not in human-readable format. If a client wants to display the address, -     * formatting is required. -     * -     * @param address A memory region of at least $ADDRESS_SIZE bytes. If this -     *   parameter is NULL, this function has no effect. -     * @see $ADDRESS_SIZE for the address format. -     */ -    get(); -  } - - -  uint32_t nospam { -    /** -     * Set the 4-byte nospam part of the address. This value is expected in host -     * byte order. I.e. 0x12345678 will form the bytes [12, 34, 56, 78] in the -     * nospam part of the Tox friend address. -     * -     * @param nospam Any 32 bit unsigned integer. -     */ -    set(); - -    /** -     * Get the 4-byte nospam part of the address. This value is returned in host -     * byte order. -     */ -    get(); -  } - - -  uint8_t[PUBLIC_KEY_SIZE] public_key { -    /** -     * Copy the Tox Public Key (long term) from the Tox object. -     * -     * @param public_key A memory region of at least $PUBLIC_KEY_SIZE bytes. If -     *   this parameter is NULL, this function has no effect. -     */ -    get(); -  } - - -  uint8_t[SECRET_KEY_SIZE] secret_key { -    /** -     * Copy the Tox Secret Key from the Tox object. -     * -     * @param secret_key A memory region of at least $SECRET_KEY_SIZE bytes. If -     *   this parameter is NULL, this function has no effect. -     */ -    get(); -  } - -} - - -/******************************************************************************* - * - * :: User-visible client information (nickname/status) - * - ******************************************************************************/ - - -/** - * Common error codes for all functions that set a piece of user-visible - * client information. - */ -error for set_info { -  NULL, -  /** -   * Information length exceeded maximum permissible size. -   */ -  TOO_LONG, -} - - -namespace self { - -  uint8_t[length <= MAX_NAME_LENGTH] name { -    /** -     * Set the nickname for the Tox client. -     * -     * Nickname length cannot exceed $MAX_NAME_LENGTH. If length is 0, the name -     * parameter is ignored (it can be NULL), and the nickname is set back to empty. -     * -     * @param name A byte array containing the new nickname. -     * @param length The size of the name byte array. -     * -     * @return true on success. -     */ -    set() with error for set_info; - -    /** -     * Return the length of the current nickname as passed to $set. -     * -     * If no nickname was set before calling this function, the name is empty, -     * and this function returns 0. -     * -     * @see threading for concurrency implications. -     */ -    size(); - -    /** -     * Write the nickname set by $set to a byte array. -     * -     * If no nickname was set before calling this function, the name is empty, -     * and this function has no effect. -     * -     * Call $size to find out how much memory to allocate for -     * the result. -     * -     * @param name A valid memory location large enough to hold the nickname. -     *   If this parameter is NULL, the function has no effect. -     */ -    get(); -  } - - -  uint8_t[length <= MAX_STATUS_MESSAGE_LENGTH] status_message { -    /** -     * Set the client's status message. -     * -     * Status message length cannot exceed $MAX_STATUS_MESSAGE_LENGTH. If -     * length is 0, the status parameter is ignored (it can be NULL), and the -     * user status is set back to empty. -     */ -    set() with error for set_info; - -    /** -     * Return the length of the current status message as passed to $set. -     * -     * If no status message was set before calling this function, the status -     * is empty, and this function returns 0. -     * -     * @see threading for concurrency implications. -     */ -    size(); - -    /** -     * Write the status message set by $set to a byte array. -     * -     * If no status message was set before calling this function, the status is -     * empty, and this function has no effect. -     * -     * Call $size to find out how much memory to allocate for -     * the result. -     * -     * @param status_message A valid memory location large enough to hold the -     *   status message. If this parameter is NULL, the function has no effect. -     */ -    get(); -  } - - -  USER_STATUS status { -    /** -     * Set the client's user status. -     * -     * @param status One of the user statuses listed in the enumeration above. -     */ -    set(); - -    /** -     * Returns the client's user status. -     */ -    get(); -  } - -} - - -/******************************************************************************* - * - * :: Friend list management - * - ******************************************************************************/ - - -namespace friend { - -  /** -   * Add a friend to the friend list and send a friend request. -   * -   * A friend request message must be at least 1 byte long and at most -   * $MAX_FRIEND_REQUEST_LENGTH. -   * -   * Friend numbers are unique identifiers used in all functions that operate on -   * friends. Once added, a friend number is stable for the lifetime of the Tox -   * object. After saving the state and reloading it, the friend numbers may not -   * be the same as before. Deleting a friend creates a gap in the friend number -   * set, which is filled by the next adding of a friend. Any pattern in friend -   * numbers should not be relied on. -   * -   * If more than INT32_MAX friends are added, this function causes undefined -   * behaviour. -   * -   * @param address The address of the friend (returned by ${self.address.get} of -   *   the friend you wish to add) it must be $ADDRESS_SIZE bytes. -   * @param message The message that will be sent along with the friend request. -   * @param length The length of the data byte array. -   * -   * @return the friend number on success, an unspecified value on failure. -   */ -  uint32_t add( -      const uint8_t[ADDRESS_SIZE] address, -      const uint8_t[length <= MAX_FRIEND_REQUEST_LENGTH] message -  ) { -    NULL, -    /** -     * The length of the friend request message exceeded -     * $MAX_FRIEND_REQUEST_LENGTH. -     */ -    TOO_LONG, -    /** -     * The friend request message was empty. This, and the TOO_LONG code will -     * never be returned from $add_norequest. -     */ -    NO_MESSAGE, -    /** -     * The friend address belongs to the sending client. -     */ -    OWN_KEY, -    /** -     * A friend request has already been sent, or the address belongs to a friend -     * that is already on the friend list. -     */ -    ALREADY_SENT, -    /** -     * The friend address checksum failed. -     */ -    BAD_CHECKSUM, -    /** -     * The friend was already there, but the nospam value was different. -     */ -    SET_NEW_NOSPAM, -    /** -     * A memory allocation failed when trying to increase the friend list size. -     */ -    MALLOC, -  } - - -  /** -   * Add a friend without sending a friend request. -   * -   * This function is used to add a friend in response to a friend request. If the -   * client receives a friend request, it can be reasonably sure that the other -   * client added this client as a friend, eliminating the need for a friend -   * request. -   * -   * This function is also useful in a situation where both instances are -   * controlled by the same entity, so that this entity can perform the mutual -   * friend adding. In this case, there is no need for a friend request, either. -   * -   * @param public_key A byte array of length $PUBLIC_KEY_SIZE containing the -   *   Public Key (not the Address) of the friend to add. -   * -   * @return the friend number on success, an unspecified value on failure. -   * @see $add for a more detailed description of friend numbers. -   */ -  uint32_t add_norequest(const uint8_t[PUBLIC_KEY_SIZE] public_key) -      with error for add; - - -  /** -   * Remove a friend from the friend list. -   * -   * This does not notify the friend of their deletion. After calling this -   * function, this client will appear offline to the friend and no communication -   * can occur between the two. -   * -   * @param friend_number Friend number for the friend to be deleted. -   * -   * @return true on success. -   */ -  bool delete(uint32_t friend_number) { -    /** -     * There was no friend with the given friend number. No friends were deleted. -     */ -    FRIEND_NOT_FOUND, -  } - -} - - -/******************************************************************************* - * - * :: Friend list queries - * - ******************************************************************************/ - -namespace friend { - -  /** -   * Return the friend number associated with that Public Key. -   * -   * @return the friend number on success, an unspecified value on failure. -   * @param public_key A byte array containing the Public Key. -   */ -  const uint32_t by_public_key(const uint8_t[PUBLIC_KEY_SIZE] public_key) { -    NULL, -    /** -     * No friend with the given Public Key exists on the friend list. -     */ -    NOT_FOUND, -  } - - -  /** -   * Checks if a friend with the given friend number exists and returns true if -   * it does. -   */ -  const bool exists(uint32_t friend_number); - -} - -namespace self { - -  uint32_t[size] friend_list { -    /** -     * Return the number of friends on the friend list. -     * -     * This function can be used to determine how much memory to allocate for -     * $get. -     */ -    size(); - - -    /** -     * Copy a list of valid friend numbers into an array. -     * -     * Call $size to determine the number of elements to allocate. -     * -     * @param friend_list A memory region with enough space to hold the friend -     *   list. If this parameter is NULL, this function has no effect. -     */ -    get(); -  } - -} - - - -namespace friend { - -  uint8_t[PUBLIC_KEY_SIZE] public_key { -    /** -     * Copies the Public Key associated with a given friend number to a byte array. -     * -     * @param friend_number The friend number you want the Public Key of. -     * @param public_key A memory region of at least $PUBLIC_KEY_SIZE bytes. If -     *   this parameter is NULL, this function has no effect. -     * -     * @return true on success. -     */ -    get(uint32_t friend_number) { -      /** -       * No friend with the given number exists on the friend list. -       */ -      FRIEND_NOT_FOUND, -    } -  } - -} - -namespace friend { - -  uint64_t last_online { -    /** -     * Return a unix-time timestamp of the last time the friend associated with a given -     * friend number was seen online. This function will return UINT64_MAX on error. -     * -     * @param friend_number The friend number you want to query. -     */ -    get(uint32_t friend_number) { -      /** -       * No friend with the given number exists on the friend list. -       */ -      FRIEND_NOT_FOUND, -    } -  } - -} - -/******************************************************************************* - * - * :: Friend-specific state queries (can also be received through callbacks) - * - ******************************************************************************/ - - -namespace friend { - -  /** -   * Common error codes for friend state query functions. -   */ -  error for query { -    /** -     * The pointer parameter for storing the query result (name, message) was -     * NULL. Unlike the `_self_` variants of these functions, which have no effect -     * when a parameter is NULL, these functions return an error in that case. -     */ -    NULL, -    /** -     * The friend_number did not designate a valid friend. -     */ -    FRIEND_NOT_FOUND, -  } - - -  uint8_t[length <= MAX_NAME_LENGTH] name { -    /** -     * Return the length of the friend's name. If the friend number is invalid, the -     * return value is unspecified. -     * -     * The return value is equal to the `length` argument received by the last -     * `${event name}` callback. -     */ -    size(uint32_t friend_number) -        with error for query; - -    /** -     * Write the name of the friend designated by the given friend number to a byte -     * array. -     * -     * Call $size to determine the allocation size for the `name` -     * parameter. -     * -     * The data written to `name` is equal to the data received by the last -     * `${event name}` callback. -     * -     * @param name A valid memory region large enough to store the friend's name. -     * -     * @return true on success. -     */ -    get(uint32_t friend_number) -        with error for query; -  } - - -  /** -   * This event is triggered when a friend changes their name. -   */ -  event name const { -    /** -     * @param friend_number The friend number of the friend whose name changed. -     * @param name A byte array containing the same data as -     *   ${name.get} would write to its `name` parameter. -     * @param length A value equal to the return value of -     *   ${name.size}. -     */ -    typedef void(uint32_t friend_number, const uint8_t[length <= MAX_NAME_LENGTH] name); -  } - - -  uint8_t[length <= MAX_STATUS_MESSAGE_LENGTH] status_message { -    /** -     * Return the length of the friend's status message. If the friend number is -     * invalid, the return value is SIZE_MAX. -     */ -    size(uint32_t friend_number) -        with error for query; - -    /** -     * Write the status message of the friend designated by the given friend number to a byte -     * array. -     * -     * Call $size to determine the allocation size for the `status_message` -     * parameter. -     * -     * The data written to `status_message` is equal to the data received by the last -     * `${event status_message}` callback. -     * -     * @param status_message A valid memory region large enough to store the friend's status message. -     */ -    get(uint32_t friend_number) -        with error for query; -  } - - -  /** -   * This event is triggered when a friend changes their status message. -   */ -  event status_message const { -    /** -     * @param friend_number The friend number of the friend whose status message -     *   changed. -     * @param message A byte array containing the same data as -     *   ${status_message.get} would write to its `status_message` parameter. -     * @param length A value equal to the return value of -     *   ${status_message.size}. -     */ -    typedef void(uint32_t friend_number, const uint8_t[length <= MAX_STATUS_MESSAGE_LENGTH] message); -  } - - -  USER_STATUS status { -    /** -     * Return the friend's user status (away/busy/...). If the friend number is -     * invalid, the return value is unspecified. -     * -     * The status returned is equal to the last status received through the -     * `${event status}` callback. -     * -     * @deprecated This getter is deprecated. Use the event and store the status -     *   in the client state. -     */ -    get(uint32_t friend_number) -        with error for query; -  } - - -  /** -   * This event is triggered when a friend changes their user status. -   */ -  event status const { -    /** -     * @param friend_number The friend number of the friend whose user status -     *   changed. -     * @param status The new user status. -     */ -    typedef void(uint32_t friend_number, USER_STATUS status); -  } - - -  CONNECTION connection_status { -    /** -     * Check whether a friend is currently connected to this client. -     * -     * The result of this function is equal to the last value received by the -     * `${event connection_status}` callback. -     * -     * @param friend_number The friend number for which to query the connection -     *   status. -     * -     * @return the friend's connection status as it was received through the -     *   `${event connection_status}` event. -     * -     * @deprecated This getter is deprecated. Use the event and store the status -     *   in the client state. -     */ -    get(uint32_t friend_number) -        with error for query; -  } - - -  /** -   * This event is triggered when a friend goes offline after having been online, -   * or when a friend goes online. -   * -   * This callback is not called when adding friends. It is assumed that when -   * adding friends, their connection status is initially offline. -   */ -  event connection_status const { -    /** -     * @param friend_number The friend number of the friend whose connection status -     *   changed. -     * @param connection_status The result of calling -     *   ${connection_status.get} on the passed friend_number. -     */ -    typedef void(uint32_t friend_number, CONNECTION connection_status); -  } - - -  bool typing { -    /** -     * Check whether a friend is currently typing a message. -     * -     * @param friend_number The friend number for which to query the typing status. -     * -     * @return true if the friend is typing. -     * @return false if the friend is not typing, or the friend number was -     *   invalid. Inspect the error code to determine which case it is. -     * -     * @deprecated This getter is deprecated. Use the event and store the status -     *   in the client state. -     */ -    get(uint32_t friend_number) -        with error for query; -  } - - -  /** -   * This event is triggered when a friend starts or stops typing. -   */ -  event typing const { -    /** -     * @param friend_number The friend number of the friend who started or stopped -     *   typing. -     * @param is_typing The result of calling ${typing.get} on the passed -     *   friend_number. -     */ -    typedef void(uint32_t friend_number, bool is_typing); -  } - -} - - -/******************************************************************************* - * - * :: Sending private messages - * - ******************************************************************************/ - -error for set_typing { -  /** -   * The friend number did not designate a valid friend. -   */ -  FRIEND_NOT_FOUND, -} - -namespace self { - -  bool typing { -    /** -     * Set the client's typing status for a friend. -     * -     * The client is responsible for turning it on or off. -     * -     * @param friend_number The friend to which the client is typing a message. -     * @param typing The typing status. True means the client is typing. -     * -     * @return true on success. -     */ -    set(uint32_t friend_number) with error for set_typing; -  } - -} - - -namespace friend { - -  namespace send { - -    /** -     * Send a text chat message to an online friend. -     * -     * This function creates a chat message packet and pushes it into the send -     * queue. -     * -     * The message length may not exceed $MAX_MESSAGE_LENGTH. Larger messages -     * must be split by the client and sent as separate messages. Other clients can -     * then reassemble the fragments. Messages may not be empty. -     * -     * The return value of this function is the message ID. If a read receipt is -     * received, the triggered `${event read_receipt}` event will be passed this message ID. -     * -     * Message IDs are unique per friend. The first message ID is 0. Message IDs are -     * incremented by 1 each time a message is sent. If UINT32_MAX messages were -     * sent, the next message ID is 0. -     * -     * @param type Message type (normal, action, ...). -     * @param friend_number The friend number of the friend to send the message to. -     * @param message A non-NULL pointer to the first element of a byte array -     *   containing the message text. -     * @param length Length of the message to be sent. -     */ -    uint32_t message(uint32_t friend_number, MESSAGE_TYPE type, -                     const uint8_t[length <= MAX_MESSAGE_LENGTH] message) { -      NULL, -      /** -       * The friend number did not designate a valid friend. -       */ -      FRIEND_NOT_FOUND, -      /** -       * This client is currently not connected to the friend. -       */ -      FRIEND_NOT_CONNECTED, -      /** -       * An allocation error occurred while increasing the send queue size. -       */ -      SENDQ, -      /** -       * Message length exceeded $MAX_MESSAGE_LENGTH. -       */ -      TOO_LONG, -      /** -       * Attempted to send a zero-length message. -       */ -      EMPTY, -    } - -  } - - -  /** -   * This event is triggered when the friend receives the message sent with -   * ${send.message} with the corresponding message ID. -   */ -  event read_receipt const { -    /** -     * @param friend_number The friend number of the friend who received the message. -     * @param message_id The message ID as returned from ${send.message} -     *   corresponding to the message sent. -     */ -    typedef void(uint32_t friend_number, uint32_t message_id); -  } - -} - - -/******************************************************************************* - * - * :: Receiving private messages and friend requests - * - ******************************************************************************/ - - -namespace friend { - -  /** -   * This event is triggered when a friend request is received. -   */ -  event request const { -    /** -     * @param public_key The Public Key of the user who sent the friend request. -     * @param message The message they sent along with the request. -     * @param length The size of the message byte array. -     */ -    typedef void(const uint8_t[PUBLIC_KEY_SIZE] public_key, -                 const uint8_t[length <= MAX_MESSAGE_LENGTH] message); -  } - - -  /** -   * This event is triggered when a message from a friend is received. -   */ -  event message const { -    /** -     * @param friend_number The friend number of the friend who sent the message. -     * @param message The message data they sent. -     * @param length The size of the message byte array. -     */ -    typedef void(uint32_t friend_number, MESSAGE_TYPE type, -                 const uint8_t[length <= MAX_MESSAGE_LENGTH] message); -  } - -} - - -/******************************************************************************* - * - * :: File transmission: common between sending and receiving - * - ******************************************************************************/ - - -/** - * Generates a cryptographic hash of the given data. - * - * This function may be used by clients for any purpose, but is provided - * primarily for validating cached avatars. This use is highly recommended to - * avoid unnecessary avatar updates. - * - * If hash is NULL or data is NULL while length is not 0 the function returns false, - * otherwise it returns true. - * - * This function is a wrapper to internal message-digest functions. - * - * @param hash A valid memory location the hash data. It must be at least - *   $HASH_LENGTH bytes in size. - * @param data Data to be hashed or NULL. - * @param length Size of the data array or 0. - * - * @return true if hash was not NULL. - */ -static bool hash(uint8_t[HASH_LENGTH] hash, const uint8_t[length] data); - - -namespace file { - -  /** -   * A list of pre-defined file kinds. Toxcore itself does not behave -   * differently for different file kinds. These are a hint to the client -   * telling it what use the sender intended for the file. The `kind` parameter -   * in the send function and recv callback are `uint32_t`, not $KIND, because -   * clients can invent their own file kind. Unknown file kinds should be -   * treated as ${KIND.DATA}. -   */ -  enum KIND { -    /** -     * Arbitrary file data. Clients can choose to handle it based on the file name -     * or magic or any other way they choose. -     */ -    DATA, -    /** -     * Avatar file_id. This consists of $hash(image). -     * Avatar data. This consists of the image data. -     * -     * Avatars can be sent at any time the client wishes. Generally, a client will -     * send the avatar to a friend when that friend comes online, and to all -     * friends when the avatar changed. A client can save some traffic by -     * remembering which friend received the updated avatar already and only send -     * it if the friend has an out of date avatar. -     * -     * Clients who receive avatar send requests can reject it (by sending -     * ${CONTROL.CANCEL} before any other controls), or accept it (by -     * sending ${CONTROL.RESUME}). The file_id of length $HASH_LENGTH bytes -     * (same length as $FILE_ID_LENGTH) will contain the hash. A client can compare -     * this hash with a saved hash and send ${CONTROL.CANCEL} to terminate the avatar -     * transfer if it matches. -     * -     * When file_size is set to 0 in the transfer request it means that the client -     * has no avatar. -     */ -    AVATAR, -  } - - -  enum class CONTROL { -    /** -     * Sent by the receiving side to accept a file send request. Also sent after a -     * $PAUSE command to continue sending or receiving. -     */ -    RESUME, -    /** -     * Sent by clients to pause the file transfer. The initial state of a file -     * transfer is always paused on the receiving side and running on the sending -     * side. If both the sending and receiving side pause the transfer, then both -     * need to send $RESUME for the transfer to resume. -     */ -    PAUSE, -    /** -     * Sent by the receiving side to reject a file send request before any other -     * commands are sent. Also sent by either side to terminate a file transfer. -     */ -    CANCEL, -  } - - -  /** -   * Sends a file control command to a friend for a given file transfer. -   * -   * @param friend_number The friend number of the friend the file is being -   *   transferred to or received from. -   * @param file_number The friend-specific identifier for the file transfer. -   * @param control The control command to send. -   * -   * @return true on success. -   */ -  bool control(uint32_t friend_number, uint32_t file_number, CONTROL control) { -    /** -     * The friend_number passed did not designate a valid friend. -     */ -    FRIEND_NOT_FOUND, -    /** -     * This client is currently not connected to the friend. -     */ -    FRIEND_NOT_CONNECTED, -    /** -     * No file transfer with the given file number was found for the given friend. -     */ -    NOT_FOUND, -    /** -     * A RESUME control was sent, but the file transfer is running normally. -     */ -    NOT_PAUSED, -    /** -     * A RESUME control was sent, but the file transfer was paused by the other -     * party. Only the party that paused the transfer can resume it. -     */ -    DENIED, -    /** -     * A PAUSE control was sent, but the file transfer was already paused. -     */ -    ALREADY_PAUSED, -    /** -     * Packet queue is full. -     */ -    SENDQ, -  } - - -  /** -   * This event is triggered when a file control command is received from a -   * friend. -   */ -  event recv_control const { -    /** -     * When receiving ${CONTROL.CANCEL}, the client should release the -     * resources associated with the file number and consider the transfer failed. -     * -     * @param friend_number The friend number of the friend who is sending the file. -     * @param file_number The friend-specific file number the data received is -     *   associated with. -     * @param control The file control command received. -     */ -    typedef void(uint32_t friend_number, uint32_t file_number, CONTROL control); -  } - -  /** -   * Sends a file seek control command to a friend for a given file transfer. -   * -   * This function can only be called to resume a file transfer right before -   * ${CONTROL.RESUME} is sent. -   * -   * @param friend_number The friend number of the friend the file is being -   *   received from. -   * @param file_number The friend-specific identifier for the file transfer. -   * @param position The position that the file should be seeked to. -   */ -  bool seek(uint32_t friend_number, uint32_t file_number, uint64_t position) { -    /** -     * The friend_number passed did not designate a valid friend. -     */ -    FRIEND_NOT_FOUND, -    /** -     * This client is currently not connected to the friend. -     */ -    FRIEND_NOT_CONNECTED, -    /** -     * No file transfer with the given file number was found for the given friend. -     */ -    NOT_FOUND, -    /** -     * File was not in a state where it could be seeked. -     */ -    DENIED, -    /** -     * Seek position was invalid -     */ -    INVALID_POSITION, -    /** -     * Packet queue is full. -     */ -    SENDQ, -  } - - -  error for get { -    NULL, -    /** -     * The friend_number passed did not designate a valid friend. -     */ -    FRIEND_NOT_FOUND, -    /** -     * No file transfer with the given file number was found for the given friend. -     */ -    NOT_FOUND, -  } - -  uint8_t[FILE_ID_LENGTH] file_id { -    /** -     * Copy the file id associated to the file transfer to a byte array. -     * -     * @param friend_number The friend number of the friend the file is being -     *   transferred to or received from. -     * @param file_number The friend-specific identifier for the file transfer. -     * @param file_id A memory region of at least $FILE_ID_LENGTH bytes. If -     *   this parameter is NULL, this function has no effect. -     * -     * @return true on success. -     */ -    get(uint32_t friend_number, uint32_t file_number) -        with error for get; -  } - -} - - -/******************************************************************************* - * - * :: File transmission: sending - * - ******************************************************************************/ - - -namespace file { - -  /** -   * Send a file transmission request. -   * -   * Maximum filename length is $MAX_FILENAME_LENGTH bytes. The filename -   * should generally just be a file name, not a path with directory names. -   * -   * If a non-UINT64_MAX file size is provided, it can be used by both sides to -   * determine the sending progress. File size can be set to UINT64_MAX for streaming -   * data of unknown size. -   * -   * File transmission occurs in chunks, which are requested through the -   * `${event chunk_request}` event. -   * -   * When a friend goes offline, all file transfers associated with the friend are -   * purged from core. -   * -   * If the file contents change during a transfer, the behaviour is unspecified -   * in general. What will actually happen depends on the mode in which the file -   * was modified and how the client determines the file size. -   * -   * - If the file size was increased -   *   - and sending mode was streaming (file_size = UINT64_MAX), the behaviour -   *     will be as expected. -   *   - and sending mode was file (file_size != UINT64_MAX), the -   *     ${event chunk_request} callback will receive length = 0 when Core thinks -   *     the file transfer has finished. If the client remembers the file size as -   *     it was when sending the request, it will terminate the transfer normally. -   *     If the client re-reads the size, it will think the friend cancelled the -   *     transfer. -   * - If the file size was decreased -   *   - and sending mode was streaming, the behaviour is as expected. -   *   - and sending mode was file, the callback will return 0 at the new -   *     (earlier) end-of-file, signalling to the friend that the transfer was -   *     cancelled. -   * - If the file contents were modified -   *   - at a position before the current read, the two files (local and remote) -   *     will differ after the transfer terminates. -   *   - at a position after the current read, the file transfer will succeed as -   *     expected. -   *   - In either case, both sides will regard the transfer as complete and -   *     successful. -   * -   * @param friend_number The friend number of the friend the file send request -   *   should be sent to. -   * @param kind The meaning of the file to be sent. -   * @param file_size Size in bytes of the file the client wants to send, UINT64_MAX if -   *   unknown or streaming. -   * @param file_id A file identifier of length $FILE_ID_LENGTH that can be used to -   *   uniquely identify file transfers across core restarts. If NULL, a random one will -   *   be generated by core. It can then be obtained by using ${file_id.get}(). -   * @param filename Name of the file. Does not need to be the actual name. This -   *   name will be sent along with the file send request. -   * @param filename_length Size in bytes of the filename. -   * -   * @return A file number used as an identifier in subsequent callbacks. This -   *   number is per friend. File numbers are reused after a transfer terminates. -   *   On failure, this function returns an unspecified value. Any pattern in file numbers -   *   should not be relied on. -   */ -  uint32_t send(uint32_t friend_number, uint32_t kind, uint64_t file_size, -                const uint8_t[FILE_ID_LENGTH] file_id, -                const uint8_t[filename_length <= MAX_FILENAME_LENGTH] filename) { -    NULL, -    /** -     * The friend_number passed did not designate a valid friend. -     */ -    FRIEND_NOT_FOUND, -    /** -     * This client is currently not connected to the friend. -     */ -    FRIEND_NOT_CONNECTED, -    /** -     * Filename length exceeded $MAX_FILENAME_LENGTH bytes. -     */ -    NAME_TOO_LONG, -    /** -     * Too many ongoing transfers. The maximum number of concurrent file transfers -     * is 256 per friend per direction (sending and receiving). -     */ -    TOO_MANY, -  } - - -  /** -   * Send a chunk of file data to a friend. -   * -   * This function is called in response to the `${event chunk_request}` callback. The -   * length parameter should be equal to the one received though the callback. -   * If it is zero, the transfer is assumed complete. For files with known size, -   * Core will know that the transfer is complete after the last byte has been -   * received, so it is not necessary (though not harmful) to send a zero-length -   * chunk to terminate. For streams, core will know that the transfer is finished -   * if a chunk with length less than the length requested in the callback is sent. -   * -   * @param friend_number The friend number of the receiving friend for this file. -   * @param file_number The file transfer identifier returned by tox_file_send. -   * @param position The file or stream position from which to continue reading. -   * @return true on success. -   */ -  bool send_chunk(uint32_t friend_number, uint32_t file_number, uint64_t position, const uint8_t[length] data) { -    /** -     * The length parameter was non-zero, but data was NULL. -     */ -    NULL, -    /** -     * The friend_number passed did not designate a valid friend. -     */ -    FRIEND_NOT_FOUND, -    /** -     * This client is currently not connected to the friend. -     */ -    FRIEND_NOT_CONNECTED, -    /** -     * No file transfer with the given file number was found for the given friend. -     */ -    NOT_FOUND, -    /** -     * File transfer was found but isn't in a transferring state: (paused, done, -     * broken, etc...) (happens only when not called from the request chunk callback). -     */ -    NOT_TRANSFERRING, -    /** -     * Attempted to send more or less data than requested. The requested data size is -     * adjusted according to maximum transmission unit and the expected end of -     * the file. Trying to send less or more than requested will return this error. -     */ -    INVALID_LENGTH, -    /** -     * Packet queue is full. -     */ -    SENDQ, -    /** -     * Position parameter was wrong. -     */ -    WRONG_POSITION, -  } - - -  /** -   * This event is triggered when Core is ready to send more file data. -   */ -  event chunk_request const { -    /** -     * If the length parameter is 0, the file transfer is finished, and the client's -     * resources associated with the file number should be released. After a call -     * with zero length, the file number can be reused for future file transfers. -     * -     * If the requested position is not equal to the client's idea of the current -     * file or stream position, it will need to seek. In case of read-once streams, -     * the client should keep the last read chunk so that a seek back can be -     * supported. A seek-back only ever needs to read from the last requested chunk. -     * This happens when a chunk was requested, but the send failed. A seek-back -     * request can occur an arbitrary number of times for any given chunk. -     * -     * In response to receiving this callback, the client should call the function -     * `$send_chunk` with the requested chunk. If the number of bytes sent -     * through that function is zero, the file transfer is assumed complete. A -     * client must send the full length of data requested with this callback. -     * -     * @param friend_number The friend number of the receiving friend for this file. -     * @param file_number The file transfer identifier returned by $send. -     * @param position The file or stream position from which to continue reading. -     * @param length The number of bytes requested for the current chunk. -     */ -    typedef void(uint32_t friend_number, uint32_t file_number, uint64_t position, size_t length); -  } - -} - - -/******************************************************************************* - * - * :: File transmission: receiving - * - ******************************************************************************/ - - -namespace file { - -  /** -   * This event is triggered when a file transfer request is received. -   */ -  event recv const { -    /** -     * The client should acquire resources to be associated with the file transfer. -     * Incoming file transfers start in the PAUSED state. After this callback -     * returns, a transfer can be rejected by sending a ${CONTROL.CANCEL} -     * control command before any other control commands. It can be accepted by -     * sending ${CONTROL.RESUME}. -     * -     * @param friend_number The friend number of the friend who is sending the file -     *   transfer request. -     * @param file_number The friend-specific file number the data received is -     *   associated with. -     * @param kind The meaning of the file that was sent. -     * @param file_size Size in bytes of the file the client wants to send, -     *   UINT64_MAX if unknown or streaming. -     * @param filename Name of the file. Does not need to be the actual name. This -     *   name will be sent along with the file send request. -     * @param filename_length Size in bytes of the filename. -     */ -    typedef void(uint32_t friend_number, uint32_t file_number, uint32_t kind, -                 uint64_t file_size, const uint8_t[filename_length <= MAX_FILENAME_LENGTH] filename); -  } - - -  /** -   * This event is first triggered when a file transfer request is received, and -   * subsequently when a chunk of file data for an accepted request was received. -   */ -  event recv_chunk const { -    /** -     * When length is 0, the transfer is finished and the client should release the -     * resources it acquired for the transfer. After a call with length = 0, the -     * file number can be reused for new file transfers. -     * -     * If position is equal to file_size (received in the file_receive callback) -     * when the transfer finishes, the file was received completely. Otherwise, if -     * file_size was UINT64_MAX, streaming ended successfully when length is 0. -     * -     * @param friend_number The friend number of the friend who is sending the file. -     * @param file_number The friend-specific file number the data received is -     *   associated with. -     * @param position The file position of the first byte in data. -     * @param data A byte array containing the received chunk. -     * @param length The length of the received chunk. -     */ -    typedef void(uint32_t friend_number, uint32_t file_number, uint64_t position, -                 const uint8_t[length] data); -  } - -} - - -/******************************************************************************* - * - * :: Conference management - * - ******************************************************************************/ - -namespace conference { - -  /** -   * Conference types for the ${event invite} event. -   * -   * @deprecated All UPPER_CASE enum type names are deprecated. Use the -   *   Camel_Snake_Case versions, instead. -   */ -  enum class TYPE { -    /** -     * Text-only conferences that must be accepted with the $join function. -     */ -    TEXT, -    /** -     * Video conference. The function to accept these is in toxav. -     */ -    AV, -  } - - -  /** -   * This event is triggered when the client is invited to join a conference. -   */ -  event invite const { -    /** -     * The invitation will remain valid until the inviting friend goes offline -     * or exits the conference. -     * -     * @param friend_number The friend who invited us. -     * @param type The conference type (text only or audio/video). -     * @param cookie A piece of data of variable length required to join the -     *   conference. -     * @param length The length of the cookie. -     */ -    typedef void(uint32_t friend_number, TYPE type, const uint8_t[length] cookie); -  } - - -  /** -   * This event is triggered when the client successfully connects to a -   * conference after joining it with the $join function. -   */ -  event connected const { -    /** -     * @param conference_number The conference number of the conference to which we have connected. -     */ -    typedef void(uint32_t conference_number); -  } - - -  /** -   * This event is triggered when the client receives a conference message. -   */ -  event message const { -    /** -     * @param conference_number The conference number of the conference the message is intended for. -     * @param peer_number The ID of the peer who sent the message. -     * @param type The type of message (normal, action, ...). -     * @param message The message data. -     * @param length The length of the message. -     */ -    typedef void(uint32_t conference_number, uint32_t peer_number, MESSAGE_TYPE type, -                 const uint8_t[length] message); -  } - - -  /** -   * This event is triggered when a peer changes the conference title. -   * -   * If peer_number == UINT32_MAX, then author is unknown (e.g. initial joining the conference). -   */ -  event title const { -    /** -     * @param conference_number The conference number of the conference the title change is intended for. -     * @param peer_number The ID of the peer who changed the title. -     * @param title The title data. -     * @param length The title length. -     */ -    typedef void(uint32_t conference_number, uint32_t peer_number, const uint8_t[length] title); -  } - -  namespace peer { - -    /** -     * This event is triggered when a peer changes their name. -     */ -    event name const { -      /** -       * @param conference_number The conference number of the conference the -       *   peer is in. -       * @param peer_number The ID of the peer who changed their nickname. -       * @param name A byte array containing the new nickname. -       * @param length The size of the name byte array. -       */ -      typedef void(uint32_t conference_number, uint32_t peer_number, const uint8_t[length] name); -    } - -    /** -     * This event is triggered when a peer joins or leaves the conference. -     */ -    event list_changed const { -      /** -       * @param conference_number The conference number of the conference the -       *   peer is in. -       */ -      typedef void(uint32_t conference_number); -    } - -  } - - -  /** -   * Creates a new conference. -   * -   * This function creates and connects to a new text conference. -   * -   * @return conference number on success, or an unspecified value on failure. -   */ -  uint32_t new() { -    /** -     * The conference instance failed to initialize. -     */ -    INIT, -  } - -  /** -   * This function deletes a conference. -   * -   * @param conference_number The conference number of the conference to be deleted. -   * -   * @return true on success. -   */ -  bool delete(uint32_t conference_number) { -    /** -     * The conference number passed did not designate a valid conference. -     */ -    CONFERENCE_NOT_FOUND, -  } - -  /** -   * Error codes for peer info queries. -   */ -  error for peer_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, -  } - - -  namespace peer { - -    /** -     * Return the number of online peers in the conference. The unsigned -     * integers less than this number are the valid values of peer_number for -     * the functions querying these peers. 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 peer's name. Return value is unspecified on failure. -       */ -      size(uint32_t conference_number, uint32_t peer_number) -          with error for peer_query; - -      /** -       * Copy the name of peer_number who is in conference_number to name. -       * -       * Call $size to determine the allocation size for the `name` parameter. -       * -       * @param name A valid memory region large enough to store the peer's name. -       * -       * @return true on success. -       */ -      get(uint32_t conference_number, uint32_t peer_number) -          with error for peer_query; -    } - -    /** -     * Copy the public key of 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 peer_number) -          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 peer_query; - -  } - -  namespace offline_peer { - -    /** -     * Return the number of offline peers in the conference. The unsigned -     * integers less than this number are the valid values of offline_peer_number for -     * the functions querying these peers. 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. -       * -       * Call $size to determine the allocation size for the `name` parameter. -       * -       * @param name A valid memory region large enough to store the peer's name. -       * -       * @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; -    } - -  } - -  /** -   * Set maximum number of offline peers to store, overriding the default. -   */ -  bool set_max_offline(uint32_t conference_number, uint32_t max_offline_peers) { -    /** -     * The conference number passed did not designate a valid conference. -     */ -    CONFERENCE_NOT_FOUND, -  } - - -  /** -   * Invites a friend to a conference. -   * -   * @param friend_number The friend number of the friend we want to invite. -   * @param conference_number The conference number of the conference we want to invite the friend to. -   * -   * @return true on success. -   */ -  bool invite(uint32_t friend_number, uint32_t conference_number) { -    /** -     * The conference number passed did not designate a valid conference. -     */ -    CONFERENCE_NOT_FOUND, -    /** -     * The invite packet failed to send. -     */ -    FAIL_SEND, -    /** -     * The client is not connected to the conference. -     */ -    NO_CONNECTION, -  } - - -  /** -   * Joins a conference that the client has been invited to. -   * -   * After successfully joining the conference, the client will not be "connected" -   * to it until a handshaking procedure has been completed. A -   * `${event connected}` event will then occur for the conference. The client -   * will then remain connected to the conference until the conference is deleted, -   * even across core restarts. Many operations on a conference will fail with a -   * corresponding error if attempted on a conference to which the client is not -   * yet connected. -   * -   * @param friend_number The friend number of the friend who sent the invite. -   * @param cookie Received via the `${event invite}` event. -   * @param length The size of cookie. -   * -   * @return conference number on success, an unspecified value on failure. -   */ -  uint32_t join(uint32_t friend_number, const uint8_t[length] cookie) { -    /** -     * The cookie passed has an invalid length. -     */ -    INVALID_LENGTH, -    /** -     * The conference is not the expected type. This indicates an invalid cookie. -     */ -    WRONG_TYPE, -    /** -     * The friend number passed does not designate a valid friend. -     */ -    FRIEND_NOT_FOUND, -    /** -     * Client is already in this conference. -     */ -    DUPLICATE, -    /** -     * Conference instance failed to initialize. -     */ -    INIT_FAIL, -    /** -     * The join packet failed to send. -     */ -    FAIL_SEND, -  } - - -  namespace send { - -    /** -     * Send a text chat message to the conference. -     * -     * This function creates a conference message packet and pushes it into the send -     * queue. -     * -     * The message length may not exceed $MAX_MESSAGE_LENGTH. Larger messages -     * must be split by the client and sent as separate messages. Other clients can -     * then reassemble the fragments. -     * -     * @param conference_number The conference number of the conference the message is intended for. -     * @param type Message type (normal, action, ...). -     * @param message A non-NULL pointer to the first element of a byte array -     *   containing the message text. -     * @param length Length of the message to be sent. -     * -     * @return true on success. -     */ -    bool message(uint32_t conference_number, MESSAGE_TYPE type, const uint8_t[length] message) { -      /** -       * The conference number passed did not designate a valid conference. -       */ -      CONFERENCE_NOT_FOUND, -      /** -       * The message is too long. -       */ -      TOO_LONG, -      /** -       * The client is not connected to the conference. -       */ -      NO_CONNECTION, -      /** -       * The message packet failed to send. -       */ -      FAIL_SEND, -    } -  } - -  error for title { -    /** -     * The conference number passed did not designate a valid conference. -     */ -    CONFERENCE_NOT_FOUND, -    /** -     * The title is too long or empty. -     */ -    INVALID_LENGTH, -    /** -     * The title packet failed to send. -     */ -    FAIL_SEND, -  } - -  uint8_t[length <= MAX_NAME_LENGTH] title { - -    /** -     * Return the length of the conference title. Return value is unspecified on failure. -     * -     * The return value is equal to the `length` argument received by the last -     * `${event title}` callback. -     */ -    size(uint32_t conference_number) -        with error for title; - -    /** -     * Write the title designated by the given conference number to a byte array. -     * -     * Call $size to determine the allocation size for the `title` parameter. -     * -     * The data written to `title` is equal to the data received by the last -     * `${event title}` callback. -     * -     * @param title A valid memory region large enough to store the title. -     *   If this parameter is NULL, this function has no effect. -     * -     * @return true on success. -     */ -    get(uint32_t conference_number) -        with error for title; - -    /** -     * Set the conference title and broadcast it to the rest of the conference. -     * -     * Title length cannot be longer than $MAX_NAME_LENGTH. -     * -     * @return true on success. -     */ -    set(uint32_t conference_number) -        with error for title; -  } - - -  uint32_t[size] chatlist { -    /** -     * Return the number of conferences in the Tox instance. -     * This should be used to determine how much memory to allocate for `$get`. -     */ -    size(); - -    /** -     * Copy a list of valid conference numbers into the array chatlist. Determine -     * how much space to allocate for the array with the `$size` function. -     * -     * Note that `${savedata.get}` saves all connected conferences; -     * when toxcore is created from savedata in which conferences were saved, those -     * conferences will be connected at startup, and will be listed by -     * `$get`. -     * -     * The conference number of a loaded conference may differ from the conference -     * number it had when it was saved. -     */ -    get(); -  } - - -  /** -   * Returns the type of conference ($TYPE) that conference_number is. Return value is -   * unspecified on failure. -   */ -  TYPE type { -    get(uint32_t conference_number) { -      /** -       * The conference number passed did not designate a valid conference. -       */ -      CONFERENCE_NOT_FOUND, -    } -  } - -  /** -   * Get the conference unique ID. -   * -   * If id is NULL, this function has no effect. -   * -   * @param id A memory region large enough to store $CONFERENCE_ID_SIZE bytes. -   * -   * @return true on success. -   */ -  const bool get_id(uint32_t conference_number, uint8_t[CONFERENCE_ID_SIZE] id); - -  /** -   * Return the conference number associated with the specified id. -   * -   * @param id A byte array containing the conference id ($CONFERENCE_ID_SIZE). -   * -   * @return the conference number on success, an unspecified value on failure. -   */ -  const uint32_t by_id(const uint8_t[CONFERENCE_ID_SIZE] id) { -    NULL, -    /** -     * No conference with the given id exists on the conference list. -     */ -    NOT_FOUND, -  } - -  /** -   * Get the conference unique ID. -   * -   * If uid is NULL, this function has no effect. -   * -   * @param uid A memory region large enough to store $CONFERENCE_UID_SIZE bytes. -   * -   * @return true on success. -   * @deprecated use $get_id instead (exactly the same function, just renamed). -   */ -  const bool get_uid(uint32_t conference_number, uint8_t[CONFERENCE_UID_SIZE] uid); - -  /** -   * Return the conference number associated with the specified uid. -   * -   * @param uid A byte array containing the conference id ($CONFERENCE_UID_SIZE). -   * -   * @return the conference number on success, an unspecified value on failure. -   * @deprecated use $by_id instead (exactly the same function, just renamed). -   */ -  const uint32_t by_uid(const uint8_t[CONFERENCE_UID_SIZE] uid) { -    NULL, -    /** -     * No conference with the given uid exists on the conference list. -     */ -    NOT_FOUND, -  } - -} - - -/******************************************************************************* - * - * :: Low-level custom packet sending and receiving - * - ******************************************************************************/ - - -namespace friend { - -  error for custom_packet { -    NULL, -    /** -     * The friend number did not designate a valid friend. -     */ -    FRIEND_NOT_FOUND, -    /** -     * This client is currently not connected to the friend. -     */ -    FRIEND_NOT_CONNECTED, -    /** -     * The first byte of data was not in the specified range for the packet type. -     * This range is 192-254 for lossy, and 69, 160-191 for lossless packets. -     */ -    INVALID, -    /** -     * Attempted to send an empty packet. -     */ -    EMPTY, -    /** -     * Packet data length exceeded $MAX_CUSTOM_PACKET_SIZE. -     */ -    TOO_LONG, -    /** -     * Packet queue is full. -     */ -    SENDQ, -  } - -  namespace send { - -    /** -     * Send a custom lossy packet to a friend. -     * -     * The first byte of data must be in the range 192-254. Maximum length of a -     * custom packet is $MAX_CUSTOM_PACKET_SIZE. -     * -     * Lossy packets behave like UDP packets, meaning they might never reach the -     * other side or might arrive more than once (if someone is messing with the -     * connection) or might arrive in the wrong order. -     * -     * Unless latency is an issue, it is recommended that you use lossless custom -     * packets instead. -     * -     * @param friend_number The friend number of the friend this lossy packet -     *   should be sent to. -     * @param data A byte array containing the packet data. -     * @param length The length of the packet data byte array. -     * -     * @return true on success. -     */ -    bool lossy_packet(uint32_t friend_number, const uint8_t[length <= MAX_CUSTOM_PACKET_SIZE] data) -        with error for custom_packet; - - -    /** -     * Send a custom lossless packet to a friend. -     * -     * The first byte of data must be in the range 69, 160-191. Maximum length of a -     * custom packet is $MAX_CUSTOM_PACKET_SIZE. -     * -     * Lossless packet behaviour is comparable to TCP (reliability, arrive in order) -     * but with packets instead of a stream. -     * -     * @param friend_number The friend number of the friend this lossless packet -     *   should be sent to. -     * @param data A byte array containing the packet data. -     * @param length The length of the packet data byte array. -     * -     * @return true on success. -     */ -    bool lossless_packet(uint32_t friend_number, const uint8_t[length <= MAX_CUSTOM_PACKET_SIZE] data) -        with error for custom_packet; - -  } - - -  event lossy_packet const { -    /** -     * @param friend_number The friend number of the friend who sent a lossy packet. -     * @param data A byte array containing the received packet data. -     * @param length The length of the packet data byte array. -     */ -    typedef void(uint32_t friend_number, const uint8_t[length <= MAX_CUSTOM_PACKET_SIZE] data); -  } - - -  event lossless_packet const { -    /** -     * @param friend_number The friend number of the friend who sent the packet. -     * @param data A byte array containing the received packet data. -     * @param length The length of the packet data byte array. -     */ -    typedef void(uint32_t friend_number, const uint8_t[length <= MAX_CUSTOM_PACKET_SIZE] data); -  } - -} - - - -/******************************************************************************* - * - * :: Low-level network information - * - ******************************************************************************/ - - -error for get_port { -  /** -   * The instance was not bound to any port. -   */ -  NOT_BOUND, -} - -namespace self { - -  uint8_t[PUBLIC_KEY_SIZE] dht_id { -    /** -     * Writes the temporary DHT public key of this instance to a byte array. -     * -     * This can be used in combination with an externally accessible IP address and -     * the bound port (from ${udp_port.get}) to run a temporary bootstrap node. -     * -     * Be aware that every time a new instance is created, the DHT public key -     * changes, meaning this cannot be used to run a permanent bootstrap node. -     * -     * @param dht_id A memory region of at least $PUBLIC_KEY_SIZE bytes. If this -     *   parameter is NULL, this function has no effect. -     */ -    get(); -  } - - - -  uint16_t udp_port { -    /** -     * Return the UDP port this Tox instance is bound to. -     */ -    get() with error for get_port; -  } - - -  uint16_t tcp_port { -    /** -     * Return the TCP port this Tox instance is bound to. This is only relevant if -     * the instance is acting as a TCP relay. -     */ -    get() with error for get_port; -  } - -} - -} // class tox - -%{ -#ifdef __cplusplus -} -#endif - -typedef TOX_ERR_OPTIONS_NEW Tox_Err_Options_New; -typedef TOX_ERR_NEW Tox_Err_New; -typedef TOX_ERR_BOOTSTRAP Tox_Err_Bootstrap; -typedef TOX_ERR_SET_INFO Tox_Err_Set_Info; -typedef TOX_ERR_FRIEND_ADD Tox_Err_Friend_Add; -typedef TOX_ERR_FRIEND_DELETE Tox_Err_Friend_Delete; -typedef TOX_ERR_FRIEND_BY_PUBLIC_KEY Tox_Err_Friend_By_Public_Key; -typedef TOX_ERR_FRIEND_GET_PUBLIC_KEY Tox_Err_Friend_Get_Public_Key; -typedef TOX_ERR_FRIEND_GET_LAST_ONLINE Tox_Err_Friend_Get_Last_Online; -typedef TOX_ERR_FRIEND_QUERY Tox_Err_Friend_Query; -typedef TOX_ERR_SET_TYPING Tox_Err_Set_Typing; -typedef TOX_ERR_FRIEND_SEND_MESSAGE Tox_Err_Friend_Send_Message; -typedef TOX_ERR_FILE_CONTROL Tox_Err_File_Control; -typedef TOX_ERR_FILE_SEEK Tox_Err_File_Seek; -typedef TOX_ERR_FILE_GET Tox_Err_File_Get; -typedef TOX_ERR_FILE_SEND Tox_Err_File_Send; -typedef TOX_ERR_FILE_SEND_CHUNK Tox_Err_File_Send_Chunk; -typedef TOX_ERR_CONFERENCE_NEW Tox_Err_Conference_New; -typedef TOX_ERR_CONFERENCE_DELETE Tox_Err_Conference_Delete; -typedef TOX_ERR_CONFERENCE_PEER_QUERY Tox_Err_Conference_Peer_Query; -typedef TOX_ERR_CONFERENCE_SET_MAX_OFFLINE Tox_Err_Conference_Set_Max_Offline; -typedef TOX_ERR_CONFERENCE_BY_ID Tox_Err_Conference_By_Id; -typedef TOX_ERR_CONFERENCE_BY_UID Tox_Err_Conference_By_Uid; -typedef TOX_ERR_CONFERENCE_INVITE Tox_Err_Conference_Invite; -typedef TOX_ERR_CONFERENCE_JOIN Tox_Err_Conference_Join; -typedef TOX_ERR_CONFERENCE_SEND_MESSAGE Tox_Err_Conference_Send_Message; -typedef TOX_ERR_CONFERENCE_TITLE Tox_Err_Conference_Title; -typedef TOX_ERR_CONFERENCE_GET_TYPE Tox_Err_Conference_Get_Type; -typedef TOX_ERR_FRIEND_CUSTOM_PACKET Tox_Err_Friend_Custom_Packet; -typedef TOX_ERR_GET_PORT Tox_Err_Get_Port; -typedef TOX_USER_STATUS Tox_User_Status; -typedef TOX_MESSAGE_TYPE Tox_Message_Type; -typedef TOX_PROXY_TYPE Tox_Proxy_Type; -typedef TOX_SAVEDATA_TYPE Tox_Savedata_Type; -typedef TOX_LOG_LEVEL Tox_Log_Level; -typedef TOX_CONNECTION Tox_Connection; -typedef TOX_FILE_CONTROL Tox_File_Control; -typedef TOX_CONFERENCE_TYPE Tox_Conference_Type; - -//!TOKSTYLE+ - -#endif // C_TOXCORE_TOXCORE_TOX_H -%} diff --git a/protocols/Tox/libtox/src/toxcore/tox.c b/protocols/Tox/libtox/src/toxcore/tox.c index 780d913667..fce8347c5e 100644 --- a/protocols/Tox/libtox/src/toxcore/tox.c +++ b/protocols/Tox/libtox/src/toxcore/tox.c @@ -3,18 +3,12 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * The Tox public API.   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifndef __cplusplus  #ifndef _XOPEN_SOURCE  #define _XOPEN_SOURCE 600  #endif -#endif  #include "tox.h"  #include "tox_private.h" @@ -30,39 +24,29 @@  #include "../toxencryptsave/defines.h" -#define SET_ERROR_PARAMETER(param, x) do { if (param) { *param = x; } } while (0) - -#if TOX_HASH_LENGTH != CRYPTO_SHA256_SIZE -#error "TOX_HASH_LENGTH is assumed to be equal to CRYPTO_SHA256_SIZE" -#endif - -#if FILE_ID_LENGTH != CRYPTO_SYMMETRIC_KEY_SIZE -#error "FILE_ID_LENGTH is assumed to be equal to CRYPTO_SYMMETRIC_KEY_SIZE" -#endif - -#if TOX_FILE_ID_LENGTH != CRYPTO_SYMMETRIC_KEY_SIZE -#error "TOX_FILE_ID_LENGTH is assumed to be equal to CRYPTO_SYMMETRIC_KEY_SIZE" -#endif - -#if TOX_FILE_ID_LENGTH != TOX_HASH_LENGTH -#error "TOX_FILE_ID_LENGTH is assumed to be equal to TOX_HASH_LENGTH" -#endif - -#if TOX_PUBLIC_KEY_SIZE != CRYPTO_PUBLIC_KEY_SIZE -#error "TOX_PUBLIC_KEY_SIZE is assumed to be equal to CRYPTO_PUBLIC_KEY_SIZE" -#endif - -#if TOX_SECRET_KEY_SIZE != CRYPTO_SECRET_KEY_SIZE -#error "TOX_SECRET_KEY_SIZE is assumed to be equal to CRYPTO_SECRET_KEY_SIZE" -#endif - -#if TOX_MAX_NAME_LENGTH != MAX_NAME_LENGTH -#error "TOX_MAX_NAME_LENGTH is assumed to be equal to MAX_NAME_LENGTH" -#endif - -#if TOX_MAX_STATUS_MESSAGE_LENGTH != MAX_STATUSMESSAGE_LENGTH -#error "TOX_MAX_STATUS_MESSAGE_LENGTH is assumed to be equal to MAX_STATUSMESSAGE_LENGTH" -#endif +#define SET_ERROR_PARAMETER(param, x) \ +    do {                              \ +        if (param) {                  \ +            *param = x;               \ +        }                             \ +    } while (0) + +static_assert(TOX_HASH_LENGTH == CRYPTO_SHA256_SIZE, +              "TOX_HASH_LENGTH is assumed to be equal to CRYPTO_SHA256_SIZE"); +static_assert(FILE_ID_LENGTH == CRYPTO_SYMMETRIC_KEY_SIZE, +              "FILE_ID_LENGTH is assumed to be equal to CRYPTO_SYMMETRIC_KEY_SIZE"); +static_assert(TOX_FILE_ID_LENGTH == CRYPTO_SYMMETRIC_KEY_SIZE, +              "TOX_FILE_ID_LENGTH is assumed to be equal to CRYPTO_SYMMETRIC_KEY_SIZE"); +static_assert(TOX_FILE_ID_LENGTH == TOX_HASH_LENGTH, +              "TOX_FILE_ID_LENGTH is assumed to be equal to TOX_HASH_LENGTH"); +static_assert(TOX_PUBLIC_KEY_SIZE == CRYPTO_PUBLIC_KEY_SIZE, +              "TOX_PUBLIC_KEY_SIZE is assumed to be equal to CRYPTO_PUBLIC_KEY_SIZE"); +static_assert(TOX_SECRET_KEY_SIZE == CRYPTO_SECRET_KEY_SIZE, +              "TOX_SECRET_KEY_SIZE is assumed to be equal to CRYPTO_SECRET_KEY_SIZE"); +static_assert(TOX_MAX_NAME_LENGTH == MAX_NAME_LENGTH, +              "TOX_MAX_NAME_LENGTH is assumed to be equal to MAX_NAME_LENGTH"); +static_assert(TOX_MAX_STATUS_MESSAGE_LENGTH == MAX_STATUSMESSAGE_LENGTH, +              "TOX_MAX_STATUS_MESSAGE_LENGTH is assumed to be equal to MAX_STATUSMESSAGE_LENGTH");  struct Tox {      // XXX: Messenger *must* be the first member, because toxav casts its @@ -367,7 +351,7 @@ static State_Load_Status state_load_callback(void *outer, const uint8_t *data, u      return STATE_LOAD_STATUS_CONTINUE;  } -/* Load tox from data of size length. */ +/** Load tox from data of size length. */  static int tox_load(Tox *tox, const uint8_t *data, uint32_t length)  {      uint32_t data32[2]; @@ -388,7 +372,6 @@ static int tox_load(Tox *tox, const uint8_t *data, uint32_t length)                        length - cookie_len, STATE_COOKIE_TYPE);  } -  Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)  {      Tox *tox = (Tox *)calloc(1, sizeof(Tox)); @@ -410,13 +393,15 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)          default_options = tox_options_new(&err);          switch (err) { -            case TOX_ERR_OPTIONS_NEW_OK: +            case TOX_ERR_OPTIONS_NEW_OK: {                  break; +            } -            case TOX_ERR_OPTIONS_NEW_MALLOC: +            case TOX_ERR_OPTIONS_NEW_MALLOC: {                  SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);                  free(tox);                  return nullptr; +            }          }      } @@ -449,7 +434,7 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)              return nullptr;          } -        if (crypto_memcmp(tox_options_get_savedata_data(opts), TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) { +        if (memcmp(tox_options_get_savedata_data(opts), TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) {              SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_ENCRYPTED);              tox_options_free(default_options);              free(tox); @@ -472,23 +457,27 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)      m_options.log_user_data = tox_options_get_log_user_data(opts);      switch (tox_options_get_proxy_type(opts)) { -        case TOX_PROXY_TYPE_HTTP: +        case TOX_PROXY_TYPE_HTTP: {              m_options.proxy_info.proxy_type = TCP_PROXY_HTTP;              break; +        } -        case TOX_PROXY_TYPE_SOCKS5: +        case TOX_PROXY_TYPE_SOCKS5: {              m_options.proxy_info.proxy_type = TCP_PROXY_SOCKS5;              break; +        } -        case TOX_PROXY_TYPE_NONE: +        case TOX_PROXY_TYPE_NONE: {              m_options.proxy_info.proxy_type = TCP_PROXY_NONE;              break; +        } -        default: +        default: {              SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_TYPE);              tox_options_free(default_options);              free(tox);              return nullptr; +        }      }      if (m_options.proxy_info.proxy_type != TCP_PROXY_NONE) { @@ -526,7 +515,7 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)      }      if (tox_options_get_experimental_thread_safety(opts)) { -        tox->mutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); +        tox->mutex = (pthread_mutex_t *)calloc(1, sizeof(pthread_mutex_t));          if (tox->mutex == nullptr) {              SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC); @@ -703,20 +692,22 @@ bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *pub      const int32_t count = net_getipport(host, &root, TOX_SOCK_DGRAM);      if (count == -1) { +        LOGGER_DEBUG(tox->m->log, "could not resolve bootstrap node '%s'", host);          net_freeipport(root);          SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);          return 0;      } -    unsigned int i; -      lock(tox); -    for (i = 0; i < count; ++i) { +    for (int32_t i = 0; i < count; ++i) {          root[i].port = net_htons(port); -        onion_add_bs_path_node(tox->m->onion_c, root[i], public_key); -        dht_bootstrap(tox->m->dht, root[i], public_key); +        onion_add_bs_path_node(tox->m->onion_c, &root[i], public_key); + +        if (!tox->m->options.udp_disabled) { +            dht_bootstrap(tox->m->dht, &root[i], public_key); +        }      }      unlock(tox); @@ -728,6 +719,7 @@ bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *pub          return 1;      } +    LOGGER_DEBUG(tox->m->log, "bootstrap node '%s' resolved to 0 IP_Ports", host);      SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);      return 0;  } @@ -749,7 +741,7 @@ bool tox_add_tcp_relay(Tox *tox, const char *host, uint16_t port, const uint8_t      IP_Port *root; -    int32_t count = net_getipport(host, &root, TOX_SOCK_STREAM); +    const int32_t count = net_getipport(host, &root, TOX_SOCK_STREAM);      if (count == -1) {          net_freeipport(root); @@ -757,14 +749,12 @@ bool tox_add_tcp_relay(Tox *tox, const char *host, uint16_t port, const uint8_t          return 0;      } -    unsigned int i; -      lock(tox); -    for (i = 0; i < count; ++i) { +    for (int32_t i = 0; i < count; ++i) {          root[i].port = net_htons(port); -        add_tcp_relay(tox->m->net_crypto, root[i], public_key); +        add_tcp_relay(tox->m->net_crypto, &root[i], public_key);      }      unlock(tox); @@ -984,38 +974,46 @@ Tox_User_Status tox_self_get_status(const Tox *tox)  static void set_friend_error(const Logger *log, int32_t ret, Tox_Err_Friend_Add *error)  {      switch (ret) { -        case FAERR_TOOLONG: +        case FAERR_TOOLONG: {              SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_TOO_LONG);              break; +        } -        case FAERR_NOMESSAGE: +        case FAERR_NOMESSAGE: {              SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_NO_MESSAGE);              break; +        } -        case FAERR_OWNKEY: +        case FAERR_OWNKEY: {              SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_OWN_KEY);              break; +        } -        case FAERR_ALREADYSENT: +        case FAERR_ALREADYSENT: {              SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_ALREADY_SENT);              break; +        } -        case FAERR_BADCHECKSUM: +        case FAERR_BADCHECKSUM: {              SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_BAD_CHECKSUM);              break; +        } -        case FAERR_SETNEWNOSPAM: +        case FAERR_SETNEWNOSPAM: {              SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM);              break; +        } -        case FAERR_NOMEM: +        case FAERR_NOMEM: {              SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_MALLOC);              break; +        } -        default: +        default: {              /* can't happen */ -            LOGGER_FATAL(log, "impossible: unknown friend-add error"); +            LOGGER_FATAL(log, "impossible return value: %d", ret);              break; +        }      }  } @@ -1351,34 +1349,41 @@ bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool typing, Tox_Err_  static void set_message_error(const Logger *log, int ret, Tox_Err_Friend_Send_Message *error)  {      switch (ret) { -        case 0: +        case 0: {              SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_OK);              break; +        } -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_FOUND);              break; +        } -        case -2: +        case -2: {              SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG);              break; +        } -        case -3: +        case -3: {              SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_CONNECTED);              break; +        } -        case -4: +        case -4: {              SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ);              break; +        } -        case -5: +        case -5: {              LOGGER_FATAL(log, "impossible: Messenger and Tox disagree on message types");              break; +        } -        default: +        default: {              /* can't happen */ -            LOGGER_FATAL(log, "impossible: unknown send-message error: %d", ret); +            LOGGER_FATAL(log, "impossible return value: %d", ret);              break; +        }      }  } @@ -1447,40 +1452,51 @@ bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, To      }      switch (ret) { -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_FRIEND_NOT_FOUND);              return 0; +        } -        case -2: +        case -2: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED);              return 0; +        } -        case -3: +        case -3: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_NOT_FOUND);              return 0; +        } -        case -4: -            /* can't happen */ +        case -4: { +            /* can't happen (this code is returned if `control` is invalid type) */ +            LOGGER_FATAL(tox->m->log, "impossible return value: %d", ret);              return 0; +        } -        case -5: +        case -5: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_ALREADY_PAUSED);              return 0; +        } -        case -6: +        case -6: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_DENIED);              return 0; +        } -        case -7: +        case -7: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_NOT_PAUSED);              return 0; +        } -        case -8: +        case -8: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_SENDQ);              return 0; +        }      }      /* can't happen */ +    LOGGER_FATAL(tox->m->log, "impossible return value: %d", ret); +      return 0;  } @@ -1498,33 +1514,41 @@ bool tox_file_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint6      }      switch (ret) { -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_FRIEND_NOT_FOUND);              return 0; +        } -        case -2: +        case -2: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_FRIEND_NOT_CONNECTED);              return 0; +        } -        case -3: +        case -3: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_NOT_FOUND);              return 0; +        }          case -4: // fall-through -        case -5: +        case -5: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_DENIED);              return 0; +        } -        case -6: +        case -6: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_INVALID_POSITION);              return 0; +        } -        case -8: +        case -8: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_SENDQ);              return 0; +        }      }      /* can't happen */ +    LOGGER_FATAL(tox->m->log, "impossible return value: %d", ret); +      return 0;  } @@ -1590,24 +1614,30 @@ uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t      }      switch (file_num) { -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_FRIEND_NOT_FOUND);              return UINT32_MAX; +        } -        case -2: +        case -2: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NAME_TOO_LONG);              return UINT32_MAX; +        } -        case -3: +        case -3: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_TOO_MANY);              return UINT32_MAX; +        } -        case -4: +        case -4: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED);              return UINT32_MAX; +        }      }      /* can't happen */ +    LOGGER_FATAL(tox->m->log, "impossible return value: %ld", file_num); +      return UINT32_MAX;  } @@ -1625,36 +1655,45 @@ bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number,      }      switch (ret) { -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_FOUND);              return 0; +        } -        case -2: +        case -2: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_CONNECTED);              return 0; +        } -        case -3: +        case -3: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_NOT_FOUND);              return 0; +        } -        case -4: +        case -4: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_NOT_TRANSFERRING);              return 0; +        } -        case -5: +        case -5: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_INVALID_LENGTH);              return 0; +        } -        case -6: +        case -6: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_SENDQ);              return 0; +        } -        case -7: +        case -7: {              SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_WRONG_POSITION);              return 0; +        }      }      /* can't happen */ +    LOGGER_FATAL(tox->m->log, "impossible return value: %d", ret); +      return 0;  } @@ -1769,13 +1808,15 @@ size_t tox_conference_peer_get_name_size(const Tox *tox, uint32_t conference_num      unlock(tox);      switch (ret) { -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);              return -1; +        } -        case -2: +        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); @@ -1791,13 +1832,15 @@ bool tox_conference_peer_get_name(const Tox *tox, uint32_t conference_number, ui      unlock(tox);      switch (ret) { -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);              return false; +        } -        case -2: +        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); @@ -1813,13 +1856,15 @@ bool tox_conference_peer_get_public_key(const Tox *tox, uint32_t conference_numb      unlock(tox);      switch (ret) { -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);              return false; +        } -        case -2: +        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); @@ -1835,17 +1880,20 @@ bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t conference_numb      unlock(tox);      switch (ret) { -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);              return false; +        } -        case -2: +        case -2: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);              return false; +        } -        case -3: +        case -3: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_NO_CONNECTION);              return false; +        }      }      SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK); @@ -1879,13 +1927,15 @@ size_t tox_conference_offline_peer_get_name_size(const Tox *tox, uint32_t confer      unlock(tox);      switch (ret) { -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);              return -1; +        } -        case -2: +        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); @@ -1902,13 +1952,15 @@ bool tox_conference_offline_peer_get_name(const Tox *tox, uint32_t conference_nu      unlock(tox);      switch (ret) { -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);              return false; +        } -        case -2: +        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); @@ -1925,13 +1977,15 @@ bool tox_conference_offline_peer_get_public_key(const Tox *tox, uint32_t confere      unlock(tox);      switch (ret) { -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);              return false; +        } -        case -2: +        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); @@ -1950,13 +2004,15 @@ uint64_t tox_conference_offline_peer_get_last_active(const Tox *tox, uint32_t co      unlock(tox);      switch (ret) { -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);              return UINT64_MAX; +        } -        case -2: +        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); @@ -1990,17 +2046,20 @@ bool tox_conference_invite(Tox *tox, uint32_t friend_number, uint32_t conference      unlock(tox);      switch (ret) { -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_CONFERENCE_NOT_FOUND);              return false; +        } -        case -2: +        case -2: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_FAIL_SEND);              return false; +        } -        case -3: +        case -3: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_NO_CONNECTION);              return false; +        }      }      SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_OK); @@ -2016,29 +2075,35 @@ uint32_t tox_conference_join(Tox *tox, uint32_t friend_number, const uint8_t *co      unlock(tox);      switch (ret) { -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_INVALID_LENGTH);              return UINT32_MAX; +        } -        case -2: +        case -2: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_WRONG_TYPE);              return UINT32_MAX; +        } -        case -3: +        case -3: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_FRIEND_NOT_FOUND);              return UINT32_MAX; +        } -        case -4: +        case -4: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_DUPLICATE);              return UINT32_MAX; +        } -        case -5: +        case -5: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_INIT_FAIL);              return UINT32_MAX; +        } -        case -6: +        case -6: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_FAIL_SEND);              return UINT32_MAX; +        }      }      SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_OK); @@ -2061,21 +2126,25 @@ bool tox_conference_send_message(Tox *tox, uint32_t conference_number, Tox_Messa      unlock(tox);      switch (ret) { -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_CONFERENCE_NOT_FOUND);              return false; +        } -        case -2: +        case -2: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_TOO_LONG);              return false; +        } -        case -3: +        case -3: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_NO_CONNECTION);              return false; +        } -        case -4: +        case -4: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_FAIL_SEND);              return false; +        }      }      SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_OK); @@ -2090,13 +2159,15 @@ size_t tox_conference_get_title_size(const Tox *tox, uint32_t conference_number,      unlock(tox);      switch (ret) { -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND);              return -1; +        } -        case -2: +        case -2: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH);              return -1; +        }      }      SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_OK); @@ -2112,13 +2183,15 @@ bool tox_conference_get_title(const Tox *tox, uint32_t conference_number, uint8_      unlock(tox);      switch (ret) { -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND);              return false; +        } -        case -2: +        case -2: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH);              return false; +        }      }      SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_OK); @@ -2134,17 +2207,20 @@ bool tox_conference_set_title(Tox *tox, uint32_t conference_number, const uint8_      unlock(tox);      switch (ret) { -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND);              return false; +        } -        case -2: +        case -2: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH);              return false; +        } -        case -3: +        case -3: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_FAIL_SEND);              return false; +        }      }      SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_OK); @@ -2186,7 +2262,6 @@ Tox_Conference_Type tox_conference_get_type(const Tox *tox, uint32_t conference_      return (Tox_Conference_Type)ret;  } -/* id is TOX_CONFERENCE_ID_SIZE bytes */  bool tox_conference_get_id(const Tox *tox, uint32_t conference_number, uint8_t *id)  {      assert(tox != nullptr); @@ -2197,7 +2272,6 @@ bool tox_conference_get_id(const Tox *tox, uint32_t conference_number, uint8_t *  }  // TODO(iphydf): Delete in 0.3.0. -/* uid is TOX_CONFERENCE_ID_SIZE bytes */  bool tox_conference_get_uid(const Tox *tox, uint32_t conference_number, uint8_t *uid)  {      assert(tox != nullptr); @@ -2234,17 +2308,20 @@ uint32_t tox_conference_by_uid(const Tox *tox, const uint8_t *uid, Tox_Err_Confe      const uint32_t res = tox_conference_by_id(tox, uid, &id_error);      switch (id_error) { -        case TOX_ERR_CONFERENCE_BY_ID_OK: +        case TOX_ERR_CONFERENCE_BY_ID_OK: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_BY_UID_OK);              break; +        } -        case TOX_ERR_CONFERENCE_BY_ID_NULL: +        case TOX_ERR_CONFERENCE_BY_ID_NULL: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_BY_UID_NULL);              break; +        } -        case TOX_ERR_CONFERENCE_BY_ID_NOT_FOUND: +        case TOX_ERR_CONFERENCE_BY_ID_NOT_FOUND: {              SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_BY_UID_NOT_FOUND);              break; +        }      }      return res; @@ -2253,29 +2330,35 @@ uint32_t tox_conference_by_uid(const Tox *tox, const uint8_t *uid, Tox_Err_Confe  static void set_custom_packet_error(int ret, Tox_Err_Friend_Custom_Packet *error)  {      switch (ret) { -        case 0: +        case 0: {              SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_OK);              break; +        } -        case -1: +        case -1: {              SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_FOUND);              break; +        } -        case -2: +        case -2: {              SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_TOO_LONG);              break; +        } -        case -3: +        case -3: {              SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID);              break; +        } -        case -4: +        case -4: {              SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED);              break; +        } -        case -5: +        case -5: {              SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_SENDQ);              break; +        }      }  } diff --git a/protocols/Tox/libtox/src/toxcore/tox.h b/protocols/Tox/libtox/src/toxcore/tox.h index ab71986e9e..38ec9f4b5a 100644 --- a/protocols/Tox/libtox/src/toxcore/tox.h +++ b/protocols/Tox/libtox/src/toxcore/tox.h @@ -3,33 +3,8 @@   * Copyright © 2013 Tox project.   */ -/* - * The Tox public API. - */ -#ifndef C_TOXCORE_TOXCORE_TOX_H -#define C_TOXCORE_TOXCORE_TOX_H - -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -//!TOKSTYLE- - -#ifdef __cplusplus -extern "C" { -#endif - - -/******************************************************************************* - * `tox.h` SHOULD *NOT* BE EDITED MANUALLY – any changes should be made to   * - * `tox.api.h`, located in `toxcore/`. For instructions on how to            * - * generate `tox.h` from `tox.api.h` please refer to `docs/apidsl.md`        * - ******************************************************************************/ - - - -/** - * @page core Public core API for Tox clients. +/** @file + * @brief Public core API for Tox clients.   *   * Every function that can fail takes a function-specific error code pointer   * that can be used to diagnose problems with the Tox state or the function @@ -66,9 +41,8 @@ extern "C" {   *   * Integer constants and the memory layout of publicly exposed structs are not   * part of the ABI. - */ -/** - * @subsection events Events and callbacks + * + * @section events Events and callbacks   *   * Events are handled by callbacks. One callback can be registered per event.   * All events have a callback function type named `tox_{event}_cb` and a @@ -89,9 +63,8 @@ extern "C" {   * Old style callbacks that are registered together with a user data pointer   * receive that pointer as argument when they are called. They can each have   * their own user data pointer of their own type. - */ -/** - * @subsection threading Threading implications + * + * @section threading Threading implications   *   * It is possible to run multiple concurrent threads with a Tox instance for   * each thread. It is also possible to run all Tox instances in the same thread. @@ -124,30 +97,40 @@ extern "C" {   * memory, the length may have become invalid, and the call to   * tox_self_get_name may cause undefined behaviour.   */ +#ifndef C_TOXCORE_TOXCORE_TOX_H +#define C_TOXCORE_TOXCORE_TOX_H + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef TOX_DEFINED +#define TOX_DEFINED  /** - * The Tox instance type. All the state associated with a connection is held + * @brief The Tox instance type. + * + * All the state associated with a connection is held   * within the instance. Multiple instances can exist and operate concurrently.   * The maximum number of Tox instances that can exist on a single network   * device is limited. Note that this is not just a per-process limit, since the   * limiting factor is the number of usable ports on a device.   */ -#ifndef TOX_DEFINED -#define TOX_DEFINED  typedef struct Tox Tox;  #endif /* TOX_DEFINED */ -/******************************************************************************* - * - * :: API version - * - ******************************************************************************/ - - +/** @{ + * @name API version + */  /** - * The major version number. Incremented when the API or ABI changes in an - * incompatible way. + * @brief The major version number. + * + * Incremented when the API or ABI changes in an incompatible way.   *   * The function variants of these constants return the version number of the   * library. They can be used to display the Tox library version or to check @@ -158,27 +141,33 @@ typedef struct Tox Tox;  uint32_t tox_version_major(void);  /** - * The minor version number. Incremented when functionality is added without - * breaking the API or ABI. Set to 0 when the major version number is - * incremented. + * @brief The minor version number. + * + * Incremented when functionality is added without  breaking the API or ABI. + * Set to 0 when the major version number is incremented.   */  #define TOX_VERSION_MINOR              2  uint32_t tox_version_minor(void);  /** - * The patch or revision number. Incremented when bugfixes are applied without - * changing any functionality or API or ABI. + * @brief The patch or revision number. + * + * Incremented when bugfixes are applied without changing any functionality or + * API or ABI.   */ -#define TOX_VERSION_PATCH              13 +#define TOX_VERSION_PATCH              15  uint32_t tox_version_patch(void); +//!TOKSTYLE-  /** - * A macro to check at preprocessing time whether the client code is compatible - * with the installed version of Tox. Leading zeros in the version number are - * ignored. E.g. 0.1.5 is to 0.1.4 what 1.5 is to 1.4, that is: it can add new - * features, but can't break the API. + * @brief A macro to check at preprocessing time whether the client code is + * compatible with the installed version of Tox. + * + * Leading zeros in the version number are  ignored. E.g. 0.1.5 is to 0.1.4 + * what 1.5 is to 1.4, that is: it can add new features, but can't break the + * API.   */  #define TOX_VERSION_IS_API_COMPATIBLE(MAJOR, MINOR, PATCH)              \    ((TOX_VERSION_MAJOR > 0 && TOX_VERSION_MAJOR == MAJOR) && (           \ @@ -194,49 +183,48 @@ uint32_t tox_version_patch(void);        TOX_VERSION_PATCH == PATCH                                        \      ))                                                                  \    )) +//!TOKSTYLE+  /** - * Return whether the compiled library version is compatible with the passed - * version numbers. + * @brief Return whether the compiled library version is compatible with the + * passed version numbers.   */  bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch);  /** - * A convenience macro to call tox_version_is_compatible with the currently - * compiling API version. + * @brief A convenience macro to call tox_version_is_compatible with the + * currently compiling API version.   */  #define TOX_VERSION_IS_ABI_COMPATIBLE()                         \    tox_version_is_compatible(TOX_VERSION_MAJOR, TOX_VERSION_MINOR, TOX_VERSION_PATCH) +/** @} */ -/******************************************************************************* - * - * :: Numeric constants + +/** @{ + * @name Numeric constants   *   * The values of these are not part of the ABI. Prefer to use the function   * versions of them for code that should remain compatible with future versions   * of toxcore. - * - ******************************************************************************/ - - + */  /** - * The size of a Tox Public Key in bytes. + * @brief The size of a Tox Public Key in bytes.   */  #define TOX_PUBLIC_KEY_SIZE            32  uint32_t tox_public_key_size(void);  /** - * The size of a Tox Secret Key in bytes. + * @brief The size of a Tox Secret Key in bytes.   */  #define TOX_SECRET_KEY_SIZE            32  uint32_t tox_secret_key_size(void);  /** - * The size of a Tox Conference unique id in bytes. + * @brief The size of a Tox Conference unique id in bytes.   *   * @deprecated Use TOX_CONFERENCE_ID_SIZE instead.   */ @@ -245,22 +233,24 @@ uint32_t tox_secret_key_size(void);  uint32_t tox_conference_uid_size(void);  /** - * The size of a Tox Conference unique id in bytes. + * @brief The size of a Tox Conference unique id in bytes.   */  #define TOX_CONFERENCE_ID_SIZE         32  uint32_t tox_conference_id_size(void);  /** - * The size of the nospam in bytes when written in a Tox address. + * @brief The size of the nospam in bytes when written in a Tox address.   */  #define TOX_NOSPAM_SIZE                (sizeof(uint32_t))  uint32_t tox_nospam_size(void);  /** - * The size of a Tox address in bytes. Tox addresses are in the format - * [Public Key (TOX_PUBLIC_KEY_SIZE bytes)][nospam (4 bytes)][checksum (2 bytes)]. + * @brief The size of a Tox address in bytes. + * + * Tox addresses are in the format + * `[Public Key (TOX_PUBLIC_KEY_SIZE bytes)][nospam (4 bytes)][checksum (2 bytes)]`.   *   * The checksum is computed over the Public Key and the nospam value. The first   * byte is an XOR of all the even bytes (0, 2, 4, ...), the second byte is an @@ -271,7 +261,7 @@ uint32_t tox_nospam_size(void);  uint32_t tox_address_size(void);  /** - * Maximum length of a nickname in bytes. + * @brief Maximum length of a nickname in bytes.   *   * @deprecated The macro will be removed in 0.3.0. Use the function instead.   */ @@ -280,7 +270,7 @@ uint32_t tox_address_size(void);  uint32_t tox_max_name_length(void);  /** - * Maximum length of a status message in bytes. + * @brief Maximum length of a status message in bytes.   *   * @deprecated The macro will be removed in 0.3.0. Use the function instead.   */ @@ -289,7 +279,7 @@ uint32_t tox_max_name_length(void);  uint32_t tox_max_status_message_length(void);  /** - * Maximum length of a friend request message in bytes. + * @brief Maximum length of a friend request message in bytes.   *   * @deprecated The macro will be removed in 0.3.0. Use the function instead.   */ @@ -298,7 +288,7 @@ uint32_t tox_max_status_message_length(void);  uint32_t tox_max_friend_request_length(void);  /** - * Maximum length of a single message after which it should be split. + * @brief Maximum length of a single message after which it should be split.   *   * @deprecated The macro will be removed in 0.3.0. Use the function instead.   */ @@ -307,7 +297,7 @@ uint32_t tox_max_friend_request_length(void);  uint32_t tox_max_message_length(void);  /** - * Maximum size of custom packets. TODO(iphydf): should be LENGTH? + * @brief Maximum size of custom packets. TODO(iphydf): should be LENGTH?   *   * @deprecated The macro will be removed in 0.3.0. Use the function instead.   */ @@ -316,21 +306,21 @@ uint32_t tox_max_message_length(void);  uint32_t tox_max_custom_packet_size(void);  /** - * The number of bytes in a hash generated by tox_hash. + * @brief The number of bytes in a hash generated by tox_hash.   */  #define TOX_HASH_LENGTH                32  uint32_t tox_hash_length(void);  /** - * The number of bytes in a file id. + * @brief The number of bytes in a file id.   */  #define TOX_FILE_ID_LENGTH             32  uint32_t tox_file_id_length(void);  /** - * Maximum file name length for file transfers. + * @brief Maximum file name length for file transfers.   *   * @deprecated The macro will be removed in 0.3.0. Use the function instead.   */ @@ -339,7 +329,7 @@ uint32_t tox_file_id_length(void);  uint32_t tox_max_filename_length(void);  /** - * Maximum length of a hostname, e.g. proxy or bootstrap node names. + * @brief Maximum length of a hostname, e.g. proxy or bootstrap node names.   *   * This length does not include the NUL byte. Hostnames are NUL-terminated C   * strings, so they are 255 characters plus one NUL byte. @@ -350,22 +340,17 @@ uint32_t tox_max_filename_length(void);  uint32_t tox_max_hostname_length(void); - -/******************************************************************************* - * - * :: Global enumerations - * - ******************************************************************************/ +/** @} */ +/** @{ + * @name Global enumerations + */  /** - * Represents the possible statuses a client can have. - * - * @deprecated All UPPER_CASE enum type names are deprecated. Use the - *   Camel_Snake_Case versions, instead. + * @brief Represents the possible statuses a client can have.   */ -typedef enum TOX_USER_STATUS { +typedef enum Tox_User_Status {      /**       * User is online and available. @@ -384,17 +369,14 @@ typedef enum TOX_USER_STATUS {       */      TOX_USER_STATUS_BUSY, -} TOX_USER_STATUS; +} Tox_User_Status;  /** - * Represents message types for tox_friend_send_message and conference + * @brief Represents message types for tox_friend_send_message and conference   * messages. - * - * @deprecated All UPPER_CASE enum type names are deprecated. Use the - *   Camel_Snake_Case versions, instead.   */ -typedef enum TOX_MESSAGE_TYPE { +typedef enum Tox_Message_Type {      /**       * Normal text message. Similar to PRIVMSG on IRC. @@ -407,25 +389,19 @@ typedef enum TOX_MESSAGE_TYPE {       */      TOX_MESSAGE_TYPE_ACTION, -} TOX_MESSAGE_TYPE; +} Tox_Message_Type; +/** @} */ -/******************************************************************************* - * - * :: Startup options - * - ******************************************************************************/ - - +/** @{ + * @name Startup options + */  /** - * Type of proxy used to connect to TCP relays. - * - * @deprecated All UPPER_CASE enum type names are deprecated. Use the - *   Camel_Snake_Case versions, instead. + * @brief Type of proxy used to connect to TCP relays.   */ -typedef enum TOX_PROXY_TYPE { +typedef enum Tox_Proxy_Type {      /**       * Don't use a proxy. @@ -442,16 +418,13 @@ typedef enum TOX_PROXY_TYPE {       */      TOX_PROXY_TYPE_SOCKS5, -} TOX_PROXY_TYPE; +} Tox_Proxy_Type;  /** - * Type of savedata to create the Tox instance from. - * - * @deprecated All UPPER_CASE enum type names are deprecated. Use the - *   Camel_Snake_Case versions, instead. + * @brief Type of savedata to create the Tox instance from.   */ -typedef enum TOX_SAVEDATA_TYPE { +typedef enum Tox_Savedata_Type {      /**       * No savedata. @@ -468,16 +441,13 @@ typedef enum TOX_SAVEDATA_TYPE {       */      TOX_SAVEDATA_TYPE_SECRET_KEY, -} TOX_SAVEDATA_TYPE; +} Tox_Savedata_Type;  /** - * Severity level of log messages. - * - * @deprecated All UPPER_CASE enum type names are deprecated. Use the - *   Camel_Snake_Case versions, instead. + * @brief Severity level of log messages.   */ -typedef enum TOX_LOG_LEVEL { +typedef enum Tox_Log_Level {      /**       * Very detailed traces including all network activity. @@ -504,11 +474,12 @@ typedef enum TOX_LOG_LEVEL {       */      TOX_LOG_LEVEL_ERROR, -} TOX_LOG_LEVEL; +} Tox_Log_Level;  /** - * This event is triggered when the toxcore library logs an internal message. + * @brief This event is triggered when the toxcore library logs an internal message. + *   * This is mostly useful for debugging. This callback can be called from any   * function, not just tox_iterate. This means the user data lifetime must at   * least extend between registering and unregistering it or tox_kill. @@ -524,13 +495,14 @@ typedef enum TOX_LOG_LEVEL {   * @param message The log message.   * @param user_data The user data pointer passed to tox_new in options.   */ -typedef void tox_log_cb(Tox *tox, TOX_LOG_LEVEL level, const char *file, uint32_t line, const char *func, +typedef void tox_log_cb(Tox *tox, Tox_Log_Level level, const char *file, uint32_t line, const char *func,                          const char *message, void *user_data);  /** - * This struct contains all the startup options for Tox. You must tox_options_new to - * allocate an object of this type. + * @brief This struct contains all the startup options for Tox. + * + * You must tox_options_new to allocate an object of this type.   *   * WARNING: Although this struct happens to be visible in the API, it is   * effectively private. Do not allocate this yourself or access members @@ -577,7 +549,7 @@ struct Tox_Options {      /**       * Pass communications through a proxy.       */ -    TOX_PROXY_TYPE proxy_type; +    Tox_Proxy_Type proxy_type;      /** @@ -608,7 +580,7 @@ struct Tox_Options {       * The start port of the inclusive port range to attempt to use.       *       * If both start_port and end_port are 0, the default port range will be -     * used: [33445, 33545]. +     * used: `[33445, 33545]`.       *       * If either start_port or end_port is 0 while the other is non-zero, the       * non-zero port will be the only port in the range. @@ -648,7 +620,7 @@ struct Tox_Options {      /**       * The type of savedata to load from.       */ -    TOX_SAVEDATA_TYPE savedata_type; +    Tox_Savedata_Type savedata_type;      /** @@ -706,9 +678,9 @@ bool tox_options_get_local_discovery_enabled(const struct Tox_Options *options);  void tox_options_set_local_discovery_enabled(struct Tox_Options *options, bool local_discovery_enabled); -TOX_PROXY_TYPE tox_options_get_proxy_type(const struct Tox_Options *options); +Tox_Proxy_Type tox_options_get_proxy_type(const struct Tox_Options *options); -void tox_options_set_proxy_type(struct Tox_Options *options, TOX_PROXY_TYPE type); +void tox_options_set_proxy_type(struct Tox_Options *options, Tox_Proxy_Type type);  const char *tox_options_get_proxy_host(const struct Tox_Options *options); @@ -734,9 +706,9 @@ bool tox_options_get_hole_punching_enabled(const struct Tox_Options *options);  void tox_options_set_hole_punching_enabled(struct Tox_Options *options, bool hole_punching_enabled); -TOX_SAVEDATA_TYPE tox_options_get_savedata_type(const struct Tox_Options *options); +Tox_Savedata_Type tox_options_get_savedata_type(const struct Tox_Options *options); -void tox_options_set_savedata_type(struct Tox_Options *options, TOX_SAVEDATA_TYPE type); +void tox_options_set_savedata_type(struct Tox_Options *options, Tox_Savedata_Type type);  const uint8_t *tox_options_get_savedata_data(const struct Tox_Options *options); @@ -759,7 +731,7 @@ bool tox_options_get_experimental_thread_safety(const struct Tox_Options *option  void tox_options_set_experimental_thread_safety(struct Tox_Options *options, bool thread_safety);  /** - * Initialises a Tox_Options object with the default options. + * @brief Initialises a Tox_Options object with the default options.   *   * The result of this function is independent of the original options. All   * values will be overwritten, no values will be read (so it is permissible @@ -771,7 +743,7 @@ void tox_options_set_experimental_thread_safety(struct Tox_Options *options, boo   */  void tox_options_default(struct Tox_Options *options); -typedef enum TOX_ERR_OPTIONS_NEW { +typedef enum Tox_Err_Options_New {      /**       * The function returned successfully. @@ -783,12 +755,14 @@ typedef enum TOX_ERR_OPTIONS_NEW {       */      TOX_ERR_OPTIONS_NEW_MALLOC, -} TOX_ERR_OPTIONS_NEW; +} Tox_Err_Options_New;  /** - * Allocates a new Tox_Options object and initialises it with the default - * options. This function can be used to preserve long term ABI compatibility by + * @brief Allocates a new Tox_Options object and initialises it with the default + * options. + * + * This function can be used to preserve long term ABI compatibility by   * giving the responsibility of allocation and deallocation to the Tox library.   *   * Objects returned from this function must be freed using the tox_options_free @@ -796,26 +770,24 @@ typedef enum TOX_ERR_OPTIONS_NEW {   *   * @return A new Tox_Options object with default options or NULL on failure.   */ -struct Tox_Options *tox_options_new(TOX_ERR_OPTIONS_NEW *error); +struct Tox_Options *tox_options_new(Tox_Err_Options_New *error);  /** - * Releases all resources associated with an options objects. + * @brief Releases all resources associated with an options objects.   *   * Passing a pointer that was not returned by tox_options_new results in   * undefined behaviour.   */  void tox_options_free(struct Tox_Options *options); - -/******************************************************************************* - * - * :: Creation and destruction - * - ******************************************************************************/ +/** @} */ +/** @{ + * @name Creation and destruction + */ -typedef enum TOX_ERR_NEW { +typedef enum Tox_Err_New {      /**       * The function returned successfully. @@ -875,7 +847,7 @@ typedef enum TOX_ERR_NEW {       */      TOX_ERR_NEW_LOAD_BAD_FORMAT, -} TOX_ERR_NEW; +} Tox_Err_New;  /** @@ -894,11 +866,11 @@ typedef enum TOX_ERR_NEW {   *   * @return A new Tox instance pointer on success or NULL on failure.   */ -Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error); +Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error);  /** - * Releases all resources associated with the Tox instance and disconnects from - * the network. + * @brief Releases all resources associated with the Tox instance and + * disconnects from the network.   *   * After calling this function, the Tox pointer becomes invalid. No other   * functions can be called, and the pointer value can no longer be read. @@ -906,15 +878,17 @@ Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error);  void tox_kill(Tox *tox);  /** - * Calculates the number of bytes required to store the tox instance with - * tox_get_savedata. This function cannot fail. The result is always greater than 0. + * @brief Calculates the number of bytes required to store the tox instance with + * tox_get_savedata. + * + * This function cannot fail. The result is always greater than 0.   *   * @see threading for concurrency implications.   */  size_t tox_get_savedata_size(const Tox *tox);  /** - * Store all information associated with the tox instance to a byte array. + * @brief Store all information associated with the tox instance to a byte array.   *   * @param savedata A memory region large enough to store the tox instance   *   data. Call tox_get_savedata_size to find the number of bytes required. If this parameter @@ -922,16 +896,14 @@ size_t tox_get_savedata_size(const Tox *tox);   */  void tox_get_savedata(const Tox *tox, uint8_t *savedata); - -/******************************************************************************* - * - * :: Connection lifecycle and event loop - * - ******************************************************************************/ +/** @} */ +/** @{ + * @name Connection lifecycle and event loop + */ -typedef enum TOX_ERR_BOOTSTRAP { +typedef enum Tox_Err_Bootstrap {      /**       * The function returned successfully. @@ -954,11 +926,11 @@ typedef enum TOX_ERR_BOOTSTRAP {       */      TOX_ERR_BOOTSTRAP_BAD_PORT, -} TOX_ERR_BOOTSTRAP; +} Tox_Err_Bootstrap;  /** - * Sends a "get nodes" request to the given bootstrap node with IP, port, and + * @brief Sends a "get nodes" request to the given bootstrap node with IP, port, and   * public key to setup connections.   *   * This function will attempt to connect to the node using UDP. You must use @@ -972,10 +944,10 @@ typedef enum TOX_ERR_BOOTSTRAP {   *   (TOX_PUBLIC_KEY_SIZE bytes).   * @return true on success.   */ -bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error); +bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key, Tox_Err_Bootstrap *error);  /** - * Adds additional host:port pair as TCP relay. + * @brief Adds additional host:port pair as TCP relay.   *   * This function can be used to initiate TCP connections to different ports on   * the same bootstrap node, or to add TCP relays without using them as @@ -988,15 +960,12 @@ bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *pub   *   (TOX_PUBLIC_KEY_SIZE bytes).   * @return true on success.   */ -bool tox_add_tcp_relay(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error); +bool tox_add_tcp_relay(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key, Tox_Err_Bootstrap *error);  /** - * Protocols that can be used to connect to the network or friends. - * - * @deprecated All UPPER_CASE enum type names are deprecated. Use the - *   Camel_Snake_Case versions, instead. + * @brief Protocols that can be used to connect to the network or friends.   */ -typedef enum TOX_CONNECTION { +typedef enum Tox_Connection {      /**       * There is no connection. This instance, or the friend the state change is @@ -1019,26 +988,30 @@ typedef enum TOX_CONNECTION {       */      TOX_CONNECTION_UDP, -} TOX_CONNECTION; +} Tox_Connection;  /** - * Return whether we are connected to the DHT. The return value is equal to the - * last value received through the `self_connection_status` callback. + * @brief Return whether we are connected to the DHT. + * + * The return value is equal to the last value received through the + * `self_connection_status` callback.   *   * @deprecated This getter is deprecated. Use the event and store the status   * in the client state.   */ -TOX_CONNECTION tox_self_get_connection_status(const Tox *tox); +Tox_Connection tox_self_get_connection_status(const Tox *tox);  /**   * @param connection_status Whether we are connected to the DHT.   */ -typedef void tox_self_connection_status_cb(Tox *tox, TOX_CONNECTION connection_status, void *user_data); +typedef void tox_self_connection_status_cb(Tox *tox, Tox_Connection connection_status, void *user_data);  /** - * Set the callback for the `self_connection_status` event. Pass NULL to unset. + * @brief Set the callback for the `self_connection_status` event. + * + * Pass NULL to unset.   *   * This event is triggered whenever there is a change in the DHT connection   * state. When disconnected, a client may choose to call tox_bootstrap again, to @@ -1051,30 +1024,29 @@ typedef void tox_self_connection_status_cb(Tox *tox, TOX_CONNECTION connection_s  void tox_callback_self_connection_status(Tox *tox, tox_self_connection_status_cb *callback);  /** - * Return the time in milliseconds before tox_iterate() should be called again + * @brief Return the time in milliseconds before tox_iterate() should be called again   * for optimal performance.   */  uint32_t tox_iteration_interval(const Tox *tox);  /** - * The main loop that needs to be run in intervals of tox_iteration_interval() + * @brief The main loop that needs to be run in intervals of tox_iteration_interval()   * milliseconds.   */  void tox_iterate(Tox *tox, void *user_data); - -/******************************************************************************* - * - * :: Internal client information (Tox address/id) - * - ******************************************************************************/ +/** @} */ +/** @{ + * @name Internal client information (Tox address/id) + */  /** - * Writes the Tox friend address of the client to a byte array. The address is - * not in human-readable format. If a client wants to display the address, - * formatting is required. + * @brief Writes the Tox friend address of the client to a byte array. + * + * The address is not in human-readable format. If a client wants to display + * the address, formatting is required.   *   * @param address A memory region of at least TOX_ADDRESS_SIZE bytes. If this   *   parameter is NULL, this function has no effect. @@ -1083,22 +1055,24 @@ void tox_iterate(Tox *tox, void *user_data);  void tox_self_get_address(const Tox *tox, uint8_t *address);  /** - * Set the 4-byte nospam part of the address. This value is expected in host - * byte order. I.e. 0x12345678 will form the bytes [12, 34, 56, 78] in the - * nospam part of the Tox friend address. + * @brief Set the 4-byte nospam part of the address. + * + * This value is expected in host byte order. I.e. 0x12345678 will form the + * bytes `[12, 34, 56, 78]` in the nospam part of the Tox friend address.   *   * @param nospam Any 32 bit unsigned integer.   */  void tox_self_set_nospam(Tox *tox, uint32_t nospam);  /** - * Get the 4-byte nospam part of the address. This value is returned in host - * byte order. + * @brief Get the 4-byte nospam part of the address. + * + * This value is returned in host byte order.   */  uint32_t tox_self_get_nospam(const Tox *tox);  /** - * Copy the Tox Public Key (long term) from the Tox object. + * @brief Copy the Tox Public Key (long term) from the Tox object.   *   * @param public_key A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If   *   this parameter is NULL, this function has no effect. @@ -1106,27 +1080,25 @@ uint32_t tox_self_get_nospam(const Tox *tox);  void tox_self_get_public_key(const Tox *tox, uint8_t *public_key);  /** - * Copy the Tox Secret Key from the Tox object. + * @brief Copy the Tox Secret Key from the Tox object.   *   * @param secret_key A memory region of at least TOX_SECRET_KEY_SIZE bytes. If   *   this parameter is NULL, this function has no effect.   */  void tox_self_get_secret_key(const Tox *tox, uint8_t *secret_key); - -/******************************************************************************* - * - * :: User-visible client information (nickname/status) - * - ******************************************************************************/ +/** @} */ +/** @{ + * @name User-visible client information (nickname/status) + */  /** - * Common error codes for all functions that set a piece of user-visible + * @brief Common error codes for all functions that set a piece of user-visible   * client information.   */ -typedef enum TOX_ERR_SET_INFO { +typedef enum Tox_Err_Set_Info {      /**       * The function returned successfully. @@ -1143,11 +1115,11 @@ typedef enum TOX_ERR_SET_INFO {       */      TOX_ERR_SET_INFO_TOO_LONG, -} TOX_ERR_SET_INFO; +} Tox_Err_Set_Info;  /** - * Set the nickname for the Tox client. + * @brief Set the nickname for the Tox client.   *   * Nickname length cannot exceed TOX_MAX_NAME_LENGTH. If length is 0, the name   * parameter is ignored (it can be NULL), and the nickname is set back to empty. @@ -1157,10 +1129,10 @@ typedef enum TOX_ERR_SET_INFO {   *   * @return true on success.   */ -bool tox_self_set_name(Tox *tox, const uint8_t *name, size_t length, TOX_ERR_SET_INFO *error); +bool tox_self_set_name(Tox *tox, const uint8_t *name, size_t length, Tox_Err_Set_Info *error);  /** - * Return the length of the current nickname as passed to tox_self_set_name. + * @brief Return the length of the current nickname as passed to tox_self_set_name.   *   * If no nickname was set before calling this function, the name is empty,   * and this function returns 0. @@ -1170,7 +1142,7 @@ bool tox_self_set_name(Tox *tox, const uint8_t *name, size_t length, TOX_ERR_SET  size_t tox_self_get_name_size(const Tox *tox);  /** - * Write the nickname set by tox_self_set_name to a byte array. + * @brief Write the nickname set by tox_self_set_name to a byte array.   *   * If no nickname was set before calling this function, the name is empty,   * and this function has no effect. @@ -1184,16 +1156,16 @@ size_t tox_self_get_name_size(const Tox *tox);  void tox_self_get_name(const Tox *tox, uint8_t *name);  /** - * Set the client's status message. + * @brief Set the client's status message.   *   * Status message length cannot exceed TOX_MAX_STATUS_MESSAGE_LENGTH. If   * length is 0, the status parameter is ignored (it can be NULL), and the   * user status is set back to empty.   */ -bool tox_self_set_status_message(Tox *tox, const uint8_t *status_message, size_t length, TOX_ERR_SET_INFO *error); +bool tox_self_set_status_message(Tox *tox, const uint8_t *status_message, size_t length, Tox_Err_Set_Info *error);  /** - * Return the length of the current status message as passed to tox_self_set_status_message. + * @brief Return the length of the current status message as passed to tox_self_set_status_message.   *   * If no status message was set before calling this function, the status   * is empty, and this function returns 0. @@ -1203,7 +1175,7 @@ bool tox_self_set_status_message(Tox *tox, const uint8_t *status_message, size_t  size_t tox_self_get_status_message_size(const Tox *tox);  /** - * Write the status message set by tox_self_set_status_message to a byte array. + * @brief Write the status message set by tox_self_set_status_message to a byte array.   *   * If no status message was set before calling this function, the status is   * empty, and this function has no effect. @@ -1217,27 +1189,25 @@ size_t tox_self_get_status_message_size(const Tox *tox);  void tox_self_get_status_message(const Tox *tox, uint8_t *status_message);  /** - * Set the client's user status. + * @brief Set the client's user status.   *   * @param status One of the user statuses listed in the enumeration above.   */ -void tox_self_set_status(Tox *tox, TOX_USER_STATUS status); +void tox_self_set_status(Tox *tox, Tox_User_Status status);  /** - * Returns the client's user status. + * @brief Returns the client's user status.   */ -TOX_USER_STATUS tox_self_get_status(const Tox *tox); - +Tox_User_Status tox_self_get_status(const Tox *tox); -/******************************************************************************* - * - * :: Friend list management - * - ******************************************************************************/ +/** @} */ +/** @{ + * @name Friend list management + */ -typedef enum TOX_ERR_FRIEND_ADD { +typedef enum Tox_Err_Friend_Add {      /**       * The function returned successfully. @@ -1287,11 +1257,11 @@ typedef enum TOX_ERR_FRIEND_ADD {       */      TOX_ERR_FRIEND_ADD_MALLOC, -} TOX_ERR_FRIEND_ADD; +} Tox_Err_Friend_Add;  /** - * Add a friend to the friend list and send a friend request. + * @brief Add a friend to the friend list and send a friend request.   *   * A friend request message must be at least 1 byte long and at most   * TOX_MAX_FRIEND_REQUEST_LENGTH. @@ -1314,10 +1284,10 @@ typedef enum TOX_ERR_FRIEND_ADD {   * @return the friend number on success, an unspecified value on failure.   */  uint32_t tox_friend_add(Tox *tox, const uint8_t *address, const uint8_t *message, size_t length, -                        TOX_ERR_FRIEND_ADD *error); +                        Tox_Err_Friend_Add *error);  /** - * Add a friend without sending a friend request. + * @brief Add a friend without sending a friend request.   *   * This function is used to add a friend in response to a friend request. If the   * client receives a friend request, it can be reasonably sure that the other @@ -1334,9 +1304,9 @@ uint32_t tox_friend_add(Tox *tox, const uint8_t *address, const uint8_t *message   * @return the friend number on success, an unspecified value on failure.   * @see tox_friend_add for a more detailed description of friend numbers.   */ -uint32_t tox_friend_add_norequest(Tox *tox, const uint8_t *public_key, TOX_ERR_FRIEND_ADD *error); +uint32_t tox_friend_add_norequest(Tox *tox, const uint8_t *public_key, Tox_Err_Friend_Add *error); -typedef enum TOX_ERR_FRIEND_DELETE { +typedef enum Tox_Err_Friend_Delete {      /**       * The function returned successfully. @@ -1348,11 +1318,11 @@ typedef enum TOX_ERR_FRIEND_DELETE {       */      TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND, -} TOX_ERR_FRIEND_DELETE; +} Tox_Err_Friend_Delete;  /** - * Remove a friend from the friend list. + * @brief Remove a friend from the friend list.   *   * This does not notify the friend of their deletion. After calling this   * function, this client will appear offline to the friend and no communication @@ -1362,18 +1332,16 @@ typedef enum TOX_ERR_FRIEND_DELETE {   *   * @return true on success.   */ -bool tox_friend_delete(Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_DELETE *error); +bool tox_friend_delete(Tox *tox, uint32_t friend_number, Tox_Err_Friend_Delete *error); - -/******************************************************************************* - * - * :: Friend list queries - * - ******************************************************************************/ +/** @} */ +/** @{ + * @name Friend list queries + */ -typedef enum TOX_ERR_FRIEND_BY_PUBLIC_KEY { +typedef enum Tox_Err_Friend_By_Public_Key {      /**       * The function returned successfully. @@ -1390,25 +1358,25 @@ typedef enum TOX_ERR_FRIEND_BY_PUBLIC_KEY {       */      TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND, -} TOX_ERR_FRIEND_BY_PUBLIC_KEY; +} Tox_Err_Friend_By_Public_Key;  /** - * Return the friend number associated with that Public Key. + * @brief Return the friend number associated with that Public Key.   *   * @return the friend number on success, an unspecified value on failure.   * @param public_key A byte array containing the Public Key.   */ -uint32_t tox_friend_by_public_key(const Tox *tox, const uint8_t *public_key, TOX_ERR_FRIEND_BY_PUBLIC_KEY *error); +uint32_t tox_friend_by_public_key(const Tox *tox, const uint8_t *public_key, Tox_Err_Friend_By_Public_Key *error);  /** - * Checks if a friend with the given friend number exists and returns true if + * @brief Checks if a friend with the given friend number exists and returns true if   * it does.   */  bool tox_friend_exists(const Tox *tox, uint32_t friend_number);  /** - * Return the number of friends on the friend list. + * @brief Return the number of friends on the friend list.   *   * This function can be used to determine how much memory to allocate for   * tox_self_get_friend_list. @@ -1416,7 +1384,7 @@ bool tox_friend_exists(const Tox *tox, uint32_t friend_number);  size_t tox_self_get_friend_list_size(const Tox *tox);  /** - * Copy a list of valid friend numbers into an array. + * @brief Copy a list of valid friend numbers into an array.   *   * Call tox_self_get_friend_list_size to determine the number of elements to allocate.   * @@ -1425,7 +1393,7 @@ size_t tox_self_get_friend_list_size(const Tox *tox);   */  void tox_self_get_friend_list(const Tox *tox, uint32_t *friend_list); -typedef enum TOX_ERR_FRIEND_GET_PUBLIC_KEY { +typedef enum Tox_Err_Friend_Get_Public_Key {      /**       * The function returned successfully. @@ -1437,11 +1405,11 @@ typedef enum TOX_ERR_FRIEND_GET_PUBLIC_KEY {       */      TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND, -} TOX_ERR_FRIEND_GET_PUBLIC_KEY; +} Tox_Err_Friend_Get_Public_Key;  /** - * Copies the Public Key associated with a given friend number to a byte array. + * @brief Copies the Public Key associated with a given friend number to a byte array.   *   * @param friend_number The friend number you want the Public Key of.   * @param public_key A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If @@ -1450,9 +1418,9 @@ typedef enum TOX_ERR_FRIEND_GET_PUBLIC_KEY {   * @return true on success.   */  bool tox_friend_get_public_key(const Tox *tox, uint32_t friend_number, uint8_t *public_key, -                               TOX_ERR_FRIEND_GET_PUBLIC_KEY *error); +                               Tox_Err_Friend_Get_Public_Key *error); -typedef enum TOX_ERR_FRIEND_GET_LAST_ONLINE { +typedef enum Tox_Err_Friend_Get_Last_Online {      /**       * The function returned successfully. @@ -1464,30 +1432,30 @@ typedef enum TOX_ERR_FRIEND_GET_LAST_ONLINE {       */      TOX_ERR_FRIEND_GET_LAST_ONLINE_FRIEND_NOT_FOUND, -} TOX_ERR_FRIEND_GET_LAST_ONLINE; +} Tox_Err_Friend_Get_Last_Online;  /** - * Return a unix-time timestamp of the last time the friend associated with a given - * friend number was seen online. This function will return UINT64_MAX on error. + * @brief Return a unix-time timestamp of the last time the friend associated with a given + * friend number was seen online. + * + * This function will return UINT64_MAX on error.   *   * @param friend_number The friend number you want to query.   */ -uint64_t tox_friend_get_last_online(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_GET_LAST_ONLINE *error); - +uint64_t tox_friend_get_last_online(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Get_Last_Online *error); -/******************************************************************************* - * - * :: Friend-specific state queries (can also be received through callbacks) - * - ******************************************************************************/ +/** @} */ +/** @{ + * @name Friend-specific state queries (can also be received through callbacks) + */  /** - * Common error codes for friend state query functions. + * @brief Common error codes for friend state query functions.   */ -typedef enum TOX_ERR_FRIEND_QUERY { +typedef enum Tox_Err_Friend_Query {      /**       * The function returned successfully. @@ -1506,20 +1474,21 @@ typedef enum TOX_ERR_FRIEND_QUERY {       */      TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND, -} TOX_ERR_FRIEND_QUERY; +} Tox_Err_Friend_Query;  /** - * Return the length of the friend's name. If the friend number is invalid, the - * return value is unspecified. + * @brief Return the length of the friend's name. + * + * If the friend number is invalid, the return value is unspecified.   *   * The return value is equal to the `length` argument received by the last   * `friend_name` callback.   */ -size_t tox_friend_get_name_size(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); +size_t tox_friend_get_name_size(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error);  /** - * Write the name of the friend designated by the given friend number to a byte + * @brief Write the name of the friend designated by the given friend number to a byte   * array.   *   * Call tox_friend_get_name_size to determine the allocation size for the `name` @@ -1532,7 +1501,7 @@ size_t tox_friend_get_name_size(const Tox *tox, uint32_t friend_number, TOX_ERR_   *   * @return true on success.   */ -bool tox_friend_get_name(const Tox *tox, uint32_t friend_number, uint8_t *name, TOX_ERR_FRIEND_QUERY *error); +bool tox_friend_get_name(const Tox *tox, uint32_t friend_number, uint8_t *name, Tox_Err_Friend_Query *error);  /**   * @param friend_number The friend number of the friend whose name changed. @@ -1545,20 +1514,23 @@ typedef void tox_friend_name_cb(Tox *tox, uint32_t friend_number, const uint8_t  /** - * Set the callback for the `friend_name` event. Pass NULL to unset. + * @brief Set the callback for the `friend_name` event. + * + * Pass NULL to unset.   *   * This event is triggered when a friend changes their name.   */  void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *callback);  /** - * Return the length of the friend's status message. If the friend number is - * invalid, the return value is SIZE_MAX. + * @brief Return the length of the friend's status message. + * + * If the friend number isinvalid, the return value is SIZE_MAX.   */ -size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); +size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error);  /** - * Write the status message of the friend designated by the given friend number to a byte + * @brief Write the status message of the friend designated by the given friend number to a byte   * array.   *   * Call tox_friend_get_status_message_size to determine the allocation size for the `status_message` @@ -1570,7 +1542,7 @@ size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number   * @param status_message A valid memory region large enough to store the friend's status message.   */  bool tox_friend_get_status_message(const Tox *tox, uint32_t friend_number, uint8_t *status_message, -                                   TOX_ERR_FRIEND_QUERY *error); +                                   Tox_Err_Friend_Query *error);  /**   * @param friend_number The friend number of the friend whose status message @@ -1585,15 +1557,18 @@ typedef void tox_friend_status_message_cb(Tox *tox, uint32_t friend_number, cons  /** - * Set the callback for the `friend_status_message` event. Pass NULL to unset. + * @brief Set the callback for the `friend_status_message` event. + * + * Pass NULL to unset.   *   * This event is triggered when a friend changes their status message.   */  void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *callback);  /** - * Return the friend's user status (away/busy/...). If the friend number is - * invalid, the return value is unspecified. + * @brief Return the friend's user status (away/busy/...). + * + * If the friend number is invalid, the return value is unspecified.   *   * The status returned is equal to the last status received through the   * `friend_status` callback. @@ -1601,25 +1576,27 @@ void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *   * @deprecated This getter is deprecated. Use the event and store the status   *   in the client state.   */ -TOX_USER_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); +Tox_User_Status tox_friend_get_status(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error);  /**   * @param friend_number The friend number of the friend whose user status   *   changed.   * @param status The new user status.   */ -typedef void tox_friend_status_cb(Tox *tox, uint32_t friend_number, TOX_USER_STATUS status, void *user_data); +typedef void tox_friend_status_cb(Tox *tox, uint32_t friend_number, Tox_User_Status status, void *user_data);  /** - * Set the callback for the `friend_status` event. Pass NULL to unset. + * @brief Set the callback for the `friend_status` event. + * + * Pass NULL to unset.   *   * This event is triggered when a friend changes their user status.   */  void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *callback);  /** - * Check whether a friend is currently connected to this client. + * @brief Check whether a friend is currently connected to this client.   *   * The result of this function is equal to the last value received by the   * `friend_connection_status` callback. @@ -1633,7 +1610,7 @@ void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *callback);   * @deprecated This getter is deprecated. Use the event and store the status   *   in the client state.   */ -TOX_CONNECTION tox_friend_get_connection_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); +Tox_Connection tox_friend_get_connection_status(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error);  /**   * @param friend_number The friend number of the friend whose connection status @@ -1641,12 +1618,14 @@ TOX_CONNECTION tox_friend_get_connection_status(const Tox *tox, uint32_t friend_   * @param connection_status The result of calling   *   tox_friend_get_connection_status on the passed friend_number.   */ -typedef void tox_friend_connection_status_cb(Tox *tox, uint32_t friend_number, TOX_CONNECTION connection_status, +typedef void tox_friend_connection_status_cb(Tox *tox, uint32_t friend_number, Tox_Connection connection_status,          void *user_data);  /** - * Set the callback for the `friend_connection_status` event. Pass NULL to unset. + * @brief Set the callback for the `friend_connection_status` event. + * + * Pass NULL to unset.   *   * This event is triggered when a friend goes offline after having been online,   * or when a friend goes online. @@ -1657,7 +1636,7 @@ typedef void tox_friend_connection_status_cb(Tox *tox, uint32_t friend_number, T  void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_status_cb *callback);  /** - * Check whether a friend is currently typing a message. + * @brief Check whether a friend is currently typing a message.   *   * @param friend_number The friend number for which to query the typing status.   * @@ -1668,7 +1647,7 @@ void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_statu   * @deprecated This getter is deprecated. Use the event and store the status   *   in the client state.   */ -bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); +bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error);  /**   * @param friend_number The friend number of the friend who started or stopped @@ -1680,22 +1659,22 @@ typedef void tox_friend_typing_cb(Tox *tox, uint32_t friend_number, bool is_typi  /** - * Set the callback for the `friend_typing` event. Pass NULL to unset. + * @brief Set the callback for the `friend_typing` event. + * + * Pass NULL to unset.   *   * This event is triggered when a friend starts or stops typing.   */  void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *callback); - -/******************************************************************************* - * - * :: Sending private messages - * - ******************************************************************************/ +/** @} */ +/** @{ + * @name Sending private messages + */ -typedef enum TOX_ERR_SET_TYPING { +typedef enum Tox_Err_Set_Typing {      /**       * The function returned successfully. @@ -1707,11 +1686,11 @@ typedef enum TOX_ERR_SET_TYPING {       */      TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND, -} TOX_ERR_SET_TYPING; +} Tox_Err_Set_Typing;  /** - * Set the client's typing status for a friend. + * @brief Set the client's typing status for a friend.   *   * The client is responsible for turning it on or off.   * @@ -1720,9 +1699,9 @@ typedef enum TOX_ERR_SET_TYPING {   *   * @return true on success.   */ -bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool typing, TOX_ERR_SET_TYPING *error); +bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool typing, Tox_Err_Set_Typing *error); -typedef enum TOX_ERR_FRIEND_SEND_MESSAGE { +typedef enum Tox_Err_Friend_Send_Message {      /**       * The function returned successfully. @@ -1759,11 +1738,11 @@ typedef enum TOX_ERR_FRIEND_SEND_MESSAGE {       */      TOX_ERR_FRIEND_SEND_MESSAGE_EMPTY, -} TOX_ERR_FRIEND_SEND_MESSAGE; +} Tox_Err_Friend_Send_Message;  /** - * Send a text chat message to an online friend. + * @brief Send a text chat message to an online friend.   *   * This function creates a chat message packet and pushes it into the send   * queue. @@ -1785,8 +1764,8 @@ typedef enum TOX_ERR_FRIEND_SEND_MESSAGE {   *   containing the message text.   * @param length Length of the message to be sent.   */ -uint32_t tox_friend_send_message(Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type, const uint8_t *message, -                                 size_t length, TOX_ERR_FRIEND_SEND_MESSAGE *error); +uint32_t tox_friend_send_message(Tox *tox, uint32_t friend_number, Tox_Message_Type type, const uint8_t *message, +                                 size_t length, Tox_Err_Friend_Send_Message *error);  /**   * @param friend_number The friend number of the friend who received the message. @@ -1797,21 +1776,21 @@ typedef void tox_friend_read_receipt_cb(Tox *tox, uint32_t friend_number, uint32  /** - * Set the callback for the `friend_read_receipt` event. Pass NULL to unset. + * @brief Set the callback for the `friend_read_receipt` event. + * + * Pass NULL to unset.   *   * This event is triggered when the friend receives the message sent with   * tox_friend_send_message with the corresponding message ID.   */  void tox_callback_friend_read_receipt(Tox *tox, tox_friend_read_receipt_cb *callback); - -/******************************************************************************* - * - * :: Receiving private messages and friend requests - * - ******************************************************************************/ +/** @} */ +/** @{ + * @name Receiving private messages and friend requests + */  /**   * @param public_key The Public Key of the user who sent the friend request. @@ -1823,7 +1802,9 @@ typedef void tox_friend_request_cb(Tox *tox, const uint8_t *public_key, const ui  /** - * Set the callback for the `friend_request` event. Pass NULL to unset. + * @brief Set the callback for the `friend_request` event. + * + * Pass NULL to unset.   *   * This event is triggered when a friend request is received.   */ @@ -1834,28 +1815,28 @@ void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *callback);   * @param message The message data they sent.   * @param length The size of the message byte array.   */ -typedef void tox_friend_message_cb(Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type, const uint8_t *message, +typedef void tox_friend_message_cb(Tox *tox, uint32_t friend_number, Tox_Message_Type type, const uint8_t *message,                                     size_t length, void *user_data);  /** - * Set the callback for the `friend_message` event. Pass NULL to unset. + * @brief Set the callback for the `friend_message` event. + * + * Pass NULL to unset.   *   * This event is triggered when a message from a friend is received.   */  void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *callback); - -/******************************************************************************* - * - * :: File transmission: common between sending and receiving - * - ******************************************************************************/ +/** @} */ +/** @{ + * @name File transmission: common between sending and receiving + */  /** - * Generates a cryptographic hash of the given data. + * @brief Generates a cryptographic hash of the given data.   *   * This function may be used by clients for any purpose, but is provided   * primarily for validating cached avatars. This use is highly recommended to @@ -1876,14 +1857,15 @@ void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *callback);  bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length);  /** - * A list of pre-defined file kinds. Toxcore itself does not behave - * differently for different file kinds. These are a hint to the client - * telling it what use the sender intended for the file. The `kind` parameter - * in the send function and recv callback are `uint32_t`, not TOX_FILE_KIND, because - * clients can invent their own file kind. Unknown file kinds should be - * treated as TOX_FILE_KIND_DATA. + * @brief A list of pre-defined file kinds. + * + * Toxcore itself does not behave differently for different file kinds. These + * are a hint to the client telling it what use the sender intended for the + * file. The `kind` parameter in the send function and recv callback are + * `uint32_t`, not Tox_File_Kind, because clients can invent their own file + * kind. Unknown file kinds should be treated as TOX_FILE_KIND_DATA.   */ -enum TOX_FILE_KIND { +enum Tox_File_Kind {      /**       * Arbitrary file data. Clients can choose to handle it based on the file name @@ -1916,7 +1898,7 @@ enum TOX_FILE_KIND {  }; -typedef enum TOX_FILE_CONTROL { +typedef enum Tox_File_Control {      /**       * Sent by the receiving side to accept a file send request. Also sent after a @@ -1938,10 +1920,10 @@ typedef enum TOX_FILE_CONTROL {       */      TOX_FILE_CONTROL_CANCEL, -} TOX_FILE_CONTROL; +} Tox_File_Control; -typedef enum TOX_ERR_FILE_CONTROL { +typedef enum Tox_Err_File_Control {      /**       * The function returned successfully. @@ -1984,11 +1966,11 @@ typedef enum TOX_ERR_FILE_CONTROL {       */      TOX_ERR_FILE_CONTROL_SENDQ, -} TOX_ERR_FILE_CONTROL; +} Tox_Err_File_Control;  /** - * Sends a file control command to a friend for a given file transfer. + * @brief Sends a file control command to a friend for a given file transfer.   *   * @param friend_number The friend number of the friend the file is being   *   transferred to or received from. @@ -1997,11 +1979,11 @@ typedef enum TOX_ERR_FILE_CONTROL {   *   * @return true on success.   */ -bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control, -                      TOX_ERR_FILE_CONTROL *error); +bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, Tox_File_Control control, +                      Tox_Err_File_Control *error);  /** - * When receiving TOX_FILE_CONTROL_CANCEL, the client should release the + * @brief When receiving TOX_FILE_CONTROL_CANCEL, the client should release the   * resources associated with the file number and consider the transfer failed.   *   * @param friend_number The friend number of the friend who is sending the file. @@ -2009,19 +1991,21 @@ bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TO   *   associated with.   * @param control The file control command received.   */ -typedef void tox_file_recv_control_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control, +typedef void tox_file_recv_control_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, Tox_File_Control control,                                        void *user_data);  /** - * Set the callback for the `file_recv_control` event. Pass NULL to unset. + * @brief Set the callback for the `file_recv_control` event. + * + * Pass NULL to unset.   *   * This event is triggered when a file control command is received from a   * friend.   */  void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *callback); -typedef enum TOX_ERR_FILE_SEEK { +typedef enum Tox_Err_File_Seek {      /**       * The function returned successfully. @@ -2058,11 +2042,11 @@ typedef enum TOX_ERR_FILE_SEEK {       */      TOX_ERR_FILE_SEEK_SENDQ, -} TOX_ERR_FILE_SEEK; +} Tox_Err_File_Seek;  /** - * Sends a file seek control command to a friend for a given file transfer. + * @brief Sends a file seek control command to a friend for a given file transfer.   *   * This function can only be called to resume a file transfer right before   * TOX_FILE_CONTROL_RESUME is sent. @@ -2072,9 +2056,9 @@ typedef enum TOX_ERR_FILE_SEEK {   * @param file_number The friend-specific identifier for the file transfer.   * @param position The position that the file should be seeked to.   */ -bool tox_file_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, TOX_ERR_FILE_SEEK *error); +bool tox_file_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, Tox_Err_File_Seek *error); -typedef enum TOX_ERR_FILE_GET { +typedef enum Tox_Err_File_Get {      /**       * The function returned successfully. @@ -2096,11 +2080,11 @@ typedef enum TOX_ERR_FILE_GET {       */      TOX_ERR_FILE_GET_NOT_FOUND, -} TOX_ERR_FILE_GET; +} Tox_Err_File_Get;  /** - * Copy the file id associated to the file transfer to a byte array. + * @brief Copy the file id associated to the file transfer to a byte array.   *   * @param friend_number The friend number of the friend the file is being   *   transferred to or received from. @@ -2111,18 +2095,16 @@ typedef enum TOX_ERR_FILE_GET {   * @return true on success.   */  bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t *file_id, -                          TOX_ERR_FILE_GET *error); +                          Tox_Err_File_Get *error); - -/******************************************************************************* - * - * :: File transmission: sending - * - ******************************************************************************/ +/** @} */ +/** @{ + * @name File transmission: sending + */ -typedef enum TOX_ERR_FILE_SEND { +typedef enum Tox_Err_File_Send {      /**       * The function returned successfully. @@ -2155,11 +2137,11 @@ typedef enum TOX_ERR_FILE_SEND {       */      TOX_ERR_FILE_SEND_TOO_MANY, -} TOX_ERR_FILE_SEND; +} Tox_Err_File_Send;  /** - * Send a file transmission request. + * @brief Send a file transmission request.   *   * Maximum filename length is TOX_MAX_FILENAME_LENGTH bytes. The filename   * should generally just be a file name, not a path with directory names. @@ -2218,9 +2200,9 @@ typedef enum TOX_ERR_FILE_SEND {   *   should not be relied on.   */  uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *file_id, -                       const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error); +                       const uint8_t *filename, size_t filename_length, Tox_Err_File_Send *error); -typedef enum TOX_ERR_FILE_SEND_CHUNK { +typedef enum Tox_Err_File_Send_Chunk {      /**       * The function returned successfully. @@ -2270,11 +2252,11 @@ typedef enum TOX_ERR_FILE_SEND_CHUNK {       */      TOX_ERR_FILE_SEND_CHUNK_WRONG_POSITION, -} TOX_ERR_FILE_SEND_CHUNK; +} Tox_Err_File_Send_Chunk;  /** - * Send a chunk of file data to a friend. + * @brief Send a chunk of file data to a friend.   *   * This function is called in response to the `file_chunk_request` callback. The   * length parameter should be equal to the one received though the callback. @@ -2290,7 +2272,7 @@ typedef enum TOX_ERR_FILE_SEND_CHUNK {   * @return true on success.   */  bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, const uint8_t *data, -                         size_t length, TOX_ERR_FILE_SEND_CHUNK *error); +                         size_t length, Tox_Err_File_Send_Chunk *error);  /**   * If the length parameter is 0, the file transfer is finished, and the client's @@ -2319,20 +2301,20 @@ typedef void tox_file_chunk_request_cb(Tox *tox, uint32_t friend_number, uint32_  /** - * Set the callback for the `file_chunk_request` event. Pass NULL to unset. + * @brief Set the callback for the `file_chunk_request` event. + * + * Pass NULL to unset.   *   * This event is triggered when Core is ready to send more file data.   */  void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *callback); - -/******************************************************************************* - * - * :: File transmission: receiving - * - ******************************************************************************/ +/** @} */ +/** @{ + * @name File transmission: receiving + */  /**   * The client should acquire resources to be associated with the file transfer. @@ -2357,7 +2339,9 @@ typedef void tox_file_recv_cb(Tox *tox, uint32_t friend_number, uint32_t file_nu  /** - * Set the callback for the `file_recv` event. Pass NULL to unset. + * @brief Set the callback for the `file_recv` event. + * + * Pass NULL to unset.   *   * This event is triggered when a file transfer request is received.   */ @@ -2384,29 +2368,26 @@ typedef void tox_file_recv_chunk_cb(Tox *tox, uint32_t friend_number, uint32_t f  /** - * Set the callback for the `file_recv_chunk` event. Pass NULL to unset. + * @brief Set the callback for the `file_recv_chunk` event. + * + * Pass NULL to unset.   *   * This event is first triggered when a file transfer request is received, and   * subsequently when a chunk of file data for an accepted request was received.   */  void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *callback); - -/******************************************************************************* - * - * :: Conference management - * - ******************************************************************************/ +/** @} */ +/** @{ + * @name Conference management + */  /** - * Conference types for the conference_invite event. - * - * @deprecated All UPPER_CASE enum type names are deprecated. Use the - *   Camel_Snake_Case versions, instead. + * @brief Conference types for the conference_invite event.   */ -typedef enum TOX_CONFERENCE_TYPE { +typedef enum Tox_Conference_Type {      /**       * Text-only conferences that must be accepted with the tox_conference_join function. @@ -2418,7 +2399,7 @@ typedef enum TOX_CONFERENCE_TYPE {       */      TOX_CONFERENCE_TYPE_AV, -} TOX_CONFERENCE_TYPE; +} Tox_Conference_Type;  /** @@ -2431,12 +2412,14 @@ typedef enum TOX_CONFERENCE_TYPE {   *   conference.   * @param length The length of the cookie.   */ -typedef void tox_conference_invite_cb(Tox *tox, uint32_t friend_number, TOX_CONFERENCE_TYPE type, const uint8_t *cookie, +typedef void tox_conference_invite_cb(Tox *tox, uint32_t friend_number, Tox_Conference_Type type, const uint8_t *cookie,                                        size_t length, void *user_data);  /** - * Set the callback for the `conference_invite` event. Pass NULL to unset. + * @brief Set the callback for the `conference_invite` event. + * + * Pass NULL to unset.   *   * This event is triggered when the client is invited to join a conference.   */ @@ -2449,7 +2432,9 @@ typedef void tox_conference_connected_cb(Tox *tox, uint32_t conference_number, v  /** - * Set the callback for the `conference_connected` event. Pass NULL to unset. + * @brief Set the callback for the `conference_connected` event. + * + * Pass NULL to unset.   *   * This event is triggered when the client successfully connects to a   * conference after joining it with the tox_conference_join function. @@ -2464,11 +2449,13 @@ void tox_callback_conference_connected(Tox *tox, tox_conference_connected_cb *ca   * @param length The length of the message.   */  typedef void tox_conference_message_cb(Tox *tox, uint32_t conference_number, uint32_t peer_number, -                                       TOX_MESSAGE_TYPE type, const uint8_t *message, size_t length, void *user_data); +                                       Tox_Message_Type type, const uint8_t *message, size_t length, void *user_data);  /** - * Set the callback for the `conference_message` event. Pass NULL to unset. + * @brief Set the callback for the `conference_message` event. + * + * Pass NULL to unset.   *   * This event is triggered when the client receives a conference message.   */ @@ -2485,7 +2472,9 @@ typedef void tox_conference_title_cb(Tox *tox, uint32_t conference_number, uint3  /** - * Set the callback for the `conference_title` event. Pass NULL to unset. + * @brief Set the callback for the `conference_title` event. + * + * Pass NULL to unset.   *   * This event is triggered when a peer changes the conference title.   * @@ -2505,7 +2494,9 @@ typedef void tox_conference_peer_name_cb(Tox *tox, uint32_t conference_number, u  /** - * Set the callback for the `conference_peer_name` event. Pass NULL to unset. + * @brief Set the callback for the `conference_peer_name` event. + * + * Pass NULL to unset.   *   * This event is triggered when a peer changes their name.   */ @@ -2519,13 +2510,15 @@ typedef void tox_conference_peer_list_changed_cb(Tox *tox, uint32_t conference_n  /** - * Set the callback for the `conference_peer_list_changed` event. Pass NULL to unset. + * @brief Set the callback for the `conference_peer_list_changed` event. + * + * Pass NULL to unset.   *   * This event is triggered when a peer joins or leaves the conference.   */  void tox_callback_conference_peer_list_changed(Tox *tox, tox_conference_peer_list_changed_cb *callback); -typedef enum TOX_ERR_CONFERENCE_NEW { +typedef enum Tox_Err_Conference_New {      /**       * The function returned successfully. @@ -2537,19 +2530,21 @@ typedef enum TOX_ERR_CONFERENCE_NEW {       */      TOX_ERR_CONFERENCE_NEW_INIT, -} TOX_ERR_CONFERENCE_NEW; +} Tox_Err_Conference_New;  /** - * Creates a new conference. + * @brief Creates a new conference.   *   * This function creates and connects to a new text conference.   * - * @return conference number on success, or an unspecified value on failure. + * @return + *   - conference number on success + *   - an unspecified value on failure   */ -uint32_t tox_conference_new(Tox *tox, TOX_ERR_CONFERENCE_NEW *error); +uint32_t tox_conference_new(Tox *tox, Tox_Err_Conference_New *error); -typedef enum TOX_ERR_CONFERENCE_DELETE { +typedef enum Tox_Err_Conference_Delete {      /**       * The function returned successfully. @@ -2561,22 +2556,22 @@ typedef enum TOX_ERR_CONFERENCE_DELETE {       */      TOX_ERR_CONFERENCE_DELETE_CONFERENCE_NOT_FOUND, -} TOX_ERR_CONFERENCE_DELETE; +} Tox_Err_Conference_Delete;  /** - * This function deletes a conference. + * @brief This function deletes a conference.   *   * @param conference_number The conference number of the conference to be deleted.   *   * @return true on success.   */ -bool tox_conference_delete(Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_DELETE *error); +bool tox_conference_delete(Tox *tox, uint32_t conference_number, Tox_Err_Conference_Delete *error);  /** - * Error codes for peer info queries. + * @brief Error codes for peer info queries.   */ -typedef enum TOX_ERR_CONFERENCE_PEER_QUERY { +typedef enum Tox_Err_Conference_Peer_Query {      /**       * The function returned successfully. @@ -2598,25 +2593,28 @@ typedef enum TOX_ERR_CONFERENCE_PEER_QUERY {       */      TOX_ERR_CONFERENCE_PEER_QUERY_NO_CONNECTION, -} TOX_ERR_CONFERENCE_PEER_QUERY; +} Tox_Err_Conference_Peer_Query;  /** - * Return the number of online peers in the conference. The unsigned - * integers less than this number are the valid values of peer_number for - * the functions querying these peers. Return value is unspecified on - * failure. + * @brief Return the number of online peers in the conference. + * + * The unsigned integers less than this number are the valid values of + * peer_number for the functions querying these peers. Return value is + * unspecified on failure.   */ -uint32_t tox_conference_peer_count(const Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_PEER_QUERY *error); +uint32_t tox_conference_peer_count(const Tox *tox, uint32_t conference_number, Tox_Err_Conference_Peer_Query *error);  /** - * Return the length of the peer's name. Return value is unspecified on failure. + * @brief Return the length of the peer's name. + * + * Return value is unspecified on failure.   */  size_t tox_conference_peer_get_name_size(const Tox *tox, uint32_t conference_number, uint32_t peer_number, -        TOX_ERR_CONFERENCE_PEER_QUERY *error); +        Tox_Err_Conference_Peer_Query *error);  /** - * Copy the name of peer_number who is in conference_number to name. + * @brief Copy the name of peer_number who is in conference_number to name.   *   * Call tox_conference_peer_get_name_size to determine the allocation size for the `name` parameter.   * @@ -2625,39 +2623,45 @@ size_t tox_conference_peer_get_name_size(const Tox *tox, uint32_t conference_num   * @return true on success.   */  bool tox_conference_peer_get_name(const Tox *tox, uint32_t conference_number, uint32_t peer_number, uint8_t *name, -                                  TOX_ERR_CONFERENCE_PEER_QUERY *error); +                                  Tox_Err_Conference_Peer_Query *error);  /** - * Copy the public key of peer_number who is in conference_number to public_key. + * @brief Copy the public key of 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_peer_get_public_key(const Tox *tox, uint32_t conference_number, uint32_t peer_number, -                                        uint8_t *public_key, TOX_ERR_CONFERENCE_PEER_QUERY *error); +                                        uint8_t *public_key, Tox_Err_Conference_Peer_Query *error);  /** - * Return true if passed peer_number corresponds to our own. + * @brief Return true if passed peer_number corresponds to our own.   */  bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t conference_number, uint32_t peer_number, -                                        TOX_ERR_CONFERENCE_PEER_QUERY *error); +                                        Tox_Err_Conference_Peer_Query *error);  /** - * Return the number of offline peers in the conference. The unsigned - * integers less than this number are the valid values of offline_peer_number for - * the functions querying these peers. Return value is unspecified on failure. + * @brief Return the number of offline peers in the conference. + * + * The unsigned integers less than this number are the valid values of + * offline_peer_number for the functions querying these peers. + * + * 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); +        Tox_Err_Conference_Peer_Query *error);  /** - * Return the length of the offline peer's name. Return value is unspecified on failure. + * @brief 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); +        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. + * @brief Copy the name of offline_peer_number who is in conference_number to name.   *   * Call tox_conference_offline_peer_get_name_size to determine the allocation size for the `name` parameter.   * @@ -2666,24 +2670,25 @@ size_t tox_conference_offline_peer_get_name_size(const Tox *tox, uint32_t confer   * @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); +        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. + * @brief 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); +        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. + * @brief 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); +        uint32_t offline_peer_number, Tox_Err_Conference_Peer_Query *error); -typedef enum TOX_ERR_CONFERENCE_SET_MAX_OFFLINE { +typedef enum Tox_Err_Conference_Set_Max_Offline {      /**       * The function returned successfully. @@ -2695,16 +2700,16 @@ typedef enum TOX_ERR_CONFERENCE_SET_MAX_OFFLINE {       */      TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_CONFERENCE_NOT_FOUND, -} TOX_ERR_CONFERENCE_SET_MAX_OFFLINE; +} Tox_Err_Conference_Set_Max_Offline;  /** - * Set maximum number of offline peers to store, overriding the default. + * @brief Set maximum number of offline peers to store, overriding the default.   */  bool tox_conference_set_max_offline(Tox *tox, uint32_t conference_number, uint32_t max_offline_peers, -                                    TOX_ERR_CONFERENCE_SET_MAX_OFFLINE *error); +                                    Tox_Err_Conference_Set_Max_Offline *error); -typedef enum TOX_ERR_CONFERENCE_INVITE { +typedef enum Tox_Err_Conference_Invite {      /**       * The function returned successfully. @@ -2726,11 +2731,11 @@ typedef enum TOX_ERR_CONFERENCE_INVITE {       */      TOX_ERR_CONFERENCE_INVITE_NO_CONNECTION, -} TOX_ERR_CONFERENCE_INVITE; +} Tox_Err_Conference_Invite;  /** - * Invites a friend to a conference. + * @brief Invites a friend to a conference.   *   * @param friend_number The friend number of the friend we want to invite.   * @param conference_number The conference number of the conference we want to invite the friend to. @@ -2738,9 +2743,9 @@ typedef enum TOX_ERR_CONFERENCE_INVITE {   * @return true on success.   */  bool tox_conference_invite(Tox *tox, uint32_t friend_number, uint32_t conference_number, -                           TOX_ERR_CONFERENCE_INVITE *error); +                           Tox_Err_Conference_Invite *error); -typedef enum TOX_ERR_CONFERENCE_JOIN { +typedef enum Tox_Err_Conference_Join {      /**       * The function returned successfully. @@ -2777,11 +2782,11 @@ typedef enum TOX_ERR_CONFERENCE_JOIN {       */      TOX_ERR_CONFERENCE_JOIN_FAIL_SEND, -} TOX_ERR_CONFERENCE_JOIN; +} Tox_Err_Conference_Join;  /** - * Joins a conference that the client has been invited to. + * @brief Joins a conference that the client has been invited to.   *   * After successfully joining the conference, the client will not be "connected"   * to it until a handshaking procedure has been completed. A @@ -2798,9 +2803,9 @@ typedef enum TOX_ERR_CONFERENCE_JOIN {   * @return conference number on success, an unspecified value on failure.   */  uint32_t tox_conference_join(Tox *tox, uint32_t friend_number, const uint8_t *cookie, size_t length, -                             TOX_ERR_CONFERENCE_JOIN *error); +                             Tox_Err_Conference_Join *error); -typedef enum TOX_ERR_CONFERENCE_SEND_MESSAGE { +typedef enum Tox_Err_Conference_Send_Message {      /**       * The function returned successfully. @@ -2827,11 +2832,11 @@ typedef enum TOX_ERR_CONFERENCE_SEND_MESSAGE {       */      TOX_ERR_CONFERENCE_SEND_MESSAGE_FAIL_SEND, -} TOX_ERR_CONFERENCE_SEND_MESSAGE; +} Tox_Err_Conference_Send_Message;  /** - * Send a text chat message to the conference. + * @brief Send a text chat message to the conference.   *   * This function creates a conference message packet and pushes it into the send   * queue. @@ -2848,10 +2853,10 @@ typedef enum TOX_ERR_CONFERENCE_SEND_MESSAGE {   *   * @return true on success.   */ -bool tox_conference_send_message(Tox *tox, uint32_t conference_number, TOX_MESSAGE_TYPE type, const uint8_t *message, -                                 size_t length, TOX_ERR_CONFERENCE_SEND_MESSAGE *error); +bool tox_conference_send_message(Tox *tox, uint32_t conference_number, Tox_Message_Type type, const uint8_t *message, +                                 size_t length, Tox_Err_Conference_Send_Message *error); -typedef enum TOX_ERR_CONFERENCE_TITLE { +typedef enum Tox_Err_Conference_Title {      /**       * The function returned successfully. @@ -2873,19 +2878,21 @@ typedef enum TOX_ERR_CONFERENCE_TITLE {       */      TOX_ERR_CONFERENCE_TITLE_FAIL_SEND, -} TOX_ERR_CONFERENCE_TITLE; +} Tox_Err_Conference_Title;  /** - * Return the length of the conference title. Return value is unspecified on failure. + * @brief Return the length of the conference title. + * + * Return value is unspecified on failure.   *   * The return value is equal to the `length` argument received by the last   * `conference_title` callback.   */ -size_t tox_conference_get_title_size(const Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_TITLE *error); +size_t tox_conference_get_title_size(const Tox *tox, uint32_t conference_number, Tox_Err_Conference_Title *error);  /** - * Write the title designated by the given conference number to a byte array. + * @brief Write the title designated by the given conference number to a byte array.   *   * Call tox_conference_get_title_size to determine the allocation size for the `title` parameter.   * @@ -2898,27 +2905,30 @@ size_t tox_conference_get_title_size(const Tox *tox, uint32_t conference_number,   * @return true on success.   */  bool tox_conference_get_title(const Tox *tox, uint32_t conference_number, uint8_t *title, -                              TOX_ERR_CONFERENCE_TITLE *error); +                              Tox_Err_Conference_Title *error);  /** - * Set the conference title and broadcast it to the rest of the conference. + * @brief Set the conference title and broadcast it to the rest of the conference.   *   * Title length cannot be longer than TOX_MAX_NAME_LENGTH.   *   * @return true on success.   */  bool tox_conference_set_title(Tox *tox, uint32_t conference_number, const uint8_t *title, size_t length, -                              TOX_ERR_CONFERENCE_TITLE *error); +                              Tox_Err_Conference_Title *error);  /** - * Return the number of conferences in the Tox instance. + * @brief Return the number of conferences in the Tox instance. + *   * This should be used to determine how much memory to allocate for `tox_conference_get_chatlist`.   */  size_t tox_conference_get_chatlist_size(const Tox *tox);  /** - * Copy a list of valid conference numbers into the array chatlist. Determine - * how much space to allocate for the array with the `tox_conference_get_chatlist_size` function. + * @brief Copy a list of valid conference numbers into the array chatlist. + * + * Determine how much space to allocate for the array with the + * `tox_conference_get_chatlist_size` function.   *   * Note that `tox_get_savedata` saves all connected conferences;   * when toxcore is created from savedata in which conferences were saved, those @@ -2931,10 +2941,11 @@ size_t tox_conference_get_chatlist_size(const Tox *tox);  void tox_conference_get_chatlist(const Tox *tox, uint32_t *chatlist);  /** - * Returns the type of conference (TOX_CONFERENCE_TYPE) that conference_number is. Return value is - * unspecified on failure. + * @brief Returns the type of conference (Tox_Conference_Type) that conference_number is. + * + * Return value is unspecified on failure.   */ -typedef enum TOX_ERR_CONFERENCE_GET_TYPE { +typedef enum Tox_Err_Conference_Get_Type {      /**       * The function returned successfully. @@ -2946,14 +2957,17 @@ typedef enum TOX_ERR_CONFERENCE_GET_TYPE {       */      TOX_ERR_CONFERENCE_GET_TYPE_CONFERENCE_NOT_FOUND, -} TOX_ERR_CONFERENCE_GET_TYPE; +} Tox_Err_Conference_Get_Type; -TOX_CONFERENCE_TYPE tox_conference_get_type(const Tox *tox, uint32_t conference_number, -        TOX_ERR_CONFERENCE_GET_TYPE *error); +/** + * @brief Get the type (text or A/V) for the conference. + */ +Tox_Conference_Type tox_conference_get_type(const Tox *tox, uint32_t conference_number, +        Tox_Err_Conference_Get_Type *error);  /** - * Get the conference unique ID. + * @brief Get the conference unique ID.   *   * If id is NULL, this function has no effect.   * @@ -2963,7 +2977,7 @@ TOX_CONFERENCE_TYPE tox_conference_get_type(const Tox *tox, uint32_t conference_   */  bool tox_conference_get_id(const Tox *tox, uint32_t conference_number, uint8_t *id); -typedef enum TOX_ERR_CONFERENCE_BY_ID { +typedef enum Tox_Err_Conference_By_Id {      /**       * The function returned successfully. @@ -2980,20 +2994,20 @@ typedef enum TOX_ERR_CONFERENCE_BY_ID {       */      TOX_ERR_CONFERENCE_BY_ID_NOT_FOUND, -} TOX_ERR_CONFERENCE_BY_ID; +} Tox_Err_Conference_By_Id;  /** - * Return the conference number associated with the specified id. + * @brief Return the conference number associated with the specified id.   *   * @param id A byte array containing the conference id (TOX_CONFERENCE_ID_SIZE).   *   * @return the conference number on success, an unspecified value on failure.   */ -uint32_t tox_conference_by_id(const Tox *tox, const uint8_t *id, TOX_ERR_CONFERENCE_BY_ID *error); +uint32_t tox_conference_by_id(const Tox *tox, const uint8_t *id, Tox_Err_Conference_By_Id *error);  /** - * Get the conference unique ID. + * @brief Get the conference unique ID.   *   * If uid is NULL, this function has no effect.   * @@ -3004,7 +3018,7 @@ uint32_t tox_conference_by_id(const Tox *tox, const uint8_t *id, TOX_ERR_CONFERE   */  bool tox_conference_get_uid(const Tox *tox, uint32_t conference_number, uint8_t *uid); -typedef enum TOX_ERR_CONFERENCE_BY_UID { +typedef enum Tox_Err_Conference_By_Uid {      /**       * The function returned successfully. @@ -3021,29 +3035,27 @@ typedef enum TOX_ERR_CONFERENCE_BY_UID {       */      TOX_ERR_CONFERENCE_BY_UID_NOT_FOUND, -} TOX_ERR_CONFERENCE_BY_UID; +} Tox_Err_Conference_By_Uid;  /** - * Return the conference number associated with the specified uid. + * @brief Return the conference number associated with the specified uid.   *   * @param uid A byte array containing the conference id (TOX_CONFERENCE_UID_SIZE).   *   * @return the conference number on success, an unspecified value on failure.   * @deprecated use tox_conference_by_id instead (exactly the same function, just renamed).   */ -uint32_t tox_conference_by_uid(const Tox *tox, const uint8_t *uid, TOX_ERR_CONFERENCE_BY_UID *error); +uint32_t tox_conference_by_uid(const Tox *tox, const uint8_t *uid, Tox_Err_Conference_By_Uid *error); - -/******************************************************************************* - * - * :: Low-level custom packet sending and receiving - * - ******************************************************************************/ +/** @} */ +/** @{ + * @name Low-level custom packet sending and receiving + */ -typedef enum TOX_ERR_FRIEND_CUSTOM_PACKET { +typedef enum Tox_Err_Friend_Custom_Packet {      /**       * The function returned successfully. @@ -3086,11 +3098,11 @@ typedef enum TOX_ERR_FRIEND_CUSTOM_PACKET {       */      TOX_ERR_FRIEND_CUSTOM_PACKET_SENDQ, -} TOX_ERR_FRIEND_CUSTOM_PACKET; +} Tox_Err_Friend_Custom_Packet;  /** - * Send a custom lossy packet to a friend. + * @brief Send a custom lossy packet to a friend.   *   * The first byte of data must be in the range 192-254. Maximum length of a   * custom packet is TOX_MAX_CUSTOM_PACKET_SIZE. @@ -3110,10 +3122,10 @@ typedef enum TOX_ERR_FRIEND_CUSTOM_PACKET {   * @return true on success.   */  bool tox_friend_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, -                                  TOX_ERR_FRIEND_CUSTOM_PACKET *error); +                                  Tox_Err_Friend_Custom_Packet *error);  /** - * Send a custom lossless packet to a friend. + * @brief Send a custom lossless packet to a friend.   *   * The first byte of data must be in the range 69, 160-191. Maximum length of a   * custom packet is TOX_MAX_CUSTOM_PACKET_SIZE. @@ -3129,7 +3141,7 @@ bool tox_friend_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_   * @return true on success.   */  bool tox_friend_send_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, -                                     TOX_ERR_FRIEND_CUSTOM_PACKET *error); +                                     Tox_Err_Friend_Custom_Packet *error);  /**   * @param friend_number The friend number of the friend who sent a lossy packet. @@ -3141,8 +3153,9 @@ typedef void tox_friend_lossy_packet_cb(Tox *tox, uint32_t friend_number, const  /** - * Set the callback for the `friend_lossy_packet` event. Pass NULL to unset. + * @brief Set the callback for the `friend_lossy_packet` event.   * + * Pass NULL to unset.   */  void tox_callback_friend_lossy_packet(Tox *tox, tox_friend_lossy_packet_cb *callback); @@ -3156,21 +3169,20 @@ typedef void tox_friend_lossless_packet_cb(Tox *tox, uint32_t friend_number, con  /** - * Set the callback for the `friend_lossless_packet` event. Pass NULL to unset. + * @brief Set the callback for the `friend_lossless_packet` event.   * + * Pass NULL to unset.   */  void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb *callback); - -/******************************************************************************* - * - * :: Low-level network information - * - ******************************************************************************/ +/** @} */ +/** @{ + * @name Low-level network information + */ -typedef enum TOX_ERR_GET_PORT { +typedef enum Tox_Err_Get_Port {      /**       * The function returned successfully. @@ -3182,11 +3194,11 @@ typedef enum TOX_ERR_GET_PORT {       */      TOX_ERR_GET_PORT_NOT_BOUND, -} TOX_ERR_GET_PORT; +} Tox_Err_Get_Port;  /** - * Writes the temporary DHT public key of this instance to a byte array. + * @brief Writes the temporary DHT public key of this instance to a byte array.   *   * This can be used in combination with an externally accessible IP address and   * the bound port (from tox_self_get_udp_port) to run a temporary bootstrap node. @@ -3200,59 +3212,67 @@ typedef enum TOX_ERR_GET_PORT {  void tox_self_get_dht_id(const Tox *tox, uint8_t *dht_id);  /** - * Return the UDP port this Tox instance is bound to. + * @brief Return the UDP port this Tox instance is bound to.   */ -uint16_t tox_self_get_udp_port(const Tox *tox, TOX_ERR_GET_PORT *error); +uint16_t tox_self_get_udp_port(const Tox *tox, Tox_Err_Get_Port *error);  /** - * Return the TCP port this Tox instance is bound to. This is only relevant if - * the instance is acting as a TCP relay. + * @brief Return the TCP port this Tox instance is bound to. + * + * This is only relevant if the instance is acting as a TCP relay.   */ -uint16_t tox_self_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error); +uint16_t tox_self_get_tcp_port(const Tox *tox, Tox_Err_Get_Port *error); + +/** @} */  #ifdef __cplusplus  }  #endif -typedef TOX_ERR_OPTIONS_NEW Tox_Err_Options_New; -typedef TOX_ERR_NEW Tox_Err_New; -typedef TOX_ERR_BOOTSTRAP Tox_Err_Bootstrap; -typedef TOX_ERR_SET_INFO Tox_Err_Set_Info; -typedef TOX_ERR_FRIEND_ADD Tox_Err_Friend_Add; -typedef TOX_ERR_FRIEND_DELETE Tox_Err_Friend_Delete; -typedef TOX_ERR_FRIEND_BY_PUBLIC_KEY Tox_Err_Friend_By_Public_Key; -typedef TOX_ERR_FRIEND_GET_PUBLIC_KEY Tox_Err_Friend_Get_Public_Key; -typedef TOX_ERR_FRIEND_GET_LAST_ONLINE Tox_Err_Friend_Get_Last_Online; -typedef TOX_ERR_FRIEND_QUERY Tox_Err_Friend_Query; -typedef TOX_ERR_SET_TYPING Tox_Err_Set_Typing; -typedef TOX_ERR_FRIEND_SEND_MESSAGE Tox_Err_Friend_Send_Message; -typedef TOX_ERR_FILE_CONTROL Tox_Err_File_Control; -typedef TOX_ERR_FILE_SEEK Tox_Err_File_Seek; -typedef TOX_ERR_FILE_GET Tox_Err_File_Get; -typedef TOX_ERR_FILE_SEND Tox_Err_File_Send; -typedef TOX_ERR_FILE_SEND_CHUNK Tox_Err_File_Send_Chunk; -typedef TOX_ERR_CONFERENCE_NEW Tox_Err_Conference_New; -typedef TOX_ERR_CONFERENCE_DELETE Tox_Err_Conference_Delete; -typedef TOX_ERR_CONFERENCE_PEER_QUERY Tox_Err_Conference_Peer_Query; -typedef TOX_ERR_CONFERENCE_SET_MAX_OFFLINE Tox_Err_Conference_Set_Max_Offline; -typedef TOX_ERR_CONFERENCE_BY_ID Tox_Err_Conference_By_Id; -typedef TOX_ERR_CONFERENCE_BY_UID Tox_Err_Conference_By_Uid; -typedef TOX_ERR_CONFERENCE_INVITE Tox_Err_Conference_Invite; -typedef TOX_ERR_CONFERENCE_JOIN Tox_Err_Conference_Join; -typedef TOX_ERR_CONFERENCE_SEND_MESSAGE Tox_Err_Conference_Send_Message; -typedef TOX_ERR_CONFERENCE_TITLE Tox_Err_Conference_Title; -typedef TOX_ERR_CONFERENCE_GET_TYPE Tox_Err_Conference_Get_Type; -typedef TOX_ERR_FRIEND_CUSTOM_PACKET Tox_Err_Friend_Custom_Packet; -typedef TOX_ERR_GET_PORT Tox_Err_Get_Port; -typedef TOX_USER_STATUS Tox_User_Status; -typedef TOX_MESSAGE_TYPE Tox_Message_Type; -typedef TOX_PROXY_TYPE Tox_Proxy_Type; -typedef TOX_SAVEDATA_TYPE Tox_Savedata_Type; -typedef TOX_LOG_LEVEL Tox_Log_Level; -typedef TOX_CONNECTION Tox_Connection; -typedef TOX_FILE_CONTROL Tox_File_Control; -typedef TOX_CONFERENCE_TYPE Tox_Conference_Type; +//!TOKSTYLE- +#ifndef DOXYGEN_IGNORE + +typedef Tox_Err_Options_New TOX_ERR_OPTIONS_NEW; +typedef Tox_Err_New TOX_ERR_NEW; +typedef Tox_Err_Bootstrap TOX_ERR_BOOTSTRAP; +typedef Tox_Err_Set_Info TOX_ERR_SET_INFO; +typedef Tox_Err_Friend_Add TOX_ERR_FRIEND_ADD; +typedef Tox_Err_Friend_Delete TOX_ERR_FRIEND_DELETE; +typedef Tox_Err_Friend_By_Public_Key TOX_ERR_FRIEND_BY_PUBLIC_KEY; +typedef Tox_Err_Friend_Get_Public_Key TOX_ERR_FRIEND_GET_PUBLIC_KEY; +typedef Tox_Err_Friend_Get_Last_Online TOX_ERR_FRIEND_GET_LAST_ONLINE; +typedef Tox_Err_Friend_Query TOX_ERR_FRIEND_QUERY; +typedef Tox_Err_Set_Typing TOX_ERR_SET_TYPING; +typedef Tox_Err_Friend_Send_Message TOX_ERR_FRIEND_SEND_MESSAGE; +typedef Tox_Err_File_Control TOX_ERR_FILE_CONTROL; +typedef Tox_Err_File_Seek TOX_ERR_FILE_SEEK; +typedef Tox_Err_File_Get TOX_ERR_FILE_GET; +typedef Tox_Err_File_Send TOX_ERR_FILE_SEND; +typedef Tox_Err_File_Send_Chunk TOX_ERR_FILE_SEND_CHUNK; +typedef Tox_Err_Conference_New TOX_ERR_CONFERENCE_NEW; +typedef Tox_Err_Conference_Delete TOX_ERR_CONFERENCE_DELETE; +typedef Tox_Err_Conference_Peer_Query TOX_ERR_CONFERENCE_PEER_QUERY; +typedef Tox_Err_Conference_Set_Max_Offline TOX_ERR_CONFERENCE_SET_MAX_OFFLINE; +typedef Tox_Err_Conference_By_Id TOX_ERR_CONFERENCE_BY_ID; +typedef Tox_Err_Conference_By_Uid TOX_ERR_CONFERENCE_BY_UID; +typedef Tox_Err_Conference_Invite TOX_ERR_CONFERENCE_INVITE; +typedef Tox_Err_Conference_Join TOX_ERR_CONFERENCE_JOIN; +typedef Tox_Err_Conference_Send_Message TOX_ERR_CONFERENCE_SEND_MESSAGE; +typedef Tox_Err_Conference_Title TOX_ERR_CONFERENCE_TITLE; +typedef Tox_Err_Conference_Get_Type TOX_ERR_CONFERENCE_GET_TYPE; +typedef Tox_Err_Friend_Custom_Packet TOX_ERR_FRIEND_CUSTOM_PACKET; +typedef Tox_Err_Get_Port TOX_ERR_GET_PORT; +typedef Tox_User_Status TOX_USER_STATUS; +typedef Tox_Message_Type TOX_MESSAGE_TYPE; +typedef Tox_Proxy_Type TOX_PROXY_TYPE; +typedef Tox_Savedata_Type TOX_SAVEDATA_TYPE; +typedef Tox_Log_Level TOX_LOG_LEVEL; +typedef Tox_Connection TOX_CONNECTION; +typedef Tox_File_Control TOX_FILE_CONTROL; +typedef Tox_Conference_Type TOX_CONFERENCE_TYPE; +typedef enum Tox_File_Kind TOX_FILE_KIND; +#endif  //!TOKSTYLE+  #endif // C_TOXCORE_TOXCORE_TOX_H diff --git a/protocols/Tox/libtox/src/toxcore/tox_api.c b/protocols/Tox/libtox/src/toxcore/tox_api.c index 63b4bea335..89524ae4e2 100644 --- a/protocols/Tox/libtox/src/toxcore/tox_api.c +++ b/protocols/Tox/libtox/src/toxcore/tox_api.c @@ -1,11 +1,19 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2016-2021 The TokTok team. + */  #include "tox.h" -#include "ccompat.h" -  #include <stdlib.h>  #include <string.h> -#define SET_ERROR_PARAMETER(param, x) do { if (param) { *param = x; } } while (0) +#include "ccompat.h" + +#define SET_ERROR_PARAMETER(param, x) \ +    do {                              \ +        if (param) {                  \ +            *param = x;               \ +        }                             \ +    } while (0)  //!TOKSTYLE- @@ -90,7 +98,7 @@ void tox_options_default(struct Tox_Options *options)  struct Tox_Options *tox_options_new(Tox_Err_Options_New *error)  { -    struct Tox_Options *options = (struct Tox_Options *)malloc(sizeof(struct Tox_Options)); +    struct Tox_Options *options = (struct Tox_Options *)calloc(1, sizeof(struct Tox_Options));      if (options) {          tox_options_default(options); diff --git a/protocols/Tox/libtox/src/toxcore/util.c b/protocols/Tox/libtox/src/toxcore/util.c index 2f00adacb1..8174ef3fa2 100644 --- a/protocols/Tox/libtox/src/toxcore/util.c +++ b/protocols/Tox/libtox/src/toxcore/util.c @@ -4,13 +4,9 @@   * Copyright © 2013 plutooo   */ -/* +/**   * Utilities.   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -  #ifndef _XOPEN_SOURCE  #define _XOPEN_SOURCE 600  #endif @@ -24,7 +20,7 @@  #include "crypto_core.h" /* for CRYPTO_PUBLIC_KEY_SIZE */ -/* id functions */ +/** id functions */  bool id_equal(const uint8_t *dest, const uint8_t *src)  {      return public_key_cmp(dest, src) == 0; diff --git a/protocols/Tox/libtox/src/toxcore/util.h b/protocols/Tox/libtox/src/toxcore/util.h index 5483ff049e..bcae4f4a67 100644 --- a/protocols/Tox/libtox/src/toxcore/util.h +++ b/protocols/Tox/libtox/src/toxcore/util.h @@ -4,7 +4,7 @@   * Copyright © 2013 plutooo   */ -/* +/**   * Utilities.   */  #ifndef C_TOXCORE_TOXCORE_UTIL_H @@ -20,11 +20,11 @@  extern "C" {  #endif -/* id functions */ +/** id functions */  bool id_equal(const uint8_t *dest, const uint8_t *src);  uint32_t id_copy(uint8_t *dest, const uint8_t *src); /* return value is CLIENT_ID_SIZE */ -/* Returns -1 if failed or 0 if success */ +/** 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 diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h deleted file mode 100644 index 8249fa1c97..0000000000 --- a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef C_TOXCORE_TOXENCRYPTSAVE_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_H -#define C_TOXCORE_TOXENCRYPTSAVE_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#ifdef  VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ - -#ifndef crypto_pwhash_scryptsalsa208sha256_H -#define crypto_pwhash_scryptsalsa208sha256_H - -#include <stddef.h> -#include <stdint.h> - -#include "export.h" - -#ifdef __cplusplus -# if __GNUC__ -#  pragma GCC diagnostic ignored "-Wlong-long" -# endif -extern "C" { -#endif - -#define crypto_pwhash_scryptsalsa208sha256_SALTBYTES 32U -SODIUM_EXPORT -size_t crypto_pwhash_scryptsalsa208sha256_saltbytes(void); - -#define crypto_pwhash_scryptsalsa208sha256_STRBYTES 102U -SODIUM_EXPORT -size_t crypto_pwhash_scryptsalsa208sha256_strbytes(void); - -#define crypto_pwhash_scryptsalsa208sha256_STRPREFIX "$7$" -SODIUM_EXPORT -const char *crypto_pwhash_scryptsalsa208sha256_strprefix(void); - -#define crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE 524288ULL -SODIUM_EXPORT -size_t crypto_pwhash_scryptsalsa208sha256_opslimit_interactive(void); - -#define crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE 16777216ULL -SODIUM_EXPORT -size_t crypto_pwhash_scryptsalsa208sha256_memlimit_interactive(void); - -#define crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE 33554432ULL -SODIUM_EXPORT -size_t crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(void); - -#define crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE 1073741824ULL -SODIUM_EXPORT -size_t crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive(void); - -SODIUM_EXPORT -int crypto_pwhash_scryptsalsa208sha256(unsigned char * const out, -                                       unsigned long long outlen, -                                       const char * const passwd, -                                       unsigned long long passwdlen, -                                       const unsigned char * const salt, -                                       unsigned long long opslimit, -                                       size_t memlimit); - -SODIUM_EXPORT -int crypto_pwhash_scryptsalsa208sha256_str(char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES], -                                           const char * const passwd, -                                           unsigned long long passwdlen, -                                           unsigned long long opslimit, -                                           size_t memlimit); - -SODIUM_EXPORT -int crypto_pwhash_scryptsalsa208sha256_str_verify(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES], -                                                  const char * const passwd, -                                                  unsigned long long passwdlen); - -SODIUM_EXPORT -int crypto_pwhash_scryptsalsa208sha256_ll(const uint8_t * passwd, size_t passwdlen, -                                          const uint8_t * salt, size_t saltlen, -                                          uint64_t N, uint32_t r, uint32_t p, -                                          uint8_t * buf, size_t buflen); - -#ifdef __cplusplus -} -#endif - -/* Backward compatibility with version 0.5.0 */ - -#define crypto_pwhash_scryptxsalsa208sha256_SALTBYTES crypto_pwhash_scryptsalsa208sha256_SALTBYTES -#define crypto_pwhash_scryptxsalsa208sha256_saltbytes crypto_pwhash_scryptsalsa208sha256_saltbytes -#define crypto_pwhash_scryptxsalsa208sha256_STRBYTES crypto_pwhash_scryptsalsa208sha256_STRBYTES -#define crypto_pwhash_scryptxsalsa208sha256_strbytes crypto_pwhash_scryptsalsa208sha256_strbytes -#define crypto_pwhash_scryptxsalsa208sha256 crypto_pwhash_scryptsalsa208sha256 -#define crypto_pwhash_scryptxsalsa208sha256_str crypto_pwhash_scryptsalsa208sha256_str -#define crypto_pwhash_scryptxsalsa208sha256_str_verify crypto_pwhash_scryptsalsa208sha256_str_verify - -#endif - -#endif - -#endif diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt-common.c b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt-common.c deleted file mode 100644 index d3e420e068..0000000000 --- a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt-common.c +++ /dev/null @@ -1,257 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#ifdef  VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ - -/*- - * Copyright 2013 Alexander Peslyak - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <stdint.h> -#include <string.h> - -#include "crypto_pwhash_scryptsalsa208sha256.h" -#include "crypto_scrypt.h" -#include "runtime.h" -#include "../../toxcore/crypto_core.h" - -static const char * const itoa64 = -    "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - -static uint8_t * -encode64_uint32(uint8_t * dst, size_t dstlen, uint32_t src, uint32_t srcbits) -{ -    uint32_t bit; - -    for (bit = 0; bit < srcbits; bit += 6) { -        if (dstlen < 1) { -            return NULL; -        } -        *dst++ = itoa64[src & 0x3f]; -        dstlen--; -        src >>= 6; -    } - -    return dst; -} - -static uint8_t * -encode64(uint8_t * dst, size_t dstlen, const uint8_t * src, size_t srclen) -{ -    size_t i; - -    for (i = 0; i < srclen; ) { -        uint8_t * dnext; -        uint32_t value = 0, bits = 0; -        do { -            value |= (uint32_t)src[i++] << bits; -            bits += 8; -        } while (bits < 24 && i < srclen); -        dnext = encode64_uint32(dst, dstlen, value, bits); -        if (!dnext) { -            return NULL; -        } -        dstlen -= dnext - dst; -        dst = dnext; -    } - -    return dst; -} - -static int -decode64_one(uint32_t * dst, uint8_t src) -{ -    const char *ptr = strchr(itoa64, src); - -    if (ptr) { -        *dst = ptr - itoa64; -        return 0; -    } -    *dst = 0; -    return -1; -} - -static const uint8_t * -decode64_uint32(uint32_t * dst, uint32_t dstbits, const uint8_t * src) -{ -    uint32_t bit; -    uint32_t value; - -    value = 0; -    for (bit = 0; bit < dstbits; bit += 6) { -        uint32_t one; -        if (decode64_one(&one, *src)) { -            *dst = 0; -            return NULL; -        } -        src++; -        value |= one << bit; -    } - -    *dst = value; -    return src; -} - -uint8_t * -escrypt_r(escrypt_local_t * local, const uint8_t * passwd, size_t passwdlen, -          const uint8_t * setting, uint8_t * buf, size_t buflen) -{ -    uint8_t        hash[crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES]; -    escrypt_kdf_t  escrypt_kdf; -    const uint8_t *src; -    const uint8_t *salt; -    uint8_t       *dst; -    size_t         prefixlen; -    size_t         saltlen; -    size_t         need; -    uint64_t       N; -    uint32_t       N_log2; -    uint32_t       r; -    uint32_t       p; - -    if (setting[0] != '$' || setting[1] != '7' || setting[2] != '$') { -        return NULL; -    } -    src = setting + 3; - -    if (decode64_one(&N_log2, *src)) { -        return NULL; -    } -    src++; -    N = (uint64_t)1 << N_log2; - -    src = decode64_uint32(&r, 30, src); -    if (!src) { -        return NULL; -    } -    src = decode64_uint32(&p, 30, src); -    if (!src) { -        return NULL; -    } -    prefixlen = src - setting; - -    salt = src; -    src = (uint8_t *) strrchr((const char *)salt, '$'); -    if (src) { -        saltlen = src - salt; -    } else { -        saltlen = strlen((const char *)salt); -    } -    need = prefixlen + saltlen + 1 + -        crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1; -    if (need > buflen || need < saltlen) { -        return NULL; -    } -#if defined(HAVE_EMMINTRIN_H) || defined(_MSC_VER) -    escrypt_kdf = -        sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse; -#else -    escrypt_kdf = escrypt_kdf_nosse; -#endif -    if (escrypt_kdf(local, passwd, passwdlen, salt, saltlen, -                    N, r, p, hash, sizeof(hash))) { -        return NULL; -    } - -    dst = buf; -    memcpy(dst, setting, prefixlen + saltlen); -    dst += prefixlen + saltlen; -    *dst++ = '$'; - -    dst = encode64(dst, buflen - (dst - buf), hash, sizeof(hash)); -    crypto_memzero(hash, sizeof hash); -    if (!dst || dst >= buf + buflen) { /* Can't happen */ -        return NULL; -    } -    *dst = 0; /* NUL termination */ - -    return buf; -} - -uint8_t * -escrypt_gensalt_r(uint32_t N_log2, uint32_t r, uint32_t p, -                  const uint8_t * src, size_t srclen, -                  uint8_t * buf, size_t buflen) -{ -    uint8_t *dst; -    size_t   prefixlen = -        (sizeof "$7$" - 1U) + (1U /* N_log2 */) + (5U /* r */) + (5U /* p */); -    size_t   saltlen = BYTES2CHARS(srclen); -    size_t   need; - -    need = prefixlen + saltlen + 1; -    if (need > buflen || need < saltlen || saltlen < srclen) { -        return NULL; -    } -    if (N_log2 > 63 || ((uint64_t)r * (uint64_t)p >= (1U << 30))) { -        return NULL; -    } -    dst = buf; -    *dst++ = '$'; -    *dst++ = '7'; -    *dst++ = '$'; - -    *dst++ = itoa64[N_log2]; - -    dst = encode64_uint32(dst, buflen - (dst - buf), r, 30); -    if (!dst) { /* Can't happen */ -        return NULL; -    } -    dst = encode64_uint32(dst, buflen - (dst - buf), p, 30); -    if (!dst) { /* Can't happen */ -        return NULL; -    } -    dst = encode64(dst, buflen - (dst - buf), src, srclen); -    if (!dst || dst >= buf + buflen) { /* Can't happen */ -        return NULL; -    } -    *dst = 0; /* NUL termination */ - -    return buf; -} - -int -crypto_pwhash_scryptsalsa208sha256_ll(const uint8_t * passwd, size_t passwdlen, -                                      const uint8_t * salt, size_t saltlen, -                                      uint64_t N, uint32_t r, uint32_t p, -                                      uint8_t * buf, size_t buflen) -{ -    escrypt_kdf_t   escrypt_kdf; -    escrypt_local_t local; -    int             retval; - -    if (escrypt_init_local(&local)) { -        return -1; -    } -#if defined(HAVE_EMMINTRIN_H) || defined(_MSC_VER) -    escrypt_kdf = -        sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse; -#else -    escrypt_kdf = escrypt_kdf_nosse; -#endif -    retval = escrypt_kdf(&local, -                         passwd, passwdlen, salt, saltlen, -                         N, r, p, buf, buflen); -    if (escrypt_free_local(&local)) { -        return -1; -    } -    return retval; -} - -#endif diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt.h b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt.h deleted file mode 100644 index 978ac918d0..0000000000 --- a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef C_TOXCORE_TOXENCRYPTSAVE_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_CRYPTO_SCRYPT_H -#define C_TOXCORE_TOXENCRYPTSAVE_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_CRYPTO_SCRYPT_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#ifdef  VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ - -/*- - * Copyright 2009 Colin Percival - * Copyright 2013 Alexander Peslyak - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - *    notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - *    notice, this list of conditions and the following disclaimer in the - *    documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ -#ifndef _CRYPTO_SCRYPT_H_ -#define _CRYPTO_SCRYPT_H_ - -#include <stdint.h> - -#define crypto_pwhash_scryptsalsa208sha256_STRPREFIXBYTES 14 -#define crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES 57 -#define crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES 32 -#define crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES_ENCODED 43 -#define crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES 32 -#define crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED 43 - -#define BYTES2CHARS(bytes) ((((bytes) * 8) + 5) / 6) - -typedef struct { -	void * base, * aligned; -	size_t size; -} escrypt_region_t; - -typedef escrypt_region_t escrypt_local_t; - -extern int escrypt_init_local(escrypt_local_t * __local); - -extern int escrypt_free_local(escrypt_local_t * __local); - -extern void *alloc_region(escrypt_region_t * region, size_t size); -extern int free_region(escrypt_region_t * region); - -typedef int (*escrypt_kdf_t)(escrypt_local_t * __local, -                             const uint8_t * __passwd, size_t __passwdlen, -                             const uint8_t * __salt, size_t __saltlen, -                             uint64_t __N, uint32_t __r, uint32_t __p, -                             uint8_t * __buf, size_t __buflen); - -extern int escrypt_kdf_nosse(escrypt_local_t * __local, -    const uint8_t * __passwd, size_t __passwdlen, -    const uint8_t * __salt, size_t __saltlen, -    uint64_t __N, uint32_t __r, uint32_t __p, -    uint8_t * __buf, size_t __buflen); - -extern int escrypt_kdf_sse(escrypt_local_t * __local, -    const uint8_t * __passwd, size_t __passwdlen, -    const uint8_t * __salt, size_t __saltlen, -    uint64_t __N, uint32_t __r, uint32_t __p, -    uint8_t * __buf, size_t __buflen); - -extern uint8_t * escrypt_r(escrypt_local_t * __local, -    const uint8_t * __passwd, size_t __passwdlen, -    const uint8_t * __setting, -    uint8_t * __buf, size_t __buflen); - -extern uint8_t * escrypt_gensalt_r( -    uint32_t __N_log2, uint32_t __r, uint32_t __p, -    const uint8_t * __src, size_t __srclen, -    uint8_t * __buf, size_t __buflen); - -#endif /* !_CRYPTO_SCRYPT_H_ */ - -#endif - -#endif diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/export.h b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/export.h deleted file mode 100644 index ebf8d9dfb9..0000000000 --- a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/export.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef C_TOXCORE_TOXENCRYPTSAVE_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_EXPORT_H -#define C_TOXCORE_TOXENCRYPTSAVE_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_EXPORT_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#ifdef  VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ - -#ifndef __SODIUM_EXPORT_H__ -#define __SODIUM_EXPORT_H__ - -#ifndef __GNUC__ -# ifdef __attribute__ -#  undef __attribute__ -# endif -# define __attribute__(a) -#endif - -#ifdef SODIUM_STATIC -# define SODIUM_EXPORT -#else -# if defined(_MSC_VER) -#  ifdef DLL_EXPORT -#   define SODIUM_EXPORT __declspec(dllexport) -#  else -#   define SODIUM_EXPORT __declspec(dllimport) -#  endif -# else -#  if defined(__SUNPRO_C) -#   define SODIUM_EXPORT __attribute__ __global -#  elif defined(_MSG_VER) -#   define SODIUM_EXPORT extern __declspec(dllexport) -#  else -#   define SODIUM_EXPORT __attribute__ ((visibility ("default"))) -#  endif -# endif -#endif - -#endif - -#endif - -#endif diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c deleted file mode 100644 index 97d9ba6878..0000000000 --- a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c +++ /dev/null @@ -1,309 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#ifdef  VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ - -/*- - * Copyright 2009 Colin Percival - * Copyright 2013 Alexander Peslyak - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - *    notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - *    notice, this list of conditions and the following disclaimer in the - *    documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ - -#include <errno.h> -#include <limits.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> - -#include "../pbkdf2-sha256.h" -#include "../sysendian.h" -#include "../crypto_scrypt.h" - -static inline void -blkcpy(void * dest, const void * src, size_t len) -{ -	size_t * D = (size_t *) dest; -	const size_t * S = (const size_t *) src; -	size_t L = len / sizeof(size_t); -	size_t i; - -	for (i = 0; i < L; i++) -		D[i] = S[i]; -} - -static inline void -blkxor(void * dest, const void * src, size_t len) -{ -	size_t * D = (size_t *) dest; -	const size_t * S = (const size_t *) src; -	size_t L = len / sizeof(size_t); -	size_t i; - -	for (i = 0; i < L; i++) -		D[i] ^= S[i]; -} - -/** - * salsa20_8(B): - * Apply the salsa20/8 core to the provided block. - */ -static void -salsa20_8(uint32_t B[16]) -{ -	uint32_t x[16]; -	size_t i; - -	blkcpy(x, B, 64); -	for (i = 0; i < 8; i += 2) { -#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) -		/* Operate on columns. */ -		x[ 4] ^= R(x[ 0]+x[12], 7);  x[ 8] ^= R(x[ 4]+x[ 0], 9); -		x[12] ^= R(x[ 8]+x[ 4],13);  x[ 0] ^= R(x[12]+x[ 8],18); - -		x[ 9] ^= R(x[ 5]+x[ 1], 7);  x[13] ^= R(x[ 9]+x[ 5], 9); -		x[ 1] ^= R(x[13]+x[ 9],13);  x[ 5] ^= R(x[ 1]+x[13],18); - -		x[14] ^= R(x[10]+x[ 6], 7);  x[ 2] ^= R(x[14]+x[10], 9); -		x[ 6] ^= R(x[ 2]+x[14],13);  x[10] ^= R(x[ 6]+x[ 2],18); - -		x[ 3] ^= R(x[15]+x[11], 7);  x[ 7] ^= R(x[ 3]+x[15], 9); -		x[11] ^= R(x[ 7]+x[ 3],13);  x[15] ^= R(x[11]+x[ 7],18); - -		/* Operate on rows. */ -		x[ 1] ^= R(x[ 0]+x[ 3], 7);  x[ 2] ^= R(x[ 1]+x[ 0], 9); -		x[ 3] ^= R(x[ 2]+x[ 1],13);  x[ 0] ^= R(x[ 3]+x[ 2],18); - -		x[ 6] ^= R(x[ 5]+x[ 4], 7);  x[ 7] ^= R(x[ 6]+x[ 5], 9); -		x[ 4] ^= R(x[ 7]+x[ 6],13);  x[ 5] ^= R(x[ 4]+x[ 7],18); - -		x[11] ^= R(x[10]+x[ 9], 7);  x[ 8] ^= R(x[11]+x[10], 9); -		x[ 9] ^= R(x[ 8]+x[11],13);  x[10] ^= R(x[ 9]+x[ 8],18); - -		x[12] ^= R(x[15]+x[14], 7);  x[13] ^= R(x[12]+x[15], 9); -		x[14] ^= R(x[13]+x[12],13);  x[15] ^= R(x[14]+x[13],18); -#undef R -	} -	for (i = 0; i < 16; i++) -		B[i] += x[i]; -} - -/** - * blockmix_salsa8(Bin, Bout, X, r): - * Compute Bout = BlockMix_{salsa20/8, r}(Bin).  The input Bin must be 128r - * bytes in length; the output Bout must also be the same size.  The - * temporary space X must be 64 bytes. - */ -static void -blockmix_salsa8(const uint32_t * Bin, uint32_t * Bout, uint32_t * X, size_t r) -{ -	size_t i; - -	/* 1: X <-- B_{2r - 1} */ -	blkcpy(X, &Bin[(2 * r - 1) * 16], 64); - -	/* 2: for i = 0 to 2r - 1 do */ -	for (i = 0; i < 2 * r; i += 2) { -		/* 3: X <-- H(X \xor B_i) */ -		blkxor(X, &Bin[i * 16], 64); -		salsa20_8(X); - -		/* 4: Y_i <-- X */ -		/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ -		blkcpy(&Bout[i * 8], X, 64); - -		/* 3: X <-- H(X \xor B_i) */ -		blkxor(X, &Bin[i * 16 + 16], 64); -		salsa20_8(X); - -		/* 4: Y_i <-- X */ -		/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ -		blkcpy(&Bout[i * 8 + r * 16], X, 64); -	} -} - -/** - * integerify(B, r): - * Return the result of parsing B_{2r-1} as a little-endian integer. - */ -static inline uint64_t -integerify(const void * B, size_t r) -{ -	const uint32_t * X = (const uint32_t *)((uintptr_t)(B) + (2 * r - 1) * 64); - -	return (((uint64_t)(X[1]) << 32) + X[0]); -} - -/** - * smix(B, r, N, V, XY): - * Compute B = SMix_r(B, N).  The input B must be 128r bytes in length; - * the temporary storage V must be 128rN bytes in length; the temporary - * storage XY must be 256r + 64 bytes in length.  The value N must be a - * power of 2 greater than 1.  The arrays B, V, and XY must be aligned to a - * multiple of 64 bytes. - */ -static void -smix(uint8_t * B, size_t r, uint64_t N, uint32_t * V, uint32_t * XY) -{ -	uint32_t * X = XY; -	uint32_t * Y = &XY[32 * r]; -	uint32_t * Z = &XY[64 * r]; -	uint64_t i; -	uint64_t j; -	size_t k; - -	/* 1: X <-- B */ -	for (k = 0; k < 32 * r; k++) -		X[k] = le32dec(&B[4 * k]); - -	/* 2: for i = 0 to N - 1 do */ -	for (i = 0; i < N; i += 2) { -		/* 3: V_i <-- X */ -		blkcpy(&V[i * (32 * r)], X, 128 * r); - -		/* 4: X <-- H(X) */ -		blockmix_salsa8(X, Y, Z, r); - -		/* 3: V_i <-- X */ -		blkcpy(&V[(i + 1) * (32 * r)], Y, 128 * r); - -		/* 4: X <-- H(X) */ -		blockmix_salsa8(Y, X, Z, r); -	} - -	/* 6: for i = 0 to N - 1 do */ -	for (i = 0; i < N; i += 2) { -		/* 7: j <-- Integerify(X) mod N */ -		j = integerify(X, r) & (N - 1); - -		/* 8: X <-- H(X \xor V_j) */ -		blkxor(X, &V[j * (32 * r)], 128 * r); -		blockmix_salsa8(X, Y, Z, r); - -		/* 7: j <-- Integerify(X) mod N */ -		j = integerify(Y, r) & (N - 1); - -		/* 8: X <-- H(X \xor V_j) */ -		blkxor(Y, &V[j * (32 * r)], 128 * r); -		blockmix_salsa8(Y, X, Z, r); -	} -	/* 10: B' <-- X */ -	for (k = 0; k < 32 * r; k++) -		le32enc(&B[4 * k], X[k]); -} - -/** - * escrypt_kdf(local, passwd, passwdlen, salt, saltlen, - *     N, r, p, buf, buflen): - * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, - * p, buflen) and write the result into buf.  The parameters r, p, and buflen - * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32.  The parameter N - * must be a power of 2 greater than 1. - * - * Return 0 on success; or -1 on error. - */ -int -escrypt_kdf_nosse(escrypt_local_t * local, -    const uint8_t * passwd, size_t passwdlen, -    const uint8_t * salt, size_t saltlen, -    uint64_t N, uint32_t _r, uint32_t _p, -    uint8_t * buf, size_t buflen) -{ -	size_t B_size, V_size, XY_size, need; -	uint8_t * B; -	uint32_t * V, * XY; -    size_t r = _r, p = _p; -	uint32_t i; - -	/* Sanity-check parameters. */ -#if SIZE_MAX > UINT32_MAX -	if (buflen > (((uint64_t)(1) << 32) - 1) * 32) { -		errno = EFBIG; -		return -1; -	} -#endif -	if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) { -		errno = EFBIG; -		return -1; -	} -	if (((N & (N - 1)) != 0) || (N < 2)) { -		errno = EINVAL; -		return -1; -	} -	if (r == 0 || p == 0) { -		errno = EINVAL; -		return -1; -	} -	if ((r > SIZE_MAX / 128 / p) || -#if SIZE_MAX / 256 <= UINT32_MAX -	    (r > SIZE_MAX / 256) || -#endif -	    (N > SIZE_MAX / 128 / r)) { -		errno = ENOMEM; -		return -1; -	} - -	/* Allocate memory. */ -	B_size = (size_t)128 * r * p; -	V_size = (size_t)128 * r * N; -	need = B_size + V_size; -	if (need < V_size) { -		errno = ENOMEM; -		return -1; -	} -	XY_size = (size_t)256 * r + 64; -	need += XY_size; -	if (need < XY_size) { -		errno = ENOMEM; -		return -1; -	} -	if (local->size < need) { -		if (free_region(local)) -			return -1; -		if (!alloc_region(local, need)) -			return -1; -	} -	B = (uint8_t *)local->aligned; -	V = (uint32_t *)((uint8_t *)B + B_size); -	XY = (uint32_t *)((uint8_t *)V + V_size); - -	/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ -	PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, B_size); - -	/* 2: for i = 0 to p - 1 do */ -	for (i = 0; i < p; i++) { -		/* 3: B_i <-- MF(B_i, N) */ -		smix(&B[(size_t)128 * i * r], r, N, V, XY); -	} - -	/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ -	PBKDF2_SHA256(passwd, passwdlen, B, B_size, 1, buf, buflen); - -	/* Success! */ -	return 0; -} - -#endif diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/note_to_maintainers.txt b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/note_to_maintainers.txt deleted file mode 100644 index 66bbfe2db9..0000000000 --- a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/note_to_maintainers.txt +++ /dev/null @@ -1,14 +0,0 @@ -This folder is only meant for use with nacl, i.e. when sodium is unavailable. - - -The files in this folder were mostly copied from -https://github.com/jedisct1/libsodium/tree/0.7.0/src/libsodium/crypto_pwhash/scryptsalsa208sha256, -with #ifdef VANILLA_NACL added around each of them as required for this module. - -export.h, utils.h, and runtime.h were copied from -https://github.com/jedisct1/libsodium/tree/0.7.0/src/libsodium/include/sodium. -utils.h was significantly truncated. - -utils.c and runtime.c were copied from  -https://github.com/jedisct1/libsodium/blob/0.7.0/src/libsodium/sodium. -utils.c was also significantly truncated. diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.c b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.c deleted file mode 100644 index c69d7c22e7..0000000000 --- a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.c +++ /dev/null @@ -1,97 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#ifdef  VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ - -/*- - * Copyright 2005,2007,2009 Colin Percival - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - *    notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - *    notice, this list of conditions and the following disclaimer in the - *    documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/types.h> - -#include <stdint.h> -#include <stdlib.h> -#include <string.h> - -#include <crypto_hash_sha256.h> -#include <crypto_auth_hmacsha256.h> - -#include "pbkdf2-sha256.h" -#include "sysendian.h" -#include "../../toxcore/crypto_core.h" - -/** - * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): - * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and - * write the output to buf.  The value dkLen must be at most 32 * (2^32 - 1). - */ -void -PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, -              size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen) -{ -        uint8_t         key[32] = {0}; -        size_t          i; -        uint8_t         salt_and_ivec[saltlen + 4]; -        uint8_t         U[32]; -        uint8_t         T[32]; -        uint64_t        j; -        int             k; -        size_t          clen; - -    if (passwdlen > 32) { -        /* For some reason libsodium allows 64byte keys meaning keys -         * between 32byte and 64bytes are not compatible with libsodium. -           toxencryptsave should only give 32byte passwds so this isn't an issue here.*/ -        crypto_hash_sha256(key, passwd, passwdlen); -    } else { -        memcpy(key, passwd, passwdlen); -    } - -    memcpy(salt_and_ivec, salt, saltlen); - -        for (i = 0; i * 32 < dkLen; i++) { -                be32enc(salt_and_ivec + saltlen, (uint32_t)(i + 1)); -                crypto_auth_hmacsha256(U, salt_and_ivec, sizeof(salt_and_ivec), key); - -                memcpy(T, U, 32); - -                for (j = 2; j <= c; j++) { -                        crypto_auth_hmacsha256(U, U, 32, key); - -                        for (k = 0; k < 32; k++) { -                                T[k] ^= U[k]; -            } -                } - -                clen = dkLen - i * 32; -                if (clen > 32) { -                        clen = 32; -        } -                memcpy(&buf[i * 32], T, clen); -        } -    crypto_memzero((void *) key, sizeof(key)); -} - -#endif diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.h b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.h deleted file mode 100644 index 17cd211258..0000000000 --- a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef C_TOXCORE_TOXENCRYPTSAVE_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_PBKDF2_SHA256_H -#define C_TOXCORE_TOXENCRYPTSAVE_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_PBKDF2_SHA256_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#ifdef  VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ - -/*- - * Copyright 2005,2007,2009 Colin Percival - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - *    notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - *    notice, this list of conditions and the following disclaimer in the - *    documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#ifndef _SHA256_H_ -#define _SHA256_H_ - -#include <sys/types.h> - -#include <stdint.h> - -#include "crypto_auth_hmacsha256.h" - -/** - * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): - * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and - * write the output to buf.  The value dkLen must be at most 32 * (2^32 - 1). - */ -void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t, -                   uint64_t, uint8_t *, size_t); - -#endif /* !_SHA256_H_ */ - -#endif - -#endif diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c deleted file mode 100644 index 3aab156f9d..0000000000 --- a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c +++ /dev/null @@ -1,210 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#ifdef  VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ - -#include <errno.h> -#include <limits.h> -#include <stddef.h> -#include <stdint.h> -#include <string.h> -//#include <stdio.h> - -#include "crypto_pwhash_scryptsalsa208sha256.h" -#include "crypto_scrypt.h" -#include "../../toxcore/crypto_core.h" - -#define SETTING_SIZE(saltbytes) \ -    (sizeof "$7$" - 1U) + \ -    (1U /* N_log2 */) + (5U /* r */) + (5U /* p */) + BYTES2CHARS(saltbytes) - -static int -pickparams(unsigned long long opslimit, const size_t memlimit, -           uint32_t * const N_log2, uint32_t * const p, uint32_t * const r) -{ -    unsigned long long maxN; -    unsigned long long maxrp; - -    if (opslimit < 32768) { -        opslimit = 32768; -    } -    *r = 8; -    if (opslimit < memlimit / 32) { -        *p = 1; -        maxN = opslimit / (*r * 4); -        for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) { -            if ((uint64_t)(1) << *N_log2 > maxN / 2) { -                break; -            } -        } -    } else { -        maxN = memlimit / (*r * 128); -        for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) { -            if ((uint64_t) (1) << *N_log2 > maxN / 2) { -                break; -            } -        } -        maxrp = (opslimit / 4) / ((uint64_t) (1) << *N_log2); -        if (maxrp > 0x3fffffff) { -            maxrp = 0x3fffffff; -        } -        *p = (uint32_t) (maxrp) / *r; -    } -    return 0; -} - -size_t -crypto_pwhash_scryptsalsa208sha256_saltbytes(void) -{ -    return crypto_pwhash_scryptsalsa208sha256_SALTBYTES; -} - -size_t -crypto_pwhash_scryptsalsa208sha256_strbytes(void) -{ -    return crypto_pwhash_scryptsalsa208sha256_STRBYTES; -} - -const char * -crypto_pwhash_scryptsalsa208sha256_strprefix(void) -{ -    return crypto_pwhash_scryptsalsa208sha256_STRPREFIX; -} - -size_t -crypto_pwhash_scryptsalsa208sha256_opslimit_interactive(void) -{ -    return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE; -} - -size_t -crypto_pwhash_scryptsalsa208sha256_memlimit_interactive(void) -{ -    return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE; -} - -size_t -crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(void) -{ -    return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE; -} - -size_t -crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive(void) -{ -    return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE; -} - -int -crypto_pwhash_scryptsalsa208sha256(unsigned char * const out, -                                    unsigned long long outlen, -                                    const char * const passwd, -                                    unsigned long long passwdlen, -                                    const unsigned char * const salt, -                                    unsigned long long opslimit, -                                    size_t memlimit) -{ -    //fprintf(stderr, "Doing that dirty thang!!!!\n"); -    uint32_t N_log2; -    uint32_t p; -    uint32_t r; - -    memset(out, 0, outlen); -    if (passwdlen > SIZE_MAX || outlen > SIZE_MAX) { -        errno = EFBIG; -        return -1; -    } -    if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) { -        errno = EINVAL; -        return -1; -    } -    return crypto_pwhash_scryptsalsa208sha256_ll((const uint8_t *) passwd, -                                                 (size_t) passwdlen, -                                                 (const uint8_t *) salt, -                                                 crypto_pwhash_scryptsalsa208sha256_SALTBYTES, -                                                 (uint64_t) (1) << N_log2, r, p, -                                                 out, (size_t) outlen); -} - -int -crypto_pwhash_scryptsalsa208sha256_str(char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES], -                                        const char * const passwd, -                                        unsigned long long passwdlen, -                                        unsigned long long opslimit, -                                        size_t memlimit) -{ -    uint8_t         salt[crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES]; -    char            setting[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U]; -    escrypt_local_t escrypt_local; -    uint32_t        N_log2; -    uint32_t        p; -    uint32_t        r; - -    memset(out, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES); -    if (passwdlen > SIZE_MAX) { -        errno = EFBIG; -        return -1; -    } -    if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) { -        errno = EINVAL; -        return -1; -    } -    random_bytes(salt, sizeof salt); -    if (escrypt_gensalt_r(N_log2, r, p, salt, sizeof salt, -                          (uint8_t *) setting, sizeof setting) == NULL) { -        errno = EINVAL; -        return -1; -    } -    if (escrypt_init_local(&escrypt_local) != 0) { -        return -1; -    } -    if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen, -                  (const uint8_t *) setting, (uint8_t *) out, -                  crypto_pwhash_scryptsalsa208sha256_STRBYTES) == NULL) { -        escrypt_free_local(&escrypt_local); -        errno = EINVAL; -        return -1; -    } -    escrypt_free_local(&escrypt_local); - -    (void) sizeof -        (int[SETTING_SIZE(crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES) -            == crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES ? 1 : -1]); -    (void) sizeof -        (int[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U + -             crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1U -             == crypto_pwhash_scryptsalsa208sha256_STRBYTES ? 1 : -1]); - -    return 0; -} - -int -crypto_pwhash_scryptsalsa208sha256_str_verify(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES], -                                               const char * const passwd, -                                               unsigned long long passwdlen) -{ -    char            wanted[crypto_pwhash_scryptsalsa208sha256_STRBYTES]; -    escrypt_local_t escrypt_local; -    int             ret = -1; - -    if (memchr(str, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES) != -        &str[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U]) { -        return -1; -    } -    if (escrypt_init_local(&escrypt_local) != 0) { -        return -1; -    } -    if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen, -                  (const uint8_t *) str, (uint8_t *) wanted, -                  sizeof wanted) == NULL) { -        escrypt_free_local(&escrypt_local); -        return -1; -    } -    escrypt_free_local(&escrypt_local); -    ret = crypto_memcmp((const uint8_t *) wanted, (const uint8_t *) str, sizeof wanted); -    crypto_memzero(wanted, sizeof wanted); - -    return ret; -} - -#endif diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.c b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.c deleted file mode 100644 index a813b50609..0000000000 --- a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.c +++ /dev/null @@ -1,144 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#ifdef  VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ - -#ifdef HAVE_ANDROID_GETCPUFEATURES -# include <cpu-features.h> -#endif - -#include "runtime.h" - -typedef struct CPUFeatures_ { -    int initialized; -    int has_neon; -    int has_sse2; -    int has_sse3; -} CPUFeatures; - -static CPUFeatures _cpu_features; - -#ifdef HAVE_EMMINTRIN_H -#define CPUID_SSE2     0x04000000 -#endif -#ifdef HAVE_PMMINTRIN_H -#define CPUIDECX_SSE3  0x00000001 -#endif - -static int -_sodium_runtime_arm_cpu_features(CPUFeatures * const cpu_features) -{ -#ifndef __arm__ -    cpu_features->has_neon = 0; -    return -1; -#else -# ifdef __APPLE__ -#  ifdef __ARM_NEON__ -    cpu_features->has_neon = 1; -#  else -    cpu_features->has_neon = 0; -#  endif -# elif defined(HAVE_ANDROID_GETCPUFEATURES) && defined(ANDROID_CPU_ARM_FEATURE_NEON) -    cpu_features->has_neon = -        (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0x0; -# else -    cpu_features->has_neon = 0; -# endif -    return 0; -#endif -} - -static void -_cpuid(unsigned int cpu_info[4U], const unsigned int cpu_info_type) -{ -#ifdef _MSC_VER -    __cpuidex((int *) cpu_info, cpu_info_type, 0); -#elif defined(HAVE_CPUID) -    cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0; -# ifdef __i386__ -    __asm__ __volatile__ ("pushfl; pushfl; " -                          "popl %0; " -                          "movl %0, %1; xorl %2, %0; " -                          "pushl %0; " -                          "popfl; pushfl; popl %0; popfl" : -                          "=&r" (cpu_info[0]), "=&r" (cpu_info[1]) : -                          "i" (0x200000)); -    if (((cpu_info[0] ^ cpu_info[1]) & 0x200000) == 0x0) { -        return; -    } -# endif -# ifdef __i386__ -    __asm__ __volatile__ ("xchgl %%ebx, %k1; cpuid; xchgl %%ebx, %k1" : -                          "=a" (cpu_info[0]), "=&r" (cpu_info[1]), -                          "=c" (cpu_info[2]), "=d" (cpu_info[3]) : -                          "0" (cpu_info_type), "2" (0U)); -# elif defined(__x86_64__) -    __asm__ __volatile__ ("xchgq %%rbx, %q1; cpuid; xchgq %%rbx, %q1" : -                          "=a" (cpu_info[0]), "=&r" (cpu_info[1]), -                          "=c" (cpu_info[2]), "=d" (cpu_info[3]) : -                          "0" (cpu_info_type), "2" (0U)); -# else -    __asm__ __volatile__ ("cpuid" : -                          "=a" (cpu_info[0]), "=b" (cpu_info[1]), -                          "=c" (cpu_info[2]), "=d" (cpu_info[3]) : -                          "0" (cpu_info_type), "2" (0U)); -# endif -#else -    cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0; -#endif -} - -static int -_sodium_runtime_intel_cpu_features(CPUFeatures * const cpu_features) -{ -    unsigned int cpu_info[4]; -    unsigned int id; - -    _cpuid(cpu_info, 0x0); -    if ((id = cpu_info[0]) == 0U) { -        return -1; -    } -    _cpuid(cpu_info, 0x00000001); -#ifndef HAVE_EMMINTRIN_H -    cpu_features->has_sse2 = 0; -#else -    cpu_features->has_sse2 = ((cpu_info[3] & CPUID_SSE2) != 0x0); -#endif - -#ifndef HAVE_PMMINTRIN_H -    cpu_features->has_sse3 = 0; -#else -    cpu_features->has_sse3 = ((cpu_info[2] & CPUIDECX_SSE3) != 0x0); -#endif - -    return 0; -} - -int -sodium_runtime_get_cpu_features(void) -{ -    int ret = -1; - -    ret &= _sodium_runtime_arm_cpu_features(&_cpu_features); -    ret &= _sodium_runtime_intel_cpu_features(&_cpu_features); -    _cpu_features.initialized = 1; - -    return ret; -} - -int -sodium_runtime_has_neon(void) { -    return _cpu_features.has_neon; -} - -int -sodium_runtime_has_sse2(void) { -    return _cpu_features.has_sse2; -} - -int -sodium_runtime_has_sse3(void) { -    return _cpu_features.has_sse3; -} - -#endif diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.h b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.h deleted file mode 100644 index 260a4550a9..0000000000 --- a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef C_TOXCORE_TOXENCRYPTSAVE_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_RUNTIME_H -#define C_TOXCORE_TOXENCRYPTSAVE_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_RUNTIME_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#ifdef  VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ - -#ifndef __SODIUM_RUNTIME_H__ -#define __SODIUM_RUNTIME_H__ 1 - -#include "export.h" - -#ifdef __cplusplus -extern "C" { -#endif - -SODIUM_EXPORT -int sodium_runtime_get_cpu_features(void); - -SODIUM_EXPORT -int sodium_runtime_has_neon(void); - -SODIUM_EXPORT -int sodium_runtime_has_sse2(void); - -SODIUM_EXPORT -int sodium_runtime_has_sse3(void); - -#ifdef __cplusplus -} -#endif - -#endif - -#endif - -#endif diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/scrypt_platform.c b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/scrypt_platform.c deleted file mode 100644 index 5819651454..0000000000 --- a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/scrypt_platform.c +++ /dev/null @@ -1,107 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#ifdef  VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ - -/*- - * Copyright 2013 Alexander Peslyak - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifdef HAVE_SYS_MMAN_H -# include <sys/mman.h> -#endif -#include <errno.h> -#include <stdlib.h> - -#include "crypto_scrypt.h" -#include "runtime.h" - -#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS) -# define MAP_ANON MAP_ANONYMOUS -#endif - -void * -alloc_region(escrypt_region_t * region, size_t size) -{ -	uint8_t * base, * aligned; -#ifdef MAP_ANON -	if ((base = (uint8_t *) mmap(NULL, size, PROT_READ | PROT_WRITE, -#ifdef MAP_NOCORE -	    MAP_ANON | MAP_PRIVATE | MAP_NOCORE, -#else -	    MAP_ANON | MAP_PRIVATE, -#endif -	    -1, 0)) == MAP_FAILED) -		base = NULL; -	aligned = base; -#elif defined(HAVE_POSIX_MEMALIGN) -	if ((errno = posix_memalign((void **) &base, 64, size)) != 0) -		base = NULL; -	aligned = base; -#else -	base = aligned = NULL; -	if (size + 63 < size) -		errno = ENOMEM; -	else if ((base = (uint8_t *) malloc(size + 63)) != NULL) { -		aligned = base + 63; -		aligned -= (uintptr_t)aligned & 63; -	} -#endif -	region->base = base; -	region->aligned = aligned; -	region->size = base ? size : 0; -	return aligned; -} - -static inline void -init_region(escrypt_region_t * region) -{ -	region->base = region->aligned = NULL; -	region->size = 0; -} - -int -free_region(escrypt_region_t * region) -{ -	if (region->base) { -#ifdef MAP_ANON -		if (munmap(region->base, region->size)) -			return -1; -#else -		free(region->base); -#endif -	} -	init_region(region); -	return 0; -} - -int -escrypt_init_local(escrypt_local_t * local) -{ -	init_region(local); -	return 0; -} - -int -escrypt_free_local(escrypt_local_t * local) -{ -	return free_region(local); -} - -#endif diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c deleted file mode 100644 index 38a536a61a..0000000000 --- a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c +++ /dev/null @@ -1,401 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#ifdef  VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ - -/*- - * Copyright 2009 Colin Percival - * Copyright 2012,2013 Alexander Peslyak - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - *    notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - *    notice, this list of conditions and the following disclaimer in the - *    documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ - -#if defined(HAVE_EMMINTRIN_H) || defined(_MSC_VER) -#if __GNUC__ -# pragma GCC target("sse2") -#endif -#include <emmintrin.h> -#if defined(__XOP__) && defined(DISABLED) -# include <x86intrin.h> -#endif - -#include <errno.h> -#include <limits.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> - -#include "../pbkdf2-sha256.h" -#include "../sysendian.h" -#include "../crypto_scrypt.h" - -#if defined(__XOP__) && defined(DISABLED) -#define ARX(out, in1, in2, s) \ -	out = _mm_xor_si128(out, _mm_roti_epi32(_mm_add_epi32(in1, in2), s)); -#else -#define ARX(out, in1, in2, s) \ -	{ \ -		__m128i T = _mm_add_epi32(in1, in2); \ -		out = _mm_xor_si128(out, _mm_slli_epi32(T, s)); \ -		out = _mm_xor_si128(out, _mm_srli_epi32(T, 32-s)); \ -	} -#endif - -#define SALSA20_2ROUNDS \ -	/* Operate on "columns". */ \ -	ARX(X1, X0, X3, 7) \ -	ARX(X2, X1, X0, 9) \ -	ARX(X3, X2, X1, 13) \ -	ARX(X0, X3, X2, 18) \ -\ -	/* Rearrange data. */ \ -	X1 = _mm_shuffle_epi32(X1, 0x93); \ -	X2 = _mm_shuffle_epi32(X2, 0x4E); \ -	X3 = _mm_shuffle_epi32(X3, 0x39); \ -\ -	/* Operate on "rows". */ \ -	ARX(X3, X0, X1, 7) \ -	ARX(X2, X3, X0, 9) \ -	ARX(X1, X2, X3, 13) \ -	ARX(X0, X1, X2, 18) \ -\ -	/* Rearrange data. */ \ -	X1 = _mm_shuffle_epi32(X1, 0x39); \ -	X2 = _mm_shuffle_epi32(X2, 0x4E); \ -	X3 = _mm_shuffle_epi32(X3, 0x93); - -/** - * Apply the salsa20/8 core to the block provided in (X0 ... X3) ^ (Z0 ... Z3). - */ -#define SALSA20_8_XOR(in, out) \ -	{ \ -		__m128i Y0 = X0 = _mm_xor_si128(X0, (in)[0]); \ -		__m128i Y1 = X1 = _mm_xor_si128(X1, (in)[1]); \ -		__m128i Y2 = X2 = _mm_xor_si128(X2, (in)[2]); \ -		__m128i Y3 = X3 = _mm_xor_si128(X3, (in)[3]); \ -		SALSA20_2ROUNDS \ -		SALSA20_2ROUNDS \ -		SALSA20_2ROUNDS \ -		SALSA20_2ROUNDS \ -		(out)[0] = X0 = _mm_add_epi32(X0, Y0); \ -		(out)[1] = X1 = _mm_add_epi32(X1, Y1); \ -		(out)[2] = X2 = _mm_add_epi32(X2, Y2); \ -		(out)[3] = X3 = _mm_add_epi32(X3, Y3); \ -	} - -/** - * blockmix_salsa8(Bin, Bout, r): - * Compute Bout = BlockMix_{salsa20/8, r}(Bin).  The input Bin must be 128r - * bytes in length; the output Bout must also be the same size. - */ -static inline void -blockmix_salsa8(const __m128i * Bin, __m128i * Bout, size_t r) -{ -	__m128i X0, X1, X2, X3; -	size_t i; - -	/* 1: X <-- B_{2r - 1} */ -	X0 = Bin[8 * r - 4]; -	X1 = Bin[8 * r - 3]; -	X2 = Bin[8 * r - 2]; -	X3 = Bin[8 * r - 1]; - -	/* 3: X <-- H(X \xor B_i) */ -	/* 4: Y_i <-- X */ -	/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ -	SALSA20_8_XOR(Bin, Bout) - -	/* 2: for i = 0 to 2r - 1 do */ -	r--; -	for (i = 0; i < r;) { -		/* 3: X <-- H(X \xor B_i) */ -		/* 4: Y_i <-- X */ -		/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ -		SALSA20_8_XOR(&Bin[i * 8 + 4], &Bout[(r + i) * 4 + 4]) - -		i++; - -		/* 3: X <-- H(X \xor B_i) */ -		/* 4: Y_i <-- X */ -		/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ -		SALSA20_8_XOR(&Bin[i * 8], &Bout[i * 4]) -	} - -	/* 3: X <-- H(X \xor B_i) */ -	/* 4: Y_i <-- X */ -	/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ -	SALSA20_8_XOR(&Bin[i * 8 + 4], &Bout[(r + i) * 4 + 4]) -} - -#define XOR4(in) \ -	X0 = _mm_xor_si128(X0, (in)[0]); \ -	X1 = _mm_xor_si128(X1, (in)[1]); \ -	X2 = _mm_xor_si128(X2, (in)[2]); \ -	X3 = _mm_xor_si128(X3, (in)[3]); - -#define XOR4_2(in1, in2) \ -	X0 = _mm_xor_si128((in1)[0], (in2)[0]); \ -	X1 = _mm_xor_si128((in1)[1], (in2)[1]); \ -	X2 = _mm_xor_si128((in1)[2], (in2)[2]); \ -	X3 = _mm_xor_si128((in1)[3], (in2)[3]); - -static inline uint32_t -blockmix_salsa8_xor(const __m128i * Bin1, const __m128i * Bin2, __m128i * Bout, -    size_t r) -{ -	__m128i X0, X1, X2, X3; -	size_t i; - -	/* 1: X <-- B_{2r - 1} */ -	XOR4_2(&Bin1[8 * r - 4], &Bin2[8 * r - 4]) - -	/* 3: X <-- H(X \xor B_i) */ -	/* 4: Y_i <-- X */ -	/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ -	XOR4(Bin1) -	SALSA20_8_XOR(Bin2, Bout) - -	/* 2: for i = 0 to 2r - 1 do */ -	r--; -	for (i = 0; i < r;) { -		/* 3: X <-- H(X \xor B_i) */ -		/* 4: Y_i <-- X */ -		/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ -		XOR4(&Bin1[i * 8 + 4]) -		SALSA20_8_XOR(&Bin2[i * 8 + 4], &Bout[(r + i) * 4 + 4]) - -		i++; - -		/* 3: X <-- H(X \xor B_i) */ -		/* 4: Y_i <-- X */ -		/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ -		XOR4(&Bin1[i * 8]) -		SALSA20_8_XOR(&Bin2[i * 8], &Bout[i * 4]) -	} - -	/* 3: X <-- H(X \xor B_i) */ -	/* 4: Y_i <-- X */ -	/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ -	XOR4(&Bin1[i * 8 + 4]) -	SALSA20_8_XOR(&Bin2[i * 8 + 4], &Bout[(r + i) * 4 + 4]) - -	return _mm_cvtsi128_si32(X0); -} - -#undef ARX -#undef SALSA20_2ROUNDS -#undef SALSA20_8_XOR -#undef XOR4 -#undef XOR4_2 - -/** - * integerify(B, r): - * Return the result of parsing B_{2r-1} as a little-endian integer. - */ -static inline uint32_t -integerify(const void * B, size_t r) -{ -	return *(const uint32_t *)((uintptr_t)(B) + (2 * r - 1) * 64); -} - -/** - * smix(B, r, N, V, XY): - * Compute B = SMix_r(B, N).  The input B must be 128r bytes in length; - * the temporary storage V must be 128rN bytes in length; the temporary - * storage XY must be 256r + 64 bytes in length.  The value N must be a - * power of 2 greater than 1.  The arrays B, V, and XY must be aligned to a - * multiple of 64 bytes. - */ -static void -smix(uint8_t * B, size_t r, uint32_t N, void * V, void * XY) -{ -	size_t s = 128 * r; -	__m128i * X = (__m128i *) V, * Y; -	uint32_t * X32 = (uint32_t *) V; -	uint32_t i, j; -	size_t k; - -	/* 1: X <-- B */ -	/* 3: V_i <-- X */ -	for (k = 0; k < 2 * r; k++) { -		for (i = 0; i < 16; i++) { -			X32[k * 16 + i] = -			    le32dec(&B[(k * 16 + (i * 5 % 16)) * 4]); -		} -	} - -	/* 2: for i = 0 to N - 1 do */ -	for (i = 1; i < N - 1; i += 2) { -		/* 4: X <-- H(X) */ -		/* 3: V_i <-- X */ -		Y = (__m128i *)((uintptr_t)(V) + i * s); -		blockmix_salsa8(X, Y, r); - -		/* 4: X <-- H(X) */ -		/* 3: V_i <-- X */ -		X = (__m128i *)((uintptr_t)(V) + (i + 1) * s); -		blockmix_salsa8(Y, X, r); -	} - -	/* 4: X <-- H(X) */ -	/* 3: V_i <-- X */ -	Y = (__m128i *)((uintptr_t)(V) + i * s); -	blockmix_salsa8(X, Y, r); - -	/* 4: X <-- H(X) */ -	/* 3: V_i <-- X */ -	X = (__m128i *) XY; -	blockmix_salsa8(Y, X, r); - -	X32 = (uint32_t *) XY; -	Y = (__m128i *)((uintptr_t)(XY) + s); - -	/* 7: j <-- Integerify(X) mod N */ -	j = integerify(X, r) & (N - 1); - -	/* 6: for i = 0 to N - 1 do */ -	for (i = 0; i < N; i += 2) { -		__m128i * V_j = (__m128i *)((uintptr_t)(V) + j * s); - -		/* 8: X <-- H(X \xor V_j) */ -		/* 7: j <-- Integerify(X) mod N */ -		j = blockmix_salsa8_xor(X, V_j, Y, r) & (N - 1); -		V_j = (__m128i *)((uintptr_t)(V) + j * s); - -		/* 8: X <-- H(X \xor V_j) */ -		/* 7: j <-- Integerify(X) mod N */ -		j = blockmix_salsa8_xor(Y, V_j, X, r) & (N - 1); -	} - -	/* 10: B' <-- X */ -	for (k = 0; k < 2 * r; k++) { -		for (i = 0; i < 16; i++) { -			le32enc(&B[(k * 16 + (i * 5 % 16)) * 4], -			    X32[k * 16 + i]); -		} -	} -} - -/** - * escrypt_kdf(local, passwd, passwdlen, salt, saltlen, - *     N, r, p, buf, buflen): - * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, - * p, buflen) and write the result into buf.  The parameters r, p, and buflen - * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32.  The parameter N - * must be a power of 2 greater than 1. - * - * Return 0 on success; or -1 on error. - */ -int -escrypt_kdf_sse(escrypt_local_t * local, -    const uint8_t * passwd, size_t passwdlen, -    const uint8_t * salt, size_t saltlen, -    uint64_t N, uint32_t _r, uint32_t _p, -    uint8_t * buf, size_t buflen) -{ -	size_t B_size, V_size, XY_size, need; -	uint8_t * B; -	uint32_t * V, * XY; -    size_t r = _r, p = _p; -	uint32_t i; - -	/* Sanity-check parameters. */ -#if SIZE_MAX > UINT32_MAX -	if (buflen > (((uint64_t)(1) << 32) - 1) * 32) { -		errno = EFBIG; -		return -1; -	} -#endif -	if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) { -		errno = EFBIG; -		return -1; -	} -	if (N > UINT32_MAX) { -		errno = EFBIG; -		return -1; -	} -	if (((N & (N - 1)) != 0) || (N < 2)) { -		errno = EINVAL; -		return -1; -	} -	if (r == 0 || p == 0) { -		errno = EINVAL; -		return -1; -	} -	if ((r > SIZE_MAX / 128 / p) || -#if SIZE_MAX / 256 <= UINT32_MAX -	    (r > SIZE_MAX / 256) || -#endif -	    (N > SIZE_MAX / 128 / r)) { -		errno = ENOMEM; -		return -1; -	} - -	/* Allocate memory. */ -	B_size = (size_t)128 * r * p; -	V_size = (size_t)128 * r * N; -	need = B_size + V_size; -	if (need < V_size) { -		errno = ENOMEM; -		return -1; -	} -	XY_size = (size_t)256 * r + 64; -	need += XY_size; -	if (need < XY_size) { -		errno = ENOMEM; -		return -1; -	} -	if (local->size < need) { -		if (free_region(local)) -			return -1; -		if (!alloc_region(local, need)) -			return -1; -	} -	B = (uint8_t *)local->aligned; -	V = (uint32_t *)((uint8_t *)B + B_size); -	XY = (uint32_t *)((uint8_t *)V + V_size); - -	/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ -	PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, B_size); - -	/* 2: for i = 0 to p - 1 do */ -	for (i = 0; i < p; i++) { -		/* 3: B_i <-- MF(B_i, N) */ -		smix(&B[(size_t)128 * i * r], r, N, V, XY); -	} - -	/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ -	PBKDF2_SHA256(passwd, passwdlen, B, B_size, 1, buf, buflen); - -	/* Success! */ -	return 0; -} -#endif - -#endif - -/* ISO C requires a translation unit to contain at least one declaration */ -typedef int non_empty_tu_decl; diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sysendian.h b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sysendian.h deleted file mode 100644 index 4deca4c645..0000000000 --- a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sysendian.h +++ /dev/null @@ -1,158 +0,0 @@ -#ifndef C_TOXCORE_TOXENCRYPTSAVE_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SYSENDIAN_H -#define C_TOXCORE_TOXENCRYPTSAVE_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SYSENDIAN_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#ifdef  VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ - -#ifndef _SYSENDIAN_H_ -#define _SYSENDIAN_H_ - -#include <stdint.h> - -/* Avoid namespace collisions with BSD <sys/endian.h>. */ -#define be16dec scrypt_be16dec -#define be16enc scrypt_be16enc -#define be32dec scrypt_be32dec -#define be32enc scrypt_be32enc -#define be64dec scrypt_be64dec -#define be64enc scrypt_be64enc -#define le16dec scrypt_le16dec -#define le16enc scrypt_le16enc -#define le32dec scrypt_le32dec -#define le32enc scrypt_le32enc -#define le64dec scrypt_le64dec -#define le64enc scrypt_le64enc - -static inline uint16_t -be16dec(const void *pp) -{ -	const uint8_t *p = (uint8_t const *)pp; - -	return ((uint16_t)(p[1]) + ((uint16_t)(p[0]) << 8)); -} - -static inline void -be16enc(void *pp, uint16_t x) -{ -	uint8_t * p = (uint8_t *)pp; - -	p[1] = x & 0xff; -	p[0] = (x >> 8) & 0xff; -} - -static inline uint32_t -be32dec(const void *pp) -{ -	const uint8_t *p = (uint8_t const *)pp; - -	return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) + -	    ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24)); -} - -static inline void -be32enc(void *pp, uint32_t x) -{ -	uint8_t * p = (uint8_t *)pp; - -	p[3] = x & 0xff; -	p[2] = (x >> 8) & 0xff; -	p[1] = (x >> 16) & 0xff; -	p[0] = (x >> 24) & 0xff; -} - -static inline uint64_t -be64dec(const void *pp) -{ -	const uint8_t *p = (uint8_t const *)pp; - -	return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) + -	    ((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) + -	    ((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) + -	    ((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56)); -} - -static inline void -be64enc(void *pp, uint64_t x) -{ -	uint8_t * p = (uint8_t *)pp; - -	p[7] = x & 0xff; -	p[6] = (x >> 8) & 0xff; -	p[5] = (x >> 16) & 0xff; -	p[4] = (x >> 24) & 0xff; -	p[3] = (x >> 32) & 0xff; -	p[2] = (x >> 40) & 0xff; -	p[1] = (x >> 48) & 0xff; -	p[0] = (x >> 56) & 0xff; -} - -static inline uint16_t -le16dec(const void *pp) -{ -	const uint8_t *p = (uint8_t const *)pp; - -	return ((uint16_t)(p[0]) + ((uint16_t)(p[1]) << 8)); -} - -static inline void -le16enc(void *pp, uint16_t x) -{ -	uint8_t * p = (uint8_t *)pp; - -	p[0] = x & 0xff; -	p[1] = (x >> 8) & 0xff; -} - -static inline uint32_t -le32dec(const void *pp) -{ -	const uint8_t *p = (uint8_t const *)pp; - -	return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) + -	    ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24)); -} - -static inline void -le32enc(void *pp, uint32_t x) -{ -	uint8_t * p = (uint8_t *)pp; - -	p[0] = x & 0xff; -	p[1] = (x >> 8) & 0xff; -	p[2] = (x >> 16) & 0xff; -	p[3] = (x >> 24) & 0xff; -} - -static inline uint64_t -le64dec(const void *pp) -{ -	const uint8_t *p = (uint8_t const *)pp; - -	return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) + -	    ((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) + -	    ((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) + -	    ((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56)); -} - -static inline void -le64enc(void *pp, uint64_t x) -{ -	uint8_t * p = (uint8_t *)pp; - -	p[0] = x & 0xff; -	p[1] = (x >> 8) & 0xff; -	p[2] = (x >> 16) & 0xff; -	p[3] = (x >> 24) & 0xff; -	p[4] = (x >> 32) & 0xff; -	p[5] = (x >> 40) & 0xff; -	p[6] = (x >> 48) & 0xff; -	p[7] = (x >> 56) & 0xff; -} - -#endif /* !_SYSENDIAN_H_ */ - -#endif - -#endif diff --git a/protocols/Tox/libtox/src/toxencryptsave/defines.h b/protocols/Tox/libtox/src/toxencryptsave/defines.h index 8a490344a7..71c0f105a5 100644 --- a/protocols/Tox/libtox/src/toxencryptsave/defines.h +++ b/protocols/Tox/libtox/src/toxencryptsave/defines.h @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2016-2021 The TokTok team. + * Copyright © 2013 Tox project. + */ +  #ifndef C_TOXCORE_TOXENCRYPTSAVE_DEFINES_H  #define C_TOXCORE_TOXENCRYPTSAVE_DEFINES_H diff --git a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.api.h b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.api.h deleted file mode 100644 index df5d1136f3..0000000000 --- a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.api.h +++ /dev/null @@ -1,311 +0,0 @@ -%{ -/* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. - * Copyright © 2013-2016 Tox Developers. - */ - -/* - * Batch encryption functions. - */ -#ifndef C_TOXCORE_TOXENCRYPTSAVE_TOXENCRYPTSAVE_H -#define C_TOXCORE_TOXENCRYPTSAVE_TOXENCRYPTSAVE_H - -//!TOKSTYLE- - -#ifdef __cplusplus -extern "C" { -#endif - -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> -%} - -/******************************************************************************* - * - * This module is organized into two parts. - * - * 1. A simple API operating on plain text/cipher text data and a password to - *    encrypt or decrypt it. - * 2. A more advanced API that splits key derivation and encryption into two - *    separate function calls. - * - * The first part is implemented in terms of the second part and simply calls - * the separate functions in sequence. Since key derivation is very expensive - * compared to the actual encryption, clients that do a lot of crypto should - * prefer the advanced API and reuse pass-key objects. - * - * To use the second part, first derive an encryption key from a password with - * ${tox.pass_Key.derive}, then use the derived key to encrypt the data. - * - * The encrypted data is prepended with a magic number, to aid validity - * checking (no guarantees are made of course). Any data to be decrypted must - * start with the magic number. - * - * Clients should consider alerting their users that, unlike plain data, if - * even one bit becomes corrupted, the data will be entirely unrecoverable. - * Ditto if they forget their password, there is no way to recover the data. - * - *******************************************************************************/ - -class tox { - -/** - * The size of the salt part of a pass-key. - */ -const PASS_SALT_LENGTH                  = 32; -/** - * The size of the key part of a pass-key. - */ -const PASS_KEY_LENGTH                   = 32; -/** - * The amount of additional data required to store any encrypted byte array. - * Encrypting an array of N bytes requires N + $PASS_ENCRYPTION_EXTRA_LENGTH - * bytes in the encrypted byte array. - */ -const PASS_ENCRYPTION_EXTRA_LENGTH      = 80; - -error for key_derivation { -  NULL, -  /** -   * The crypto lib was unable to derive a key from the given passphrase, -   * which is usually a lack of memory issue. -   */ -  FAILED, -} - -error for encryption { -  NULL, -  /** -   * The crypto lib was unable to derive a key from the given passphrase, -   * which is usually a lack of memory issue. The functions accepting keys -   * do not produce this error. -   */ -  KEY_DERIVATION_FAILED, -  /** -   * The encryption itself failed. -   */ -  FAILED, -} - -error for decryption { -  NULL, -  /** -   * The input data was shorter than $PASS_ENCRYPTION_EXTRA_LENGTH bytes -   */ -  INVALID_LENGTH, -  /** -   * The input data is missing the magic number (i.e. wasn't created by this -   * module, or is corrupted). -   */ -  BAD_FORMAT, -  /** -   * The crypto lib was unable to derive a key from the given passphrase, -   * which is usually a lack of memory issue. The functions accepting keys -   * do not produce this error. -   */ -  KEY_DERIVATION_FAILED, -  /** -   * The encrypted byte array could not be decrypted. Either the data was -   * corrupted or the password/key was incorrect. -   */ -  FAILED, -} - - -/******************************************************************************* - * - *                                BEGIN PART 1 - * - * The simple API is presented first. If your code spends too much time using - * these functions, consider using the advanced functions instead and caching - * the generated pass-key. - * - *******************************************************************************/ - -/** - * Encrypts the given data with the given passphrase. - * - * The output array must be at least `plaintext_len + $PASS_ENCRYPTION_EXTRA_LENGTH` - * bytes long. This delegates to ${pass_Key.derive} and - * ${pass_Key.encrypt}. - * - * @param plaintext A byte array of length `plaintext_len`. - * @param plaintext_len The length of the plain text array. Bigger than 0. - * @param passphrase The user-provided password. Can be empty. - * @param passphrase_len The length of the password. - * @param ciphertext The cipher text array to write the encrypted data to. - * - * @return true on success. - */ -static bool pass_encrypt(const uint8_t[plaintext_len] plaintext, const uint8_t[passphrase_len] passphrase, uint8_t *ciphertext) -    with error for encryption; - - -/** - * Decrypts the given data with the given passphrase. - * - * The output array must be at least `ciphertext_len - $PASS_ENCRYPTION_EXTRA_LENGTH` - * bytes long. This delegates to ${pass_Key.decrypt}. - * - * @param ciphertext A byte array of length `ciphertext_len`. - * @param ciphertext_len The length of the cipher text array. At least $PASS_ENCRYPTION_EXTRA_LENGTH. - * @param passphrase The user-provided password. Can be empty. - * @param passphrase_len The length of the password. - * @param plaintext The plain text array to write the decrypted data to. - * - * @return true on success. - */ -static bool pass_decrypt(const uint8_t[ciphertext_len] ciphertext, const uint8_t[passphrase_len] passphrase, uint8_t *plaintext) -    with error for decryption; - - -/******************************************************************************* - * - *                                BEGIN PART 2 - * - * And now part 2, which does the actual encryption, and can be used to write - * less CPU intensive client code than part one. - * - *******************************************************************************/ - -class pass_Key { -  /** -   * This type represents a pass-key. -   * -   * A pass-key and a password are two different concepts: a password is given -   * by the user in plain text. A pass-key is the generated symmetric key used -   * for encryption and decryption. It is derived from a salt and the user- -   * provided password. -   * -   * The $this structure is hidden in the implementation. It can be created -   * using $derive or $derive_with_salt and must be deallocated using $free. -   */ -  struct this; - -  /** -   * Deallocate a $this. This function behaves like free(), so NULL is an -   * acceptable argument value. -   */ -  void free(); - -  /** -   * Generates a secret symmetric key from the given passphrase. -   * -   * Be sure to not compromise the key! Only keep it in memory, do not write -   * it to disk. -   * -   * Note that this function is not deterministic; to derive the same key from -   * a password, you also must know the random salt that was used. A -   * deterministic version of this function is $derive_with_salt. -   * -   * @param passphrase The user-provided password. Can be empty. -   * @param passphrase_len The length of the password. -   * -   * @return true on success. -   */ -  static this derive(const uint8_t[passphrase_len] passphrase) -      with error for key_derivation; - -  /** -   * Same as above, except use the given salt for deterministic key derivation. -   * -   * @param passphrase The user-provided password. Can be empty. -   * @param passphrase_len The length of the password. -   * @param salt An array of at least $PASS_SALT_LENGTH bytes. -   * -   * @return true on success. -   */ -  static this derive_with_salt(const uint8_t[passphrase_len] passphrase, const uint8_t[PASS_SALT_LENGTH] salt) -      with error for key_derivation; - -  /** -   * Encrypt a plain text with a key produced by $derive or $derive_with_salt. -   * -   * The output array must be at least `plaintext_len + $PASS_ENCRYPTION_EXTRA_LENGTH` -   * bytes long. -   * -   * @param plaintext A byte array of length `plaintext_len`. -   * @param plaintext_len The length of the plain text array. Bigger than 0. -   * @param ciphertext The cipher text array to write the encrypted data to. -   * -   * @return true on success. -   */ -  const bool encrypt(const uint8_t[plaintext_len] plaintext, uint8_t *ciphertext) -      with error for encryption; - -  /** -   * This is the inverse of $encrypt, also using only keys produced by -   * $derive or $derive_with_salt. -   * -   * @param ciphertext A byte array of length `ciphertext_len`. -   * @param ciphertext_len The length of the cipher text array. At least $PASS_ENCRYPTION_EXTRA_LENGTH. -   * @param plaintext The plain text array to write the decrypted data to. -   * -   * @return true on success. -   */ -  const bool decrypt(const uint8_t[ciphertext_len] ciphertext, uint8_t *plaintext) -      with error for decryption; -} - -/** - * Retrieves the salt used to encrypt the given data. - * - * The retrieved salt can then be passed to ${pass_Key.derive_with_salt} to - * produce the same key as was previously used. Any data encrypted with this - * module can be used as input. - * - * The cipher text must be at least $PASS_ENCRYPTION_EXTRA_LENGTH bytes in length. - * The salt must be $PASS_SALT_LENGTH bytes in length. - * If the passed byte arrays are smaller than required, the behaviour is - * undefined. - * - * If the cipher text pointer or the salt is NULL, this function returns false. - * - * Success does not say anything about the validity of the data, only that - * data of the appropriate size was copied. - * - * @return true on success. - */ -static bool get_salt(const uint8_t *ciphertext, uint8_t[PASS_SALT_LENGTH] salt) { -  NULL, -  /** -   * The input data is missing the magic number (i.e. wasn't created by this -   * module, or is corrupted). -   */ -  BAD_FORMAT, -} - -/** - * Determines whether or not the given data is encrypted by this module. - * - * It does this check by verifying that the magic number is the one put in - * place by the encryption functions. - * - * The data must be at least $PASS_ENCRYPTION_EXTRA_LENGTH bytes in length. - * If the passed byte array is smaller than required, the behaviour is - * undefined. - * - * If the data pointer is NULL, the behaviour is undefined - * - * @return true if the data is encrypted by this module. - */ -static bool is_data_encrypted(const uint8_t *data); - -} - -%{ - -#ifdef __cplusplus -} -#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; - -//!TOKSTYLE+ - -#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 be4bcaf26c..1d464534d0 100644 --- a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c +++ b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c @@ -3,32 +3,20 @@   * Copyright © 2013 Tox project.   */ -/* +/**   * Batch encryption functions.   */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "../toxcore/ccompat.h" -#include "../toxcore/crypto_core.h" -#include "defines.h"  #include "toxencryptsave.h" -#define SET_ERROR_PARAMETER(param, x) do { if (param) { *param = x; } } while (0) - -#ifdef VANILLA_NACL -#include <crypto_box.h> -#include <crypto_hash_sha256.h> -#include "crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h" -#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) -#else +  #include <sodium.h> -#endif  #include <stdlib.h>  #include <string.h> -//!TOKSTYLE- +#include "../toxcore/ccompat.h" +#include "../toxcore/crypto_core.h" +#include "defines.h" +  static_assert(TOX_PASS_SALT_LENGTH == crypto_pwhash_scryptsalsa208sha256_SALTBYTES,                "TOX_PASS_SALT_LENGTH is assumed to be equal to crypto_pwhash_scryptsalsa208sha256_SALTBYTES");  static_assert(TOX_PASS_KEY_LENGTH == CRYPTO_SHARED_KEY_SIZE, @@ -36,7 +24,13 @@ static_assert(TOX_PASS_KEY_LENGTH == CRYPTO_SHARED_KEY_SIZE,  static_assert(TOX_PASS_ENCRYPTION_EXTRA_LENGTH == (crypto_box_MACBYTES + crypto_box_NONCEBYTES +                crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH),                "TOX_PASS_ENCRYPTION_EXTRA_LENGTH is assumed to be equal to (crypto_box_MACBYTES + crypto_box_NONCEBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH)"); -//!TOKSTYLE+ + +#define SET_ERROR_PARAMETER(param, x) \ +    do {                              \ +        if (param) {                  \ +            *param = x;               \ +        }                             \ +    } while (0)  uint32_t tox_pass_salt_length(void)  { @@ -142,7 +136,7 @@ Tox_Pass_Key *tox_pass_key_derive_with_salt(const uint8_t *passphrase, size_t pp      crypto_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ -    Tox_Pass_Key *out_key = (Tox_Pass_Key *)malloc(sizeof(Tox_Pass_Key)); +    Tox_Pass_Key *out_key = (Tox_Pass_Key *)calloc(1, sizeof(Tox_Pass_Key));      if (!out_key) {          SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_FAILED); @@ -156,18 +150,21 @@ Tox_Pass_Key *tox_pass_key_derive_with_salt(const uint8_t *passphrase, size_t pp  }  /** - * Encrypt arbitrary with a key produced by `tox_derive_key_*`. The output - * array must be at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. - * key must be TOX_PASS_KEY_LENGTH bytes. - * If you already have a symmetric key from somewhere besides this module, simply - * call encrypt_data_symmetric in toxcore/crypto_core directly. + * Encrypt a plain text with a key produced by tox_pass_key_derive or tox_pass_key_derive_with_salt.   * - * returns true on success + * The output array must be at least `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH` + * bytes long. + * + * @param plaintext A byte array of length `plaintext_len`. + * @param plaintext_len The length of the plain text array. Bigger than 0. + * @param ciphertext The cipher text array to write the encrypted data to. + * + * @return 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) +bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t *plaintext, size_t plaintext_len, +                          uint8_t *ciphertext, Tox_Err_Encryption *error)  { -    if (data_len == 0 || !data || !key || !out) { +    if (plaintext_len == 0 || !plaintext || !key || !ciphertext) {          SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL);          return 0;      } @@ -180,21 +177,21 @@ bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t *data, size_t d      // need them to decrypt the data      /* first add the magic number */ -    memcpy(out, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH); -    out += TOX_ENC_SAVE_MAGIC_LENGTH; +    memcpy(ciphertext, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH); +    ciphertext += TOX_ENC_SAVE_MAGIC_LENGTH;      /* then add the rest prefix */ -    memcpy(out, key->salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); -    out += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; +    memcpy(ciphertext, key->salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); +    ciphertext += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;      uint8_t nonce[crypto_box_NONCEBYTES];      random_nonce(nonce); -    memcpy(out, nonce, crypto_box_NONCEBYTES); -    out += crypto_box_NONCEBYTES; +    memcpy(ciphertext, nonce, crypto_box_NONCEBYTES); +    ciphertext += crypto_box_NONCEBYTES;      /* now encrypt */ -    if (encrypt_data_symmetric(key->key, nonce, data, data_len, out) -            != data_len + crypto_box_MACBYTES) { +    if (encrypt_data_symmetric(key->key, nonce, plaintext, plaintext_len, ciphertext) +            != plaintext_len + crypto_box_MACBYTES) {          SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_FAILED);          return 0;      } diff --git a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h index 4b58165e7d..3f22b75884 100644 --- a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h +++ b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h @@ -3,23 +3,22 @@   * Copyright © 2013-2016 Tox Developers.   */ -/* +/**   * Batch encryption functions.   */ +  #ifndef C_TOXCORE_TOXENCRYPTSAVE_TOXENCRYPTSAVE_H  #define C_TOXCORE_TOXENCRYPTSAVE_TOXENCRYPTSAVE_H -//!TOKSTYLE- - -#ifdef __cplusplus -extern "C" { -#endif -  #include <stdbool.h>  #include <stddef.h>  #include <stdint.h> +#ifdef __cplusplus +extern "C" { +#endif +  /*******************************************************************************   *   * This module is organized into two parts. @@ -72,7 +71,7 @@ uint32_t tox_pass_key_length(void);  uint32_t tox_pass_encryption_extra_length(void); -typedef enum TOX_ERR_KEY_DERIVATION { +typedef enum Tox_Err_Key_Derivation {      /**       * The function returned successfully. @@ -90,10 +89,10 @@ typedef enum TOX_ERR_KEY_DERIVATION {       */      TOX_ERR_KEY_DERIVATION_FAILED, -} TOX_ERR_KEY_DERIVATION; +} Tox_Err_Key_Derivation; -typedef enum TOX_ERR_ENCRYPTION { +typedef enum Tox_Err_Encryption {      /**       * The function returned successfully. @@ -117,10 +116,10 @@ typedef enum TOX_ERR_ENCRYPTION {       */      TOX_ERR_ENCRYPTION_FAILED, -} TOX_ERR_ENCRYPTION; +} Tox_Err_Encryption; -typedef enum TOX_ERR_DECRYPTION { +typedef enum Tox_Err_Decryption {      /**       * The function returned successfully. @@ -156,7 +155,7 @@ typedef enum TOX_ERR_DECRYPTION {       */      TOX_ERR_DECRYPTION_FAILED, -} TOX_ERR_DECRYPTION; +} Tox_Err_Decryption; @@ -188,7 +187,7 @@ typedef enum TOX_ERR_DECRYPTION {   * @return true on success.   */  bool tox_pass_encrypt(const uint8_t *plaintext, size_t plaintext_len, const uint8_t *passphrase, size_t passphrase_len, -                      uint8_t *ciphertext, TOX_ERR_ENCRYPTION *error); +                      uint8_t *ciphertext, Tox_Err_Encryption *error);  /**   * Decrypts the given data with the given passphrase. @@ -205,7 +204,7 @@ bool tox_pass_encrypt(const uint8_t *plaintext, size_t plaintext_len, const uint   * @return true on success.   */  bool tox_pass_decrypt(const uint8_t *ciphertext, size_t ciphertext_len, const uint8_t *passphrase, -                      size_t passphrase_len, uint8_t *plaintext, TOX_ERR_DECRYPTION *error); +                      size_t passphrase_len, uint8_t *plaintext, Tox_Err_Decryption *error);  /******************************************************************************* @@ -239,7 +238,7 @@ typedef struct Tox_Pass_Key Tox_Pass_Key;   * Deallocate a Tox_Pass_Key. This function behaves like free(), so NULL is an   * acceptable argument value.   */ -void tox_pass_key_free(struct Tox_Pass_Key *_key); +void tox_pass_key_free(struct Tox_Pass_Key *key);  /**   * Generates a secret symmetric key from the given passphrase. @@ -249,7 +248,7 @@ void tox_pass_key_free(struct Tox_Pass_Key *_key);   *   * Note that this function is not deterministic; to derive the same key from   * a password, you also must know the random salt that was used. A - * deterministic version of this function is tox_pass_key_derive_with_salt. + * deterministic version of this function is `tox_pass_key_derive_with_salt`.   *   * @param passphrase The user-provided password. Can be empty.   * @param passphrase_len The length of the password. @@ -257,7 +256,7 @@ void tox_pass_key_free(struct Tox_Pass_Key *_key);   * @return true on success.   */  struct Tox_Pass_Key *tox_pass_key_derive(const uint8_t *passphrase, size_t passphrase_len, -        TOX_ERR_KEY_DERIVATION *error); +        Tox_Err_Key_Derivation *error);  /**   * Same as above, except use the given salt for deterministic key derivation. @@ -269,7 +268,7 @@ struct Tox_Pass_Key *tox_pass_key_derive(const uint8_t *passphrase, size_t passp   * @return true on success.   */  struct Tox_Pass_Key *tox_pass_key_derive_with_salt(const uint8_t *passphrase, size_t passphrase_len, -        const uint8_t *salt, TOX_ERR_KEY_DERIVATION *error); +        const uint8_t *salt, Tox_Err_Key_Derivation *error);  /**   * Encrypt a plain text with a key produced by tox_pass_key_derive or tox_pass_key_derive_with_salt. @@ -283,8 +282,8 @@ struct Tox_Pass_Key *tox_pass_key_derive_with_salt(const uint8_t *passphrase, si   *   * @return true on success.   */ -bool tox_pass_key_encrypt(const struct Tox_Pass_Key *_key, const uint8_t *plaintext, size_t plaintext_len, -                          uint8_t *ciphertext, TOX_ERR_ENCRYPTION *error); +bool tox_pass_key_encrypt(const struct Tox_Pass_Key *key, const uint8_t *plaintext, size_t plaintext_len, +                          uint8_t *ciphertext, Tox_Err_Encryption *error);  /**   * This is the inverse of tox_pass_key_encrypt, also using only keys produced by @@ -296,10 +295,10 @@ bool tox_pass_key_encrypt(const struct Tox_Pass_Key *_key, const uint8_t *plaint   *   * @return true on success.   */ -bool tox_pass_key_decrypt(const struct Tox_Pass_Key *_key, const uint8_t *ciphertext, size_t ciphertext_len, -                          uint8_t *plaintext, TOX_ERR_DECRYPTION *error); +bool tox_pass_key_decrypt(const struct Tox_Pass_Key *key, const uint8_t *ciphertext, size_t ciphertext_len, +                          uint8_t *plaintext, Tox_Err_Decryption *error); -typedef enum TOX_ERR_GET_SALT { +typedef enum Tox_Err_Get_Salt {      /**       * The function returned successfully. @@ -317,7 +316,7 @@ typedef enum TOX_ERR_GET_SALT {       */      TOX_ERR_GET_SALT_BAD_FORMAT, -} TOX_ERR_GET_SALT; +} Tox_Err_Get_Salt;  /** @@ -339,7 +338,7 @@ typedef enum TOX_ERR_GET_SALT {   *   * @return true on success.   */ -bool tox_get_salt(const uint8_t *ciphertext, uint8_t *salt, TOX_ERR_GET_SALT *error); +bool tox_get_salt(const uint8_t *ciphertext, uint8_t *salt, Tox_Err_Get_Salt *error);  /**   * Determines whether or not the given data is encrypted by this module. @@ -362,10 +361,12 @@ 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; +//!TOKSTYLE- + +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;  //!TOKSTYLE+  | 
