diff options
Diffstat (limited to 'protocols/Tox/libtox/src/toxcore')
52 files changed, 1941 insertions, 1360 deletions
diff --git a/protocols/Tox/libtox/src/toxcore/DHT.c b/protocols/Tox/libtox/src/toxcore/DHT.c index 37dd9385a0..1eebb0c736 100644 --- a/protocols/Tox/libtox/src/toxcore/DHT.c +++ b/protocols/Tox/libtox/src/toxcore/DHT.c @@ -76,7 +76,7 @@ struct DHT_Friend {      /* number of times get_node packets were sent. */      uint32_t    bootstrap_times; -    /* Symetric NAT hole punching stuff. */ +    /* Symmetric NAT hole punching stuff. */      NAT         nat;      uint16_t lock_count; @@ -93,6 +93,7 @@ typedef struct Cryptopacket_Handler {  struct DHT {      const Logger *log; +    Mono_Time *mono_time;      Networking_Core *net;      bool hole_punching_enabled; @@ -237,13 +238,14 @@ 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 therefor smart to store commonly used +/* 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.   *   * 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   */ -void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t *secret_key, const uint8_t *public_key) +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)  {      uint32_t num = ~0;      uint32_t curr = 0; @@ -256,12 +258,12 @@ void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t              if (id_equal(public_key, key->public_key)) {                  memcpy(shared_key, key->shared_key, CRYPTO_SHARED_KEY_SIZE);                  ++key->times_requested; -                key->time_last_requested = unix_time(); +                key->time_last_requested = mono_time_get(mono_time);                  return;              }              if (num != 0) { -                if (is_timeout(key->time_last_requested, KEYS_TIMEOUT)) { +                if (mono_time_is_timeout(mono_time, key->time_last_requested, KEYS_TIMEOUT)) {                      num = 0;                      curr = index;                  } else if (num > key->times_requested) { @@ -279,11 +281,11 @@ void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t      if (num != UINT32_MAX) {          Shared_Key *const key = &shared_keys->keys[curr]; -        key->stored = 1; +        key->stored = true;          key->times_requested = 1;          memcpy(key->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);          memcpy(key->shared_key, shared_key, CRYPTO_SHARED_KEY_SIZE); -        key->time_last_requested = unix_time(); +        key->time_last_requested = mono_time_get(mono_time);      }  } @@ -292,7 +294,7 @@ void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t   */  void dht_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *public_key)  { -    get_shared_key(&dht->shared_keys_recv, shared_key, dht->self_secret_key, public_key); +    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 @@ -300,7 +302,7 @@ void dht_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *publi   */  void dht_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *public_key)  { -    get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, public_key); +    get_shared_key(dht->mono_time, &dht->shared_keys_sent, shared_key, dht->self_secret_key, public_key);  }  #define CRYPTO_SIZE 1 + CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE @@ -489,7 +491,7 @@ static int dht_create_packet(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],   * 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, uint8_t tcp_enabled) +int unpack_ip_port(IP_Port *ip_port, const uint8_t *data, uint16_t length, bool tcp_enabled)  {      if (data == nullptr) {          return -1; @@ -572,7 +574,9 @@ int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_          memcpy(data + packed_length, nodes[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);          packed_length += CRYPTO_PUBLIC_KEY_SIZE; +#ifndef NDEBUG          const uint32_t increment = ipp_size + CRYPTO_PUBLIC_KEY_SIZE; +#endif          assert(increment == PACKED_NODE_SIZE_IP4 || increment == PACKED_NODE_SIZE_IP6);      } @@ -587,7 +591,7 @@ int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_   * return -1 on failure.   */  int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, const uint8_t *data, -                 uint16_t length, uint8_t tcp_enabled) +                 uint16_t length, bool tcp_enabled)  {      uint32_t num = 0, len_processed = 0; @@ -608,7 +612,9 @@ int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed          len_processed += CRYPTO_PUBLIC_KEY_SIZE;          ++num; +#ifndef NDEBUG          const uint32_t increment = ipp_size + CRYPTO_PUBLIC_KEY_SIZE; +#endif          assert(increment == PACKED_NODE_SIZE_IP4 || increment == PACKED_NODE_SIZE_IP6);      } @@ -667,7 +673,8 @@ static uint32_t index_of_client_ip_port(const Client_data *array, uint32_t size,  /* Update ip_port of client if it's needed.   */ -static void update_client(const Logger *log, int index, Client_data *client, IP_Port ip_port) +static void update_client(const Logger *log, const Mono_Time *mono_time, int index, Client_data *client, +                          IP_Port ip_port)  {      IPPTsPng *assoc;      int ip_version; @@ -692,12 +699,12 @@ static void update_client(const Logger *log, int index, Client_data *client, IP_                       net_ntohs(ip_port.port));      } -    if (ip_is_lan(assoc->ip_port.ip) != 0 && ip_is_lan(ip_port.ip) == 0) { +    if (!ip_is_lan(assoc->ip_port.ip) && ip_is_lan(ip_port.ip)) {          return;      }      assoc->ip_port = ip_port; -    assoc->timestamp = unix_time(); +    assoc->timestamp = mono_time_get(mono_time);  }  /* Check if client with public_key is already in list of length length. @@ -707,15 +714,15 @@ static void update_client(const Logger *log, int index, Client_data *client, IP_   *   *  return True(1) or False(0)   */ -static int client_or_ip_port_in_list(const Logger *log, Client_data *list, uint16_t length, const uint8_t *public_key, -                                     IP_Port ip_port) +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 uint64_t temp_time = unix_time(); +    const uint64_t temp_time = mono_time_get(mono_time);      uint32_t index = index_of_client_pk(list, length, public_key);      /* if public_key is in list, find it and maybe overwrite ip_port */      if (index != UINT32_MAX) { -        update_client(log, index, &list[index], ip_port); +        update_client(log, mono_time, index, &list[index], ip_port);          return 1;      } @@ -752,30 +759,26 @@ static int client_or_ip_port_in_list(const Logger *log, Client_data *list, uint1      return 1;  } -/* Add node to the node list making sure only the nodes closest to cmp_pk are in the list. - */ -bool add_to_list(Node_format *nodes_list, unsigned int length, const uint8_t *pk, IP_Port ip_port, +bool add_to_list(Node_format *nodes_list, uint32_t length, const uint8_t *pk, IP_Port ip_port,                   const uint8_t *cmp_pk)  { -    uint8_t pk_bak[CRYPTO_PUBLIC_KEY_SIZE]; -    IP_Port ip_port_bak; - -    for (size_t i = 0; i < length; ++i) { +    for (uint32_t i = 0; i < length; ++i) {          if (id_closest(cmp_pk, nodes_list[i].public_key, pk) == 2) { +            uint8_t pk_bak[CRYPTO_PUBLIC_KEY_SIZE];              memcpy(pk_bak, nodes_list[i].public_key, CRYPTO_PUBLIC_KEY_SIZE); -            ip_port_bak = nodes_list[i].ip_port; +            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; -            if (i != (length - 1)) { +            if (i != length - 1) {                  add_to_list(nodes_list, length, pk_bak, ip_port_bak, cmp_pk);              } -            return 1; +            return true;          }      } -    return 0; +    return false;  }  /* TODO(irungentoo): change this to 7 when done*/ @@ -793,9 +796,9 @@ static uint8_t hardening_correct(const Hardening *h)  /*   * helper for get_close_nodes(). argument list is a monster :D   */ -static void get_close_nodes_inner(const uint8_t *public_key, Node_format *nodes_list, +static void get_close_nodes_inner(const Mono_Time *mono_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, uint8_t is_LAN, uint8_t want_good) +                                  uint32_t *num_nodes_ptr, bool is_LAN, uint8_t want_good)  {      if (!net_family_is_ipv4(sa_family) && !net_family_is_ipv6(sa_family) && !net_family_is_unspec(sa_family)) {          return; @@ -824,16 +827,16 @@ static void get_close_nodes_inner(const uint8_t *public_key, Node_format *nodes_          }          /* node not in a good condition? */ -        if (is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT)) { +        if (mono_time_is_timeout(mono_time, ipptp->timestamp, BAD_NODE_TIMEOUT)) {              continue;          }          /* don't send LAN ips to non LAN peers */ -        if (ip_is_lan(ipptp->ip_port.ip) == 0 && !is_LAN) { +        if (ip_is_lan(ipptp->ip_port.ip) && !is_LAN) {              continue;          } -        if (ip_is_lan(ipptp->ip_port.ip) != 0 && want_good && hardening_correct(&ipptp->hardening) != HARDENING_ALL_OK +        if (!ip_is_lan(ipptp->ip_port.ip) && want_good && hardening_correct(&ipptp->hardening) != HARDENING_ALL_OK                  && !id_equal(public_key, client->public_key)) {              continue;          } @@ -859,17 +862,17 @@ static void get_close_nodes_inner(const uint8_t *public_key, Node_format *nodes_   * 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, uint8_t is_LAN, uint8_t want_good) +                                    Family sa_family, bool is_LAN, uint8_t want_good)  {      uint32_t num_nodes = 0; -    get_close_nodes_inner(public_key, nodes_list, sa_family, +    get_close_nodes_inner(dht->mono_time, 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      for (uint32_t i = 0; i < dht->num_friends; ++i) { -        get_close_nodes_inner(dht, public_key, nodes_list, sa_family, +        get_close_nodes_inner(dht->mono_time, public_key, nodes_list, sa_family,                                dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,                                &num_nodes, is_LAN, want_good);      } @@ -877,7 +880,7 @@ static int get_somewhat_close_nodes(const DHT *dht, const uint8_t *public_key, N  #endif      for (uint32_t i = 0; i < dht->num_friends; ++i) { -        get_close_nodes_inner(public_key, nodes_list, sa_family, +        get_close_nodes_inner(dht->mono_time, public_key, nodes_list, sa_family,                                dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,                                &num_nodes, is_LAN, 0);      } @@ -886,20 +889,21 @@ static int get_somewhat_close_nodes(const DHT *dht, const uint8_t *public_key, N  }  int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, Family sa_family, -                    uint8_t is_LAN, uint8_t want_good) +                    bool is_LAN, uint8_t want_good)  {      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);  }  typedef struct DHT_Cmp_data { +    const Mono_Time *mono_time;      const uint8_t *base_public_key;      Client_data entry;  } DHT_Cmp_data; -static bool assoc_timeout(const IPPTsPng *assoc) +static bool assoc_timeout(const Mono_Time *mono_time, const IPPTsPng *assoc)  { -    return is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT); +    return mono_time_is_timeout(mono_time, assoc->timestamp, BAD_NODE_TIMEOUT);  }  static bool incorrect_hardening(const IPPTsPng *assoc) @@ -916,8 +920,8 @@ static int cmp_dht_entry(const void *a, const void *b)      const Client_data entry2 = cmp2.entry;      const uint8_t *cmp_public_key = cmp1.base_public_key; -    bool t1 = assoc_timeout(&entry1.assoc4) && assoc_timeout(&entry1.assoc6); -    bool t2 = assoc_timeout(&entry2.assoc4) && assoc_timeout(&entry2.assoc6); +    bool t1 = assoc_timeout(cmp1.mono_time, &entry1.assoc4) && assoc_timeout(cmp1.mono_time, &entry1.assoc6); +    bool t2 = assoc_timeout(cmp2.mono_time, &entry2.assoc4) && assoc_timeout(cmp2.mono_time, &entry2.assoc6);      if (t1 && t2) {          return 0; @@ -960,20 +964,23 @@ static int cmp_dht_entry(const void *a, const void *b)   * return 0 if node can't be stored.   * return 1 if it can.   */ -static unsigned int store_node_ok(const Client_data *client, const uint8_t *public_key, const uint8_t *comp_public_key) +static unsigned int store_node_ok(const Client_data *client, const Mono_Time *mono_time, const uint8_t *public_key, +                                  const uint8_t *comp_public_key)  { -    return (is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) -            && is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) +    return (mono_time_is_timeout(mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT) +            && mono_time_is_timeout(mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT))             || id_closest(comp_public_key, client->public_key, public_key) == 2;  } -static void sort_client_list(Client_data *list, unsigned int length, const uint8_t *comp_public_key) +static void sort_client_list(Client_data *list, const Mono_Time *mono_time, unsigned int length, +                             const uint8_t *comp_public_key)  {      // 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);      for (uint32_t i = 0; i < length; ++i) { +        cmp_list[i].mono_time = mono_time;          cmp_list[i].base_public_key = comp_public_key;          cmp_list[i].entry = list[i];      } @@ -985,7 +992,7 @@ static void sort_client_list(Client_data *list, unsigned int length, const uint8      }  } -static void update_client_with_reset(Client_data *client, const IP_Port *ip_port) +static void update_client_with_reset(const Mono_Time *mono_time, Client_data *client, const IP_Port *ip_port)  {      IPPTsPng *ipptp_write = nullptr;      IPPTsPng *ipptp_clear = nullptr; @@ -999,7 +1006,7 @@ static void update_client_with_reset(Client_data *client, const IP_Port *ip_port      }      ipptp_write->ip_port = *ip_port; -    ipptp_write->timestamp = unix_time(); +    ipptp_write->timestamp = mono_time_get(mono_time);      ip_reset(&ipptp_write->ret_ip_port.ip);      ipptp_write->ret_ip_port.port = 0; @@ -1022,7 +1029,8 @@ static void update_client_with_reset(Client_data *client, const IP_Port *ip_port   *  than public_key.   *   *  returns true when the item was stored, false otherwise */ -static bool replace_all(Client_data    *list, +static bool replace_all(const Mono_Time *mono_time, +                        Client_data    *list,                          uint16_t        length,                          const uint8_t  *public_key,                          IP_Port         ip_port, @@ -1032,17 +1040,17 @@ static bool replace_all(Client_data    *list,          return false;      } -    if (!store_node_ok(&list[1], public_key, comp_public_key) && -            !store_node_ok(&list[0], public_key, comp_public_key)) { +    if (!store_node_ok(&list[1], mono_time, public_key, comp_public_key) && +            !store_node_ok(&list[0], mono_time, public_key, comp_public_key)) {          return false;      } -    sort_client_list(list, length, comp_public_key); +    sort_client_list(list, mono_time, length, comp_public_key);      Client_data *const client = &list[0];      id_copy(client->public_key, public_key); -    update_client_with_reset(client, &ip_port); +    update_client_with_reset(mono_time, client, &ip_port);      return true;  } @@ -1066,8 +1074,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 (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) || -                !is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) { +        if (!mono_time_is_timeout(dht->mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT) || +                !mono_time_is_timeout(dht->mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT)) {              continue;          } @@ -1076,7 +1084,7 @@ 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(client, &ip_port); +        update_client_with_reset(dht->mono_time, client, &ip_port);          return 0;      } @@ -1090,8 +1098,8 @@ bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_      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, const uint8_t *public_key, -                                 IP_Port ip_port) +static bool is_pk_in_client_list(const Client_data *list, unsigned int client_list_length, const Mono_Time *mono_time, +                                 const uint8_t *public_key, IP_Port ip_port)  {      const uint32_t index = index_of_client_pk(list, client_list_length, public_key); @@ -1103,7 +1111,7 @@ static bool is_pk_in_client_list(const Client_data *list, unsigned int client_li                              ? &list[index].assoc4                              : &list[index].assoc6; -    return !is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT); +    return !mono_time_is_timeout(mono_time, assoc->timestamp, BAD_NODE_TIMEOUT);  }  static bool is_pk_in_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port) @@ -1114,7 +1122,8 @@ 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, public_key, ip_port); +    return is_pk_in_client_list(dht->close_clientlist + index * LCLIENT_NODES, LCLIENT_NODES, dht->mono_time, public_key, +                                ip_port);  }  /* Check if the node obtained with a get_nodes with public_key should be pinged. @@ -1153,17 +1162,18 @@ 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], public_key, dht_friend->public_key)) { +        if (store_node_ok(&dht_friend->client_list[1], dht->mono_time, public_key, dht_friend->public_key)) {              store_ok = true;          } -        if (store_node_ok(&dht_friend->client_list[0], public_key, dht_friend->public_key)) { +        if (store_node_ok(&dht_friend->client_list[0], dht->mono_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, public_key, ip_port); +        const bool pk_in_list = is_pk_in_client_list(dht_friend->client_list, MAX_FRIEND_CLIENTS, dht->mono_time, public_key, +                                ip_port);          if (store_ok && index == UINT32_MAX && !pk_in_list) {              if (*friend_num < MAX_SENT_NODES) { @@ -1200,8 +1210,8 @@ uint32_t addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key)      /* 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->close_clientlist, -                               LCLIENT_LIST, public_key, ip_port); +    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);      /* 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)) { @@ -1211,12 +1221,13 @@ uint32_t addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key)      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->friends_list[i].client_list, +        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);          /* replace_all should be called only if !in_list (don't extract to variable) */ -        if (in_list || replace_all(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, public_key, -                                   ip_port, dht->friends_list[i].public_key)) { +        if (in_list +                || replace_all(dht->mono_time, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, public_key, ip_port, +                               dht->friends_list[i].public_key)) {              DHT_Friend *dht_friend = &dht->friends_list[i];              if (id_equal(public_key, dht_friend->public_key)) { @@ -1241,9 +1252,10 @@ uint32_t addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key)      return used;  } -static bool update_client_data(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, IP_Port ip_port, +                               const uint8_t *pk)  { -    const uint64_t temp_time = unix_time(); +    const uint64_t temp_time = mono_time_get(mono_time);      const uint32_t index = index_of_client_pk(array, size, pk);      if (index == UINT32_MAX) { @@ -1278,7 +1290,7 @@ static void returnedip_ports(DHT *dht, IP_Port ip_port, const uint8_t *public_ke      }      if (id_equal(public_key, dht->self_public_key)) { -        update_client_data(dht->close_clientlist, LCLIENT_LIST, ip_port, nodepublic_key); +        update_client_data(dht->mono_time, dht->close_clientlist, LCLIENT_LIST, ip_port, nodepublic_key);          return;      } @@ -1286,7 +1298,7 @@ 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(client_list, MAX_FRIEND_CLIENTS, ip_port, nodepublic_key)) { +            if (update_client_data(dht->mono_time, client_list, MAX_FRIEND_CLIENTS, ip_port, nodepublic_key)) {                  return;              }          } @@ -1314,9 +1326,9 @@ static int getnodes(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const      if (sendback_node != nullptr) {          memcpy(plain_message + sizeof(receiver), sendback_node, sizeof(Node_format)); -        ping_id = ping_array_add(dht->dht_harden_ping_array, plain_message, sizeof(plain_message)); +        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, plain_message, sizeof(receiver)); +        ping_id = ping_array_add(dht->dht_ping_array, dht->mono_time, plain_message, sizeof(receiver));      }      if (ping_id == 0) { @@ -1358,8 +1370,8 @@ static int sendnodes_ipv6(const DHT *dht, IP_Port ip_port, const uint8_t *public      const size_t node_format_size = sizeof(Node_format);      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) == 0, -                               1); +    const uint32_t num_nodes = +        get_close_nodes(dht, client_id, nodes_list, net_family_unspec, ip_is_lan(ip_port.ip), 1);      VLA(uint8_t, plain, 1 + node_format_size * MAX_SENT_NODES + length); @@ -1433,9 +1445,9 @@ static bool sent_getnode_to_node(DHT *dht, const uint8_t *public_key, IP_Port no  {      uint8_t data[sizeof(Node_format) * 2]; -    if (ping_array_check(dht->dht_ping_array, data, sizeof(data), ping_id) == sizeof(Node_format)) { +    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, data, sizeof(data), ping_id) == sizeof(data)) { +    } 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 {          return false; @@ -1678,7 +1690,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 (!is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT)) { +        if (!mono_time_is_timeout(dht->mono_time, assoc->timestamp, BAD_NODE_TIMEOUT)) {              *ip_port = assoc->ip_port;              return 1;          } @@ -1692,7 +1704,7 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co          Client_data *list, uint32_t list_count, uint32_t *bootstrap_times, bool sortable)  {      uint8_t not_kill = 0; -    const uint64_t temp_time = unix_time(); +    const uint64_t temp_time = mono_time_get(dht->mono_time);      uint32_t num_nodes = 0;      VLA(Client_data *, client_list, list_count * 2); @@ -1709,17 +1721,17 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co          for (uint32_t j = 0; j < sizeof(assocs) / sizeof(assocs[0]); ++j) {              IPPTsPng *const assoc = assocs[j]; -            if (!is_timeout(assoc->timestamp, KILL_NODE_TIMEOUT)) { +            if (!mono_time_is_timeout(dht->mono_time, assoc->timestamp, KILL_NODE_TIMEOUT)) {                  sort = 0;                  ++not_kill; -                if (is_timeout(assoc->last_pinged, PING_INTERVAL)) { +                if (mono_time_is_timeout(dht->mono_time, assoc->last_pinged, PING_INTERVAL)) {                      getnodes(dht, assoc->ip_port, client->public_key, public_key, nullptr);                      assoc->last_pinged = temp_time;                  }                  /* If node is good. */ -                if (!is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT)) { +                if (!mono_time_is_timeout(dht->mono_time, assoc->timestamp, BAD_NODE_TIMEOUT)) {                      client_list[num_nodes] = client;                      assoc_list[num_nodes] = assoc;                      ++num_nodes; @@ -1736,10 +1748,11 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co      }      if (sortable && sort_ok) { -        sort_client_list(list, list_count, public_key); +        sort_client_list(list, dht->mono_time, list_count, public_key);      } -    if ((num_nodes != 0) && (is_timeout(*lastgetnode, GET_NODE_INTERVAL) || *bootstrap_times < MAX_BOOTSTRAP_TIMES)) { +    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;          if ((num_nodes - 1) != rand_node) { @@ -1801,7 +1814,7 @@ static void do_Close(DHT *dht)       *       * so: reset all nodes to be BAD_NODE_TIMEOUT, but not       * KILL_NODE_TIMEOUT, so we at least keep trying pings */ -    const uint64_t badonly = unix_time() - BAD_NODE_TIMEOUT; +    const uint64_t badonly = mono_time_get(dht->mono_time) - BAD_NODE_TIMEOUT;      for (size_t i = 0; i < LCLIENT_LIST; ++i) {          Client_data *const client = &dht->close_clientlist[i]; @@ -1906,19 +1919,21 @@ static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_n          const Client_data *const client = &dht_friend->client_list[i];          /* If ip is not zero and node is good. */ -        if (ip_isset(&client->assoc4.ret_ip_port.ip) && !is_timeout(client->assoc4.ret_timestamp, BAD_NODE_TIMEOUT)) { +        if (ip_isset(&client->assoc4.ret_ip_port.ip) +                && !mono_time_is_timeout(dht->mono_time, client->assoc4.ret_timestamp, BAD_NODE_TIMEOUT)) {              ipv4s[num_ipv4s] = client->assoc4.ret_ip_port;              ++num_ipv4s;          } -        if (ip_isset(&client->assoc6.ret_ip_port.ip) && !is_timeout(client->assoc6.ret_timestamp, BAD_NODE_TIMEOUT)) { +        if (ip_isset(&client->assoc6.ret_ip_port.ip) +                && !mono_time_is_timeout(dht->mono_time, client->assoc6.ret_timestamp, BAD_NODE_TIMEOUT)) {              ipv6s[num_ipv6s] = client->assoc6.ret_ip_port;              ++num_ipv6s;          }          if (id_equal(client->public_key, dht_friend->public_key)) { -            if (!is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT) -                    || !is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT)) { +            if (!mono_time_is_timeout(dht->mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT) +                    || !mono_time_is_timeout(dht->mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT)) {                  return 0; /* direct connectivity */              }          } @@ -1997,7 +2012,7 @@ int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *pack              const IPPTsPng *const assoc = *it;              /* If ip is not zero and node is good. */ -            if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { +            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) { @@ -2039,7 +2054,7 @@ static int routeone_tofriend(DHT *dht, const uint8_t *friend_id, const uint8_t *              const IPPTsPng *const assoc = *it;              /* If ip is not zero and node is good. */ -            if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { +            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;              } @@ -2116,7 +2131,7 @@ static int handle_NATping(void *object, IP_Port source, const uint8_t *source_pu      if (packet[0] == NAT_PING_REQUEST) {          /* 1 is reply */          send_NATping(dht, source_pubkey, ping_id, NAT_PING_RESPONSE); -        dht_friend->nat.recv_nat_ping_timestamp = unix_time(); +        dht_friend->nat.recv_nat_ping_timestamp = mono_time_get(dht->mono_time);          return 0;      } @@ -2243,7 +2258,7 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports,  static void do_NAT(DHT *dht)  { -    const uint64_t temp_time = unix_time(); +    const uint64_t temp_time = mono_time_get(dht->mono_time);      for (uint32_t i = 0; i < dht->num_friends; ++i) {          IP_Port ip_list[MAX_FRIEND_CLIENTS]; @@ -2393,7 +2408,7 @@ static uint32_t have_nodes_closelist(DHT *dht, Node_format *nodes, uint16_t num)          const IPPTsPng *const temp = get_closelist_IPPTsPng(dht, nodes[i].public_key, nodes[i].ip_port.ip.family);          if (temp) { -            if (!is_timeout(temp->timestamp, BAD_NODE_TIMEOUT)) { +            if (!mono_time_is_timeout(dht->mono_time, temp->timestamp, BAD_NODE_TIMEOUT)) {                  ++counter;              }          } @@ -2464,7 +2479,7 @@ static int handle_hardening(void *object, IP_Port source, const uint8_t *source_                  return 1;              } -            if (is_timeout(temp->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) { +            if (mono_time_is_timeout(dht->mono_time, temp->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) {                  return 1;              } @@ -2512,7 +2527,8 @@ static Node_format random_node(DHT *dht, Family sa_family)   *   * return the number of nodes.   */ -static uint16_t list_nodes(Client_data *list, size_t length, Node_format *nodes, uint16_t max_num) +static uint16_t list_nodes(Client_data *list, size_t length, const Mono_Time *mono_time, Node_format *nodes, +                           uint16_t max_num)  {      if (max_num == 0) {          return 0; @@ -2523,11 +2539,11 @@ static uint16_t list_nodes(Client_data *list, size_t length, Node_format *nodes,      for (size_t i = length; i != 0; --i) {          const IPPTsPng *assoc = nullptr; -        if (!is_timeout(list[i - 1].assoc4.timestamp, BAD_NODE_TIMEOUT)) { +        if (!mono_time_is_timeout(mono_time, list[i - 1].assoc4.timestamp, BAD_NODE_TIMEOUT)) {              assoc = &list[i - 1].assoc4;          } -        if (!is_timeout(list[i - 1].assoc6.timestamp, BAD_NODE_TIMEOUT)) { +        if (!mono_time_is_timeout(mono_time, list[i - 1].assoc6.timestamp, BAD_NODE_TIMEOUT)) {              if (assoc == nullptr) {                  assoc = &list[i - 1].assoc6;              } else if (random_u08() % 2) { @@ -2563,8 +2579,8 @@ 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, nodes + count, -                            max_num - count); +        count += list_nodes(dht->friends_list[(i + r) % DHT_FAKE_FRIEND_NUMBER].client_list, MAX_FRIEND_CLIENTS, dht->mono_time, +                            nodes + count, max_num - count);          if (count >= max_num) {              break; @@ -2580,7 +2596,7 @@ uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)   */  uint16_t closelist_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)  { -    return list_nodes(dht->close_clientlist, LCLIENT_LIST, nodes, max_num); +    return list_nodes(dht->close_clientlist, LCLIENT_LIST, dht->mono_time, nodes, max_num);  }  #if DHT_HARDENING @@ -2599,12 +2615,12 @@ static void do_hardening(DHT *dht)              sa_family = net_family_ipv6;          } -        if (is_timeout(cur_iptspng->timestamp, BAD_NODE_TIMEOUT)) { +        if (mono_time_is_timeout(dht->mono_time, cur_iptspng->timestamp, BAD_NODE_TIMEOUT)) {              continue;          }          if (cur_iptspng->hardening.send_nodes_ok == 0) { -            if (is_timeout(cur_iptspng->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) { +            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)) { @@ -2622,11 +2638,11 @@ static void do_hardening(DHT *dht)                  // 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 = unix_time(); +                    cur_iptspng->hardening.send_nodes_timestamp = mono_time_get(dht->mono_time);                  }              }          } else { -            if (is_timeout(cur_iptspng->hardening.send_nodes_timestamp, HARDEN_TIMEOUT)) { +            if (mono_time_is_timeout(dht->mono_time, cur_iptspng->hardening.send_nodes_timestamp, HARDEN_TIMEOUT)) {                  cur_iptspng->hardening.send_nodes_ok = 0;              }          } @@ -2688,11 +2704,8 @@ static int cryptopacket_handle(void *object, IP_Port source, const uint8_t *pack  /*----------------------------------------------------------------------------------*/ -DHT *new_dht(const Logger *log, Networking_Core *net, bool holepunching_enabled) +DHT *new_dht(const Logger *log, Mono_Time *mono_time, Networking_Core *net, bool holepunching_enabled)  { -    /* init time */ -    unix_time_update(); -      if (net == nullptr) {          return nullptr;      } @@ -2703,12 +2716,13 @@ DHT *new_dht(const Logger *log, Networking_Core *net, bool holepunching_enabled)          return nullptr;      } +    dht->mono_time = mono_time;      dht->log = log;      dht->net = net;      dht->hole_punching_enabled = holepunching_enabled; -    dht->ping = ping_new(dht); +    dht->ping = ping_new(mono_time, dht);      if (dht->ping == nullptr) {          kill_dht(dht); @@ -2741,9 +2755,7 @@ DHT *new_dht(const Logger *log, Networking_Core *net, bool holepunching_enabled)  void do_dht(DHT *dht)  { -    unix_time_update(); - -    if (dht->last_run == unix_time()) { +    if (dht->last_run == mono_time_get(dht->mono_time)) {          return;      } @@ -2759,7 +2771,7 @@ void do_dht(DHT *dht)  #if DHT_HARDENING      do_hardening(dht);  #endif -    dht->last_run = unix_time(); +    dht->last_run = mono_time_get(dht->mono_time);  }  void kill_dht(DHT *dht) @@ -2811,26 +2823,16 @@ uint32_t dht_size(const DHT *dht)      return size32 + sizesubhead + packed_node_size(net_family_ipv4) * numv4 + packed_node_size(net_family_ipv6) * numv6;  } -static uint8_t *dht_save_subheader(uint8_t *data, uint32_t len, uint16_t type) -{ -    host_to_lendian32(data, len); -    data += sizeof(uint32_t); -    host_to_lendian32(data, (host_tolendian16(DHT_STATE_COOKIE_TYPE) << 16) | host_tolendian16(type)); -    data += sizeof(uint32_t); -    return data; -} - -  /* Save the DHT in data where data is an array of size dht_size(). */  void dht_save(const DHT *dht, uint8_t *data)  { -    host_to_lendian32(data,  DHT_STATE_COOKIE_GLOBAL); +    host_to_lendian32(data, DHT_STATE_COOKIE_GLOBAL);      data += sizeof(uint32_t);      uint8_t *const old_data = data;      /* get right offset. we write the actual header later. */ -    data = dht_save_subheader(data, 0, 0); +    data = state_write_section_header(data, DHT_STATE_COOKIE_TYPE, 0, 0);      Node_format clients[MAX_SAVED_DHT_NODES]; @@ -2868,7 +2870,8 @@ void dht_save(const DHT *dht, uint8_t *data)          }      } -    dht_save_subheader(old_data, pack_nodes(data, sizeof(Node_format) * num, clients, num), DHT_STATE_TYPE_NODES); +    state_write_section_header(old_data, DHT_STATE_COOKIE_TYPE, pack_nodes(data, sizeof(Node_format) * num, clients, num), +                               DHT_STATE_TYPE_NODES);  }  /* Bootstrap from this number of nodes every time dht_connect_after_load() is called */ @@ -2963,13 +2966,11 @@ int dht_load(DHT *dht, const uint8_t *data, uint32_t length)   */  bool dht_isconnected(const DHT *dht)  { -    unix_time_update(); -      for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {          const Client_data *const client = &dht->close_clientlist[i]; -        if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) || -                !is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) { +        if (!mono_time_is_timeout(dht->mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT) || +                !mono_time_is_timeout(dht->mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT)) {              return true;          }      } @@ -2982,16 +2983,16 @@ bool dht_isconnected(const DHT *dht)   */  bool dht_non_lan_connected(const DHT *dht)  { -    unix_time_update(); -      for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {          const Client_data *const client = &dht->close_clientlist[i]; -        if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) && ip_is_lan(client->assoc4.ip_port.ip) == -1) { +        if (!mono_time_is_timeout(dht->mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT) +                && !ip_is_lan(client->assoc4.ip_port.ip)) {              return true;          } -        if (!is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT) && ip_is_lan(client->assoc6.ip_port.ip) == -1) { +        if (!mono_time_is_timeout(dht->mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT) +                && !ip_is_lan(client->assoc6.ip_port.ip)) {              return true;          }      } diff --git a/protocols/Tox/libtox/src/toxcore/DHT.h b/protocols/Tox/libtox/src/toxcore/DHT.h index 0852827c8d..5feb74d275 100644 --- a/protocols/Tox/libtox/src/toxcore/DHT.h +++ b/protocols/Tox/libtox/src/toxcore/DHT.h @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -21,11 +21,12 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef DHT_H -#define DHT_H +#ifndef C_TOXCORE_TOXCORE_DHT_H +#define C_TOXCORE_TOXCORE_DHT_H  #include "crypto_core.h"  #include "logger.h" +#include "mono_time.h"  #include "network.h"  #include "ping_array.h" @@ -173,7 +174,7 @@ int pack_ip_port(uint8_t *data, uint16_t length, const IP_Port *ip_port);   * 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, uint8_t tcp_enabled); +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.   * @@ -190,7 +191,7 @@ int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_   * return -1 on failure.   */  int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, const uint8_t *data, -                 uint16_t length, uint8_t tcp_enabled); +                 uint16_t length, bool tcp_enabled);  /*----------------------------------------------------------------------------------*/ @@ -202,7 +203,7 @@ typedef struct Shared_Key {      uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];      uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];      uint32_t times_requested; -    uint8_t  stored; /* 0 if not, 1 if is */ +    bool stored;      uint64_t time_last_requested;  } Shared_Key; @@ -234,14 +235,14 @@ const uint8_t *dht_get_friend_public_key(const DHT *dht, uint32_t friend_num);  /*----------------------------------------------------------------------------------*/ -/* Shared key generations are costly, it is therefor smart to store commonly used +/* 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.   *   * 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   */ -void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t *secret_key, -                    const uint8_t *public_key); +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   * for packets that we receive. @@ -301,9 +302,12 @@ 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. +/** + * 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, unsigned int length, const uint8_t *pk, IP_Port ip_port, +bool add_to_list(Node_format *nodes_list, uint32_t length, const uint8_t *pk, IP_Port ip_port,                   const uint8_t *cmp_pk);  /* Return 1 if node can be added to close list, 0 if it can't. @@ -321,7 +325,7 @@ 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, -                    uint8_t is_LAN, uint8_t want_good); +                    bool is_LAN, uint8_t want_good);  /* Put up to max_num nodes in nodes from the random friends. @@ -401,7 +405,7 @@ void dht_save(const DHT *dht, uint8_t *data);  int dht_load(DHT *dht, const uint8_t *data, uint32_t length);  /* Initialize DHT. */ -DHT *new_dht(const Logger *log, Networking_Core *net, bool holepunching_enabled); +DHT *new_dht(const Logger *log, Mono_Time *mono_time, Networking_Core *net, bool holepunching_enabled);  void kill_dht(DHT *dht); diff --git a/protocols/Tox/libtox/src/toxcore/LAN_discovery.api.h b/protocols/Tox/libtox/src/toxcore/LAN_discovery.api.h index 9e6c648164..31d6a5f64b 100644 --- a/protocols/Tox/libtox/src/toxcore/LAN_discovery.api.h +++ b/protocols/Tox/libtox/src/toxcore/LAN_discovery.api.h @@ -4,7 +4,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -22,8 +22,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef LAN_DISCOVERY_H -#define LAN_DISCOVERY_H +#ifndef C_TOXCORE_TOXCORE_LAN_DISCOVERY_H +#define C_TOXCORE_TOXCORE_LAN_DISCOVERY_H  #include "DHT.h"  %} @@ -61,13 +61,12 @@ static void kill(dHT::this *dht);  static bool ip_is_local(iP::this ip);  /** - * checks if a given IP isn't routable + * Checks if a given IP isn't routable.   * - *  return 0 if ip is a LAN ip. - *  return -1 if it is not. + * @return true if ip is a LAN ip, false if it is not.   */ -static int32_t ip_is_lan(iP::this ip); +static bool ip_is_lan(iP::this ip);  %{ -#endif +#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 0b2a87831b..aeeea5661a 100644 --- a/protocols/Tox/libtox/src/toxcore/LAN_discovery.c +++ b/protocols/Tox/libtox/src/toxcore/LAN_discovery.c @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -272,91 +272,93 @@ static IP broadcast_ip(Family family_socket, Family family_broadcast)      return ip;  } +static bool ip4_is_local(IP4 ip4) +{ +    /* Loopback. */ +    return ip4.uint8[0] == 127; +} +  /* Is IP a local ip or not. */  bool ip_is_local(IP ip)  {      if (net_family_is_ipv4(ip.family)) { -        IP4 ip4 = ip.ip.v4; +        return ip4_is_local(ip.ip.v4); +    } -        /* Loopback. */ -        if (ip4.uint8[0] == 127) { -            return 1; -        } -    } else { -        /* embedded IPv4-in-IPv6 */ -        if (ipv6_ipv4_in_v6(ip.ip.v6)) { -            IP ip4; -            ip4.family = net_family_ipv4; -            ip4.ip.v4.uint32 = ip.ip.v6.uint32[3]; -            return ip_is_local(ip4); -        } +    /* embedded IPv4-in-IPv6 */ +    if (ipv6_ipv4_in_v6(ip.ip.v6)) { +        IP4 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)) { -            return 1; -        } +    /* 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)) { +        return true;      } -    return 0; +    return false;  } -/*  return 0 if ip is a LAN ip. - *  return -1 if it is not. - */ -int ip_is_lan(IP ip) +static bool ip4_is_lan(IP4 ip4)  { -    if (ip_is_local(ip)) { -        return 0; +    /* 10.0.0.0 to 10.255.255.255 range. */ +    if (ip4.uint8[0] == 10) { +        return true;      } -    if (net_family_is_ipv4(ip.family)) { -        IP4 ip4 = ip.ip.v4; +    /* 172.16.0.0 to 172.31.255.255 range. */ +    if (ip4.uint8[0] == 172 && ip4.uint8[1] >= 16 && ip4.uint8[1] <= 31) { +        return true; +    } -        /* 10.0.0.0 to 10.255.255.255 range. */ -        if (ip4.uint8[0] == 10) { -            return 0; -        } +    /* 192.168.0.0 to 192.168.255.255 range. */ +    if (ip4.uint8[0] == 192 && ip4.uint8[1] == 168) { +        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) { -            return 0; -        } +    /* 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) { +        return true; +    } -        /* 192.168.0.0 to 192.168.255.255 range. */ -        if (ip4.uint8[0] == 192 && ip4.uint8[1] == 168) { -            return 0; -        } +    /* 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)) { +        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) { -            return 0; -        } +    return false; +} -        /* 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)) { -            return 0; -        } -    } else if (net_family_is_ipv6(ip.family)) { +bool ip_is_lan(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_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))) { -            return 0; +            return true;          }          /* embedded IPv4-in-IPv6 */          if (ipv6_ipv4_in_v6(ip.ip.v6)) { -            IP ip4; -            ip4.family = net_family_ipv4; -            ip4.ip.v4.uint32 = ip.ip.v6.uint32[3]; -            return ip_is_lan(ip4); +            IP4 ip4; +            ip4.uint32 = ip.ip.v6.uint32[3]; +            return ip4_is_lan(ip4);          }      } -    return -1; +    return false;  }  static int handle_LANdiscovery(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) @@ -366,7 +368,7 @@ static int handle_LANdiscovery(void *object, IP_Port source, const uint8_t *pack      char ip_str[IP_NTOA_LEN] = { 0 };      ip_ntoa(&source.ip, ip_str, sizeof(ip_str)); -    if (ip_is_lan(source.ip) == -1) { +    if (!ip_is_lan(source.ip)) {          return 1;      } diff --git a/protocols/Tox/libtox/src/toxcore/LAN_discovery.h b/protocols/Tox/libtox/src/toxcore/LAN_discovery.h index 6d9d17b664..8c48316d9e 100644 --- a/protocols/Tox/libtox/src/toxcore/LAN_discovery.h +++ b/protocols/Tox/libtox/src/toxcore/LAN_discovery.h @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -21,8 +21,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef LAN_DISCOVERY_H -#define LAN_DISCOVERY_H +#ifndef C_TOXCORE_TOXCORE_LAN_DISCOVERY_H +#define C_TOXCORE_TOXCORE_LAN_DISCOVERY_H  #include "DHT.h" @@ -64,11 +64,10 @@ void lan_discovery_kill(DHT *dht);  bool ip_is_local(IP ip);  /** - * checks if a given IP isn't routable + * Checks if a given IP isn't routable.   * - *  return 0 if ip is a LAN ip. - *  return -1 if it is not. + * @return true if ip is a LAN ip, false if it is not.   */ -int32_t ip_is_lan(IP ip); +bool ip_is_lan(IP ip);  #endif diff --git a/protocols/Tox/libtox/src/toxcore/Messenger.c b/protocols/Tox/libtox/src/toxcore/Messenger.c index acf9f806f7..594fc79a07 100644 --- a/protocols/Tox/libtox/src/toxcore/Messenger.c +++ b/protocols/Tox/libtox/src/toxcore/Messenger.c @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -41,6 +41,7 @@  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);  // friend_not_valid determines if the friendnumber passed is valid in the Messenger object  static uint8_t friend_not_valid(const Messenger *m, int32_t friendnumber) @@ -1949,7 +1950,7 @@ static int friend_already_added(const uint8_t *real_pk, void *data)  }  /* Run this at startup. */ -Messenger *new_messenger(Messenger_Options *options, unsigned int *error) +Messenger *new_messenger(Mono_Time *mono_time, Messenger_Options *options, unsigned int *error)  {      if (!options) {          return nullptr; @@ -1965,6 +1966,8 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)          return nullptr;      } +    m->mono_time = mono_time; +      m->fr = friendreq_new();      if (!m->fr) { @@ -2010,7 +2013,7 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)          return nullptr;      } -    m->dht = new_dht(m->log, m->net, options->hole_punching_enabled); +    m->dht = new_dht(m->log, m->mono_time, m->net, options->hole_punching_enabled);      if (m->dht == nullptr) {          kill_networking(m->net); @@ -2020,7 +2023,7 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)          return nullptr;      } -    m->net_crypto = new_net_crypto(m->log, m->dht, &options->proxy_info); +    m->net_crypto = new_net_crypto(m->log, m->mono_time, m->dht, &options->proxy_info);      if (m->net_crypto == nullptr) {          kill_networking(m->net); @@ -2031,10 +2034,10 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)          return nullptr;      } -    m->onion = new_onion(m->dht); -    m->onion_a = new_onion_announce(m->dht); -    m->onion_c =  new_onion_client(m->net_crypto); -    m->fr_c = new_friend_connections(m->onion_c, options->local_discovery_enabled); +    m->onion = new_onion(m->mono_time, m->dht); +    m->onion_a = new_onion_announce(m->mono_time, m->dht); +    m->onion_c =  new_onion_client(m->mono_time, m->net_crypto); +    m->fr_c = new_friend_connections(m->mono_time, m->onion_c, options->local_discovery_enabled);      if (!(m->onion && m->onion_a && m->onion_c)) {          kill_friend_connections(m->fr_c); @@ -2081,6 +2084,8 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)      m->lastdump = 0; +    m_register_default_plugins(m); +      if (error) {          *error = MESSENGER_ERROR_NONE;      } @@ -2116,6 +2121,8 @@ void kill_messenger(Messenger *m)      logger_kill(m->log);      free(m->friendlist);      friendreq_kill(m->fr); + +    free(m->options.state_plugins);      free(m);  } @@ -2468,7 +2475,7 @@ 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 = unix_time(); +    uint64_t temp_time = mono_time_get(m->mono_time);      for (i = 0; i < m->numfriends; ++i) {          if (m->friendlist[i].status == FRIEND_ADDED) { @@ -2583,8 +2590,8 @@ uint32_t messenger_run_interval(const Messenger *m)  void do_messenger(Messenger *m, void *userdata)  {      // Add the TCP relays, but only if this is the first time calling do_messenger -    if (m->has_added_relays == 0) { -        m->has_added_relays = 1; +    if (!m->has_added_relays) { +        m->has_added_relays = true;          int i; @@ -2603,15 +2610,13 @@ void do_messenger(Messenger *m, void *userdata)          }      } -    unix_time_update(); -      if (!m->options.udp_disabled) {          networking_poll(m->net, userdata);          do_dht(m->dht);      }      if (m->tcp_server) { -        do_TCP_server(m->tcp_server); +        do_TCP_server(m->tcp_server, m->mono_time);      }      do_net_crypto(m->net_crypto, userdata); @@ -2620,8 +2625,8 @@ void do_messenger(Messenger *m, void *userdata)      do_friends(m, userdata);      connection_status_callback(m, userdata); -    if (unix_time() > m->lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) { -        m->lastdump = unix_time(); +    if (mono_time_get(m->mono_time) > m->lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) { +        m->lastdump = mono_time_get(m->mono_time);          uint32_t client, last_pinged;          for (client = 0; client < LCLIENT_LIST; ++client) { @@ -2737,15 +2742,6 @@ void do_messenger(Messenger *m, void *userdata)  #define MESSENGER_STATE_COOKIE_GLOBAL 0x15ed1b1f  #define MESSENGER_STATE_COOKIE_TYPE      0x01ce -#define MESSENGER_STATE_TYPE_NOSPAMKEYS    1 -#define MESSENGER_STATE_TYPE_DHT           2 -#define MESSENGER_STATE_TYPE_FRIENDS       3 -#define MESSENGER_STATE_TYPE_NAME          4 -#define MESSENGER_STATE_TYPE_STATUSMESSAGE 5 -#define MESSENGER_STATE_TYPE_STATUS        6 -#define MESSENGER_STATE_TYPE_TCP_RELAY     10 -#define MESSENGER_STATE_TYPE_PATH_NODE     11 -#define MESSENGER_STATE_TYPE_END           255  #define SAVED_FRIEND_REQUEST_SIZE 1024  #define NUM_SAVED_PATH_NODES 8 @@ -2794,11 +2790,6 @@ static uint32_t friend_size(void)      return data;  } -static uint32_t saved_friendslist_size(const Messenger *m) -{ -    return count_friendlist(m) * friend_size(); -} -  static uint8_t *friend_save(const struct Saved_Friend *temp, uint8_t *data)  {  #define VALUE_MEMBER(name) do {                     \ @@ -2833,13 +2824,202 @@ static uint8_t *friend_save(const struct Saved_Friend *temp, uint8_t *data)      return data;  } -static uint32_t friends_list_save(const Messenger *m, uint8_t *data) + +static const uint8_t *friend_load(struct Saved_Friend *temp, const uint8_t *data)  { -    uint32_t i; +#define VALUE_MEMBER(name) do {                     \ +    memcpy(&temp->name, data, sizeof(temp->name));  \ +    data += sizeof(temp->name);                     \ +} while (0) + +#define ARRAY_MEMBER(name) do {                     \ +    memcpy(temp->name, data, sizeof(temp->name));   \ +    data += sizeof(temp->name);                     \ +} while (0) + +    // Exactly the same in friend_load, friend_save, and friend_size +    VALUE_MEMBER(status); +    ARRAY_MEMBER(real_pk); +    ARRAY_MEMBER(info); +    ++data; // padding +    VALUE_MEMBER(info_size); +    ARRAY_MEMBER(name); +    VALUE_MEMBER(name_length); +    ARRAY_MEMBER(statusmessage); +    ++data; // padding +    VALUE_MEMBER(statusmessage_length); +    VALUE_MEMBER(userstatus); +    data += 3; // padding +    VALUE_MEMBER(friendrequest_nospam); +    VALUE_MEMBER(last_seen_time); + +#undef VALUE_MEMBER +#undef ARRAY_MEMBER + +    return data; +} + + +static uint32_t m_state_plugins_size(const Messenger *m) +{ +    const uint32_t size32 = sizeof(uint32_t); +    const uint32_t sizesubhead = size32 * 2; + +    uint32_t size = 0; + +    for (const Messenger_State_Plugin *plugin = m->options.state_plugins; +            plugin != m->options.state_plugins + m->options.state_plugins_length; +            ++plugin) { +        size += sizesubhead + plugin->size(m); +    } + +    return size; +} + +/* + * Registers a state plugin with the messenger + * returns true on success + * returns false on failure + */ +bool m_register_state_plugin(Messenger *m, Messenger_State_Type type, m_state_size_cb size_callback, +                             m_state_load_cb load_callback, +                             m_state_save_cb save_callback) +{ +    Messenger_State_Plugin *temp = (Messenger_State_Plugin *)realloc(m->options.state_plugins, +                                   sizeof(Messenger_State_Plugin) * (m->options.state_plugins_length + 1)); + +    if (!temp) { +        return false; +    } + +    m->options.state_plugins = temp; +    ++m->options.state_plugins_length; + +    const uint8_t index = m->options.state_plugins_length - 1; +    m->options.state_plugins[index].type = type; +    m->options.state_plugins[index].size = size_callback; +    m->options.state_plugins[index].load = load_callback; +    m->options.state_plugins[index].save = save_callback; + +    return true; +} + +static uint32_t m_plugin_size(const Messenger *m, Messenger_State_Type type) +{ +    for (uint8_t i = 0; i < m->options.state_plugins_length; ++i) { +        const Messenger_State_Plugin plugin = m->options.state_plugins[i]; + +        if (plugin.type == type) { +            return plugin.size(m); +        } +    } + +    LOGGER_ERROR(m->log, "Unknown type encountered: %u", type); + +    return UINT32_MAX; +} + +/*  return size of the messenger data (for saving) */ +uint32_t messenger_size(const Messenger *m) +{ +    const uint32_t size32 = sizeof(uint32_t); +    const uint32_t sizesubhead = size32 * 2; +    return   size32 * 2                       // global cookie +             + m_state_plugins_size(m) +             + sizesubhead; +} + +/* Save the messenger in data of size Messenger_size(). */ +void messenger_save(const Messenger *m, uint8_t *data) +{ +    memset(data, 0, messenger_size(m)); + +    const uint32_t size32 = sizeof(uint32_t); + +    // write cookie +    memset(data, 0, size32); +    data += size32; +    host_to_lendian32(data, MESSENGER_STATE_COOKIE_GLOBAL); +    data += size32; + +    for (uint8_t i = 0; i < m->options.state_plugins_length; ++i) { +        const Messenger_State_Plugin plugin = m->options.state_plugins[i]; +        data = plugin.save(m, data); +    } +} + +// nospam state plugin +static uint32_t nospam_keys_size(const Messenger *m) +{ +    return sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE; +} + +static State_Load_Status load_nospam_keys(Messenger *m, const uint8_t *data, uint32_t length) +{ +    if (length != m_plugin_size(m, MESSENGER_STATE_TYPE_NOSPAMKEYS)) { +        return STATE_LOAD_STATUS_ERROR; +    } + +    uint32_t nospam; +    lendian_to_host32(&nospam, data); +    set_nospam(m->fr, nospam); +    load_secret_key(m->net_crypto, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE); + +    if (public_key_cmp(data + sizeof(uint32_t), nc_get_self_public_key(m->net_crypto)) != 0) { +        return STATE_LOAD_STATUS_ERROR; +    } + +    return STATE_LOAD_STATUS_CONTINUE; +} + +static uint8_t *save_nospam_keys(const Messenger *m, uint8_t *data) +{ +    const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_NOSPAMKEYS); +    assert(sizeof(get_nospam(m->fr)) == sizeof(uint32_t)); +    data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_NOSPAMKEYS); +    uint32_t nospam = get_nospam(m->fr); +    host_to_lendian32(data, nospam); +    save_keys(m->net_crypto, data + sizeof(uint32_t)); +    data += len; +    return data; +} + +// DHT state plugin +static uint32_t m_dht_size(const Messenger *m) +{ +    return dht_size(m->dht); +} + +static uint8_t *save_dht(const Messenger *m, uint8_t *data) +{ +    const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_DHT); +    data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_DHT); +    dht_save(m->dht, data); +    data += len; +    return data; +} + +static State_Load_Status m_dht_load(Messenger *m, const uint8_t *data, uint32_t length) +{ +    dht_load(m->dht, data, length); // TODO(endoffile78): Should we throw an error if dht_load fails? +    return STATE_LOAD_STATUS_CONTINUE; +} + +// friendlist state plugin +static uint32_t saved_friendslist_size(const Messenger *m) +{ +    return count_friendlist(m) * friend_size(); +} + +static uint8_t *friends_list_save(const Messenger *m, uint8_t *data) +{ +    const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_FRIENDS); +    data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_FRIENDS); +      uint32_t num = 0;      uint8_t *cur_data = data; -    for (i = 0; i < m->numfriends; ++i) { +    for (uint32_t i = 0; i < m->numfriends; ++i) {          if (m->friendlist[i].status > 0) {              struct Saved_Friend temp = { 0 };              temp.status = m->friendlist[i].status; @@ -2878,47 +3058,15 @@ static uint32_t friends_list_save(const Messenger *m, uint8_t *data)      }      assert(cur_data - data == num * friend_size()); -    return cur_data - data; -} - -static const uint8_t *friend_load(struct Saved_Friend *temp, const uint8_t *data) -{ -#define VALUE_MEMBER(name) do {                     \ -    memcpy(&temp->name, data, sizeof(temp->name));  \ -    data += sizeof(temp->name);                     \ -} while (0) - -#define ARRAY_MEMBER(name) do {                     \ -    memcpy(temp->name, data, sizeof(temp->name));   \ -    data += sizeof(temp->name);                     \ -} while (0) - -    // Exactly the same in friend_load, friend_save, and friend_size -    VALUE_MEMBER(status); -    ARRAY_MEMBER(real_pk); -    ARRAY_MEMBER(info); -    ++data; // padding -    VALUE_MEMBER(info_size); -    ARRAY_MEMBER(name); -    VALUE_MEMBER(name_length); -    ARRAY_MEMBER(statusmessage); -    ++data; // padding -    VALUE_MEMBER(statusmessage_length); -    VALUE_MEMBER(userstatus); -    data += 3; // padding -    VALUE_MEMBER(friendrequest_nospam); -    VALUE_MEMBER(last_seen_time); - -#undef VALUE_MEMBER -#undef ARRAY_MEMBER +    data += len;      return data;  } -static int friends_list_load(Messenger *m, const uint8_t *data, uint32_t length) +static State_Load_Status friends_list_load(Messenger *m, const uint8_t *data, uint32_t length)  {      if (length % friend_size() != 0) { -        return -1; +        return STATE_LOAD_STATUS_ERROR; // TODO(endoffile78): error or continue?      }      uint32_t num = length / friend_size(); @@ -2959,205 +3107,202 @@ static int friends_list_load(Messenger *m, const uint8_t *data, uint32_t length)          }      } -    return num; +    return STATE_LOAD_STATUS_CONTINUE;  } -/*  return size of the messenger data (for saving) */ -uint32_t messenger_size(const Messenger *m) +// name state plugin +static uint32_t name_size(const Messenger *m)  { -    uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2; -    return   size32 * 2                                      // global cookie -             + sizesubhead + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE -             + sizesubhead + dht_size(m->dht)                  // DHT -             + sizesubhead + saved_friendslist_size(m)         // Friendlist itself. -             + sizesubhead + m->name_length                    // Own nickname. -             + sizesubhead + m->statusmessage_length           // status message -             + sizesubhead + 1                                 // status -             + sizesubhead + NUM_SAVED_TCP_RELAYS * packed_node_size(net_family_tcp_ipv6) // TCP relays -             + sizesubhead + NUM_SAVED_PATH_NODES * packed_node_size(net_family_tcp_ipv6) // saved path nodes -             + sizesubhead; +    return m->name_length;  } -static uint8_t *messenger_save_subheader(uint8_t *data, uint32_t len, uint16_t type) +static uint8_t *save_name(const Messenger *m, uint8_t *data)  { -    host_to_lendian32(data, len); -    data += sizeof(uint32_t); -    host_to_lendian32(data, (host_tolendian16(MESSENGER_STATE_COOKIE_TYPE) << 16) | host_tolendian16(type)); -    data += sizeof(uint32_t); +    const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_NAME); +    data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_NAME); +    memcpy(data, m->name, len); +    data += len;      return data;  } -/* Save the messenger in data of size Messenger_size(). */ -void messenger_save(const Messenger *m, uint8_t *data) +static State_Load_Status load_name(Messenger *m, const uint8_t *data, uint32_t length)  { -    memset(data, 0, messenger_size(m)); +    if (length > 0 && length <= MAX_NAME_LENGTH) { +        setname(m, data, length); +    } -    uint32_t len; -    uint16_t type; -    uint32_t size32 = sizeof(uint32_t); +    return STATE_LOAD_STATUS_CONTINUE; +} -    memset(data, 0, size32); -    data += size32; -    host_to_lendian32(data, MESSENGER_STATE_COOKIE_GLOBAL); -    data += size32; +// status message state plugin +static uint32_t status_message_size(const Messenger *m) +{ +    return m->statusmessage_length; +} -    assert(sizeof(get_nospam(m->fr)) == sizeof(uint32_t)); -    len = size32 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE; -    type = MESSENGER_STATE_TYPE_NOSPAMKEYS; -    data = messenger_save_subheader(data, len, type); -    *(uint32_t *)data = get_nospam(m->fr); -    save_keys(m->net_crypto, data + size32); +static uint8_t *save_status_message(const Messenger *m, uint8_t *data) +{ +    const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_STATUSMESSAGE); +    data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_STATUSMESSAGE); +    memcpy(data, m->statusmessage, len);      data += len; +    return data; +} -    len = saved_friendslist_size(m); -    type = MESSENGER_STATE_TYPE_FRIENDS; -    data = messenger_save_subheader(data, len, type); -    friends_list_save(m, data); -    data += len; +static State_Load_Status load_status_message(Messenger *m, const uint8_t *data, uint32_t length) +{ +    if (length > 0 && length <= MAX_STATUSMESSAGE_LENGTH) { +        m_set_statusmessage(m, data, length); +    } -    len = m->name_length; -    type = MESSENGER_STATE_TYPE_NAME; -    data = messenger_save_subheader(data, len, type); -    memcpy(data, m->name, len); -    data += len; +    return STATE_LOAD_STATUS_CONTINUE; +} -    len = m->statusmessage_length; -    type = MESSENGER_STATE_TYPE_STATUSMESSAGE; -    data = messenger_save_subheader(data, len, type); -    memcpy(data, m->statusmessage, len); -    data += len; +// status state plugin +static uint32_t status_size(const Messenger *m) +{ +    return 1; +} -    len = 1; -    type = MESSENGER_STATE_TYPE_STATUS; -    data = messenger_save_subheader(data, len, type); +static uint8_t *save_status(const Messenger *m, uint8_t *data) +{ +    const uint32_t len = m_plugin_size(m, MESSENGER_STATE_TYPE_STATUS); +    data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_STATUS);      *data = m->userstatus;      data += len; +    return data; +} -    len = dht_size(m->dht); -    type = MESSENGER_STATE_TYPE_DHT; -    data = messenger_save_subheader(data, len, type); -    dht_save(m->dht, data); -    data += len; +static State_Load_Status load_status(Messenger *m, const uint8_t *data, uint32_t length) +{ +    if (length == 1) { +        m_set_userstatus(m, *data); +    } +    return STATE_LOAD_STATUS_CONTINUE; +} + +// TCP Relay state plugin +static uint32_t tcp_relay_size(const Messenger *m) +{ +    return NUM_SAVED_TCP_RELAYS * packed_node_size(net_family_tcp_ipv6); +} + +static uint8_t *save_tcp_relays(const Messenger *m, uint8_t *data) +{      Node_format relays[NUM_SAVED_TCP_RELAYS]; -    type = MESSENGER_STATE_TYPE_TCP_RELAY;      uint8_t *temp_data = data; -    data = messenger_save_subheader(temp_data, 0, type); +    data = state_write_section_header(temp_data, MESSENGER_STATE_COOKIE_TYPE, 0, MESSENGER_STATE_TYPE_TCP_RELAY);      unsigned int num = copy_connected_tcp_relays(m->net_crypto, relays, NUM_SAVED_TCP_RELAYS);      int l = pack_nodes(data, NUM_SAVED_TCP_RELAYS * packed_node_size(net_family_tcp_ipv6), relays, num);      if (l > 0) { -        len = l; -        data = messenger_save_subheader(temp_data, len, type); +        const uint32_t len = l; +        data = state_write_section_header(temp_data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_TCP_RELAY);          data += len;      } -    Node_format nodes[NUM_SAVED_PATH_NODES]; -    type = MESSENGER_STATE_TYPE_PATH_NODE; -    temp_data = data; -    data = messenger_save_subheader(data, 0, type); -    memset(nodes, 0, sizeof(nodes)); -    num = onion_backup_nodes(m->onion_c, nodes, NUM_SAVED_PATH_NODES); -    l = pack_nodes(data, NUM_SAVED_PATH_NODES * packed_node_size(net_family_tcp_ipv6), nodes, num); +    return data; +} -    if (l > 0) { -        len = l; -        data = messenger_save_subheader(temp_data, len, type); -        data += len; +static State_Load_Status load_tcp_relays(Messenger *m, const uint8_t *data, uint32_t length) +{ +    if (length != 0) { +        unpack_nodes(m->loaded_relays, NUM_SAVED_TCP_RELAYS, nullptr, data, length, 1); +        m->has_added_relays = false;      } -    messenger_save_subheader(data, 0, MESSENGER_STATE_TYPE_END); +    return STATE_LOAD_STATUS_CONTINUE;  } -static State_Load_Status messenger_load_state_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type) +// path node state plugin +static uint32_t path_node_size(const Messenger *m)  { -    Messenger *m = (Messenger *)outer; - -    switch (type) { -        case MESSENGER_STATE_TYPE_NOSPAMKEYS: -            if (length == CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE + sizeof(uint32_t)) { -                set_nospam(m->fr, *(const uint32_t *)data); -                load_secret_key(m->net_crypto, (&data[sizeof(uint32_t)]) + CRYPTO_PUBLIC_KEY_SIZE); - -                if (public_key_cmp((&data[sizeof(uint32_t)]), nc_get_self_public_key(m->net_crypto)) != 0) { -                    return STATE_LOAD_STATUS_ERROR; -                } -            } else { -                return STATE_LOAD_STATUS_ERROR;    /* critical */ -            } - -            break; - -        case MESSENGER_STATE_TYPE_DHT: -            dht_load(m->dht, data, length); -            break; - -        case MESSENGER_STATE_TYPE_FRIENDS: -            friends_list_load(m, data, length); -            break; - -        case MESSENGER_STATE_TYPE_NAME: -            if ((length > 0) && (length <= MAX_NAME_LENGTH)) { -                setname(m, data, length); -            } +    return NUM_SAVED_PATH_NODES * packed_node_size(net_family_tcp_ipv6); +} -            break; +static uint8_t *save_path_nodes(const Messenger *m, uint8_t *data) +{ +    Node_format nodes[NUM_SAVED_PATH_NODES]; +    uint8_t *temp_data = data; +    data = state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, 0, MESSENGER_STATE_TYPE_PATH_NODE); +    memset(nodes, 0, sizeof(nodes)); +    const unsigned int num = onion_backup_nodes(m->onion_c, nodes, NUM_SAVED_PATH_NODES); +    const int l = pack_nodes(data, NUM_SAVED_PATH_NODES * packed_node_size(net_family_tcp_ipv6), nodes, num); -        case MESSENGER_STATE_TYPE_STATUSMESSAGE: -            if ((length > 0) && (length <= MAX_STATUSMESSAGE_LENGTH)) { -                m_set_statusmessage(m, data, length); -            } +    if (l > 0) { +        const uint32_t len = l; +        data = state_write_section_header(temp_data, MESSENGER_STATE_COOKIE_TYPE, len, MESSENGER_STATE_TYPE_PATH_NODE); +        data += len; +    } -            break; +    return data; +} -        case MESSENGER_STATE_TYPE_STATUS: -            if (length == 1) { -                m_set_userstatus(m, *data); -            } +static State_Load_Status load_path_nodes(Messenger *m, const uint8_t *data, uint32_t length) +{ +    Node_format nodes[NUM_SAVED_PATH_NODES]; -            break; +    if (length != 0) { +        const int num = unpack_nodes(nodes, NUM_SAVED_PATH_NODES, nullptr, data, length, 0); -        case MESSENGER_STATE_TYPE_TCP_RELAY: { -            if (length == 0) { -                break; -            } +        for (int i = 0; i < num; ++i) { +            onion_add_bs_path_node(m->onion_c, nodes[i].ip_port, nodes[i].public_key); +        } +    } -            unpack_nodes(m->loaded_relays, NUM_SAVED_TCP_RELAYS, nullptr, data, length, 1); -            m->has_added_relays = 0; +    return STATE_LOAD_STATUS_CONTINUE; +} -            break; -        } +// end state plugin +static uint32_t end_size(const Messenger *m) +{ +    return 0; +} -        case MESSENGER_STATE_TYPE_PATH_NODE: { -            Node_format nodes[NUM_SAVED_PATH_NODES]; +static uint8_t *save_end(const Messenger *m, uint8_t *data) +{ +    return state_write_section_header(data, MESSENGER_STATE_COOKIE_TYPE, 0, MESSENGER_STATE_TYPE_END); +} -            if (length == 0) { -                break; -            } +static State_Load_Status load_end(Messenger *m, const uint8_t *data, uint32_t length) +{ +    if (length != 0) { +        return STATE_LOAD_STATUS_ERROR; +    } -            int i, num = unpack_nodes(nodes, NUM_SAVED_PATH_NODES, nullptr, data, length, 0); +    return STATE_LOAD_STATUS_END; +} -            for (i = 0; i < num; ++i) { -                onion_add_bs_path_node(m->onion_c, nodes[i].ip_port, nodes[i].public_key); -            } +static void m_register_default_plugins(Messenger *m) +{ +    m_register_state_plugin(m, MESSENGER_STATE_TYPE_NOSPAMKEYS, nospam_keys_size, load_nospam_keys, save_nospam_keys); +    m_register_state_plugin(m, MESSENGER_STATE_TYPE_DHT, m_dht_size, m_dht_load, save_dht); +    m_register_state_plugin(m, MESSENGER_STATE_TYPE_FRIENDS, saved_friendslist_size, friends_list_load, friends_list_save); +    m_register_state_plugin(m, MESSENGER_STATE_TYPE_NAME, name_size, load_name, save_name); +    m_register_state_plugin(m, MESSENGER_STATE_TYPE_STATUSMESSAGE, status_message_size, load_status_message, +                            save_status_message); +    m_register_state_plugin(m, MESSENGER_STATE_TYPE_STATUS, status_size, load_status, save_status); +    m_register_state_plugin(m, MESSENGER_STATE_TYPE_TCP_RELAY, tcp_relay_size, load_tcp_relays, save_tcp_relays); +    m_register_state_plugin(m, MESSENGER_STATE_TYPE_PATH_NODE, path_node_size, load_path_nodes, save_path_nodes); +    m_register_state_plugin(m, MESSENGER_STATE_TYPE_END, end_size, load_end, save_end); +} -            break; -        } +static State_Load_Status messenger_load_state_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type) +{ +    Messenger *m = (Messenger *)outer; -        case MESSENGER_STATE_TYPE_END: { -            if (length != 0) { -                return STATE_LOAD_STATUS_ERROR; -            } +    for (uint8_t i = 0; i < m->options.state_plugins_length; ++i) { +        const Messenger_State_Plugin *const plugin = &m->options.state_plugins[i]; -            return STATE_LOAD_STATUS_END; +        if (plugin->type == type) { +            return plugin->load(m, data, length);          } - -        default: -            LOGGER_ERROR(m->log, "Load state: contains unrecognized part (len %u, type %u)\n", -                         length, type); -            break;      } +    LOGGER_ERROR(m->log, "Load state: contains unrecognized part (len %u, type %u)\n", +                 length, type); +      return STATE_LOAD_STATUS_CONTINUE;  } diff --git a/protocols/Tox/libtox/src/toxcore/Messenger.h b/protocols/Tox/libtox/src/toxcore/Messenger.h index 6fc4df024c..ab9d72568e 100644 --- a/protocols/Tox/libtox/src/toxcore/Messenger.h +++ b/protocols/Tox/libtox/src/toxcore/Messenger.h @@ -4,7 +4,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -22,13 +22,14 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef MESSENGER_H -#define MESSENGER_H +#ifndef C_TOXCORE_TOXCORE_MESSENGER_H +#define C_TOXCORE_TOXCORE_MESSENGER_H  #include "friend_connection.h"  #include "friend_requests.h"  #include "logger.h"  #include "net_crypto.h" +#include "state.h"  #define MAX_NAME_LENGTH 128  /* TODO(irungentoo): this must depend on other variable. */ @@ -50,6 +51,36 @@ typedef enum Message_Type {      MESSAGE_ACTION  } Message_Type; +typedef struct Messenger Messenger; + +// Returns the size of the data +typedef uint32_t m_state_size_cb(const Messenger *m); + +// Returns the new pointer to data +typedef uint8_t *m_state_save_cb(const Messenger *m, uint8_t *data); + +// Returns if there were any erros during loading +typedef State_Load_Status m_state_load_cb(Messenger *m, const uint8_t *data, uint32_t length); + +typedef enum Messenger_State_Type { +    MESSENGER_STATE_TYPE_NOSPAMKEYS    = 1, +    MESSENGER_STATE_TYPE_DHT           = 2, +    MESSENGER_STATE_TYPE_FRIENDS       = 3, +    MESSENGER_STATE_TYPE_NAME          = 4, +    MESSENGER_STATE_TYPE_STATUSMESSAGE = 5, +    MESSENGER_STATE_TYPE_STATUS        = 6, +    MESSENGER_STATE_TYPE_TCP_RELAY     = 10, +    MESSENGER_STATE_TYPE_PATH_NODE     = 11, +    MESSENGER_STATE_TYPE_END           = 255, +} Messenger_State_Type; + +typedef struct Messenger_State_Plugin { +    Messenger_State_Type type; +    m_state_size_cb *size; +    m_state_save_cb *save; +    m_state_load_cb *load; +} Messenger_State_Plugin; +  typedef struct Messenger_Options {      bool ipv6enabled;      bool udp_disabled; @@ -63,6 +94,9 @@ typedef struct Messenger_Options {      logger_cb *log_callback;      void *log_context;      void *log_user_data; + +    Messenger_State_Plugin *state_plugins; +    uint8_t state_plugins_length;  } Messenger_Options; @@ -156,8 +190,6 @@ typedef enum Filekind {  } Filekind; -typedef struct Messenger Messenger; -  typedef void m_self_connection_status_cb(Messenger *m, unsigned int connection_status, void *user_data);  typedef void m_friend_status_cb(Messenger *m, uint32_t friend_number, unsigned int status, void *user_data);  typedef void m_friend_connection_status_cb(Messenger *m, uint32_t friend_number, unsigned int connection_status, @@ -233,6 +265,7 @@ typedef struct Friend {  struct Messenger {      Logger *log; +    Mono_Time *mono_time;      Networking_Core *net;      Net_Crypto *net_crypto; @@ -259,7 +292,7 @@ struct Messenger {      time_t lastdump; -    uint8_t has_added_relays; // If the first connection has occurred in do_messenger +    bool has_added_relays; // If the first connection has occurred in do_messenger      Node_format loaded_relays[NUM_SAVED_TCP_RELAYS]; // Relays loaded from config      m_friend_message_cb *friend_message; @@ -738,7 +771,7 @@ typedef enum Messenger_Error {   *   *  if error is not NULL it will be set to one of the values in the enum above.   */ -Messenger *new_messenger(Messenger_Options *options, unsigned int *error); +Messenger *new_messenger(Mono_Time *mono_time, Messenger_Options *options, unsigned int *error);  /* Run this before closing shop   * Free all datastructures. @@ -757,6 +790,14 @@ 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 + * + * returns true on success + * returns false on error + */ +bool m_register_state_plugin(Messenger *m, Messenger_State_Type type, m_state_size_cb size_callback, +                             m_state_load_cb load_callback, m_state_save_cb save_callback); +  /* return size of the messenger data (for saving). */  uint32_t messenger_size(const Messenger *m); diff --git a/protocols/Tox/libtox/src/toxcore/TCP_client.c b/protocols/Tox/libtox/src/toxcore/TCP_client.c index 381d9b801a..6eae84086a 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_client.c +++ b/protocols/Tox/libtox/src/toxcore/TCP_client.c @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2014 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -419,17 +419,6 @@ static bool client_add_priority(TCP_Client_Connection *con, const uint8_t *packe      return 1;  } -static void wipe_priority_list(TCP_Client_Connection *con) -{ -    TCP_Priority_List *p = con->priority_queue_start; - -    while (p) { -        TCP_Priority_List *pp = p; -        p = p->next; -        free(pp); -    } -} -  /* return 1 on success.   * return 0 if could not send packet.   * return -1 on failure (connection must be killed). @@ -688,8 +677,8 @@ void onion_response_handler(TCP_Client_Connection *con, tcp_onion_response_cb *o  /* Create new TCP connection to ip_port/public_key   */ -TCP_Client_Connection *new_TCP_connection(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 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)  {      if (networking_at_startup() != 0) {          return nullptr; @@ -765,7 +754,7 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public              break;      } -    temp->kill_at = unix_time() + TCP_CONNECTION_TIMEOUT; +    temp->kill_at = mono_time_get(mono_time) + TCP_CONNECTION_TIMEOUT;      return temp;  } @@ -949,13 +938,13 @@ static bool tcp_process_packet(TCP_Client_Connection *conn, void *userdata)      return true;  } -static int do_confirmed_TCP(TCP_Client_Connection *conn, void *userdata) +static int do_confirmed_TCP(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); -    if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) { +    if (mono_time_is_timeout(mono_time, conn->last_pinged, TCP_PING_FREQUENCY)) {          uint64_t ping_id = random_u64();          if (!ping_id) { @@ -965,10 +954,10 @@ static int do_confirmed_TCP(TCP_Client_Connection *conn, void *userdata)          conn->ping_request_id = ping_id;          conn->ping_id = ping_id;          tcp_send_ping_request(conn); -        conn->last_pinged = unix_time(); +        conn->last_pinged = mono_time_get(mono_time);      } -    if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) { +    if (conn->ping_id && mono_time_is_timeout(mono_time, conn->last_pinged, TCP_PING_TIMEOUT)) {          conn->status = TCP_CLIENT_DISCONNECTED;          return 0;      } @@ -983,10 +972,8 @@ static int do_confirmed_TCP(TCP_Client_Connection *conn, void *userdata)  /* Run the TCP connection   */ -void do_TCP_connection(TCP_Client_Connection *tcp_connection, void *userdata) +void do_TCP_connection(Mono_Time *mono_time, TCP_Client_Connection *tcp_connection, void *userdata)  { -    unix_time_update(); -      if (tcp_connection->status == TCP_CLIENT_DISCONNECTED) {          return;      } @@ -1061,10 +1048,10 @@ void do_TCP_connection(TCP_Client_Connection *tcp_connection, void *userdata)      }      if (tcp_connection->status == TCP_CLIENT_CONFIRMED) { -        do_confirmed_TCP(tcp_connection, userdata); +        do_confirmed_TCP(tcp_connection, mono_time, userdata);      } -    if (tcp_connection->kill_at <= unix_time()) { +    if (tcp_connection->kill_at <= mono_time_get(mono_time)) {          tcp_connection->status = TCP_CLIENT_DISCONNECTED;      }  } @@ -1077,7 +1064,7 @@ void kill_TCP_connection(TCP_Client_Connection *tcp_connection)          return;      } -    wipe_priority_list(tcp_connection); +    wipe_priority_list(tcp_connection->priority_queue_start);      kill_sock(tcp_connection->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 6d1cbb3bd3..9d43d642b3 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_client.h +++ b/protocols/Tox/libtox/src/toxcore/TCP_client.h @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2014 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -21,8 +21,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef TCP_CLIENT_H -#define TCP_CLIENT_H +#ifndef C_TOXCORE_TOXCORE_TCP_CLIENT_H +#define C_TOXCORE_TOXCORE_TCP_CLIENT_H  #include "TCP_server.h"  #include "crypto_core.h" @@ -64,12 +64,12 @@ void tcp_con_set_custom_uint(TCP_Client_Connection *con, uint32_t value);  /* Create new TCP connection to ip_port/public_key   */ -TCP_Client_Connection *new_TCP_connection(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 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);  /* Run the TCP connection   */ -void do_TCP_connection(TCP_Client_Connection *tcp_connection, void *userdata); +void do_TCP_connection(Mono_Time *mono_time, TCP_Client_Connection *tcp_connection, void *userdata);  /* Kill the TCP connection   */ diff --git a/protocols/Tox/libtox/src/toxcore/TCP_connection.c b/protocols/Tox/libtox/src/toxcore/TCP_connection.c index 6763328da4..b11b1e3b08 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_connection.c +++ b/protocols/Tox/libtox/src/toxcore/TCP_connection.c @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2015 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -36,6 +36,7 @@  struct TCP_Connections { +    Mono_Time *mono_time;      DHT *dht;      uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; @@ -794,8 +795,8 @@ 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(ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, -                          &tcp_c->proxy_info); +    tcp_con->connection = new_TCP_connection(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) {          kill_tcp_relay_connection(tcp_c, tcp_connections_number); @@ -884,7 +885,7 @@ static int unsleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connecti          return -1;      } -    tcp_con->connection = new_TCP_connection(tcp_con->ip_port, tcp_con->relay_pk, tcp_c->self_public_key, +    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);      if (!tcp_con->connection) { @@ -1122,7 +1123,7 @@ static int tcp_relay_on_online(TCP_Connections *tcp_c, int tcp_connections_numbe      /* If this connection isn't used by any connection, we don't need to wait for them to come online. */      if (sent) { -        tcp_con->connected_time = unix_time(); +        tcp_con->connected_time = mono_time_get(tcp_c->mono_time);      } else {          tcp_con->connected_time = 0;      } @@ -1155,8 +1156,8 @@ 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(ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, -                          &tcp_c->proxy_info); +    tcp_con->connection = new_TCP_connection(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) {          return -1; @@ -1216,7 +1217,7 @@ int add_tcp_number_relay_connection(TCP_Connections *tcp_c, int connections_numb      if (tcp_con->status == TCP_CONN_CONNECTED) {          if (send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key) == 0) { -            tcp_con->connected_time = unix_time(); +            tcp_con->connected_time = mono_time_get(tcp_c->mono_time);          }      } @@ -1391,7 +1392,7 @@ int set_tcp_onion_status(TCP_Connections *tcp_c, bool status)   *   * Returns NULL on failure.   */ -TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *proxy_info) +TCP_Connections *new_tcp_connections(Mono_Time *mono_time, const uint8_t *secret_key, TCP_Proxy_Info *proxy_info)  {      if (secret_key == nullptr) {          return nullptr; @@ -1403,6 +1404,8 @@ TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *          return nullptr;      } +    temp->mono_time = mono_time; +      memcpy(temp->self_secret_key, secret_key, CRYPTO_SECRET_KEY_SIZE);      crypto_derive_public_key(temp->self_public_key, temp->self_secret_key);      temp->proxy_info = *proxy_info; @@ -1419,7 +1422,7 @@ static void do_tcp_conns(TCP_Connections *tcp_c, void *userdata)          if (tcp_con) {              if (tcp_con->status != TCP_CONN_SLEEPING) { -                do_TCP_connection(tcp_con->connection, userdata); +                do_TCP_connection(tcp_c->mono_time, tcp_con->connection, userdata);                  /* callbacks can change TCP connection address. */                  tcp_con = get_tcp_connection(tcp_c, i); @@ -1443,7 +1446,7 @@ static void do_tcp_conns(TCP_Connections *tcp_c, void *userdata)                  if (tcp_con->status == TCP_CONN_CONNECTED && !tcp_con->onion && tcp_con->lock_count                          && tcp_con->lock_count == tcp_con->sleep_count -                        && is_timeout(tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) { +                        && mono_time_is_timeout(tcp_c->mono_time, tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) {                      sleep_tcp_relay_connection(tcp_c, i);                  }              } @@ -1471,7 +1474,8 @@ static void kill_nonused_tcp(TCP_Connections *tcp_c)          if (tcp_con) {              if (tcp_con->status == TCP_CONN_CONNECTED) { -                if (!tcp_con->onion && !tcp_con->lock_count && is_timeout(tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) { +                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;                  } diff --git a/protocols/Tox/libtox/src/toxcore/TCP_connection.h b/protocols/Tox/libtox/src/toxcore/TCP_connection.h index 2d99e12288..1962fb1aca 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_connection.h +++ b/protocols/Tox/libtox/src/toxcore/TCP_connection.h @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2015 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -21,8 +21,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef TCP_CONNECTION_H -#define TCP_CONNECTION_H +#ifndef C_TOXCORE_TOXCORE_TCP_CONNECTION_H +#define C_TOXCORE_TOXCORE_TCP_CONNECTION_H  #include "TCP_client.h" @@ -219,7 +219,7 @@ uint32_t tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_rela   *   * Returns NULL on failure.   */ -TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *proxy_info); +TCP_Connections *new_tcp_connections(Mono_Time *mono_time, const uint8_t *secret_key, TCP_Proxy_Info *proxy_info);  void do_tcp_connections(TCP_Connections *tcp_c, void *userdata);  void kill_tcp_connections(TCP_Connections *tcp_c); diff --git a/protocols/Tox/libtox/src/toxcore/TCP_server.c b/protocols/Tox/libtox/src/toxcore/TCP_server.c index cc59d08824..23b9594015 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_server.c +++ b/protocols/Tox/libtox/src/toxcore/TCP_server.c @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2014 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -124,43 +124,74 @@ size_t tcp_server_listen_count(const TCP_Server *tcp_server)  #endif  #endif -/* Set the size of the connection list to numfriends. +/* Increase the size of the connection list   * - *  return -1 if realloc fails. - *  return 0 if it succeeds. + *  return -1 on failure + *  return 0 on success.   */ -static int realloc_connection(TCP_Server *tcp_server, uint32_t num) +static int alloc_new_connections(TCP_Server *tcp_server, uint32_t num)  { -    if (num == 0) { -        free(tcp_server->accepted_connection_array); -        tcp_server->accepted_connection_array = nullptr; -        tcp_server->size_accepted_connections = 0; -        return 0; -    } +    const uint32_t new_size = tcp_server->size_accepted_connections + num; -    if (num == tcp_server->size_accepted_connections) { -        return 0; +    if (new_size < tcp_server->size_accepted_connections) { +        return -1;      }      TCP_Secure_Connection *new_connections = (TCP_Secure_Connection *)realloc(                  tcp_server->accepted_connection_array, -                num * sizeof(TCP_Secure_Connection)); +                new_size * sizeof(TCP_Secure_Connection));      if (new_connections == nullptr) {          return -1;      } -    if (num > tcp_server->size_accepted_connections) { -        uint32_t old_size = tcp_server->size_accepted_connections; -        uint32_t size_new_entries = (num - old_size) * sizeof(TCP_Secure_Connection); -        memset(new_connections + old_size, 0, size_new_entries); -    } +    const uint32_t old_size = tcp_server->size_accepted_connections; +    const uint32_t size_new_entries = num * sizeof(TCP_Secure_Connection); +    memset(new_connections + old_size, 0, size_new_entries);      tcp_server->accepted_connection_array = new_connections; -    tcp_server->size_accepted_connections = num; +    tcp_server->size_accepted_connections = new_size;      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); +        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)); +    crypto_memzero(con_old, sizeof(TCP_Secure_Connection)); +} + +static void free_accepted_connection_array(TCP_Server *tcp_server) +{ +    if (tcp_server->accepted_connection_array == nullptr) { +        return; +    } + +    for (uint32_t i = 0; i < tcp_server->size_accepted_connections; ++i) { +        wipe_secure_connection(&tcp_server->accepted_connection_array[i]); +    } + +    free(tcp_server->accepted_connection_array); +    tcp_server->accepted_connection_array = nullptr; +    tcp_server->size_accepted_connections = 0; +} +  /* return index corresponding to connection with peer on success   * return -1 on failure.   */ @@ -177,7 +208,7 @@ static int kill_accepted(TCP_Server *tcp_server, int index);   * return index on success   * return -1 on failure   */ -static int add_accepted(TCP_Server *tcp_server, const TCP_Secure_Connection *con) +static int add_accepted(TCP_Server *tcp_server, const Mono_Time *mono_time, TCP_Secure_Connection *con)  {      int index = get_TCP_connection_index(tcp_server, con->public_key); @@ -187,7 +218,7 @@ static int add_accepted(TCP_Server *tcp_server, const TCP_Secure_Connection *con      }      if (tcp_server->size_accepted_connections == tcp_server->num_accepted_connections) { -        if (realloc_connection(tcp_server, tcp_server->size_accepted_connections + 4) == -1) { +        if (alloc_new_connections(tcp_server, 4) == -1) {              return -1;          } @@ -212,11 +243,12 @@ static int add_accepted(TCP_Server *tcp_server, const TCP_Secure_Connection *con          return -1;      } -    memcpy(&tcp_server->accepted_connection_array[index], con, sizeof(TCP_Secure_Connection)); +    move_secure_connection(&tcp_server->accepted_connection_array[index], con); +      tcp_server->accepted_connection_array[index].status = TCP_STATUS_CONFIRMED;      ++tcp_server->num_accepted_connections;      tcp_server->accepted_connection_array[index].identifier = ++tcp_server->counter; -    tcp_server->accepted_connection_array[index].last_pinged = unix_time(); +    tcp_server->accepted_connection_array[index].last_pinged = mono_time_get(mono_time);      tcp_server->accepted_connection_array[index].ping_id = 0;      return index; @@ -241,11 +273,11 @@ static int del_accepted(TCP_Server *tcp_server, int index)          return -1;      } -    crypto_memzero(&tcp_server->accepted_connection_array[index], sizeof(TCP_Secure_Connection)); +    wipe_secure_connection(&tcp_server->accepted_connection_array[index]);      --tcp_server->num_accepted_connections;      if (tcp_server->num_accepted_connections == 0) { -        realloc_connection(tcp_server, 0); +        free_accepted_connection_array(tcp_server);      }      return 0; @@ -513,7 +545,7 @@ static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const  static void kill_TCP_secure_connection(TCP_Secure_Connection *con)  {      kill_sock(con->sock); -    crypto_memzero(con, sizeof(TCP_Secure_Connection)); +    wipe_secure_connection(con);  }  static int rm_connection_index(TCP_Server *tcp_server, TCP_Secure_Connection *con, uint8_t con_number); @@ -954,17 +986,18 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint  } -static int confirm_TCP_connection(TCP_Server *tcp_server, TCP_Secure_Connection *con, const uint8_t *data, +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)  { -    int index = add_accepted(tcp_server, con); +    int index = add_accepted(tcp_server, mono_time, con);      if (index == -1) {          kill_TCP_secure_connection(con);          return -1;      } -    crypto_memzero(con, sizeof(TCP_Secure_Connection)); +    wipe_secure_connection(con);      if (handle_TCP_packet(tcp_server, index, data, length) == -1) {          kill_accepted(tcp_server, index); @@ -1151,8 +1184,7 @@ static int do_incoming(TCP_Server *tcp_server, uint32_t i)              kill_TCP_secure_connection(conn_new);          } -        memcpy(conn_new, conn_old, sizeof(TCP_Secure_Connection)); -        crypto_memzero(conn_old, sizeof(TCP_Secure_Connection)); +        move_secure_connection(conn_new, conn_old);          ++tcp_server->unconfirmed_connection_queue_index;          return index_new; @@ -1161,7 +1193,7 @@ static int do_incoming(TCP_Server *tcp_server, uint32_t i)      return -1;  } -static int do_unconfirmed(TCP_Server *tcp_server, uint32_t i) +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]; @@ -1182,7 +1214,7 @@ static int do_unconfirmed(TCP_Server *tcp_server, uint32_t i)          return -1;      } -    return confirm_TCP_connection(tcp_server, conn, packet, len); +    return confirm_TCP_connection(tcp_server, mono_time, conn, packet, len);  }  static bool tcp_process_secure_packet(TCP_Server *tcp_server, uint32_t i) @@ -1221,32 +1253,28 @@ static void do_confirmed_recv(TCP_Server *tcp_server, uint32_t i)  #ifndef TCP_SERVER_USE_EPOLL  static void do_TCP_incoming(TCP_Server *tcp_server)  { -    uint32_t i; - -    for (i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) { +    for (uint32_t i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) {          do_incoming(tcp_server, i);      }  } -static void do_TCP_unconfirmed(TCP_Server *tcp_server) +static void do_TCP_unconfirmed(TCP_Server *tcp_server, const Mono_Time *mono_time)  { -    uint32_t i; - -    for (i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) { -        do_unconfirmed(tcp_server, i); +    for (uint32_t i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) { +        do_unconfirmed(tcp_server, mono_time, i);      }  }  #endif -static void do_TCP_confirmed(TCP_Server *tcp_server) +static void do_TCP_confirmed(TCP_Server *tcp_server, const Mono_Time *mono_time)  {  #ifdef TCP_SERVER_USE_EPOLL -    if (tcp_server->last_run_pinged == unix_time()) { +    if (tcp_server->last_run_pinged == mono_time_get(mono_time)) {          return;      } -    tcp_server->last_run_pinged = unix_time(); +    tcp_server->last_run_pinged = mono_time_get(mono_time);  #endif      uint32_t i; @@ -1257,7 +1285,7 @@ static void do_TCP_confirmed(TCP_Server *tcp_server)              continue;          } -        if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) { +        if (mono_time_is_timeout(mono_time, conn->last_pinged, TCP_PING_FREQUENCY)) {              uint8_t ping[1 + sizeof(uint64_t)];              ping[0] = TCP_PACKET_PING;              uint64_t ping_id = random_u64(); @@ -1270,17 +1298,17 @@ static void do_TCP_confirmed(TCP_Server *tcp_server)              int ret = write_packet_TCP_secure_connection(conn, ping, sizeof(ping), 1);              if (ret == 1) { -                conn->last_pinged = unix_time(); +                conn->last_pinged = mono_time_get(mono_time);                  conn->ping_id = ping_id;              } else { -                if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY + TCP_PING_TIMEOUT)) { +                if (mono_time_is_timeout(mono_time, conn->last_pinged, TCP_PING_FREQUENCY + TCP_PING_TIMEOUT)) {                      kill_accepted(tcp_server, i);                      continue;                  }              }          } -        if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) { +        if (conn->ping_id && mono_time_is_timeout(mono_time, conn->last_pinged, TCP_PING_TIMEOUT)) {              kill_accepted(tcp_server, i);              continue;          } @@ -1296,7 +1324,7 @@ static void do_TCP_confirmed(TCP_Server *tcp_server)  }  #ifdef TCP_SERVER_USE_EPOLL -static bool tcp_epoll_process(TCP_Server *tcp_server) +static bool tcp_epoll_process(TCP_Server *tcp_server, const Mono_Time *mono_time)  {  #define MAX_EVENTS 16      struct epoll_event events[MAX_EVENTS]; @@ -1387,7 +1415,7 @@ static bool tcp_epoll_process(TCP_Server *tcp_server)              }              case TCP_SOCKET_UNCONFIRMED: { -                const int index_new = do_unconfirmed(tcp_server, index); +                const int index_new = do_unconfirmed(tcp_server, mono_time, index);                  if (index_new != -1) {                      events[n].events = EPOLLIN | EPOLLET | EPOLLRDHUP; @@ -1413,36 +1441,32 @@ static bool tcp_epoll_process(TCP_Server *tcp_server)      return nfds > 0;  } -static void do_TCP_epoll(TCP_Server *tcp_server) +static void do_TCP_epoll(TCP_Server *tcp_server, const Mono_Time *mono_time)  { -    while (tcp_epoll_process(tcp_server)) { +    while (tcp_epoll_process(tcp_server, mono_time)) {          // Keep processing packets until there are no more FDs ready for reading.          continue;      }  }  #endif -void do_TCP_server(TCP_Server *tcp_server) +void do_TCP_server(TCP_Server *tcp_server, Mono_Time *mono_time)  { -    unix_time_update(); -  #ifdef TCP_SERVER_USE_EPOLL -    do_TCP_epoll(tcp_server); +    do_TCP_epoll(tcp_server, mono_time);  #else      do_TCP_accept_new(tcp_server);      do_TCP_incoming(tcp_server); -    do_TCP_unconfirmed(tcp_server); +    do_TCP_unconfirmed(tcp_server, mono_time);  #endif -    do_TCP_confirmed(tcp_server); +    do_TCP_confirmed(tcp_server, mono_time);  }  void kill_TCP_server(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) {          kill_sock(tcp_server->socks_listening[i]);      } @@ -1456,7 +1480,13 @@ void kill_TCP_server(TCP_Server *tcp_server)      close(tcp_server->efd);  #endif +    for (uint32_t i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) { +        wipe_secure_connection(&tcp_server->incoming_connection_queue[i]); +        wipe_secure_connection(&tcp_server->unconfirmed_connection_queue[i]); +    } + +    free_accepted_connection_array(tcp_server); +      free(tcp_server->socks_listening); -    free(tcp_server->accepted_connection_array);      free(tcp_server);  } diff --git a/protocols/Tox/libtox/src/toxcore/TCP_server.h b/protocols/Tox/libtox/src/toxcore/TCP_server.h index 632a5e79b9..252df9faf2 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_server.h +++ b/protocols/Tox/libtox/src/toxcore/TCP_server.h @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2014 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -21,8 +21,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef TCP_SERVER_H -#define TCP_SERVER_H +#ifndef C_TOXCORE_TOXCORE_TCP_SERVER_H +#define C_TOXCORE_TOXCORE_TCP_SERVER_H  #include "crypto_core.h"  #include "list.h" @@ -75,6 +75,8 @@ struct TCP_Priority_List {      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); @@ -87,7 +89,7 @@ TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, const uin  /* Run the TCP_server   */ -void do_TCP_server(TCP_Server *tcp_server); +void do_TCP_server(TCP_Server *tcp_server, Mono_Time *mono_time);  /* Kill the TCP server   */ diff --git a/protocols/Tox/libtox/src/toxcore/ccompat.h b/protocols/Tox/libtox/src/toxcore/ccompat.h index 5b37a29457..ba8c7fe8da 100644 --- a/protocols/Tox/libtox/src/toxcore/ccompat.h +++ b/protocols/Tox/libtox/src/toxcore/ccompat.h @@ -1,8 +1,8 @@  /*   * C language compatibility macros for varying compiler support.   */ -#ifndef CCOMPAT_H -#define CCOMPAT_H +#ifndef C_TOXCORE_TOXCORE_CCOMPAT_H +#define C_TOXCORE_TOXCORE_CCOMPAT_H  // Variable length arrays.  // VLA(type, name, size) allocates a variable length array with automatic @@ -48,4 +48,4 @@  #define GNU_PRINTF(f, a)  #endif -#endif /* CCOMPAT_H */ +#endif // C_TOXCORE_TOXCORE_CCOMPAT_H diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core.api.h b/protocols/Tox/libtox/src/toxcore/crypto_core.api.h index 4b40860d44..b6b49624e3 100644 --- a/protocols/Tox/libtox/src/toxcore/crypto_core.api.h +++ b/protocols/Tox/libtox/src/toxcore/crypto_core.api.h @@ -4,7 +4,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -22,8 +22,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef CRYPTO_CORE_H -#define CRYPTO_CORE_H +#ifndef C_TOXCORE_TOXCORE_CRYPTO_CORE_H +#define C_TOXCORE_TOXCORE_CRYPTO_CORE_H  #include <stdbool.h>  #include <stddef.h> @@ -207,7 +207,7 @@ static int32_t decrypt_data(  /**   * 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 preformed on every encrypt/decrypt. + * to be performed on every encrypt/decrypt.   */  static int32_t encrypt_precompute(      const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key, @@ -264,5 +264,5 @@ static void new_symmetric_key(uint8_t[CRYPTO_SYMMETRIC_KEY_SIZE] key);  }  // extern "C"  #endif -#endif /* CRYPTO_CORE_H */ +#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 b9ec23a80d..1fd6286681 100644 --- a/protocols/Tox/libtox/src/toxcore/crypto_core.c +++ b/protocols/Tox/libtox/src/toxcore/crypto_core.c @@ -5,7 +5,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -129,13 +129,14 @@ bool public_key_valid(const uint8_t *public_key)   * 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) +int32_t encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key, +                           uint8_t *shared_key)  {      return crypto_box_beforenm(shared_key, public_key, secret_key);  } -int32_t encrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *plain, size_t length, -                               uint8_t *encrypted) +int32_t encrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, +                               const uint8_t *plain, size_t length, uint8_t *encrypted)  {      if (length == 0 || !secret_key || !nonce || !plain || !encrypted) {          return -1; @@ -145,19 +146,21 @@ int32_t encrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce,      VLA(uint8_t, temp_encrypted, length + crypto_box_MACBYTES + crypto_box_BOXZEROBYTES);      memset(temp_plain, 0, crypto_box_ZEROBYTES); -    memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); // Pad the message with 32 0 bytes. +    // Pad the message with 32 0 bytes. +    memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); -    if (crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, secret_key) != 0) { +    if (crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, +                           secret_key) != 0) {          return -1;      } -    /* Unpad the encrypted message. */ +    // Unpad the encrypted message.      memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES);      return length + crypto_box_MACBYTES;  } -int32_t decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *encrypted, size_t length, -                               uint8_t *plain) +int32_t decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, +                               const uint8_t *encrypted, size_t length, uint8_t *plain)  {      if (length <= crypto_box_BOXZEROBYTES || !secret_key || !nonce || !encrypted || !plain) {          return -1; @@ -167,9 +170,11 @@ int32_t decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce,      VLA(uint8_t, temp_encrypted, length + crypto_box_BOXZEROBYTES);      memset(temp_encrypted, 0, crypto_box_BOXZEROBYTES); -    memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); // Pad the message with 16 0 bytes. +    // Pad the message with 16 0 bytes. +    memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); -    if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce, secret_key) != 0) { +    if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce, +                                secret_key) != 0) {          return -1;      } @@ -205,12 +210,13 @@ 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 sodium_increment (change to little endian) -     * NOTE don't use breaks inside this loop +    /* TODO(irungentoo): use increment_nonce_number(nonce, 1) or +     * sodium_increment (change to little endian). +     * +     * 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). @@ -219,8 +225,8 @@ void increment_nonce(uint8_t *nonce)      uint_fast16_t carry = 1U;      for (; i != 0; --i) { -        carry += (uint_fast16_t) nonce[i - 1]; -        nonce[i - 1] = (uint8_t) carry; +        carry += (uint_fast16_t)nonce[i - 1]; +        nonce[i - 1] = (uint8_t)carry;          carry >>= 8;      }  } @@ -228,11 +234,10 @@ void increment_nonce(uint8_t *nonce)  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 +    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 @@ -247,7 +252,7 @@ void increment_nonce_number(uint8_t *nonce, uint32_t host_order_num)       * 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; +    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]; @@ -258,7 +263,7 @@ void increment_nonce_number(uint8_t *nonce, uint32_t host_order_num)      uint_fast16_t carry = 0U;      for (; i != 0; --i) { -        carry += (uint_fast16_t) nonce[i - 1] + (uint_fast16_t) num_as_nonce[i - 1]; +        carry += (uint_fast16_t)nonce[i - 1] + (uint_fast16_t)num_as_nonce[i - 1];          nonce[i - 1] = (uint8_t)carry;          carry >>= 8;      } diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core.h b/protocols/Tox/libtox/src/toxcore/crypto_core.h index 18c1339e65..c2f0296e15 100644 --- a/protocols/Tox/libtox/src/toxcore/crypto_core.h +++ b/protocols/Tox/libtox/src/toxcore/crypto_core.h @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -21,8 +21,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef CRYPTO_CORE_H -#define CRYPTO_CORE_H +#ifndef C_TOXCORE_TOXCORE_CRYPTO_CORE_H +#define C_TOXCORE_TOXCORE_CRYPTO_CORE_H  #include <stdbool.h>  #include <stddef.h> @@ -202,7 +202,7 @@ int32_t decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const  /**   * 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 preformed on every encrypt/decrypt. + * 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); @@ -249,4 +249,4 @@ void new_symmetric_key(uint8_t *key);  }  // extern "C"  #endif -#endif /* CRYPTO_CORE_H */ +#endif // C_TOXCORE_TOXCORE_CRYPTO_CORE_H diff --git a/protocols/Tox/libtox/src/toxcore/friend_connection.c b/protocols/Tox/libtox/src/toxcore/friend_connection.c index 4d24587147..9c805b45ed 100644 --- a/protocols/Tox/libtox/src/toxcore/friend_connection.c +++ b/protocols/Tox/libtox/src/toxcore/friend_connection.c @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2014 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -74,6 +74,7 @@ typedef struct Friend_Conn {  struct Friend_Connections { +    const Mono_Time *mono_time;      Net_Crypto *net_crypto;      DHT *dht;      Onion_Client *onion_c; @@ -298,7 +299,7 @@ static unsigned int send_relays(Friend_Connections *fr_c, int friendcon_id)      ++length;      if (write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, data, length, 0) != -1) { -        friend_con->share_relays_lastsent = unix_time(); +        friend_con->share_relays_lastsent = mono_time_get(fr_c->mono_time);          return 1;      } @@ -339,7 +340,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_lastrecv = unix_time(); +    friend_con->dht_ip_port_lastrecv = mono_time_get(fr_c->mono_time);      if (friend_con->hosting_tcp_relay) {          friend_add_tcp_relay(fr_c, number, ip_port, friend_con->dht_temp_pk); @@ -355,7 +356,7 @@ static void change_dht_pk(Friend_Connections *fr_c, int friendcon_id, const uint          return;      } -    friend_con->dht_pk_lastrecv = unix_time(); +    friend_con->dht_pk_lastrecv = mono_time_get(fr_c->mono_time);      if (friend_con->dht_lock) {          if (dht_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock) != 0) { @@ -384,13 +385,13 @@ static int handle_status(void *object, int number, uint8_t status, void *userdat      if (status) {  /* Went online. */          status_changed = 1;          friend_con->status = FRIENDCONN_STATUS_CONNECTED; -        friend_con->ping_lastrecv = unix_time(); +        friend_con->ping_lastrecv = mono_time_get(fr_c->mono_time);          friend_con->share_relays_lastsent = 0;          onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status);      } else {  /* Went offline. */          if (friend_con->status != FRIENDCONN_STATUS_CONNECTING) {              status_changed = 1; -            friend_con->dht_pk_lastrecv = unix_time(); +            friend_con->dht_pk_lastrecv = mono_time_get(fr_c->mono_time);              onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status);          } @@ -463,7 +464,7 @@ static int handle_packet(void *object, int number, const uint8_t *data, uint16_t      }      if (data[0] == PACKET_ID_ALIVE) { -        friend_con->ping_lastrecv = unix_time(); +        friend_con->ping_lastrecv = mono_time_get(fr_c->mono_time);          return 0;      } @@ -558,7 +559,7 @@ static int handle_new_connections(void *object, New_Connection *n_c)          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 = unix_time(); +        friend_con->dht_ip_port_lastrecv = mono_time_get(fr_c->mono_time);      }      if (public_key_cmp(friend_con->dht_temp_pk, n_c->dht_public_key) != 0) { @@ -613,7 +614,7 @@ static int send_ping(const Friend_Connections *fr_c, int friendcon_id)      const int64_t ret = write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, &ping, sizeof(ping), 0);      if (ret != -1) { -        friend_con->ping_lastsent = unix_time(); +        friend_con->ping_lastsent = mono_time_get(fr_c->mono_time);          return 0;      } @@ -850,7 +851,8 @@ int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint3  }  /* Create new friend_connections instance. */ -Friend_Connections *new_friend_connections(Onion_Client *onion_c, bool local_discovery_enabled) +Friend_Connections *new_friend_connections(const Mono_Time *mono_time, Onion_Client *onion_c, +        bool local_discovery_enabled)  {      if (onion_c == nullptr) {          return nullptr; @@ -862,6 +864,7 @@ Friend_Connections *new_friend_connections(Onion_Client *onion_c, bool local_dis          return nullptr;      } +    temp->mono_time = mono_time;      temp->dht = onion_get_dht(onion_c);      temp->net_crypto = onion_get_net_crypto(onion_c);      temp->onion_c = onion_c; @@ -881,7 +884,7 @@ Friend_Connections *new_friend_connections(Onion_Client *onion_c, bool local_dis  /* 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 < unix_time()) { +    if (fr_c->last_lan_discovery + LAN_DISCOVERY_INTERVAL < mono_time_get(fr_c->mono_time)) {          const uint16_t first = fr_c->next_lan_port;          uint16_t last = first + PORTS_PER_DISCOVERY;          last = last > TOX_PORTRANGE_TO ? TOX_PORTRANGE_TO : last; @@ -896,14 +899,14 @@ static void lan_discovery(Friend_Connections *fr_c)          // Don't include default port in port range          fr_c->next_lan_port = last != TOX_PORTRANGE_TO ? last : TOX_PORTRANGE_FROM + 1; -        fr_c->last_lan_discovery = unix_time(); +        fr_c->last_lan_discovery = mono_time_get(fr_c->mono_time);      }  }  /* main friend_connections loop. */  void do_friend_connections(Friend_Connections *fr_c, void *userdata)  { -    const uint64_t temp_time = unix_time(); +    const uint64_t temp_time = mono_time_get(fr_c->mono_time);      for (uint32_t i = 0; i < fr_c->num_cons; ++i) {          Friend_Conn *const friend_con = get_conn(fr_c, i); diff --git a/protocols/Tox/libtox/src/toxcore/friend_connection.h b/protocols/Tox/libtox/src/toxcore/friend_connection.h index 024befeec8..149a4fa7ec 100644 --- a/protocols/Tox/libtox/src/toxcore/friend_connection.h +++ b/protocols/Tox/libtox/src/toxcore/friend_connection.h @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2014 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -21,8 +21,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef FRIEND_CONNECTION_H -#define FRIEND_CONNECTION_H +#ifndef C_TOXCORE_TOXCORE_FRIEND_CONNECTION_H +#define C_TOXCORE_TOXCORE_FRIEND_CONNECTION_H  #include "DHT.h"  #include "LAN_discovery.h" @@ -158,7 +158,8 @@ typedef int fr_request_cb(void *object, const uint8_t *source_pubkey, const uint  void set_friend_request_callback(Friend_Connections *fr_c, fr_request_cb *fr_request_callback, void *object);  /* Create new friend_connections instance. */ -Friend_Connections *new_friend_connections(Onion_Client *onion_c, bool local_discovery_enabled); +Friend_Connections *new_friend_connections(const Mono_Time *mono_time, Onion_Client *onion_c, +        bool local_discovery_enabled);  /* main friend_connections loop. */  void do_friend_connections(Friend_Connections *fr_c, void *userdata); diff --git a/protocols/Tox/libtox/src/toxcore/friend_requests.c b/protocols/Tox/libtox/src/toxcore/friend_requests.c index c4f2512722..fa1defc843 100644 --- a/protocols/Tox/libtox/src/toxcore/friend_requests.c +++ b/protocols/Tox/libtox/src/toxcore/friend_requests.c @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. diff --git a/protocols/Tox/libtox/src/toxcore/friend_requests.h b/protocols/Tox/libtox/src/toxcore/friend_requests.h index 77c3af6890..7fcd3f0d35 100644 --- a/protocols/Tox/libtox/src/toxcore/friend_requests.h +++ b/protocols/Tox/libtox/src/toxcore/friend_requests.h @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2014 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -21,8 +21,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef FRIEND_REQUESTS_H -#define FRIEND_REQUESTS_H +#ifndef C_TOXCORE_TOXCORE_FRIEND_REQUESTS_H +#define C_TOXCORE_TOXCORE_FRIEND_REQUESTS_H  #include "friend_connection.h" diff --git a/protocols/Tox/libtox/src/toxcore/group.c b/protocols/Tox/libtox/src/toxcore/group.c index 20075c8b92..5feb483b74 100644 --- a/protocols/Tox/libtox/src/toxcore/group.c +++ b/protocols/Tox/libtox/src/toxcore/group.c @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2014 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -60,10 +60,10 @@ typedef enum Invite_Id {  #define ONLINE_PACKET_DATA_SIZE (sizeof(uint16_t) + 1 + GROUP_ID_LENGTH)  typedef enum Peer_Id { -    PEER_KILL_ID      = 1, -    PEER_QUERY_ID     = 8, -    PEER_RESPONSE_ID  = 9, -    PEER_TITLE_ID     = 10, +    PEER_INTRODUCED_ID  = 1, +    PEER_QUERY_ID       = 8, +    PEER_RESPONSE_ID    = 9, +    PEER_TITLE_ID       = 10,  } Peer_Id;  #define MIN_MESSAGE_PACKET_LEN (sizeof(uint16_t) * 2 + sizeof(uint32_t) + 1) @@ -232,7 +232,7 @@ int32_t conference_by_id(const Group_Chats *g_c, const uint8_t *id)  /*   * check if peer with peer_number is in peer array.   * - * return peer number if peer is in chat. + * return peer index if peer is in chat.   * return -1 if peer is not in chat.   *   * TODO(irungentoo): make this more efficient. @@ -267,10 +267,6 @@ typedef enum Groupchat_Closest {      GROUPCHAT_CLOSEST_REMOVED  } Groupchat_Closest; -static int friend_in_close(Group_c *g, int friendcon_id); -static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, uint32_t groupnumber, uint8_t closest, -                                 uint8_t lock); -  static int add_to_closest(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_pk, const uint8_t *temp_pk)  {      Group_c *g = get_group_c(g_c, groupnumber); @@ -371,6 +367,11 @@ static unsigned int pk_in_closest_peers(Group_c *g, uint8_t *real_pk)      return 0;  } +static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, uint32_t groupnumber, uint8_t reason, +                                 uint8_t lock); + +static void remove_conn_reason(Group_Chats *g_c, uint32_t groupnumber, uint16_t i, uint8_t reason); +  static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t type,                                uint8_t *id); @@ -397,7 +398,7 @@ static int connect_to_closest(Group_Chats *g_c, uint32_t groupnumber, void *user              continue;          } -        if (!g->close[i].closest) { +        if (!(g->close[i].reasons & GROUPCHAT_CLOSE_REASON_CLOSEST)) {              continue;          } @@ -406,12 +407,7 @@ static int connect_to_closest(Group_Chats *g_c, uint32_t groupnumber, void *user          get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[i].number);          if (!pk_in_closest_peers(g, real_pk)) { -            g->close[i].closest = false; - -            if (!g->close[i].introducer && !g->close[i].introduced) { -                g->close[i].type = GROUPCHAT_CLOSE_NONE; -                kill_friend_connection(g_c->fr_c, g->close[i].number); -            } +            remove_conn_reason(g_c, groupnumber, i, GROUPCHAT_CLOSE_REASON_CLOSEST);          }      } @@ -435,7 +431,7 @@ static int connect_to_closest(Group_Chats *g_c, uint32_t groupnumber, void *user              set_dht_temp_pk(g_c->fr_c, friendcon_id, g->closest_peers[i].temp_pk, userdata);          } -        add_conn_to_groupchat(g_c, friendcon_id, groupnumber, 1, lock); +        add_conn_to_groupchat(g_c, friendcon_id, groupnumber, GROUPCHAT_CLOSE_REASON_CLOSEST, lock);          if (friend_con_connected(g_c->fr_c, friendcon_id) == FRIENDCONN_STATUS_CONNECTED) {              send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->type, g->id); @@ -447,7 +443,96 @@ static int connect_to_closest(Group_Chats *g_c, uint32_t groupnumber, void *user      return 0;  } -/* Add a peer to the group chat. +static int get_frozen_index(Group_c *g, uint16_t peer_number) +{ +    for (uint32_t i = 0; i < g->numfrozen; ++i) { +        if (g->frozen[i].peer_number == peer_number) { +            return i; +        } +    } + +    return -1; +} + +/* 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. + */ +static int note_peer_active(Group_Chats *g_c, uint32_t groupnumber, uint16_t peer_number, void *userdata) +{ +    Group_c *g = get_group_c(g_c, groupnumber); + +    if (!g) { +        return -1; +    } + +    const int peer_index = get_peer_index(g, peer_number); + +    if (peer_index != -1) { +        g->group[peer_index].last_active = mono_time_get(g_c->mono_time); +        return peer_index; +    } + +    const int frozen_index = get_frozen_index(g, peer_number); + +    if (frozen_index == -1) { +        return -1; +    } + +    /* Now thaw the peer */ + +    Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * (g->numpeers + 1)); + +    if (temp == nullptr) { +        return -1; +    } + +    g->group = temp; +    g->group[g->numpeers] = g->frozen[frozen_index]; +    g->group[g->numpeers].temp_pk_updated = false; +    g->group[g->numpeers].last_active = mono_time_get(g_c->mono_time); + +    add_to_closest(g_c, groupnumber, g->group[g->numpeers].real_pk, g->group[g->numpeers].temp_pk); + +    ++g->numpeers; + +    --g->numfrozen; + +    if (g->numfrozen == 0) { +        free(g->frozen); +        g->frozen = nullptr; +    } else { +        if (g->numfrozen != (uint32_t)frozen_index) { +            g->frozen[frozen_index] = g->frozen[g->numfrozen]; +        } + +        Group_Peer *frozen_temp = (Group_Peer *)realloc(g->frozen, sizeof(Group_Peer) * (g->numfrozen)); + +        if (frozen_temp == nullptr) { +            return -1; +        } + +        g->frozen = frozen_temp; +    } + +    if (g_c->peer_list_changed_callback) { +        g_c->peer_list_changed_callback(g_c->m, groupnumber, userdata); +    } + +    if (g->peer_on_join) { +        g->peer_on_join(g->object, groupnumber, g->numpeers - 1); +    } + +    g->need_send_name = true; + +    return g->numpeers - 1; +} + +/* 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.   *   * 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 @@ -457,7 +542,7 @@ static int connect_to_closest(Group_Chats *g_c, uint32_t groupnumber, void *user   * return -1 if error.   */  static int addpeer(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_pk, const uint8_t *temp_pk, -                   uint16_t peer_number, void *userdata, bool do_gc_callback) +                   uint16_t peer_number, void *userdata, bool fresh, bool do_gc_callback)  {      Group_c *g = get_group_c(g_c, groupnumber); @@ -465,23 +550,35 @@ static int addpeer(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_p          return -1;      } -    // TODO(irungentoo): -    int peer_index = peer_in_chat(g, real_pk); +    const int peer_index = fresh ? +                           note_peer_active(g_c, groupnumber, peer_number, userdata) : +                           get_peer_index(g, peer_number);      if (peer_index != -1) { -        id_copy(g->group[peer_index].temp_pk, temp_pk); - -        if (g->group[peer_index].peer_number != peer_number) { +        if (!id_equal(g->group[peer_index].real_pk, real_pk)) {              return -1;          } +        if (fresh || !g->group[peer_index].temp_pk_updated) { +            id_copy(g->group[peer_index].temp_pk, temp_pk); +            g->group[peer_index].temp_pk_updated = true; +        } +          return peer_index;      } -    peer_index = get_peer_index(g, peer_number); +    if (!fresh) { +        const int frozen_index = get_frozen_index(g, peer_number); -    if (peer_index != -1) { -        return -1; +        if (frozen_index != -1) { +            if (!id_equal(g->frozen[frozen_index].real_pk, real_pk)) { +                return -1; +            } + +            id_copy(g->frozen[frozen_index].temp_pk, temp_pk); + +            return -1; +        }      }      Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * (g->numpeers + 1)); @@ -495,9 +592,10 @@ static int addpeer(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_p      id_copy(g->group[g->numpeers].real_pk, real_pk);      id_copy(g->group[g->numpeers].temp_pk, temp_pk); +    g->group[g->numpeers].temp_pk_updated = true;      g->group[g->numpeers].peer_number = peer_number; -    g->group[g->numpeers].last_recv = unix_time(); +    g->group[g->numpeers].last_active = mono_time_get(g_c->mono_time);      ++g->numpeers;      add_to_closest(g_c, groupnumber, real_pk, temp_pk); @@ -539,13 +637,24 @@ static int remove_close_conn(Group_Chats *g_c, uint32_t groupnumber, int friendc  } +static void remove_from_closest(Group_c *g, int peer_index) +{ +    for (uint32_t i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) { +        if (g->closest_peers[i].entry && id_equal(g->closest_peers[i].real_pk, g->group[peer_index].real_pk)) { +            g->closest_peers[i].entry = 0; +            g->changed = GROUPCHAT_CLOSEST_REMOVED; +            break; +        } +    } +} +  /*   * Delete a peer from the group chat.   *   * return 0 if success   * return -1 if error.   */ -static int delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void *userdata) +static int delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void *userdata, bool keep_connection)  {      Group_c *g = get_group_c(g_c, groupnumber); @@ -553,19 +662,11 @@ static int delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void          return -1;      } -    uint32_t i; +    remove_from_closest(g, peer_index); -    for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) { /* If peer is in closest_peers list, remove it. */ -        if (g->closest_peers[i].entry && id_equal(g->closest_peers[i].real_pk, g->group[peer_index].real_pk)) { -            g->closest_peers[i].entry = 0; -            g->changed = GROUPCHAT_CLOSEST_REMOVED; -            break; -        } -    } - -    int friendcon_id = getfriend_conn_id_pk(g_c->fr_c, g->group[peer_index].real_pk); +    const int friendcon_id = getfriend_conn_id_pk(g_c->fr_c, g->group[peer_index].real_pk); -    if (friendcon_id != -1) { +    if (friendcon_id != -1 && !keep_connection) {          remove_close_conn(g_c, groupnumber, friendcon_id);      } @@ -578,7 +679,7 @@ static int delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void          g->group = nullptr;      } else {          if (g->numpeers != (uint32_t)peer_index) { -            memcpy(&g->group[peer_index], &g->group[g->numpeers], sizeof(Group_Peer)); +            g->group[peer_index] = g->group[g->numpeers];          }          Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * (g->numpeers)); @@ -601,6 +702,32 @@ static int delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void      return 0;  } +static bool try_send_rejoin(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_pk); + +static int freeze_peer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void *userdata) +{ +    Group_c *g = get_group_c(g_c, groupnumber); + +    if (!g) { +        return -1; +    } + +    try_send_rejoin(g_c, groupnumber, g->group[peer_index].real_pk); + +    Group_Peer *temp = (Group_Peer *)realloc(g->frozen, sizeof(Group_Peer) * (g->numfrozen + 1)); + +    if (temp == nullptr) { +        return -1; +    } + +    g->frozen = temp; +    g->frozen[g->numfrozen] = g->group[peer_index]; +    ++g->numfrozen; + +    return delpeer(g_c, groupnumber, peer_index, userdata, true); +} + +  /* Set the nick for a peer.   *   * do_gc_callback indicates whether we want to trigger callbacks set by the client @@ -666,6 +793,8 @@ static int settitle(Group_Chats *g_c, uint32_t groupnumber, int peer_index, cons      memcpy(g->title, title, title_len);      g->title_len = title_len; +    g->title_fresh = true; +      if (g_c->title_callback) {          g_c->title_callback(g_c->m, groupnumber, peer_index, title, title_len, userdata);      } @@ -673,7 +802,29 @@ static int settitle(Group_Chats *g_c, uint32_t groupnumber, int peer_index, cons      return 0;  } -static void set_conns_type_close(Group_Chats *g_c, uint32_t groupnumber, int friendcon_id, uint8_t type) +/* 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); + +    if (!g) { +        return; +    } + +    for (uint32_t i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { +        if (g->close[i].type == GROUPCHAT_CLOSE_ONLINE) { +            return; +        } +    } + +    for (uint32_t i = 0; i < g->numpeers; ++i) { +        while (i < g->numpeers && !id_equal(g->group[i].real_pk, g->real_pk)) { +            freeze_peer(g_c, groupnumber, i, userdata); +        } +    } +} + +static void set_conns_type_close(Group_Chats *g_c, uint32_t groupnumber, int friendcon_id, uint8_t type, void *userdata)  {      Group_c *g = get_group_c(g_c, groupnumber); @@ -696,14 +847,36 @@ static void set_conns_type_close(Group_Chats *g_c, uint32_t groupnumber, int fri              send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->type, g->id);          } else {              g->close[i].type = type; +            check_disconnected(g_c, groupnumber, userdata);          }      }  }  /* Set the type for all close connections with friendcon_id */ -static void set_conns_status_groups(Group_Chats *g_c, int friendcon_id, uint8_t type) +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) { +        set_conns_type_close(g_c, i, friendcon_id, type, userdata); +    } +} + +static void rejoin_frozen_friend(Group_Chats *g_c, int friendcon_id)  { +    uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE]; +    get_friendcon_public_keys(real_pk, nullptr, g_c->fr_c, friendcon_id); +      for (uint16_t i = 0; i < g_c->num_chats; ++i) { -        set_conns_type_close(g_c, i, friendcon_id, type); +        Group_c *g = get_group_c(g_c, i); + +        if (!g) { +            continue; +        } + +        for (uint32_t j = 0; j < g->numfrozen; ++j) { +            if (id_equal(g->frozen[j].real_pk, real_pk)) { +                try_send_rejoin(g_c, i, real_pk); +                break; +            } +        }      }  } @@ -712,9 +885,10 @@ static int g_handle_status(void *object, int friendcon_id, uint8_t status, void      Group_Chats *g_c = (Group_Chats *)object;      if (status) { /* Went online */ -        set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_ONLINE); +        set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_ONLINE, userdata); +        rejoin_frozen_friend(g_c, friendcon_id);      } else { /* Went offline */ -        set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_CONNECTION); +        set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_CONNECTION, userdata);          // TODO(irungentoo): remove timedout connections?      } @@ -729,7 +903,7 @@ static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uin   * return close index on success   * return -1 on failure.   */ -static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, uint32_t groupnumber, uint8_t closest, +static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, uint32_t groupnumber, uint8_t reason,                                   uint8_t lock)  {      Group_c *g = get_group_c(g_c, groupnumber); @@ -738,40 +912,81 @@ static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, uint32_t gr          return -1;      } -    uint16_t i, ind = MAX_GROUP_CONNECTIONS; +    uint16_t empty = MAX_GROUP_CONNECTIONS; +    uint16_t ind = MAX_GROUP_CONNECTIONS; -    for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { +    for (uint16_t i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {          if (g->close[i].type == GROUPCHAT_CLOSE_NONE) { -            ind = i; +            empty = i;              continue;          }          if (g->close[i].number == (uint32_t)friendcon_id) { -            g->close[i].closest |= closest; -            return i; /* Already in list. */ +            ind = i; /* Already in list. */ +            break;          }      } +    if (ind == MAX_GROUP_CONNECTIONS && empty != MAX_GROUP_CONNECTIONS) { +        if (lock) { +            friend_connection_lock(g_c->fr_c, friendcon_id); +        } + +        g->close[empty].type = GROUPCHAT_CLOSE_CONNECTION; +        g->close[empty].number = friendcon_id; +        g->close[empty].reasons = 0; +        // TODO(irungentoo): +        friend_connection_callbacks(g_c->m->fr_c, friendcon_id, GROUPCHAT_CALLBACK_INDEX, &g_handle_status, &g_handle_packet, +                                    &handle_lossy, g_c, friendcon_id); +        ind = empty; +    } +      if (ind == MAX_GROUP_CONNECTIONS) {          return -1;      } -    if (lock) { -        friend_connection_lock(g_c->fr_c, friendcon_id); -    } +    if (!(g->close[ind].reasons & reason)) { +        g->close[ind].reasons |= reason; -    g->close[ind].type = GROUPCHAT_CLOSE_CONNECTION; -    g->close[ind].number = friendcon_id; -    g->close[ind].closest = closest; -    g->close[ind].introducer = false; -    g->close[ind].introduced = false; -    // TODO(irungentoo): -    friend_connection_callbacks(g_c->m->fr_c, friendcon_id, GROUPCHAT_CALLBACK_INDEX, &g_handle_status, &g_handle_packet, -                                &handle_lossy, g_c, friendcon_id); +        if (reason == GROUPCHAT_CLOSE_REASON_INTRODUCER) { +            ++g->num_introducer_connections; +        } +    }      return ind;  } +static unsigned int send_peer_introduced(Group_Chats *g_c, int friendcon_id, uint16_t group_num); + +/* Removes reason for keeping connection. + * + * Kills connection if this was the last reason. + */ +static void remove_conn_reason(Group_Chats *g_c, uint32_t groupnumber, uint16_t i, uint8_t reason) +{ +    Group_c *g = get_group_c(g_c, groupnumber); + +    if (!g) { +        return; +    } + +    if (!(g->close[i].reasons & reason)) { +        return; +    } + +    g->close[i].reasons &= ~reason; + +    if (reason == GROUPCHAT_CLOSE_REASON_INTRODUCER) { +        --g->num_introducer_connections; +        send_peer_introduced(g_c, g->close[i].number, g->close[i].group_number); +    } + +    if (g->close[i].reasons == 0) { +        kill_friend_connection(g_c->fr_c, g->close[i].number); +        g->close[i].type = GROUPCHAT_CLOSE_NONE; +    } +} +  /* Creates a new groupchat and puts it in the chats array.   *   * type is one of GROUPCHAT_TYPE_* @@ -781,7 +996,7 @@ static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, uint32_t gr   */  int add_groupchat(Group_Chats *g_c, uint8_t type)  { -    int32_t groupnumber = create_group_chat(g_c); +    const int32_t groupnumber = create_group_chat(g_c);      if (groupnumber == -1) {          return -1; @@ -790,12 +1005,12 @@ int add_groupchat(Group_Chats *g_c, uint8_t type)      Group_c *g = &g_c->chats[groupnumber];      g->status = GROUPCHAT_STATUS_CONNECTED; -    g->number_joined = -1;      g->type = type;      new_symmetric_key(g->id);      g->peer_number = 0; /* Founder is peer 0. */      memcpy(g->real_pk, nc_get_self_public_key(g_c->m->net_crypto), CRYPTO_PUBLIC_KEY_SIZE); -    int peer_index = addpeer(g_c, groupnumber, g->real_pk, dht_get_self_public_key(g_c->m->dht), 0, nullptr, false); +    const int peer_index = addpeer(g_c, groupnumber, g->real_pk, dht_get_self_public_key(g_c->m->dht), 0, nullptr, true, +                                   false);      if (peer_index == -1) {          return -1; @@ -822,9 +1037,7 @@ int del_groupchat(Group_Chats *g_c, uint32_t groupnumber)      group_kill_peer_send(g_c, groupnumber, g->peer_number); -    unsigned int i; - -    for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { +    for (uint32_t i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {          if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {              continue;          } @@ -833,11 +1046,14 @@ int del_groupchat(Group_Chats *g_c, uint32_t groupnumber)          kill_friend_connection(g_c->fr_c, g->close[i].number);      } -    if (g->peer_on_leave) { -        g->peer_on_leave(g->object, groupnumber, g->group[i].object); +    for (uint32_t i = 0; i < g->numpeers; ++i) { +        if (g->peer_on_leave) { +            g->peer_on_leave(g->object, groupnumber, g->group[i].object); +        }      }      free(g->group); +    free(g->frozen);      if (g->group_on_delete) {          g->group_on_delete(g->object, groupnumber); @@ -1087,7 +1303,7 @@ int invite_friend(Group_Chats *g_c, uint32_t friendnumber, uint32_t groupnumber)      uint8_t invite[INVITE_PACKET_SIZE];      invite[0] = INVITE_ID; -    uint16_t groupchat_num = net_htons((uint16_t)groupnumber); +    const uint16_t groupchat_num = net_htons((uint16_t)groupnumber);      memcpy(invite + 1, &groupchat_num, sizeof(groupchat_num));      invite[1 + sizeof(groupchat_num)] = g->type;      memcpy(invite + 1 + sizeof(groupchat_num) + 1, g->id, GROUP_ID_LENGTH); @@ -1099,6 +1315,39 @@ 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. + * return true if a packet was sent. + * return false otherwise. + */ +static bool try_send_rejoin(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_pk) +{ +    Group_c *g = get_group_c(g_c, groupnumber); + +    if (!g) { +        return false; +    } + +    const int friendcon_id = getfriend_conn_id_pk(g_c->fr_c, real_pk); + +    if (friendcon_id == -1) { +        return false; +    } + +    uint8_t packet[1 + 1 + GROUP_ID_LENGTH]; +    packet[0] = PACKET_ID_REJOIN_CONFERENCE; +    packet[1] = g->type; +    memcpy(packet + 2, g->id, GROUP_ID_LENGTH); + +    if (write_cryptpacket(friendconn_net_crypto(g_c->fr_c), friend_connection_crypt_connection_id(g_c->fr_c, friendcon_id), +                          packet, sizeof(packet), 0) == -1) { +        return false; +    } + +    add_conn_to_groupchat(g_c, friendcon_id, groupnumber, GROUPCHAT_CLOSE_REASON_INTRODUCER, 1); + +    return true; +} +  static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num);  /* Join a group (you need to have been invited first.) @@ -1123,7 +1372,7 @@ int join_groupchat(Group_Chats *g_c, uint32_t friendnumber, uint8_t expected_typ          return -2;      } -    int friendcon_id = getfriendcon_id(g_c->m, friendnumber); +    const int friendcon_id = getfriendcon_id(g_c->m, friendnumber);      if (friendcon_id == -1) {          return -3; @@ -1133,7 +1382,7 @@ int join_groupchat(Group_Chats *g_c, uint32_t friendnumber, uint8_t expected_typ          return -4;      } -    int groupnumber = create_group_chat(g_c); +    const int groupnumber = create_group_chat(g_c);      if (groupnumber == -1) {          return -5; @@ -1141,9 +1390,8 @@ int join_groupchat(Group_Chats *g_c, uint32_t friendnumber, uint8_t expected_typ      Group_c *g = &g_c->chats[groupnumber]; -    uint16_t group_num = net_htons(groupnumber); +    const uint16_t group_num = net_htons(groupnumber);      g->status = GROUPCHAT_STATUS_VALID; -    g->number_joined = -1;      memcpy(g->real_pk, nc_get_self_public_key(g_c->m->net_crypto), CRYPTO_PUBLIC_KEY_SIZE);      uint8_t response[INVITE_RESPONSE_PACKET_SIZE]; @@ -1157,13 +1405,11 @@ int join_groupchat(Group_Chats *g_c, uint32_t friendnumber, uint8_t expected_typ          other_groupnum = net_ntohs(other_groupnum);          g->type = data[sizeof(uint16_t)];          memcpy(g->id, data + sizeof(uint16_t) + 1, GROUP_ID_LENGTH); -        int close_index = add_conn_to_groupchat(g_c, friendcon_id, groupnumber, 0, 1); +        const int close_index = add_conn_to_groupchat(g_c, friendcon_id, groupnumber, GROUPCHAT_CLOSE_REASON_INTRODUCER, 1);          if (close_index != -1) {              g->close[close_index].group_number = other_groupnum;              g->close[close_index].type = GROUPCHAT_CLOSE_ONLINE; -            g->number_joined = friendcon_id; -            g->close[close_index].introducer = true;          }          send_peer_query(g_c, friendcon_id, other_groupnum); @@ -1420,6 +1666,25 @@ int group_title_get(const Group_Chats *g_c, uint32_t groupnumber, uint8_t *title      return g->title_len;  } +static bool get_peer_number(const Group_c *g, const uint8_t *real_pk, uint16_t *peer_number) +{ +    const int peer_index = peer_in_chat(g, real_pk); + +    if (peer_index >= 0) { +        *peer_number = g->group[peer_index].peer_number; +        return true; +    } + +    for (uint32_t i = 0; i < g->numfrozen; ++i) { +        if (id_equal(g->frozen[i].real_pk, real_pk)) { +            *peer_number = g->frozen[i].peer_number; +            return true; +        } +    } + +    return false; +} +  static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length,                                          void *userdata)  { @@ -1430,7 +1695,7 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con      }      const uint8_t *invite_data = data + 1; -    uint16_t invite_length = length - 1; +    const uint16_t invite_length = length - 1;      switch (data[0]) {          case INVITE_ID: { @@ -1438,7 +1703,7 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con                  return;              } -            int groupnumber = get_group_num(g_c, data[1 + sizeof(uint16_t)], data + 1 + sizeof(uint16_t) + 1); +            const int groupnumber = get_group_num(g_c, data[1 + sizeof(uint16_t)], data + 1 + sizeof(uint16_t) + 1);              if (groupnumber == -1) {                  if (g_c->invite_callback) { @@ -1480,7 +1745,7 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con              unsigned int tries = 0; -            while (get_peer_index(g, peer_number) != -1) { +            while (get_peer_index(g, peer_number) != -1 || get_frozen_index(g, peer_number) != -1) {                  peer_number = random_u16();                  ++tries; @@ -1502,19 +1767,19 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con              uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE], temp_pk[CRYPTO_PUBLIC_KEY_SIZE];              get_friendcon_public_keys(real_pk, temp_pk, g_c->fr_c, friendcon_id); -            addpeer(g_c, groupnum, real_pk, temp_pk, peer_number, userdata, true); -            int close_index = add_conn_to_groupchat(g_c, friendcon_id, groupnum, 0, 1); +            addpeer(g_c, groupnum, real_pk, temp_pk, peer_number, userdata, true, true); +            const int close_index = add_conn_to_groupchat(g_c, friendcon_id, groupnum, GROUPCHAT_CLOSE_REASON_INTRODUCING, 1);              if (close_index != -1) {                  g->close[close_index].group_number = other_groupnum;                  g->close[close_index].type = GROUPCHAT_CLOSE_ONLINE; -                g->close[close_index].introduced = true;              }              group_new_peer_send(g_c, groupnum, peer_number, real_pk, temp_pk);              break;          } +          default:              return;      } @@ -1572,7 +1837,7 @@ static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16                               sizeof(packet), 0) != -1;  } -static unsigned int send_peer_kill(Group_Chats *g_c, int friendcon_id, uint16_t group_num); +static int ping_groupchat(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)  { @@ -1580,7 +1845,7 @@ static int handle_packet_online(Group_Chats *g_c, int friendcon_id, const uint8_          return -1;      } -    int groupnumber = get_group_num(g_c, data[sizeof(uint16_t)], data + sizeof(uint16_t) + 1); +    const int groupnumber = get_group_num(g_c, data[sizeof(uint16_t)], data + sizeof(uint16_t) + 1);      if (groupnumber == -1) {          return -1; @@ -1596,7 +1861,7 @@ static int handle_packet_online(Group_Chats *g_c, int friendcon_id, const uint8_          return -1;      } -    int index = friend_in_close(g, friendcon_id); +    const int index = friend_in_close(g, friendcon_id);      if (index == -1) {          return -1; @@ -1606,7 +1871,7 @@ static int handle_packet_online(Group_Chats *g_c, int friendcon_id, const uint8_          return -1;      } -    if (count_close_connected(g) == 0) { +    if (count_close_connected(g) == 0 || (g->close[index].reasons & GROUPCHAT_CLOSE_REASON_INTRODUCER)) {          send_peer_query(g_c, friendcon_id, other_groupnum);      } @@ -1614,18 +1879,68 @@ static int handle_packet_online(Group_Chats *g_c, int friendcon_id, const uint8_      g->close[index].type = GROUPCHAT_CLOSE_ONLINE;      send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->type, g->id); +    if (g->close[index].reasons & GROUPCHAT_CLOSE_REASON_INTRODUCING) { +        uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE], temp_pk[CRYPTO_PUBLIC_KEY_SIZE]; +        get_friendcon_public_keys(real_pk, temp_pk, g_c->fr_c, friendcon_id); + +        const int peer_index = peer_in_chat(g, real_pk); + +        if (peer_index != -1) { +            group_new_peer_send(g_c, groupnumber, g->group[peer_index].peer_number, real_pk, temp_pk); +        } + +        g->need_send_name = true; +    } + +    ping_groupchat(g_c, groupnumber); +      return 0;  } +static int handle_packet_rejoin(Group_Chats *g_c, int friendcon_id, const uint8_t *data, uint16_t length, +                                void *userdata) +{ +    if (length < 1 + GROUP_ID_LENGTH) { +        return -1; +    } + +    const int32_t groupnum = get_group_num(g_c, *data, data + 1); + +    Group_c *g = get_group_c(g_c, groupnum); + +    if (!g) { +        return -1; +    } + +    uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE], temp_pk[CRYPTO_PUBLIC_KEY_SIZE]; +    get_friendcon_public_keys(real_pk, temp_pk, g_c->fr_c, friendcon_id); + +    uint16_t peer_number; + +    if (!get_peer_number(g, real_pk, &peer_number)) { +        return -1; +    } + +    addpeer(g_c, groupnum, real_pk, temp_pk, peer_number, userdata, true, true); +    const int close_index = add_conn_to_groupchat(g_c, friendcon_id, groupnum, GROUPCHAT_CLOSE_REASON_INTRODUCING, 1); + +    if (close_index != -1) { +        send_packet_online(g_c->fr_c, friendcon_id, groupnum, g->type, g->id); +    } + +    return 0; +} + +  // 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 0 on failure   */ -static unsigned int send_peer_kill(Group_Chats *g_c, int friendcon_id, uint16_t group_num) +static unsigned int send_peer_introduced(Group_Chats *g_c, int friendcon_id, uint16_t group_num)  {      uint8_t packet[1]; -    packet[0] = PEER_KILL_ID; +    packet[0] = PEER_INTRODUCED_ID;      return send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, packet, sizeof(packet));  } @@ -1671,7 +1986,7 @@ static unsigned int send_peers(Group_Chats *g_c, uint32_t groupnumber, int frien              p = response_packet + 1;          } -        uint16_t peer_num = net_htons(g->group[i].peer_number); +        const uint16_t peer_num = net_htons(g->group[i].peer_number);          memcpy(p, &peer_num, sizeof(peer_num));          p += sizeof(peer_num);          memcpy(p, g->group[i].real_pk, CRYPTO_PUBLIC_KEY_SIZE); @@ -1732,17 +2047,17 @@ static int handle_send_peers(Group_Chats *g_c, uint32_t groupnumber, const uint8                  g_c->connected_callback(g_c->m, groupnumber, userdata);              } -            group_name_send(g_c, groupnumber, g_c->m->name, g_c->m->name_length); +            g->need_send_name = true;          } -        int peer_index = addpeer(g_c, groupnumber, d, d + CRYPTO_PUBLIC_KEY_SIZE, peer_num, userdata, true); +        const int peer_index = addpeer(g_c, groupnumber, d, d + CRYPTO_PUBLIC_KEY_SIZE, peer_num, userdata, false, true);          if (peer_index == -1) {              return -1;          }          d += CRYPTO_PUBLIC_KEY_SIZE * 2; -        uint8_t name_length = *d; +        const uint8_t name_length = *d;          d += 1;          if (name_length > (length - (d - data)) || name_length > MAX_NAME_LENGTH) { @@ -1767,17 +2082,14 @@ static void handle_direct_packet(Group_Chats *g_c, uint32_t groupnumber, const u      }      switch (data[0]) { -        case PEER_KILL_ID: { +        case PEER_INTRODUCED_ID: {              Group_c *g = get_group_c(g_c, groupnumber);              if (!g) {                  return;              } -            if (!g->close[close_index].closest) { -                g->close[close_index].type = GROUPCHAT_CLOSE_NONE; -                kill_friend_connection(g_c->fr_c, g->close[close_index].number); -            } +            remove_conn_reason(g_c, groupnumber, close_index, GROUPCHAT_CLOSE_REASON_INTRODUCING);          }          break; @@ -1801,7 +2113,15 @@ static void handle_direct_packet(Group_Chats *g_c, uint32_t groupnumber, const u          break;          case PEER_TITLE_ID: { -            settitle(g_c, groupnumber, -1, data + 1, length - 1, userdata); +            Group_c *g = get_group_c(g_c, groupnumber); + +            if (!g) { +                break; +            } + +            if (!g->title_fresh) { +                settitle(g_c, groupnumber, -1, data + 1, length - 1, userdata); +            }          }          break; @@ -1868,7 +2188,7 @@ static unsigned int send_lossy_all_close(const Group_Chats *g_c, uint32_t groupn              continue;          } -        if (g->close[i].closest) { +        if (g->close[i].reasons & GROUPCHAT_CLOSE_REASON_CLOSEST) {              connected_closest[num_connected_closest] = i;              ++num_connected_closest;              continue; @@ -1891,7 +2211,7 @@ static unsigned int send_lossy_all_close(const Group_Chats *g_c, uint32_t groupn          uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE] = {0};          uint8_t dht_temp_pk[CRYPTO_PUBLIC_KEY_SIZE] = {0};          get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[connected_closest[i]].number); -        uint64_t comp_val = calculate_comp_value(g->real_pk, real_pk); +        const uint64_t comp_val = calculate_comp_value(g->real_pk, real_pk);          if (comp_val < comp_val_old) {              to_send = connected_closest[i]; @@ -1911,7 +2231,7 @@ static unsigned int send_lossy_all_close(const Group_Chats *g_c, uint32_t groupn          uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE] = {0};          uint8_t dht_temp_pk[CRYPTO_PUBLIC_KEY_SIZE] = {0};          get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[connected_closest[i]].number); -        uint64_t comp_val = calculate_comp_value(real_pk, g->real_pk); +        const uint64_t comp_val = calculate_comp_value(real_pk, g->real_pk);          if (comp_val < comp_val_old) {              to_send_other = connected_closest[i]; @@ -1957,7 +2277,7 @@ static int send_message_group(const Group_Chats *g_c, uint32_t groupnumber, uint      }      VLA(uint8_t, packet, sizeof(uint16_t) + sizeof(uint32_t) + 1 + len); -    uint16_t peer_num = net_htons(g->peer_number); +    const uint16_t peer_num = net_htons(g->peer_number);      memcpy(packet, &peer_num, sizeof(peer_num));      ++g->message_number; @@ -1966,7 +2286,7 @@ static int send_message_group(const Group_Chats *g_c, uint32_t groupnumber, uint          ++g->message_number;      } -    uint32_t message_num = net_htonl(g->message_number); +    const uint32_t message_num = net_htonl(g->message_number);      memcpy(packet + sizeof(uint16_t), &message_num, sizeof(message_num));      packet[sizeof(uint16_t) + sizeof(uint32_t)] = message_id; @@ -1986,7 +2306,7 @@ static int send_message_group(const Group_Chats *g_c, uint32_t groupnumber, uint   */  int group_message_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *message, uint16_t length)  { -    int ret = send_message_group(g_c, groupnumber, PACKET_ID_MESSAGE, message, length); +    const int ret = send_message_group(g_c, groupnumber, PACKET_ID_MESSAGE, message, length);      if (ret > 0) {          return 0; @@ -2001,7 +2321,7 @@ int group_message_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8   */  int group_action_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *action, uint16_t length)  { -    int ret = send_message_group(g_c, groupnumber, PACKET_ID_ACTION, action, length); +    const int ret = send_message_group(g_c, groupnumber, PACKET_ID_ACTION, action, length);      if (ret > 0) {          return 0; @@ -2025,9 +2345,9 @@ int send_group_lossy_packet(const Group_Chats *g_c, uint32_t groupnumber, const      }      VLA(uint8_t, packet, sizeof(uint16_t) * 2 + length); -    uint16_t peer_number = net_htons(g->peer_number); +    const uint16_t peer_number = net_htons(g->peer_number);      memcpy(packet, &peer_number, sizeof(uint16_t)); -    uint16_t message_num = net_htons(g->lossy_message_number); +    const uint16_t message_num = net_htons(g->lossy_message_number);      memcpy(packet + sizeof(uint16_t), &message_num, sizeof(uint16_t));      memcpy(packet + sizeof(uint16_t) * 2, data, length); @@ -2108,33 +2428,31 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber,      memcpy(&peer_number, data, sizeof(uint16_t));      peer_number = net_ntohs(peer_number); -    int index = get_peer_index(g, peer_number); +    const int index = note_peer_active(g_c, groupnumber, peer_number, userdata);      if (index == -1) { -        /* We don't know the peer this packet came from so we query the list of peers from that peer. -          (They would not have relayed it if they didn't know the peer.) */ +        /* If we don't know the peer this packet came from, then we query the +         * list of peers from the relaying peer. +         * (They would not have relayed it if they didn't know the peer.) */          send_peer_query(g_c, g->close[close_index].number, g->close[close_index].group_number);          return;      } -    if (g->number_joined != -1 && count_close_connected(g) >= DESIRED_CLOSE_CONNECTIONS) { -        const int fr_close_index = friend_in_close(g, g->number_joined); +    if (g->num_introducer_connections > 0 && count_close_connected(g) > DESIRED_CLOSE_CONNECTIONS) { +        for (uint32_t i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { +            if (g->close[i].type == GROUPCHAT_CLOSE_NONE +                    || !(g->close[i].reasons & GROUPCHAT_CLOSE_REASON_INTRODUCER) +                    || i == close_index) { +                continue; +            } -        if (fr_close_index >= 0 && fr_close_index != close_index && !g->close[fr_close_index].closest) {              uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE]; -            get_friendcon_public_keys(real_pk, nullptr, g_c->fr_c, g->close[fr_close_index].number); +            get_friendcon_public_keys(real_pk, nullptr, g_c->fr_c, g->close[i].number);              if (id_equal(g->group[index].real_pk, real_pk)) {                  /* Received message from peer relayed via another peer, so                   * the introduction was successful */ -                g->number_joined = -1; -                g->close[fr_close_index].introducer = false; - -                if (!g->close[fr_close_index].closest && !g->close[fr_close_index].introduced) { -                    g->close[fr_close_index].type = GROUPCHAT_CLOSE_NONE; -                    send_peer_kill(g_c, g->close[fr_close_index].number, g->close[fr_close_index].group_number); -                    kill_friend_connection(g_c->fr_c, g->close[fr_close_index].number); -                } +                remove_conn_reason(g_c, groupnumber, i, GROUPCHAT_CLOSE_REASON_INTRODUCER);              }          }      } @@ -2143,24 +2461,17 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber,      memcpy(&message_number, data + sizeof(uint16_t), sizeof(message_number));      message_number = net_ntohl(message_number); -    uint8_t message_id = data[sizeof(uint16_t) + sizeof(message_number)]; +    const uint8_t message_id = data[sizeof(uint16_t) + sizeof(message_number)];      const uint8_t *msg_data = data + sizeof(uint16_t) + sizeof(message_number) + 1; -    uint16_t msg_data_len = length - (sizeof(uint16_t) + sizeof(message_number) + 1); +    const uint16_t msg_data_len = length - (sizeof(uint16_t) + sizeof(message_number) + 1); -    // FIXME(zugz) update discussion of message numbers in the spec      if (!check_message_info(message_number, message_id, &g->group[index])) {          return;      }      switch (message_id) { -        case GROUP_MESSAGE_PING_ID: { -            if (msg_data_len != 0) { -                return; -            } - -            g->group[index].last_recv = unix_time(); -        } -        break; +        case GROUP_MESSAGE_PING_ID: +            break;          case GROUP_MESSAGE_NEW_PEER_ID: {              if (msg_data_len != GROUP_MESSAGE_NEW_PEER_LENGTH) { @@ -2171,7 +2482,7 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber,              memcpy(&new_peer_number, msg_data, sizeof(uint16_t));              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); +                    new_peer_number, userdata, true, true);          }          break; @@ -2185,7 +2496,7 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber,              kill_peer_number = net_ntohs(kill_peer_number);              if (peer_number == kill_peer_number) { -                delpeer(g_c, groupnumber, index, userdata); +                delpeer(g_c, groupnumber, index, userdata, false);              } else {                  return;                  // TODO(irungentoo): @@ -2260,6 +2571,10 @@ static int g_handle_packet(void *object, int friendcon_id, const uint8_t *data,          return handle_packet_online(g_c, friendcon_id, data + 1, length - 1);      } +    if (data[0] == PACKET_ID_REJOIN_CONFERENCE) { +        return handle_packet_rejoin(g_c, friendcon_id, data + 1, length - 1, userdata); +    } +      if (data[0] != PACKET_ID_DIRECT_CONFERENCE && data[0] != PACKET_ID_MESSAGE_CONFERENCE) {          return -1;      } @@ -2273,7 +2588,7 @@ static int g_handle_packet(void *object, int friendcon_id, const uint8_t *data,          return -1;      } -    int index = friend_in_close(g, friendcon_id); +    const int index = friend_in_close(g, friendcon_id);      if (index == -1) {          return -1; @@ -2335,7 +2650,7 @@ static unsigned int lossy_packet_not_received(Group_c *g, int peer_index, uint16          return -1;      } -    uint16_t top_distance = message_number - g->group[peer_index].top_lossy_number; +    const uint16_t top_distance = message_number - g->group[peer_index].top_lossy_number;      if (top_distance >= MAX_LOSSY_COUNT) {          crypto_memzero(g->group[peer_index].recv_lossy, sizeof(g->group[peer_index].recv_lossy)); @@ -2384,7 +2699,7 @@ static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uin          return -1;      } -    int index = friend_in_close(g, friendcon_id); +    const int index = friend_in_close(g, friendcon_id);      if (index == -1) {          return -1; @@ -2394,7 +2709,7 @@ static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uin          return -1;      } -    int peer_index = get_peer_index(g, peer_number); +    const int peer_index = get_peer_index(g, peer_number);      if (peer_index == -1) {          return -1; @@ -2406,7 +2721,7 @@ static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uin      const uint8_t *lossy_data = data + 1 + sizeof(uint16_t) * 3;      uint16_t lossy_length = length - (1 + sizeof(uint16_t) * 3); -    uint8_t message_id = lossy_data[0]; +    const uint8_t message_id = lossy_data[0];      ++lossy_data;      --lossy_length; @@ -2508,16 +2823,16 @@ static int ping_groupchat(Group_Chats *g_c, uint32_t groupnumber)          return -1;      } -    if (is_timeout(g->last_sent_ping, GROUP_PING_INTERVAL)) { +    if (mono_time_is_timeout(g_c->mono_time, g->last_sent_ping, GROUP_PING_INTERVAL)) {          if (group_ping_send(g_c, groupnumber) != -1) { /* Ping */ -            g->last_sent_ping = unix_time(); +            g->last_sent_ping = mono_time_get(g_c->mono_time);          }      }      return 0;  } -static int groupchat_clear_timedout(Group_Chats *g_c, uint32_t groupnumber, void *userdata) +static int groupchat_freeze_timedout(Group_Chats *g_c, uint32_t groupnumber, void *userdata)  {      Group_c *g = get_group_c(g_c, groupnumber); @@ -2526,15 +2841,19 @@ static int groupchat_clear_timedout(Group_Chats *g_c, uint32_t groupnumber, void      }      for (uint32_t i = 0; i < g->numpeers; ++i) { -        if (g->peer_number != g->group[i].peer_number && is_timeout(g->group[i].last_recv, GROUP_PING_INTERVAL * 3)) { -            delpeer(g_c, groupnumber, i, userdata); +        if (g->group[i].peer_number == g->peer_number) { +            continue;          } -        if (g->group == nullptr || i >= g->numpeers) { -            break; +        if (mono_time_is_timeout(g_c->mono_time, g->group[i].last_active, GROUP_PING_INTERVAL * 3)) { +            freeze_peer(g_c, groupnumber, i, userdata);          }      } +    if (g->numpeers <= 1) { +        g->title_fresh = false; +    } +      return 0;  } @@ -2551,12 +2870,13 @@ void send_name_all_groups(Group_Chats *g_c)          if (g->status == GROUPCHAT_STATUS_CONNECTED) {              group_name_send(g_c, i, g_c->m->name, g_c->m->name_length); +            g->need_send_name = false;          }      }  }  /* Create new groupchat instance. */ -Group_Chats *new_groupchats(Messenger *m) +Group_Chats *new_groupchats(Mono_Time *mono_time, Messenger *m)  {      if (!m) {          return nullptr; @@ -2568,6 +2888,7 @@ Group_Chats *new_groupchats(Messenger *m)          return nullptr;      } +    temp->mono_time = mono_time;      temp->m = m;      temp->fr_c = m->fr_c;      m->conferences_object = temp; @@ -2589,7 +2910,12 @@ void do_groupchats(Group_Chats *g_c, void *userdata)          if (g->status == GROUPCHAT_STATUS_CONNECTED) {              connect_to_closest(g_c, i, userdata);              ping_groupchat(g_c, i); -            groupchat_clear_timedout(g_c, i, userdata); +            groupchat_freeze_timedout(g_c, i, userdata); + +            if (g->need_send_name) { +                group_name_send(g_c, i, g_c->m->name, g_c->m->name_length); +                g->need_send_name = false; +            }          }      } diff --git a/protocols/Tox/libtox/src/toxcore/group.h b/protocols/Tox/libtox/src/toxcore/group.h index 175999ae78..7acd46371e 100644 --- a/protocols/Tox/libtox/src/toxcore/group.h +++ b/protocols/Tox/libtox/src/toxcore/group.h @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2014 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -21,8 +21,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef GROUP_H -#define GROUP_H +#ifndef C_TOXCORE_TOXCORE_GROUP_H +#define C_TOXCORE_TOXCORE_GROUP_H  #include "Messenger.h" @@ -49,12 +49,13 @@ typedef struct Message_Info {  typedef struct Group_Peer {      uint8_t     real_pk[CRYPTO_PUBLIC_KEY_SIZE];      uint8_t     temp_pk[CRYPTO_PUBLIC_KEY_SIZE]; +    bool        temp_pk_updated; -    uint64_t    last_recv; +    uint64_t    last_active;      Message_Info      last_message_infos[MAX_LAST_MESSAGE_INFOS]; /* received messages, strictly decreasing in message_number */ -    uint8_t         num_last_message_infos; +    uint8_t     num_last_message_infos;      uint8_t     nick[MAX_NAME_LENGTH];      uint8_t     nick_len; @@ -79,11 +80,18 @@ typedef enum Groupchat_Close_Type {      GROUPCHAT_CLOSE_ONLINE  } Groupchat_Close_Type; +/* Connection is to one of the closest DESIRED_CLOSE_CONNECTIONS peers */ +#define GROUPCHAT_CLOSE_REASON_CLOSEST     (1 << 0) + +/* Connection is to a peer we are introducing to the conference */ +#define GROUPCHAT_CLOSE_REASON_INTRODUCING (1 << 1) + +/* Connection is to a peer who is introducing us to the conference */ +#define GROUPCHAT_CLOSE_REASON_INTRODUCER  (1 << 2) +  typedef struct Groupchat_Close {      uint8_t type; /* GROUPCHAT_CLOSE_* */ -    bool closest; /* connected to peer because it is one of our closest peers */ -    bool introducer; /* connected to peer because it introduced us to the group */ -    bool introduced; /* connected to peer because we introduced it to the group */ +    uint8_t reasons; /* bit field with flags GROUPCHAT_CLOSE_REASON_* */      uint32_t number;      uint16_t group_number;  } Groupchat_Close; @@ -101,9 +109,15 @@ typedef void group_on_delete_cb(void *object, uint32_t conference_number);  typedef struct Group_c {      uint8_t status; +    bool need_send_name; +    bool title_fresh; +      Group_Peer *group;      uint32_t numpeers; +    Group_Peer *frozen; +    uint32_t numfrozen; +      /* TODO(zugz) rename close to something more accurate - "connected"? */      Groupchat_Close close[MAX_GROUP_CONNECTIONS]; @@ -123,7 +137,7 @@ typedef struct Group_c {      uint64_t last_sent_ping; -    int number_joined; /* friendcon_id of person that invited us to the chat. (-1 means none) */ +    uint32_t num_introducer_connections;      void *object; @@ -172,6 +186,8 @@ typedef struct Group_Lossy_Handler {  } Group_Lossy_Handler;  typedef struct Group_Chats { +    const Mono_Time *mono_time; +      Messenger *m;      Friend_Connections *fr_c; @@ -433,7 +449,7 @@ int callback_groupchat_peer_delete(Group_Chats *g_c, uint32_t groupnumber, peer_  int callback_groupchat_delete(Group_Chats *g_c, uint32_t groupnumber, group_on_delete_cb *function);  /* Create new groupchat instance. */ -Group_Chats *new_groupchats(Messenger *m); +Group_Chats *new_groupchats(Mono_Time *mono_time, Messenger *m);  /* main groupchats loop. */  void do_groupchats(Group_Chats *g_c, void *userdata); diff --git a/protocols/Tox/libtox/src/toxcore/list.c b/protocols/Tox/libtox/src/toxcore/list.c index e4c160544e..1cc143e24f 100644 --- a/protocols/Tox/libtox/src/toxcore/list.c +++ b/protocols/Tox/libtox/src/toxcore/list.c @@ -5,7 +5,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2014 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. diff --git a/protocols/Tox/libtox/src/toxcore/list.h b/protocols/Tox/libtox/src/toxcore/list.h index 628b46a051..c9c72c2a80 100644 --- a/protocols/Tox/libtox/src/toxcore/list.h +++ b/protocols/Tox/libtox/src/toxcore/list.h @@ -5,7 +5,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2014 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -23,8 +23,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef LIST_H -#define LIST_H +#ifndef C_TOXCORE_TOXCORE_LIST_H +#define C_TOXCORE_TOXCORE_LIST_H  #include <stdint.h> diff --git a/protocols/Tox/libtox/src/toxcore/logger.c b/protocols/Tox/libtox/src/toxcore/logger.c index 5e16233c9b..51c30edec4 100644 --- a/protocols/Tox/libtox/src/toxcore/logger.c +++ b/protocols/Tox/libtox/src/toxcore/logger.c @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013,2015 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. diff --git a/protocols/Tox/libtox/src/toxcore/logger.h b/protocols/Tox/libtox/src/toxcore/logger.h index dd7edee768..2cae7a0efd 100644 --- a/protocols/Tox/libtox/src/toxcore/logger.h +++ b/protocols/Tox/libtox/src/toxcore/logger.h @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -21,8 +21,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef TOXLOGGER_H -#define TOXLOGGER_H +#ifndef C_TOXCORE_TOXCORE_LOGGER_H +#define C_TOXCORE_TOXCORE_LOGGER_H  #include <stdint.h> @@ -32,6 +32,7 @@  #define MIN_LOGGER_LEVEL LOGGER_LEVEL_INFO  #endif +// NOTE: Don't forget to update build system files after modifying the enum.  typedef enum Logger_Level {      LOGGER_LEVEL_TRACE,      LOGGER_LEVEL_DEBUG, @@ -90,4 +91,4 @@ void logger_write(  #define LOGGER_WARNING(log, ...) LOGGER_WRITE(log, LOGGER_LEVEL_WARNING, __VA_ARGS__)  #define LOGGER_ERROR(log, ...)   LOGGER_WRITE(log, LOGGER_LEVEL_ERROR  , __VA_ARGS__) -#endif /* TOXLOGGER_H */ +#endif // 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 0beb72542b..6e4bc067d3 100644 --- a/protocols/Tox/libtox/src/toxcore/mono_time.c +++ b/protocols/Tox/libtox/src/toxcore/mono_time.c @@ -28,113 +28,111 @@  struct Mono_Time {      uint64_t time;      uint64_t base_time; +#ifdef OS_WIN32 +    uint64_t last_clock_mono; +    uint64_t add_clock_mono; +#endif + +    mono_time_current_time_cb *current_time_callback; +    void *user_data;  }; -Mono_Time *mono_time_new(void) +static uint64_t current_time_monotonic_default(Mono_Time *mono_time, void *user_data)  { -    Mono_Time *monotime = (Mono_Time *)malloc(sizeof(Mono_Time)); +    uint64_t time; +#ifdef OS_WIN32 +    uint64_t old_add_clock_mono = mono_time->add_clock_mono; +    time = (uint64_t)GetTickCount() + mono_time->add_clock_mono; -    if (monotime == nullptr) { -        return nullptr; +    /* Check if time has decreased because of 32 bit wrap from GetTickCount(), while avoiding false positives from race +     * conditions when multiple threads call this function at once */ +    if (time + 0x10000 < mono_time->last_clock_mono) { +        uint32_t add = ~0; +        /* use old_add_clock_mono rather than simply incrementing add_clock_mono, to handle the case that many threads +         * simultaneously detect an overflow */ +        mono_time->add_clock_mono = old_add_clock_mono + add; +        time += add;      } -    monotime->time = 0; -    monotime->base_time = 0; +    mono_time->last_clock_mono = time; +#else +    struct timespec clock_mono; +#if defined(__APPLE__) +    clock_serv_t muhclock; +    mach_timespec_t machtime; -    return monotime; -} +    host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &muhclock); +    clock_get_time(muhclock, &machtime); +    mach_port_deallocate(mach_task_self(), muhclock); -void mono_time_free(Mono_Time *monotime) -{ -    free(monotime); +    clock_mono.tv_sec = machtime.tv_sec; +    clock_mono.tv_nsec = machtime.tv_nsec; +#else +    clock_gettime(CLOCK_MONOTONIC, &clock_mono); +#endif +    time = 1000ULL * clock_mono.tv_sec + (clock_mono.tv_nsec / 1000000ULL); +#endif +    return time;  } -void mono_time_update(Mono_Time *monotime) +Mono_Time *mono_time_new(void)  { -    if (monotime->base_time == 0) { -        monotime->base_time = ((uint64_t)time(nullptr) - (current_time_monotonic() / 1000ULL)); +    Mono_Time *mono_time = (Mono_Time *)malloc(sizeof(Mono_Time)); + +    if (mono_time == nullptr) { +        return nullptr;      } -    monotime->time = (current_time_monotonic() / 1000ULL) + monotime->base_time; +    mono_time->current_time_callback = current_time_monotonic_default; +    mono_time->user_data = nullptr; + +#ifdef OS_WIN32 +    mono_time->last_clock_mono = 0; +    mono_time->add_clock_mono = 0; +#endif + +    mono_time->time = 0; +    mono_time->base_time = (uint64_t)time(nullptr) - (current_time_monotonic(mono_time) / 1000ULL); + +    mono_time_update(mono_time); + +    return mono_time;  } -uint64_t mono_time_get(const Mono_Time *monotime) +void mono_time_free(Mono_Time *mono_time)  { -    return monotime->time; +    free(mono_time);  } -bool mono_time_is_timeout(const Mono_Time *monotime, uint64_t timestamp, uint64_t timeout) +void mono_time_update(Mono_Time *mono_time)  { -    return timestamp + timeout <= mono_time_get(monotime); +    mono_time->time = (current_time_monotonic(mono_time) / 1000ULL) + mono_time->base_time;  } - -//!TOKSTYLE- -// No global mutable state in Tokstyle. -static Mono_Time global_time; -//!TOKSTYLE+ - -/* XXX: note that this is not thread-safe; if multiple threads call unix_time_update() concurrently, the return value of - * unix_time() may fail to increase monotonically with increasing time */ -void unix_time_update(void) +uint64_t mono_time_get(const Mono_Time *mono_time)  { -    mono_time_update(&global_time); +    return mono_time->time;  } -uint64_t unix_time(void) + +bool mono_time_is_timeout(const Mono_Time *mono_time, uint64_t timestamp, uint64_t timeout)  { -    return mono_time_get(&global_time); +    return timestamp + timeout <= mono_time_get(mono_time);  } -int is_timeout(uint64_t timestamp, uint64_t timeout) + +void mono_time_set_current_time_callback(Mono_Time *mono_time, +        mono_time_current_time_cb *current_time_callback, void *user_data)  { -    return mono_time_is_timeout(&global_time, timestamp, timeout); +    if (current_time_callback == nullptr) { +        mono_time->current_time_callback = current_time_monotonic_default; +        mono_time->user_data = nullptr; +    } else { +        mono_time->current_time_callback = current_time_callback; +        mono_time->user_data = user_data; +    }  } - -//!TOKSTYLE- -// No global mutable state in Tokstyle. -#ifdef OS_WIN32 -static uint64_t last_monotime; -static uint64_t add_monotime; -#endif -//!TOKSTYLE+ -  /* return current monotonic time in milliseconds (ms). */ -uint64_t current_time_monotonic(void) +uint64_t current_time_monotonic(Mono_Time *mono_time)  { -    uint64_t time; -#ifdef OS_WIN32 -    uint64_t old_add_monotime = add_monotime; -    time = (uint64_t)GetTickCount() + add_monotime; - -    /* Check if time has decreased because of 32 bit wrap from GetTickCount(), while avoiding false positives from race -     * conditions when multiple threads call this function at once */ -    if (time + 0x10000 < last_monotime) { -        uint32_t add = ~0; -        /* use old_add_monotime rather than simply incrementing add_monotime, to handle the case that many threads -         * simultaneously detect an overflow */ -        add_monotime = old_add_monotime + add; -        time += add; -    } - -    last_monotime = time; -#else -    struct timespec monotime; -#if defined(__linux__) && defined(CLOCK_MONOTONIC_RAW) -    clock_gettime(CLOCK_MONOTONIC_RAW, &monotime); -#elif defined(__APPLE__) -    clock_serv_t muhclock; -    mach_timespec_t machtime; - -    host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &muhclock); -    clock_get_time(muhclock, &machtime); -    mach_port_deallocate(mach_task_self(), muhclock); - -    monotime.tv_sec = machtime.tv_sec; -    monotime.tv_nsec = machtime.tv_nsec; -#else -    clock_gettime(CLOCK_MONOTONIC, &monotime); -#endif -    time = 1000ULL * monotime.tv_sec + (monotime.tv_nsec / 1000000ULL); -#endif -    return time; +    return mono_time->current_time_callback(mono_time, mono_time->user_data);  } diff --git a/protocols/Tox/libtox/src/toxcore/mono_time.h b/protocols/Tox/libtox/src/toxcore/mono_time.h index 9775956085..503548f222 100644 --- a/protocols/Tox/libtox/src/toxcore/mono_time.h +++ b/protocols/Tox/libtox/src/toxcore/mono_time.h @@ -8,25 +8,62 @@  extern "C" {  #endif +#ifndef MONO_TIME_DEFINED +#define MONO_TIME_DEFINED +/** + * The timer portion of the toxcore event loop. + * + * We update the time exactly once per tox_iterate call. Programs built on lower + * level APIs such as the DHT bootstrap node must update the time manually in + * each iteration. + * + * Time is kept per Tox instance, not globally, even though "time" as a concept + * is global. This is because by definition `mono_time` represents the time at + * the start of an iteration, and also by definition the time when all network + * events for the current iteration occurred. This affects mainly two situations: + * + * 1. Two timers started in the same iteration: e.g. two timers set to expire in + *    10 seconds will both expire at the same time, i.e. about 10 seconds later. + *    If the time were global, `mono_time` would be a random number that is + *    either the time at the start of an iteration, or 1 second later (since the + *    timer resolution is 1 second). This can happen when one update happens at + *    e.g. 10:00:00.995 and a few milliseconds later a concurrently running + *    instance updates the time at 10:00:01.005, making one timer expire a + *    second after the other. + * 2. One timer based on an event: if we want to encode a behaviour of a timer + *    expiring e.g. 10 seconds after a network event occurred, we simply start a + *    timer in the event handler. If a concurrent instance updates the time + *    underneath us, it may instead expire 9 seconds after the event. + * + * Both these situations cause incorrect behaviour randomly. In practice, + * toxcore is somewhat robust against strange timer behaviour, but the + * 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 *monotime); +void mono_time_free(Mono_Time *mono_time); -void mono_time_update(Mono_Time *monotime); -uint64_t mono_time_get(const Mono_Time *monotime); -bool mono_time_is_timeout(const Mono_Time *monotime, uint64_t timestamp, uint64_t timeout); - -// TODO(#405): Use per-tox monotime, delete these functions. -void unix_time_update(void); -uint64_t unix_time(void); -int is_timeout(uint64_t timestamp, uint64_t timeout); +void mono_time_update(Mono_Time *mono_time); +uint64_t mono_time_get(const Mono_Time *mono_time); +bool mono_time_is_timeout(const Mono_Time *mono_time, uint64_t timestamp, uint64_t timeout);  /* return current monotonic time in milliseconds (ms). */ -uint64_t current_time_monotonic(void); +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). + * + * The caller is obligated to ensure that current_time_monotonic() continues + * to increase monotonically. + */ +void mono_time_set_current_time_callback(Mono_Time *mono_time, +        mono_time_current_time_cb *current_time_callback, void *user_data);  #ifdef __cplusplus  }  #endif -#endif  // C_TOXCORE_TOXCORE_MONO_TIME_H +#endif // C_TOXCORE_TOXCORE_MONO_TIME_H diff --git a/protocols/Tox/libtox/src/toxcore/net_crypto.c b/protocols/Tox/libtox/src/toxcore/net_crypto.c index 8f5fd5071b..736b9c4a25 100644 --- a/protocols/Tox/libtox/src/toxcore/net_crypto.c +++ b/protocols/Tox/libtox/src/toxcore/net_crypto.c @@ -5,7 +5,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -134,6 +134,7 @@ typedef struct Crypto_Connection {  struct Net_Crypto {      const Logger *log; +    Mono_Time *mono_time;      DHT *dht;      TCP_Connections *tcp_c; @@ -248,10 +249,11 @@ static int create_cookie_request(const Net_Crypto *c, uint8_t *packet, uint8_t *   * return -1 on failure.   * return 0 on success.   */ -static int create_cookie(const Logger *log, uint8_t *cookie, const uint8_t *bytes, const uint8_t *encryption_key) +static int create_cookie(const Logger *log, const Mono_Time *mono_time, uint8_t *cookie, const uint8_t *bytes, +                         const uint8_t *encryption_key)  {      uint8_t contents[COOKIE_CONTENTS_LENGTH]; -    const uint64_t temp_time = unix_time(); +    const uint64_t temp_time = mono_time_get(mono_time);      memcpy(contents, &temp_time, sizeof(temp_time));      memcpy(contents + sizeof(temp_time), bytes, COOKIE_DATA_LENGTH);      random_nonce(cookie); @@ -269,7 +271,8 @@ static int create_cookie(const Logger *log, uint8_t *cookie, const uint8_t *byte   * return -1 on failure.   * return 0 on success.   */ -static int open_cookie(const Logger *log, uint8_t *bytes, const uint8_t *cookie, const uint8_t *encryption_key) +static int open_cookie(const Logger *log, const Mono_Time *mono_time, uint8_t *bytes, const uint8_t *cookie, +                       const uint8_t *encryption_key)  {      uint8_t contents[COOKIE_CONTENTS_LENGTH];      const int len = decrypt_data_symmetric(encryption_key, cookie, cookie + CRYPTO_NONCE_SIZE, @@ -281,7 +284,7 @@ static int open_cookie(const Logger *log, uint8_t *bytes, const uint8_t *cookie,      uint64_t cookie_time;      memcpy(&cookie_time, contents, sizeof(cookie_time)); -    const uint64_t temp_time = unix_time(); +    const uint64_t temp_time = mono_time_get(mono_time);      if (cookie_time + COOKIE_TIMEOUT < temp_time || temp_time < cookie_time) {          return -1; @@ -307,7 +310,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, plain, cookie_plain, c->secret_symmetric_key) != 0) { +    if (create_cookie(c->log, c->mono_time, plain, cookie_plain, c->secret_symmetric_key) != 0) {          return -1;      } @@ -475,8 +478,8 @@ 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, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE, cookie_plain, -                      c->secret_symmetric_key) != 0) { +    if (create_cookie(c->log, c->mono_time, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE, +                      cookie_plain, c->secret_symmetric_key) != 0) {          return -1;      } @@ -521,7 +524,7 @@ 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, cookie_plain, packet + 1, c->secret_symmetric_key) != 0) { +    if (open_cookie(c->log, c->mono_time, cookie_plain, packet + 1, c->secret_symmetric_key) != 0) {          return -1;      } @@ -581,7 +584,7 @@ static int add_ip_port_connection(Net_Crypto *c, int crypt_connection_id, IP_Por      }      if (net_family_is_ipv4(ip_port.ip.family)) { -        if (!ipport_equal(&ip_port, &conn->ip_portv4) && ip_is_lan(conn->ip_portv4.ip) != 0) { +        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)) {                  return -1;              } @@ -620,7 +623,7 @@ static IP_Port return_ip_port_connection(Net_Crypto *c, int crypt_connection_id)          return empty;      } -    uint64_t current_time = unix_time(); +    const uint64_t current_time = mono_time_get(c->mono_time);      bool v6 = 0, v4 = 0;      if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) { @@ -631,7 +634,10 @@ static IP_Port return_ip_port_connection(Net_Crypto *c, int crypt_connection_id)          v6 = 1;      } -    if (v4 && ip_is_lan(conn->ip_portv4.ip) == 0) { +    /* 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)) {          return conn->ip_portv4;      } @@ -639,6 +645,18 @@ static IP_Port return_ip_port_connection(Net_Crypto *c, int crypt_connection_id)          return conn->ip_portv6;      } +    if (v4 && net_family_is_ipv4(conn->ip_portv4.ip.family)) { +        return conn->ip_portv4; +    } + +    if (ip_is_lan(conn->ip_portv4.ip)) { +        return conn->ip_portv4; +    } + +    if (net_family_is_ipv6(conn->ip_portv6.ip.family)) { +        return conn->ip_portv6; +    } +      if (net_family_is_ipv4(conn->ip_portv4.ip.family)) {          return conn->ip_portv4;      } @@ -681,13 +699,13 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t          }          // TODO(irungentoo): a better way of sending packets directly to confirm the others ip. -        uint64_t current_time = unix_time(); +        const uint64_t current_time = mono_time_get(c->mono_time);          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) {                  direct_send_attempt = 1; -                conn->direct_send_attempt_time = unix_time(); +                conn->direct_send_attempt_time = mono_time_get(c->mono_time);              }          }      } @@ -700,7 +718,7 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t      pthread_mutex_lock(&conn->mutex);      if (ret == 0) { -        conn->last_tcp_sent = current_time_monotonic(); +        conn->last_tcp_sent = current_time_monotonic(c->mono_time);      }      pthread_mutex_unlock(&conn->mutex); @@ -954,8 +972,8 @@ static int generate_request_packet(const Logger *log, uint8_t *data, uint16_t le   * return -1 on failure.   * return number of requested packets on success.   */ -static int handle_request_packet(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, const Logger *log, 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; @@ -975,7 +993,7 @@ static int handle_request_packet(const Logger *log, Packets_Array *send_array, c      uint32_t n = 1;      uint32_t requested = 0; -    const uint64_t temp_time = current_time_monotonic(); +    const uint64_t temp_time = current_time_monotonic(mono_time);      uint64_t l_sent_time = ~0;      for (uint32_t i = send_array->buffer_start; i != send_array->buffer_end; ++i) { @@ -1117,7 +1135,7 @@ static int reset_max_speed_reached(Net_Crypto *c, int crypt_connection_id)                  return -1;              } -            dt->sent_time = current_time_monotonic(); +            dt->sent_time = current_time_monotonic(c->mono_time);          }          conn->maximum_speed_reached = 0; @@ -1170,7 +1188,7 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, cons          Packet_Data *dt1 = nullptr;          if (get_data_pointer(c->log, &conn->send_array, &dt1, packet_num) == 1) { -            dt1->sent_time = current_time_monotonic(); +            dt1->sent_time = current_time_monotonic(c->mono_time);          }      } else {          conn->maximum_speed_reached = 1; @@ -1276,7 +1294,7 @@ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32          return -1;      } -    const uint64_t temp_time = current_time_monotonic(); +    const uint64_t temp_time = current_time_monotonic(c->mono_time);      uint32_t i, num_sent = 0, array_size = num_packets_array(&conn->send_array);      for (i = 0; i < array_size; ++i) { @@ -1392,7 +1410,7 @@ static int send_temp_packet(Net_Crypto *c, int crypt_connection_id)          return -1;      } -    conn->temp_packet_sent_time = current_time_monotonic(); +    conn->temp_packet_sent_time = current_time_monotonic(c->mono_time);      ++conn->temp_packet_num_sent;      return 0;  } @@ -1542,7 +1560,8 @@ 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->log, &conn->send_array, real_data, real_length, &rtt_calc_time, rtt_time); +        int requested = handle_request_packet(c->mono_time, c->log, &conn->send_array, real_data, real_length, &rtt_calc_time, +                                              rtt_time);          if (requested == -1) {              return -1; @@ -1595,7 +1614,7 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const      }      if (rtt_calc_time != 0) { -        uint64_t rtt_time = current_time_monotonic() - rtt_calc_time; +        uint64_t rtt_time = current_time_monotonic(c->mono_time) - rtt_calc_time;          if (rtt_time < conn->rtt_time) {              conn->rtt_time = rtt_time; @@ -1841,9 +1860,9 @@ static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id,          }          if (net_family_is_ipv4(source.ip.family)) { -            conn->direct_lastrecv_timev4 = unix_time(); +            conn->direct_lastrecv_timev4 = mono_time_get(c->mono_time);          } else { -            conn->direct_lastrecv_timev6 = unix_time(); +            conn->direct_lastrecv_timev6 = mono_time_get(c->mono_time);          }          return 0; @@ -2069,7 +2088,7 @@ int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port,          return -1;      } -    const uint64_t direct_lastrecv_time = connected ? unix_time() : 0; +    const uint64_t direct_lastrecv_time = connected ? mono_time_get(c->mono_time) : 0;      if (net_family_is_ipv4(ip_port.ip.family)) {          conn->direct_lastrecv_timev4 = direct_lastrecv_time; @@ -2409,9 +2428,9 @@ 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)) { -        conn->direct_lastrecv_timev4 = unix_time(); +        conn->direct_lastrecv_timev4 = mono_time_get(c->mono_time);      } else { -        conn->direct_lastrecv_timev6 = unix_time(); +        conn->direct_lastrecv_timev6 = mono_time_get(c->mono_time);      }      pthread_mutex_unlock(&conn->mutex); @@ -2438,7 +2457,7 @@ static int udp_handle_packet(void *object, IP_Port source, const uint8_t *packet  static void send_crypto_packets(Net_Crypto *c)  { -    const uint64_t temp_time = current_time_monotonic(); +    const uint64_t temp_time = current_time_monotonic(c->mono_time);      double total_send_rate = 0;      uint32_t peak_request_packet_interval = ~0; @@ -2877,7 +2896,7 @@ Crypto_Conn_State crypto_connection_status(const Net_Crypto *c, int crypt_connec      if (direct_connected) {          *direct_connected = 0; -        uint64_t current_time = unix_time(); +        const uint64_t current_time = mono_time_get(c->mono_time);          if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) {              *direct_connected = 1; @@ -2923,10 +2942,8 @@ void load_secret_key(Net_Crypto *c, const uint8_t *sk)  /* Run this to (re)initialize net_crypto.   * Sets all the global connection variables to their default values.   */ -Net_Crypto *new_net_crypto(const Logger *log, DHT *dht, TCP_Proxy_Info *proxy_info) +Net_Crypto *new_net_crypto(const Logger *log, Mono_Time *mono_time, DHT *dht, TCP_Proxy_Info *proxy_info)  { -    unix_time_update(); -      if (dht == nullptr) {          return nullptr;      } @@ -2938,8 +2955,9 @@ Net_Crypto *new_net_crypto(const Logger *log, DHT *dht, TCP_Proxy_Info *proxy_in      }      temp->log = log; +    temp->mono_time = mono_time; -    temp->tcp_c = new_tcp_connections(dht_get_self_secret_key(dht), proxy_info); +    temp->tcp_c = new_tcp_connections(mono_time, dht_get_self_secret_key(dht), proxy_info);      if (temp->tcp_c == nullptr) {          free(temp); @@ -3016,7 +3034,6 @@ uint32_t crypto_run_interval(const Net_Crypto *c)  /* Main loop. */  void do_net_crypto(Net_Crypto *c, void *userdata)  { -    unix_time_update();      kill_timedout(c, userdata);      do_tcp(c, userdata);      send_crypto_packets(c); diff --git a/protocols/Tox/libtox/src/toxcore/net_crypto.h b/protocols/Tox/libtox/src/toxcore/net_crypto.h index e40b7bfd95..45e1a05ea2 100644 --- a/protocols/Tox/libtox/src/toxcore/net_crypto.h +++ b/protocols/Tox/libtox/src/toxcore/net_crypto.h @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -21,8 +21,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef NET_CRYPTO_H -#define NET_CRYPTO_H +#ifndef C_TOXCORE_TOXCORE_NET_CRYPTO_H +#define C_TOXCORE_TOXCORE_NET_CRYPTO_H  #include "DHT.h"  #include "LAN_discovery.h" @@ -58,9 +58,9 @@  /** Messages. **/ -#define PACKET_ID_PADDING 0 /* Denotes padding */ -#define PACKET_ID_REQUEST 1 /* Used to request unreceived packets */ -#define PACKET_ID_KILL    2 /* Used to kill connection */ +#define PACKET_ID_PADDING 0 // Denotes padding +#define PACKET_ID_REQUEST 1 // Used to request unreceived packets +#define PACKET_ID_KILL    2 // Used to kill connection  #define PACKET_ID_ONLINE 24  #define PACKET_ID_OFFLINE 25 @@ -69,8 +69,8 @@  #define PACKET_ID_USERSTATUS 50  #define PACKET_ID_TYPING 51  #define PACKET_ID_MESSAGE 64 -#define PACKET_ID_ACTION 65 /* PACKET_ID_MESSAGE + MESSAGE_ACTION */ -#define PACKET_ID_MSI 69    /* Used by AV to setup calls and etc */ +#define PACKET_ID_ACTION 65 // PACKET_ID_MESSAGE + MESSAGE_ACTION +#define PACKET_ID_MSI 69    // Used by AV to setup calls and etc  #define PACKET_ID_FILE_SENDREQUEST 80  #define PACKET_ID_FILE_CONTROL 81  #define PACKET_ID_FILE_DATA 82 @@ -78,6 +78,7 @@  #define PACKET_ID_ONLINE_PACKET 97  #define PACKET_ID_DIRECT_CONFERENCE 98  #define PACKET_ID_MESSAGE_CONFERENCE 99 +#define PACKET_ID_REJOIN_CONFERENCE 100  #define PACKET_ID_LOSSY_CONFERENCE 199  /*** Crypto connections. ***/ @@ -91,7 +92,7 @@ typedef enum Crypto_Conn_State {  } Crypto_Conn_State;  /* Maximum size of receiving and sending packet buffers. */ -#define CRYPTO_PACKET_BUFFER_SIZE 32768 /* Must be a power of 2 */ +#define CRYPTO_PACKET_BUFFER_SIZE 32768 // Must be a power of 2  /* Minimum packet rate per second. */  #define CRYPTO_PACKET_MIN_RATE 4.0 @@ -120,7 +121,8 @@ typedef enum Crypto_Conn_State {  #define MAX_TCP_CONNECTIONS 64  #define MAX_TCP_RELAYS_PEER 4 -#define CRYPTO_MAX_PADDING 8 /* 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     at the dT defined in net_crypto.c */ @@ -343,7 +345,7 @@ void load_secret_key(Net_Crypto *c, const uint8_t *sk);  /* Create new instance of Net_Crypto.   *  Sets all the global connection variables to their default values.   */ -Net_Crypto *new_net_crypto(const Logger *log, DHT *dht, TCP_Proxy_Info *proxy_info); +Net_Crypto *new_net_crypto(const Logger *log, Mono_Time *mono_time, DHT *dht, TCP_Proxy_Info *proxy_info);  /* return the optimal interval in ms for running do_net_crypto.   */ diff --git a/protocols/Tox/libtox/src/toxcore/network.c b/protocols/Tox/libtox/src/toxcore/network.c index 68ca43e5aa..917556ac44 100644 --- a/protocols/Tox/libtox/src/toxcore/network.c +++ b/protocols/Tox/libtox/src/toxcore/network.c @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -346,12 +346,7 @@ bool net_family_is_tox_tcp_ipv6(Family family)      return family.value == net_family_tox_tcp_ipv6.value;  } -/* Check if socket is valid. - * - * return 1 if valid - * return 0 if not valid - */ -int sock_valid(Socket sock) +bool sock_valid(Socket sock)  {      return sock.socket != net_invalid_socket.socket;  } @@ -367,60 +362,40 @@ void kill_sock(Socket sock)  #endif  } -/* Set socket as nonblocking - * - * return 1 on success - * return 0 on failure - */ -int set_socket_nonblock(Socket sock) +bool set_socket_nonblock(Socket sock)  {  #ifdef OS_WIN32      u_long mode = 1; -    return (ioctlsocket(sock.socket, FIONBIO, &mode) == 0); +    return ioctlsocket(sock.socket, FIONBIO, &mode) == 0;  #else -    return (fcntl(sock.socket, F_SETFL, O_NONBLOCK, 1) == 0); +    return fcntl(sock.socket, F_SETFL, O_NONBLOCK, 1) == 0;  #endif  } -/* Set socket to not emit SIGPIPE - * - * return 1 on success - * return 0 on failure - */ -int set_socket_nosigpipe(Socket sock) +bool set_socket_nosigpipe(Socket sock)  {  #if defined(__APPLE__)      int set = 1;      return setsockopt(sock.socket, SOL_SOCKET, SO_NOSIGPIPE, (const char *)&set, sizeof(int)) == 0;  #else -    return 1; +    return true;  #endif  } -/* Enable SO_REUSEADDR on socket. - * - * return 1 on success - * return 0 on failure - */ -int set_socket_reuseaddr(Socket sock) +bool set_socket_reuseaddr(Socket sock)  {      int set = 1;      return setsockopt(sock.socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&set, sizeof(set)) == 0;  } -/* Set socket to dual (IPv4 + IPv6 socket) - * - * return 1 on success - * return 0 on failure - */ -int set_socket_dualstack(Socket sock) +bool set_socket_dualstack(Socket sock)  {      int ipv6only = 0;      socklen_t optsize = sizeof(ipv6only);      int res = getsockopt(sock.socket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, &optsize);      if ((res == 0) && (ipv6only == 0)) { -        return 1; +        return true;      }      ipv6only = 0; @@ -641,8 +616,6 @@ void networking_poll(Networking_Core *net, void *userdata)          return;      } -    unix_time_update(); -      IP_Port ip_port;      uint8_t data[MAX_UDP_PACKET_SIZE];      uint32_t length; @@ -975,16 +948,10 @@ void kill_networking(Networking_Core *net)  } -/* ip_equal - *  compares two IPAny structures - *  unset means unequal - * - * returns 0 when not equal or when uninitialized - */ -int ip_equal(const IP *a, const IP *b) +bool ip_equal(const IP *a, const IP *b)  {      if (!a || !b) { -        return 0; +        return false;      }      /* same family */ @@ -1002,7 +969,7 @@ int ip_equal(const IP *a, const IP *b)                     a->ip.v6.uint64[1] == b->ip.v6.uint64[1];          } -        return 0; +        return false;      }      /* different family: check on the IPv6 one if it is the IPv4 one embedded */ @@ -1020,23 +987,17 @@ int ip_equal(const IP *a, const IP *b)          }      } -    return 0; +    return false;  } -/* ipport_equal - *  compares two IPAny_Port structures - *  unset means unequal - * - * returns 0 when not equal or when uninitialized - */ -int ipport_equal(const IP_Port *a, const IP_Port *b) +bool ipport_equal(const IP_Port *a, const IP_Port *b)  {      if (!a || !b) { -        return 0; +        return false;      }      if (!a->port || (a->port != b->port)) { -        return 0; +        return false;      }      return ip_equal(&a->ip, &b->ip); @@ -1155,25 +1116,10 @@ const char *ip_ntoa(const IP *ip, char *ip_str, size_t length)      return ip_str;  } -/* - * ip_parse_addr - *  parses IP structure into an address string - * - * input - *  ip: ip of TOX_AF_INET or TOX_AF_INET6 families - *  length: length of the address buffer - *          Must be at least INET_ADDRSTRLEN for TOX_AF_INET - *          and INET6_ADDRSTRLEN for TOX_AF_INET6 - * - * output - *  address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6) - * - * returns 1 on success, 0 on failure - */ -int ip_parse_addr(const IP *ip, char *address, size_t length) +bool ip_parse_addr(const IP *ip, char *address, size_t length)  {      if (!address || !ip) { -        return 0; +        return false;      }      if (net_family_is_ipv4(ip->family)) { @@ -1186,26 +1132,13 @@ int ip_parse_addr(const IP *ip, char *address, size_t length)          return inet_ntop(make_family(ip->family), addr, address, length) != nullptr;      } -    return 0; +    return false;  } -/* - * addr_parse_ip - *  directly parses the input into an IP structure - *  tries IPv4 first, then IPv6 - * - * input - *  address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6) - * - * output - *  IP: family and the value is set on success - * - * returns 1 on success, 0 on failure - */ -int addr_parse_ip(const char *address, IP *to) +bool addr_parse_ip(const char *address, IP *to)  {      if (!address || !to) { -        return 0; +        return false;      }      struct in_addr addr4; @@ -1213,7 +1146,7 @@ int addr_parse_ip(const char *address, IP *to)      if (inet_pton(AF_INET, address, &addr4) == 1) {          to->family = net_family_ipv4;          get_ip4(&to->ip.v4, &addr4); -        return 1; +        return true;      }      struct in6_addr addr6; @@ -1221,29 +1154,12 @@ int addr_parse_ip(const char *address, IP *to)      if (inet_pton(AF_INET6, address, &addr6) == 1) {          to->family = net_family_ipv6;          get_ip6(&to->ip.v6, &addr6); -        return 1; +        return true;      } -    return 0; +    return false;  } -/* - * addr_resolve(): - *  uses getaddrinfo to resolve an address into an IP address - *  uses the first IPv4/IPv6 addresses returned by getaddrinfo - * - * input - *  address: a hostname (or something parseable to an IP address) - *  to: to.family MUST be initialized, either set to a specific IP version - *     (TOX_AF_INET/TOX_AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both - *     IP versions are acceptable - *  extra can be NULL and is only set in special circumstances, see returns - * - * returns in *to a valid IPAny (v4/v6), - *     prefers v6 if ip.family was AF_UNSPEC and both available - * returns in *extra an IPv4 address, if family was AF_UNSPEC and *to is TOX_AF_INET6 - * returns 0 on failure, TOX_ADDR_RESOLVE_* on success. - */  int addr_resolve(const char *address, IP *to, IP *extra)  {      if (!address || !to) { @@ -1334,30 +1250,15 @@ int addr_resolve(const char *address, IP *to, IP *extra)      return result;  } -/* - * addr_resolve_or_parse_ip - *  resolves string into an IP address - * - *  address: a hostname (or something parseable to an IP address) - *  to: to.family MUST be initialized, either set to a specific IP version - *     (TOX_AF_INET/TOX_AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both - *     IP versions are acceptable - *  extra can be NULL and is only set in special circumstances, see returns - * - *  returns in *tro a matching address (IPv6 or IPv4) - *  returns in *extra, if not NULL, an IPv4 address, if to->family was AF_UNSPEC - *  returns 1 on success - *  returns 0 on failure - */ -int addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra) +bool addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra)  {      if (!addr_resolve(address, to, extra)) {          if (!addr_parse_ip(address, to)) { -            return 0; +            return false;          }      } -    return 1; +    return true;  }  int net_connect(Socket sock, IP_Port ip_port) @@ -1468,10 +1369,7 @@ void net_freeipport(IP_Port *ip_ports)      free(ip_ports);  } -/* return 1 on success - * return 0 on failure - */ -int bind_to_port(Socket sock, Family family, uint16_t port) +bool bind_to_port(Socket sock, Family family, uint16_t port)  {      struct sockaddr_storage addr = {0};      size_t addrsize; @@ -1489,7 +1387,7 @@ int bind_to_port(Socket sock, Family family, uint16_t port)          addr6->sin6_family = AF_INET6;          addr6->sin6_port = net_htons(port);      } else { -        return 0; +        return false;      }      return bind(sock.socket, (struct sockaddr *)&addr, addrsize) == 0; diff --git a/protocols/Tox/libtox/src/toxcore/network.h b/protocols/Tox/libtox/src/toxcore/network.h index 276896b6b7..a1d838422c 100644 --- a/protocols/Tox/libtox/src/toxcore/network.h +++ b/protocols/Tox/libtox/src/toxcore/network.h @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -21,8 +21,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef NETWORK_H -#define NETWORK_H +#ifndef C_TOXCORE_TOXCORE_NETWORK_H +#define C_TOXCORE_TOXCORE_NETWORK_H  #include "logger.h" @@ -64,12 +64,12 @@ typedef struct Socket {  Socket net_socket(Family domain, int type, int protocol); -/* Check if socket is valid. +/** + * Check if socket is valid.   * - * return 1 if valid - * return 0 if not valid + * @return true if valid, false otherwise.   */ -int sock_valid(Socket sock); +bool sock_valid(Socket sock);  extern const Socket net_invalid_socket; @@ -235,53 +235,49 @@ bool ipv6_ipv4_in_v6(IP6 a);  #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); -/* - * ip_parse_addr - *  parses IP structure into an address string +/** + * Parses IP structure into an address string.   * - * input - *  ip: ip of TOX_AF_INET or TOX_AF_INET6 families - *  length: length of the address buffer - *          Must be at least TOX_INET_ADDRSTRLEN for TOX_AF_INET - *          and TOX_INET6_ADDRSTRLEN for TOX_AF_INET6 + * @param ip IP of TOX_AF_INET or TOX_AF_INET6 families. + * @param length length of the address buffer. + *   Must be at least TOX_INET_ADDRSTRLEN for TOX_AF_INET + *   and TOX_INET6_ADDRSTRLEN for TOX_AF_INET6   * - * output - *  address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6) + * @param address dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6).   * - * returns 1 on success, 0 on failure + * @return true on success, false on failure.   */ -int ip_parse_addr(const IP *ip, char *address, size_t length); +bool ip_parse_addr(const IP *ip, char *address, size_t length); -/* - * addr_parse_ip - *  directly parses the input into an IP structure - *  tries IPv4 first, then IPv6 +/** + * Directly parses the input into an IP structure.   * - * input - *  address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6) + * Tries IPv4 first, then IPv6.   * - * output - *  IP: family and the value is set on success + * @param address dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6). + * @param to family and the value is set on success.   * - * returns 1 on success, 0 on failure + * @return true on success, false on failure.   */ -int addr_parse_ip(const char *address, IP *to); +bool addr_parse_ip(const char *address, IP *to); -/* ip_equal - *  compares two IPAny structures - *  unset means unequal +/** + * Compares two IPAny structures.   * - * returns 0 when not equal or when uninitialized + * Unset means unequal. + * + * @return false when not equal or when uninitialized.   */ -int ip_equal(const IP *a, const IP *b); +bool ip_equal(const IP *a, const IP *b); -/* ipport_equal - *  compares two IPAny_Port structures - *  unset means unequal +/** + * Compares two IPAny_Port structures. + * + * Unset means unequal.   * - * returns 0 when not equal or when uninitialized + * @return false when not equal or when uninitialized.   */ -int ipport_equal(const IP_Port *a, const IP_Port *b); +bool ipport_equal(const IP_Port *a, const IP_Port *b);  /* nulls out ip */  void ip_reset(IP *ip); @@ -296,41 +292,40 @@ void ip_copy(IP *target, const IP *source);  /* copies an ip_port structure */  void ipport_copy(IP_Port *target, const IP_Port *source); -/* - * addr_resolve(): - *  uses getaddrinfo to resolve an address into an IP address - *  uses the first IPv4/IPv6 addresses returned by getaddrinfo +/** + * Uses getaddrinfo to resolve an address into an IP address.   * - * input - *  address: a hostname (or something parseable to an IP address) - *  to: to.family MUST be initialized, either set to a specific IP version + * Uses the first IPv4/IPv6 addresses returned by getaddrinfo. + * + * @param address a hostname (or something parseable to an IP address) + * @param to to.family MUST be initialized, either set to a specific IP version   *     (TOX_AF_INET/TOX_AF_INET6) or to the unspecified TOX_AF_UNSPEC (= 0), if both   *     IP versions are acceptable - *  extra can be NULL and is only set in special circumstances, see returns + * @param extra can be NULL and is only set in special circumstances, see returns   *   * returns in *to a valid IPAny (v4/v6),   *     prefers v6 if ip.family was TOX_AF_UNSPEC and both available   * returns in *extra an IPv4 address, if family was TOX_AF_UNSPEC and *to is TOX_AF_INET6 - * returns 0 on failure + * + * @return 0 on failure, TOX_ADDR_RESOLVE_* on success.   */  int addr_resolve(const char *address, IP *to, IP *extra); -/* - * addr_resolve_or_parse_ip - *  resolves string into an IP address +/** + * Resolves string into an IP address   * - *  address: a hostname (or something parseable to an IP address) - *  to: to.family MUST be initialized, either set to a specific IP version + * @param address a hostname (or something parseable to an IP address) + * @param to to.family MUST be initialized, either set to a specific IP version   *     (TOX_AF_INET/TOX_AF_INET6) or to the unspecified TOX_AF_UNSPEC (= 0), if both   *     IP versions are acceptable - *  extra can be NULL and is only set in special circumstances, see returns + * @param extra can be NULL and is only set in special circumstances, see returns + * + * returns in *tro a matching address (IPv6 or IPv4) + * returns in *extra, if not NULL, an IPv4 address, if to->family was TOX_AF_UNSPEC   * - *  returns in *tro a matching address (IPv6 or IPv4) - *  returns in *extra, if not NULL, an IPv4 address, if to->family was TOX_AF_UNSPEC - *  returns 1 on success - *  returns 0 on failure + * @return true on success, false on failure   */ -int addr_resolve_or_parse_ip(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.   * Packet data is put into data. @@ -354,33 +349,33 @@ int networking_at_startup(void);   */  void kill_sock(Socket sock); -/* Set socket as nonblocking +/** + * Set socket as nonblocking   * - * return 1 on success - * return 0 on failure + * @return true on success, false on failure.   */ -int set_socket_nonblock(Socket sock); +bool set_socket_nonblock(Socket sock); -/* Set socket to not emit SIGPIPE +/** + * Set socket to not emit SIGPIPE   * - * return 1 on success - * return 0 on failure + * @return true on success, false on failure.   */ -int set_socket_nosigpipe(Socket sock); +bool set_socket_nosigpipe(Socket sock); -/* Enable SO_REUSEADDR on socket. +/** + * Enable SO_REUSEADDR on socket.   * - * return 1 on success - * return 0 on failure + * @return true on success, false on failure.   */ -int set_socket_reuseaddr(Socket sock); +bool set_socket_reuseaddr(Socket sock); -/* Set socket to dual (IPv4 + IPv6 socket) +/** + * Set socket to dual (IPv4 + IPv6 socket)   * - * return 1 on success - * return 0 on failure + * @return true on success, false on failure.   */ -int set_socket_dualstack(Socket sock); +bool set_socket_dualstack(Socket sock);  /* Basic network functions: */ @@ -413,10 +408,10 @@ int32_t net_getipport(const char *node, IP_Port **res, int tox_type);   */  void net_freeipport(IP_Port *ip_ports); -/* return 1 on success - * return 0 on failure +/** + * @return true on success, false on failure.   */ -int bind_to_port(Socket sock, Family family, uint16_t port); +bool bind_to_port(Socket sock, Family family, uint16_t port);  /* Get the last networking error code.   * diff --git a/protocols/Tox/libtox/src/toxcore/onion.c b/protocols/Tox/libtox/src/toxcore/onion.c index 5ba716fd6d..f1873992d5 100644 --- a/protocols/Tox/libtox/src/toxcore/onion.c +++ b/protocols/Tox/libtox/src/toxcore/onion.c @@ -46,9 +46,9 @@  #define KEY_REFRESH_INTERVAL (2 * 60 * 60)  static void change_symmetric_key(Onion *onion)  { -    if (is_timeout(onion->timestamp, KEY_REFRESH_INTERVAL)) { +    if (mono_time_is_timeout(onion->mono_time, onion->timestamp, KEY_REFRESH_INTERVAL)) {          new_symmetric_key(onion->secret_symmetric_key); -        onion->timestamp = unix_time(); +        onion->timestamp = mono_time_get(onion->mono_time);      }  } @@ -114,7 +114,7 @@ static int ipport_unpack(IP_Port *target, const uint8_t *data, unsigned int data   *   * Create a new onion path out of nodes (nodes is a list of ONION_PATH_LENGTH nodes)   * - * new_path must be an empty memory location of atleast Onion_Path size. + * new_path must be an empty memory location of at least Onion_Path size.   *   * return -1 on failure.   * return 0 on success. @@ -343,7 +343,8 @@ static int handle_send_initial(void *object, IP_Port source, const uint8_t *pack      uint8_t plain[ONION_MAX_PACKET_SIZE];      uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; -    get_shared_key(&onion->shared_keys_1, shared_key, dht_get_self_secret_key(onion->dht), packet + 1 + CRYPTO_NONCE_SIZE); +    get_shared_key(onion->mono_time, &onion->shared_keys_1, shared_key, dht_get_self_secret_key(onion->dht), +                   packet + 1 + CRYPTO_NONCE_SIZE);      int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,                                       length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE), plain); @@ -412,7 +413,8 @@ static int handle_send_1(void *object, IP_Port source, const uint8_t *packet, ui      uint8_t plain[ONION_MAX_PACKET_SIZE];      uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; -    get_shared_key(&onion->shared_keys_2, shared_key, dht_get_self_secret_key(onion->dht), packet + 1 + CRYPTO_NONCE_SIZE); +    get_shared_key(onion->mono_time, &onion->shared_keys_2, shared_key, dht_get_self_secret_key(onion->dht), +                   packet + 1 + CRYPTO_NONCE_SIZE);      int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,                                       length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1), plain); @@ -468,7 +470,8 @@ static int handle_send_2(void *object, IP_Port source, const uint8_t *packet, ui      uint8_t plain[ONION_MAX_PACKET_SIZE];      uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; -    get_shared_key(&onion->shared_keys_3, shared_key, dht_get_self_secret_key(onion->dht), packet + 1 + CRYPTO_NONCE_SIZE); +    get_shared_key(onion->mono_time, &onion->shared_keys_3, shared_key, dht_get_self_secret_key(onion->dht), +                   packet + 1 + CRYPTO_NONCE_SIZE);      int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,                                       length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2), plain); @@ -662,7 +665,7 @@ void set_callback_handle_recv_1(Onion *onion, onion_recv_1_cb *function, void *o      onion->callback_object = object;  } -Onion *new_onion(DHT *dht) +Onion *new_onion(Mono_Time *mono_time, DHT *dht)  {      if (dht == nullptr) {          return nullptr; @@ -676,8 +679,9 @@ Onion *new_onion(DHT *dht)      onion->dht = dht;      onion->net = dht_get_net(dht); +    onion->mono_time = mono_time;      new_symmetric_key(onion->secret_symmetric_key); -    onion->timestamp = unix_time(); +    onion->timestamp = mono_time_get(onion->mono_time);      networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_INITIAL, &handle_send_initial, onion);      networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, &handle_send_1, onion); diff --git a/protocols/Tox/libtox/src/toxcore/onion.h b/protocols/Tox/libtox/src/toxcore/onion.h index 0e025a1ceb..20cd1e5c2f 100644 --- a/protocols/Tox/libtox/src/toxcore/onion.h +++ b/protocols/Tox/libtox/src/toxcore/onion.h @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -21,15 +21,17 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef ONION_H -#define ONION_H +#ifndef C_TOXCORE_TOXCORE_ONION_H +#define C_TOXCORE_TOXCORE_ONION_H  #include "DHT.h" +#include "mono_time.h"  typedef int onion_recv_1_cb(void *object, IP_Port dest, const uint8_t *data, uint16_t length);  typedef struct Onion { -    DHT     *dht; +    Mono_Time *mono_time; +    DHT *dht;      Networking_Core *net;      uint8_t secret_symmetric_key[CRYPTO_SYMMETRIC_KEY_SIZE];      uint64_t timestamp; @@ -83,7 +85,7 @@ typedef struct Onion_Path {   *   * Create a new onion path out of nodes (nodes is a list of ONION_PATH_LENGTH nodes)   * - * new_path must be an empty memory location of atleast Onion_Path size. + * new_path must be an empty memory location of at least Onion_Path size.   *   * return -1 on failure.   * return 0 on success. @@ -158,7 +160,7 @@ int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, IP_Port   */  void set_callback_handle_recv_1(Onion *onion, onion_recv_1_cb *function, void *object); -Onion *new_onion(DHT *dht); +Onion *new_onion(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 d368facee8..f38772ddf1 100644 --- a/protocols/Tox/libtox/src/toxcore/onion_announce.c +++ b/protocols/Tox/libtox/src/toxcore/onion_announce.c @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -50,6 +50,7 @@ typedef struct Onion_Announce_Entry {  } Onion_Announce_Entry;  struct Onion_Announce { +    Mono_Time *mono_time;      DHT     *dht;      Networking_Core *net;      Onion_Announce_Entry entries[ONION_ANNOUNCE_MAX_ENTRIES]; @@ -256,7 +257,7 @@ 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) { -        if (!is_timeout(onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT) +        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;          } @@ -266,6 +267,7 @@ static int in_entries(const Onion_Announce *onion_a, const uint8_t *public_key)  }  typedef struct Cmp_data { +    const Mono_Time *mono_time;      const uint8_t *base_public_key;      Onion_Announce_Entry entry;  } Cmp_data; @@ -279,8 +281,8 @@ static int cmp_entry(const void *a, const void *b)      Onion_Announce_Entry entry2 = cmp2.entry;      const uint8_t *cmp_public_key = cmp1.base_public_key; -    int t1 = is_timeout(entry1.time, ONION_ANNOUNCE_TIMEOUT); -    int t2 = is_timeout(entry2.time, ONION_ANNOUNCE_TIMEOUT); +    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);      if (t1 && t2) {          return 0; @@ -307,13 +309,15 @@ static int cmp_entry(const void *a, const void *b)      return 0;  } -static void sort_onion_announce_list(Onion_Announce_Entry *list, unsigned int length, const uint8_t *comp_public_key) +static void sort_onion_announce_list(Onion_Announce_Entry *list, unsigned int length, const Mono_Time *mono_time, +                                     const uint8_t *comp_public_key)  {      // 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);      for (uint32_t i = 0; i < length; ++i) { +        cmp_list[i].mono_time = mono_time;          cmp_list[i].base_public_key = comp_public_key;          cmp_list[i].entry = list[i];      } @@ -338,7 +342,7 @@ static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, const ui      if (pos == -1) {          for (unsigned i = 0; i < ONION_ANNOUNCE_MAX_ENTRIES; ++i) { -            if (is_timeout(onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT)) { +            if (mono_time_is_timeout(onion_a->mono_time, onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT)) {                  pos = i;              }          } @@ -358,9 +362,10 @@ static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, const ui      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 = unix_time(); +    onion_a->entries[pos].time = mono_time_get(onion_a->mono_time); -    sort_onion_announce_list(onion_a->entries, ONION_ANNOUNCE_MAX_ENTRIES, dht_get_self_public_key(onion_a->dht)); +    sort_onion_announce_list(onion_a->entries, ONION_ANNOUNCE_MAX_ENTRIES, onion_a->mono_time, +                             dht_get_self_public_key(onion_a->dht));      return in_entries(onion_a, public_key);  } @@ -374,7 +379,8 @@ static int handle_announce_request(void *object, IP_Port source, const uint8_t *      const uint8_t *packet_public_key = packet + 1 + CRYPTO_NONCE_SIZE;      uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; -    get_shared_key(&onion_a->shared_keys_recv, shared_key, dht_get_self_secret_key(onion_a->dht), packet_public_key); +    get_shared_key(onion_a->mono_time, &onion_a->shared_keys_recv, shared_key, dht_get_self_secret_key(onion_a->dht), +                   packet_public_key);      uint8_t plain[ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE +                                       ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; @@ -387,10 +393,10 @@ static int handle_announce_request(void *object, IP_Port source, const uint8_t *      }      uint8_t ping_id1[ONION_PING_ID_SIZE]; -    generate_ping_id(onion_a, unix_time(), packet_public_key, source, ping_id1); +    generate_ping_id(onion_a, mono_time_get(onion_a->mono_time), packet_public_key, source, ping_id1);      uint8_t ping_id2[ONION_PING_ID_SIZE]; -    generate_ping_id(onion_a, unix_time() + PING_ID_TIMEOUT, packet_public_key, source, ping_id2); +    generate_ping_id(onion_a, mono_time_get(onion_a->mono_time) + PING_ID_TIMEOUT, packet_public_key, source, ping_id2);      int index; @@ -406,8 +412,8 @@ 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) == 0, 1); +    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);      uint8_t nonce[CRYPTO_NONCE_SIZE];      random_nonce(nonce); @@ -493,7 +499,7 @@ static int handle_data_request(void *object, IP_Port source, const uint8_t *pack      return 0;  } -Onion_Announce *new_onion_announce(DHT *dht) +Onion_Announce *new_onion_announce(Mono_Time *mono_time, DHT *dht)  {      if (dht == nullptr) {          return nullptr; @@ -505,6 +511,7 @@ Onion_Announce *new_onion_announce(DHT *dht)          return nullptr;      } +    onion_a->mono_time = mono_time;      onion_a->dht = dht;      onion_a->net = dht_get_net(dht);      new_symmetric_key(onion_a->secret_bytes); diff --git a/protocols/Tox/libtox/src/toxcore/onion_announce.h b/protocols/Tox/libtox/src/toxcore/onion_announce.h index 84e76a38a1..2eb5051b1f 100644 --- a/protocols/Tox/libtox/src/toxcore/onion_announce.h +++ b/protocols/Tox/libtox/src/toxcore/onion_announce.h @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -21,8 +21,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef ONION_ANNOUNCE_H -#define ONION_ANNOUNCE_H +#ifndef C_TOXCORE_TOXCORE_ONION_ANNOUNCE_H +#define C_TOXCORE_TOXCORE_ONION_ANNOUNCE_H  #include "onion.h" @@ -120,7 +120,7 @@ int send_data_request(Networking_Core *net, const Onion_Path *path, IP_Port dest                        const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length); -Onion_Announce *new_onion_announce(DHT *dht); +Onion_Announce *new_onion_announce(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 819bd23fae..1c3b34dabf 100644 --- a/protocols/Tox/libtox/src/toxcore/onion_client.c +++ b/protocols/Tox/libtox/src/toxcore/onion_client.c @@ -4,7 +4,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -84,8 +84,6 @@ typedef struct Onion_Friend {      uint8_t temp_public_key[CRYPTO_PUBLIC_KEY_SIZE];      uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE]; -    uint64_t last_reported_announced; -      uint64_t last_dht_pk_onion_sent;      uint64_t last_dht_pk_dht_sent; @@ -113,6 +111,8 @@ typedef struct Onion_Data_Handler {  } Onion_Data_Handler;  struct Onion_Client { +    Mono_Time *mono_time; +      DHT     *dht;      Net_Crypto *c;      Networking_Core *net; @@ -316,16 +316,16 @@ static uint16_t random_nodes_path_onion(const Onion_Client *onion_c, Node_format   * 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 Onion_Client_Paths *onion_paths, const Node_format *nodes) +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) { -        if (is_timeout(onion_paths->last_path_success[i], ONION_PATH_TIMEOUT)) { +        if (mono_time_is_timeout(mono_time, onion_paths->last_path_success[i], ONION_PATH_TIMEOUT)) {              continue;          } -        if (is_timeout(onion_paths->path_creation_time[i], ONION_PATH_MAX_LIFETIME)) { +        if (mono_time_is_timeout(mono_time, onion_paths->path_creation_time[i], ONION_PATH_MAX_LIFETIME)) {              continue;          } @@ -339,7 +339,7 @@ static int is_path_used(const Onion_Client_Paths *onion_paths, const Node_format  }  /* is path timed out */ -static bool path_timed_out(Onion_Client_Paths *onion_paths, uint32_t pathnum) +static bool path_timed_out(const Mono_Time *mono_time, Onion_Client_Paths *onion_paths, uint32_t pathnum)  {      pathnum = pathnum % NUMBER_ONION_PATHS; @@ -347,16 +347,16 @@ static bool path_timed_out(Onion_Client_Paths *onion_paths, uint32_t pathnum)      uint64_t timeout = is_new ? ONION_PATH_FIRST_TIMEOUT : ONION_PATH_TIMEOUT;      return ((onion_paths->last_path_used_times[pathnum] >= ONION_PATH_MAX_NO_RESPONSE_USES -             && is_timeout(onion_paths->last_path_used[pathnum], timeout)) -            || is_timeout(onion_paths->path_creation_time[pathnum], ONION_PATH_MAX_LIFETIME)); +             && mono_time_is_timeout(mono_time, onion_paths->last_path_used[pathnum], timeout)) +            || mono_time_is_timeout(mono_time, onion_paths->path_creation_time[pathnum], ONION_PATH_MAX_LIFETIME));  }  /* should node be considered to have timed out */ -static bool onion_node_timed_out(const Onion_Node *node) +static bool onion_node_timed_out(const Onion_Node *node, const Mono_Time *mono_time)  {      return (node->timestamp == 0              || (node->unsuccessful_pings >= ONION_NODE_MAX_PINGS -                && is_timeout(node->last_pinged, ONION_NODE_TIMEOUT))); +                && 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) @@ -376,21 +376,21 @@ static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_pa          pathnum = pathnum % NUMBER_ONION_PATHS;      } -    if (path_timed_out(onion_paths, pathnum)) { +    if (path_timed_out(onion_c->mono_time, onion_paths, pathnum)) {          Node_format nodes[ONION_PATH_LENGTH];          if (random_nodes_path_onion(onion_c, nodes, ONION_PATH_LENGTH) != ONION_PATH_LENGTH) {              return -1;          } -        int n = is_path_used(onion_paths, nodes); +        int n = is_path_used(onion_c->mono_time, onion_paths, nodes);          if (n == -1) {              if (create_onion_path(onion_c->dht, &onion_paths->paths[pathnum], nodes) == -1) {                  return -1;              } -            onion_paths->path_creation_time[pathnum] = unix_time(); +            onion_paths->path_creation_time[pathnum] = mono_time_get(onion_c->mono_time);              onion_paths->last_path_success[pathnum] = onion_paths->path_creation_time[pathnum];              onion_paths->last_path_used_times[pathnum] = ONION_PATH_MAX_NO_RESPONSE_USES / 2; @@ -406,7 +406,7 @@ static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_pa      }      if (onion_paths->last_path_used_times[pathnum] < ONION_PATH_MAX_NO_RESPONSE_USES) { -        onion_paths->last_path_used[pathnum] = unix_time(); +        onion_paths->last_path_used[pathnum] = mono_time_get(onion_c->mono_time);      }      ++onion_paths->last_path_used_times[pathnum]; @@ -415,9 +415,9 @@ static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_pa  }  /* Does path with path_num exist. */ -static bool path_exists(Onion_Client_Paths *onion_paths, uint32_t path_num) +static bool path_exists(const Mono_Time *mono_time, Onion_Client_Paths *onion_paths, uint32_t path_num)  { -    if (path_timed_out(onion_paths, path_num)) { +    if (path_timed_out(mono_time, onion_paths, path_num)) {          return 0;      } @@ -442,7 +442,7 @@ static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, uint32_t      }      if (onion_paths->paths[path_num % NUMBER_ONION_PATHS].path_num == path_num) { -        onion_paths->last_path_success[path_num % NUMBER_ONION_PATHS] = unix_time(); +        onion_paths->last_path_success[path_num % NUMBER_ONION_PATHS] = mono_time_get(onion_c->mono_time);          onion_paths->last_path_used_times[path_num % NUMBER_ONION_PATHS] = 0;          Node_format nodes[ONION_PATH_LENGTH]; @@ -521,7 +521,7 @@ static int new_sendback(Onion_Client *onion_c, uint32_t num, const uint8_t *publ      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 + sizeof(IP_Port), &path_num, sizeof(uint32_t)); -    *sendback = ping_array_add(onion_c->announce_ping_array, data, sizeof(data)); +    *sendback = ping_array_add(onion_c->announce_ping_array, onion_c->mono_time, data, sizeof(data));      if (*sendback == 0) {          return -1; @@ -547,7 +547,7 @@ static uint32_t check_sendback(Onion_Client *onion_c, const uint8_t *sendback, u      memcpy(&sback, sendback, sizeof(uint64_t));      uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)]; -    if (ping_array_check(onion_c->announce_ping_array, data, sizeof(data), sback) != sizeof(data)) { +    if (ping_array_check(onion_c->announce_ping_array, onion_c->mono_time, data, sizeof(data), sback) != sizeof(data)) {          return ~0;      } @@ -611,6 +611,7 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_  }  typedef struct Onion_Client_Cmp_data { +    const Mono_Time *mono_time;      const uint8_t *base_public_key;      Onion_Node entry;  } Onion_Client_Cmp_data; @@ -624,8 +625,8 @@ static int onion_client_cmp_entry(const void *a, const void *b)      Onion_Node entry2 = cmp2.entry;      const uint8_t *cmp_public_key = cmp1.base_public_key; -    int t1 = onion_node_timed_out(&entry1); -    int t2 = onion_node_timed_out(&entry2); +    int t1 = onion_node_timed_out(&entry1, cmp1.mono_time); +    int t2 = onion_node_timed_out(&entry2, cmp2.mono_time);      if (t1 && t2) {          return 0; @@ -652,13 +653,15 @@ static int onion_client_cmp_entry(const void *a, const void *b)      return 0;  } -static void sort_onion_node_list(Onion_Node *list, unsigned int length, const uint8_t *comp_public_key) +static void sort_onion_node_list(Onion_Node *list, unsigned int length, const Mono_Time *mono_time, +                                 const uint8_t *comp_public_key)  {      // 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);      for (uint32_t i = 0; i < length; ++i) { +        cmp_list[i].mono_time = mono_time;          cmp_list[i].base_public_key = comp_public_key;          cmp_list[i].entry = list[i];      } @@ -695,7 +698,7 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t          }          if (is_stored == 1) { -            onion_c->friends_list[num - 1].last_reported_announced = unix_time(); +            onion_c->friends_list[num - 1].last_seen = mono_time_get(onion_c->mono_time);          }          list_nodes = onion_c->friends_list[num - 1].clients_list; @@ -703,12 +706,12 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t          list_length = MAX_ONION_CLIENTS;      } -    sort_onion_node_list(list_nodes, list_length, reference_id); +    sort_onion_node_list(list_nodes, list_length, onion_c->mono_time, reference_id);      int index = -1, stored = 0;      unsigned int i; -    if (onion_node_timed_out(&list_nodes[0]) +    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;      } @@ -738,24 +741,25 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t      }      list_nodes[index].is_stored = is_stored; -    list_nodes[index].timestamp = unix_time(); +    list_nodes[index].timestamp = mono_time_get(onion_c->mono_time);      list_nodes[index].unsuccessful_pings = 0;      if (!stored) {          list_nodes[index].last_pinged = 0; -        list_nodes[index].added_time = unix_time(); +        list_nodes[index].added_time = mono_time_get(onion_c->mono_time);      }      list_nodes[index].path_used = path_used;      return 0;  } -static int good_to_ping(Last_Pinged *last_pinged, uint8_t *last_pinged_index, const uint8_t *public_key) +static int good_to_ping(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) { -        if (!is_timeout(last_pinged[i].timestamp, MIN_NODE_PING_TIME)) { +        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;              } @@ -763,7 +767,7 @@ static int good_to_ping(Last_Pinged *last_pinged, uint8_t *last_pinged_index, co      }      memcpy(last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); -    last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].timestamp = unix_time(); +    last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].timestamp = mono_time_get(mono_time);      ++*last_pinged_index;      return 1;  } @@ -800,21 +804,21 @@ 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;      } -    unsigned int i, j; -    int lan_ips_accepted = (ip_is_lan(source.ip) == 0); - -    for (i = 0; i < num_nodes; ++i) { +    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) == 0) { +            if (ip_is_lan(nodes[i].ip_port.ip)) {                  continue;              }          } -        if (onion_node_timed_out(&list_nodes[0]) +        if (onion_node_timed_out(&list_nodes[0], onion_c->mono_time)                  || id_closest(reference_id, list_nodes[0].public_key, nodes[i].public_key) == 2 -                || onion_node_timed_out(&list_nodes[1]) +                || onion_node_timed_out(&list_nodes[1], onion_c->mono_time)                  || id_closest(reference_id, list_nodes[1].public_key, nodes[i].public_key) == 2) { +            uint32_t j; +              /* check if node is already in list. */              for (j = 0; j < list_length; ++j) {                  if (public_key_cmp(list_nodes[j].public_key, nodes[i].public_key) == 0) { @@ -822,7 +826,7 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_for                  }              } -            if (j == list_length && good_to_ping(last_pinged, last_pinged_index, nodes[i].public_key)) { +            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, ~0);              }          } @@ -894,7 +898,7 @@ static int handle_announce_response(void *object, IP_Port source, const uint8_t      }      // TODO(irungentoo): LAN vs non LAN ips?, if we are connected only to LAN, are we offline? -    onion_c->last_packet_recv = unix_time(); +    onion_c->last_packet_recv = mono_time_get(onion_c->mono_time);      return 0;  } @@ -975,7 +979,7 @@ static int handle_dhtpk_announce(void *object, const uint8_t *source_pubkey, con      }      onion_set_friend_DHT_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t)); -    onion_c->friends_list[friend_num].last_seen = unix_time(); +    onion_c->friends_list[friend_num].last_seen = mono_time_get(onion_c->mono_time);      uint16_t len_nodes = length - DHTPK_DATA_MIN_LENGTH; @@ -1054,7 +1058,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data,      Onion_Node *list_nodes = onion_c->friends_list[friend_num].clients_list;      for (i = 0; i < MAX_ONION_CLIENTS; ++i) { -        if (onion_node_timed_out(&list_nodes[i])) { +        if (onion_node_timed_out(&list_nodes[i], onion_c->mono_time)) {              continue;          } @@ -1196,7 +1200,7 @@ static int send_dhtpk_announce(Onion_Client *onion_c, uint16_t friend_num, uint8      uint8_t data[DHTPK_DATA_MAX_LENGTH];      data[0] = ONION_DATA_DHTPK; -    uint64_t no_replay = unix_time(); +    uint64_t no_replay = mono_time_get(onion_c->mono_time);      host_to_net((uint8_t *)&no_replay, sizeof(no_replay));      memcpy(data + 1, &no_replay, sizeof(no_replay));      memcpy(data + 1 + sizeof(uint64_t), dht_get_self_public_key(onion_c->dht), CRYPTO_PUBLIC_KEY_SIZE); @@ -1397,7 +1401,7 @@ int onion_dht_pk_callback(Onion_Client *onion_c, int friend_num,      return 0;  } -/* Set a friends DHT public key. +/* Set a friend's DHT public key.   *   * return -1 on failure.   * return 0 on success. @@ -1416,11 +1420,9 @@ int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uin          if (public_key_cmp(dht_key, onion_c->friends_list[friend_num].dht_public_key) == 0) {              return -1;          } - -        onion_c->friends_list[friend_num].know_dht_public_key = 0;      } -    onion_c->friends_list[friend_num].last_seen = unix_time(); +    onion_c->friends_list[friend_num].last_seen = mono_time_get(onion_c->mono_time);      onion_c->friends_list[friend_num].know_dht_public_key = 1;      memcpy(onion_c->friends_list[friend_num].dht_public_key, dht_key, CRYPTO_PUBLIC_KEY_SIZE); @@ -1485,7 +1487,7 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on      }      if (is_online == 0 && onion_c->friends_list[friend_num].is_online == 1) { -        onion_c->friends_list[friend_num].last_seen = unix_time(); +        onion_c->friends_list[friend_num].last_seen = mono_time_get(onion_c->mono_time);      }      onion_c->friends_list[friend_num].is_online = is_online; @@ -1547,11 +1549,12 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)      if (onion_c->friends_list[friendnum].run_count < RUN_COUNT_FRIEND_ANNOUNCE_BEGINNING) {          interval = ANNOUNCE_FRIEND_BEGINNING;      } else { -        if (onion_c->friends_list[friendnum].last_reported_announced == 0) { -            onion_c->friends_list[friendnum].last_reported_announced = unix_time(); +        if (onion_c->friends_list[friendnum].last_seen == 0) { +            onion_c->friends_list[friendnum].last_seen = mono_time_get(onion_c->mono_time);          } -        uint64_t backoff_interval = (unix_time() - onion_c->friends_list[friendnum].last_reported_announced) +        uint64_t backoff_interval = (mono_time_get(onion_c->mono_time) - +                                     onion_c->friends_list[friendnum].last_seen)                                      / ONION_FRIEND_BACKOFF_FACTOR;          if (backoff_interval > ONION_FRIEND_MAX_PING_INTERVAL) { @@ -1572,15 +1575,15 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)          bool ping_random = true;          for (unsigned i = 0; i < MAX_ONION_CLIENTS; ++i) { -            if (!(is_timeout(list_nodes[i].timestamp, interval / MAX_ONION_CLIENTS) -                    && is_timeout(list_nodes[i].last_pinged, ONION_NODE_PING_INTERVAL))) { +            if (!(mono_time_is_timeout(onion_c->mono_time, list_nodes[i].timestamp, interval / MAX_ONION_CLIENTS) +                    && mono_time_is_timeout(onion_c->mono_time, list_nodes[i].last_pinged, ONION_NODE_PING_INTERVAL))) {                  ping_random = false;                  break;              }          }          for (unsigned i = 0; i < MAX_ONION_CLIENTS; ++i) { -            if (onion_node_timed_out(&list_nodes[i])) { +            if (onion_node_timed_out(&list_nodes[i], onion_c->mono_time)) {                  continue;              } @@ -1588,7 +1591,7 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)              if (list_nodes[i].last_pinged == 0) { -                list_nodes[i].last_pinged = unix_time(); +                list_nodes[i].last_pinged = mono_time_get(onion_c->mono_time);                  continue;              } @@ -1596,11 +1599,11 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)                  continue;              } -            if (is_timeout(list_nodes[i].last_pinged, interval) +            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,                                                   list_nodes[i].public_key, nullptr, ~0) == 0) { -                    list_nodes[i].last_pinged = unix_time(); +                    list_nodes[i].last_pinged = mono_time_get(onion_c->mono_time);                      ++list_nodes[i].unsuccessful_pings;                      ping_random = false;                  } @@ -1634,15 +1637,17 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)          }          /* send packets to friend telling them our DHT public key. */ -        if (is_timeout(onion_c->friends_list[friendnum].last_dht_pk_onion_sent, ONION_DHTPK_SEND_INTERVAL)) { +        if (mono_time_is_timeout(onion_c->mono_time, onion_c->friends_list[friendnum].last_dht_pk_onion_sent, +                                 ONION_DHTPK_SEND_INTERVAL)) {              if (send_dhtpk_announce(onion_c, friendnum, 0) >= 1) { -                onion_c->friends_list[friendnum].last_dht_pk_onion_sent = unix_time(); +                onion_c->friends_list[friendnum].last_dht_pk_onion_sent = mono_time_get(onion_c->mono_time);              }          } -        if (is_timeout(onion_c->friends_list[friendnum].last_dht_pk_dht_sent, DHT_DHTPK_SEND_INTERVAL)) { +        if (mono_time_is_timeout(onion_c->mono_time, onion_c->friends_list[friendnum].last_dht_pk_dht_sent, +                                 DHT_DHTPK_SEND_INTERVAL)) {              if (send_dhtpk_announce(onion_c, friendnum, 1) >= 1) { -                onion_c->friends_list[friendnum].last_dht_pk_dht_sent = unix_time(); +                onion_c->friends_list[friendnum].last_dht_pk_dht_sent = mono_time_get(onion_c->mono_time);              }          }      } @@ -1668,7 +1673,7 @@ static void do_announce(Onion_Client *onion_c)      Onion_Node *list_nodes = onion_c->clients_announce_list;      for (i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE; ++i) { -        if (onion_node_timed_out(&list_nodes[i])) { +        if (onion_node_timed_out(&list_nodes[i], onion_c->mono_time)) {              continue;          } @@ -1687,7 +1692,7 @@ static void do_announce(Onion_Client *onion_c)          unsigned int interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED; -        if (list_nodes[i].is_stored && path_exists(&onion_c->onion_paths_self, list_nodes[i].path_used)) { +        if (list_nodes[i].is_stored && path_exists(onion_c->mono_time, &onion_c->onion_paths_self, list_nodes[i].path_used)) {              interval = ANNOUNCE_INTERVAL_ANNOUNCED;              uint32_t pathnum = list_nodes[i].path_used % NUMBER_ONION_PATHS; @@ -1696,32 +1701,32 @@ static void do_announce(Onion_Client *onion_c)               * aggressively, if it has survived for at least TIME_TO_STABLE               * and the latest packets sent to it are not timing out.               */ -            if (is_timeout(list_nodes[i].added_time, TIME_TO_STABLE) +            if (mono_time_is_timeout(onion_c->mono_time, list_nodes[i].added_time, TIME_TO_STABLE)                      && !(list_nodes[i].unsuccessful_pings > 0 -                         && is_timeout(list_nodes[i].last_pinged, ONION_NODE_TIMEOUT)) -                    && is_timeout(onion_c->onion_paths_self.path_creation_time[pathnum], TIME_TO_STABLE) +                         && mono_time_is_timeout(onion_c->mono_time, list_nodes[i].last_pinged, ONION_NODE_TIMEOUT)) +                    && mono_time_is_timeout(onion_c->mono_time, onion_c->onion_paths_self.path_creation_time[pathnum], TIME_TO_STABLE)                      && !(onion_c->onion_paths_self.last_path_used_times[pathnum] > 0 -                         && is_timeout(onion_c->onion_paths_self.last_path_used[pathnum], ONION_PATH_TIMEOUT))) { +                         && mono_time_is_timeout(onion_c->mono_time, onion_c->onion_paths_self.last_path_used[pathnum], ONION_PATH_TIMEOUT))) {                  interval = ANNOUNCE_INTERVAL_STABLE;              }          } -        if (is_timeout(list_nodes[i].last_pinged, interval) -                || (is_timeout(onion_c->last_announce, ONION_NODE_PING_INTERVAL) +        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)) {              uint32_t path_to_use = list_nodes[i].path_used;              if (list_nodes[i].unsuccessful_pings == ONION_NODE_MAX_PINGS - 1 -                    && is_timeout(list_nodes[i].added_time, TIME_TO_STABLE)) { +                    && mono_time_is_timeout(onion_c->mono_time, list_nodes[i].added_time, TIME_TO_STABLE)) {                  /* Last chance for a long-lived node - try a random path */                  path_to_use = ~0;              }              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 = unix_time(); +                list_nodes[i].last_pinged = mono_time_get(onion_c->mono_time);                  ++list_nodes[i].unsuccessful_pings; -                onion_c->last_announce = unix_time(); +                onion_c->last_announce = mono_time_get(onion_c->mono_time);              }          }      } @@ -1756,7 +1761,7 @@ static int onion_isconnected(const Onion_Client *onion_c)  {      unsigned int i, num = 0, announced = 0; -    if (is_timeout(onion_c->last_packet_recv, ONION_OFFLINE_TIMEOUT)) { +    if (mono_time_is_timeout(onion_c->mono_time, onion_c->last_packet_recv, ONION_OFFLINE_TIMEOUT)) {          return 0;      } @@ -1765,7 +1770,7 @@ static int onion_isconnected(const Onion_Client *onion_c)      }      for (i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE; ++i) { -        if (!onion_node_timed_out(&onion_c->clients_announce_list[i])) { +        if (!onion_node_timed_out(&onion_c->clients_announce_list[i], onion_c->mono_time)) {              ++num;              if (onion_c->clients_announce_list[i].is_stored) { @@ -1812,11 +1817,11 @@ unsigned int onion_connection_status(const Onion_Client *onion_c)  void do_onion_client(Onion_Client *onion_c)  { -    if (onion_c->last_run == unix_time()) { +    if (onion_c->last_run == mono_time_get(onion_c->mono_time)) {          return;      } -    if (is_timeout(onion_c->first_run, ONION_CONNECTION_SECONDS)) { +    if (mono_time_is_timeout(onion_c->mono_time, onion_c->first_run, ONION_CONNECTION_SECONDS)) {          populate_path_nodes(onion_c);          do_announce(onion_c);      } @@ -1835,7 +1840,7 @@ void do_onion_client(Onion_Client *onion_c)      bool udp_connected = dht_non_lan_connected(onion_c->dht); -    if (is_timeout(onion_c->first_run, ONION_CONNECTION_SECONDS * 2)) { +    if (mono_time_is_timeout(onion_c->mono_time, onion_c->first_run, ONION_CONNECTION_SECONDS * 2)) {          set_tcp_onion_status(nc_get_tcp_c(onion_c->c), !udp_connected);      } @@ -1849,13 +1854,13 @@ void do_onion_client(Onion_Client *onion_c)      }      if (onion_c->last_run == 0) { -        onion_c->first_run = unix_time(); +        onion_c->first_run = mono_time_get(onion_c->mono_time);      } -    onion_c->last_run = unix_time(); +    onion_c->last_run = mono_time_get(onion_c->mono_time);  } -Onion_Client *new_onion_client(Net_Crypto *c) +Onion_Client *new_onion_client(Mono_Time *mono_time, Net_Crypto *c)  {      if (c == nullptr) {          return nullptr; @@ -1874,6 +1879,7 @@ Onion_Client *new_onion_client(Net_Crypto *c)          return nullptr;      } +    onion_c->mono_time = mono_time;      onion_c->dht = nc_get_dht(c);      onion_c->net = dht_get_net(onion_c->dht);      onion_c->c = c; diff --git a/protocols/Tox/libtox/src/toxcore/onion_client.h b/protocols/Tox/libtox/src/toxcore/onion_client.h index 660ccdd28e..66e417d76c 100644 --- a/protocols/Tox/libtox/src/toxcore/onion_client.h +++ b/protocols/Tox/libtox/src/toxcore/onion_client.h @@ -4,7 +4,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -22,8 +22,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef ONION_CLIENT_H -#define ONION_CLIENT_H +#ifndef C_TOXCORE_TOXCORE_ONION_CLIENT_H +#define C_TOXCORE_TOXCORE_ONION_CLIENT_H  #include "net_crypto.h"  #include "onion_announce.h" @@ -188,7 +188,7 @@ void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_ha  void do_onion_client(Onion_Client *onion_c); -Onion_Client *new_onion_client(Net_Crypto *c); +Onion_Client *new_onion_client(Mono_Time *mono_time, Net_Crypto *c);  void kill_onion_client(Onion_Client *onion_c); diff --git a/protocols/Tox/libtox/src/toxcore/ping.api.h b/protocols/Tox/libtox/src/toxcore/ping.api.h index edc04723a0..2ae5b3650b 100644 --- a/protocols/Tox/libtox/src/toxcore/ping.api.h +++ b/protocols/Tox/libtox/src/toxcore/ping.api.h @@ -4,7 +4,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   * Copyright © 2013 plutooo   * @@ -24,8 +24,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef PING_H -#define PING_H +#ifndef C_TOXCORE_TOXCORE_PING_H +#define C_TOXCORE_TOXCORE_PING_H  #include "DHT.h"  #include "network.h" @@ -35,12 +35,13 @@  class iP_Port { struct this; }  class dHT { struct this; } +class mono_Time { struct this; }  class ping {  struct this; -static this new(dHT::this *dht); +static this new(const mono_Time::this *mono_time, dHT::this *dht);  void kill();  /** Add nodes to the to_ping list. @@ -61,5 +62,5 @@ int32_t send_request(iP_Port::this ipp, const uint8_t *public_key);  }  %{ -#endif /* PING_H */ +#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 1bf096bfcc..df0adf046d 100644 --- a/protocols/Tox/libtox/src/toxcore/ping.c +++ b/protocols/Tox/libtox/src/toxcore/ping.c @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   * Copyright © 2013 plutooo   * @@ -48,6 +48,7 @@  struct Ping { +    const Mono_Time *mono_time;      DHT *dht;      Ping_Array  *ping_array; @@ -78,7 +79,7 @@ int32_t ping_send_request(Ping *ping, IP_Port ipp, const uint8_t *public_key)      uint8_t data[PING_DATA_SIZE];      id_copy(data, public_key);      memcpy(data + CRYPTO_PUBLIC_KEY_SIZE, &ipp, sizeof(IP_Port)); -    ping_id = ping_array_add(ping->ping_array, data, sizeof(data)); +    ping_id = ping_array_add(ping->ping_array, ping->mono_time, data, sizeof(data));      if (ping_id == 0) {          return 1; @@ -219,7 +220,7 @@ static int handle_ping_response(void *object, IP_Port source, const uint8_t *pac      memcpy(&ping_id, ping_plain + 1, sizeof(ping_id));      uint8_t data[PING_DATA_SIZE]; -    if (ping_array_check(ping->ping_array, data, sizeof(data), ping_id) != sizeof(data)) { +    if (ping_array_check(ping->ping_array, ping->mono_time, data, sizeof(data), ping_id) != sizeof(data)) {          return 1;      } @@ -243,7 +244,8 @@ static int handle_ping_response(void *object, IP_Port source, const uint8_t *pac   * return 1 if it is.   * return 0 if it isn't.   */ -static int in_list(const Client_data *list, uint16_t length, const uint8_t *public_key, IP_Port ip_port) +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)  {      unsigned int i; @@ -257,7 +259,7 @@ static int in_list(const Client_data *list, uint16_t length, const uint8_t *publ                  ipptp = &list[i].assoc6;              } -            if (!is_timeout(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;              }          } @@ -286,7 +288,7 @@ int32_t ping_add(Ping *ping, const uint8_t *public_key, IP_Port ip_port)          return -1;      } -    if (in_list(dht_get_close_clientlist(ping->dht), LCLIENT_LIST, public_key, ip_port)) { +    if (in_list(dht_get_close_clientlist(ping->dht), LCLIENT_LIST, ping->mono_time, public_key, ip_port)) {          return -1;      } @@ -324,7 +326,7 @@ int32_t ping_add(Ping *ping, const uint8_t *public_key, IP_Port ip_port)   */  void ping_iterate(Ping *ping)  { -    if (!is_timeout(ping->last_to_ping, TIME_TO_PING)) { +    if (!mono_time_is_timeout(ping->mono_time, ping->last_to_ping, TIME_TO_PING)) {          return;      } @@ -348,12 +350,12 @@ void ping_iterate(Ping *ping)      }      if (i != 0) { -        ping->last_to_ping = unix_time(); +        ping->last_to_ping = mono_time_get(ping->mono_time);      }  } -Ping *ping_new(DHT *dht) +Ping *ping_new(const Mono_Time *mono_time, DHT *dht)  {      Ping *ping = (Ping *)calloc(1, sizeof(Ping)); @@ -368,6 +370,7 @@ Ping *ping_new(DHT *dht)          return nullptr;      } +    ping->mono_time = mono_time;      ping->dht = dht;      networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_REQUEST, &handle_ping_request, dht);      networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_RESPONSE, &handle_ping_response, dht); diff --git a/protocols/Tox/libtox/src/toxcore/ping.h b/protocols/Tox/libtox/src/toxcore/ping.h index 61875a0bd8..0413e2856e 100644 --- a/protocols/Tox/libtox/src/toxcore/ping.h +++ b/protocols/Tox/libtox/src/toxcore/ping.h @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   * Copyright © 2013 plutooo   * @@ -23,8 +23,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef PING_H -#define PING_H +#ifndef C_TOXCORE_TOXCORE_PING_H +#define C_TOXCORE_TOXCORE_PING_H  #include "DHT.h"  #include "network.h" @@ -41,12 +41,17 @@ typedef struct IP_Port IP_Port;  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 */ +  #ifndef PING_DEFINED  #define PING_DEFINED  typedef struct Ping Ping;  #endif /* PING_DEFINED */ -Ping *ping_new(DHT *dht); +Ping *ping_new(const struct Mono_Time *mono_time, DHT *dht);  void ping_kill(Ping *ping); @@ -66,4 +71,4 @@ void ping_iterate(Ping *ping);  int32_t ping_send_request(Ping *ping, struct IP_Port ipp, const uint8_t *public_key); -#endif /* PING_H */ +#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 index 55b8057056..e0ac333b48 100644 --- a/protocols/Tox/libtox/src/toxcore/ping_array.api.h +++ b/protocols/Tox/libtox/src/toxcore/ping_array.api.h @@ -4,7 +4,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -22,23 +22,30 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef PING_ARRAY_H -#define PING_ARRAY_H +#ifndef C_TOXCORE_TOXCORE_PING_ARRAY_H +#define C_TOXCORE_TOXCORE_PING_ARRAY_H -#include "network.h" +#include <stddef.h> +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif  %} +class mono_Time { struct this; } +  class ping_Array {  struct this;  /**   * Initialize a Ping_Array. - * size represents the total size of the array and should be a power of 2. - * timeout represents the maximum timeout in seconds for the entry.   * - * return 0 on success. - * return -1 on failure. + * @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); @@ -50,23 +57,25 @@ void kill();  /**   * Add a data with length to the Ping_Array list and return a ping_id.   * - * return ping_id on success. - * return 0 on failure. + * @return ping_id on success, 0 on failure.   */ -uint64_t add(const uint8_t *data, uint32_t length); +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. - * return -1 on failure. + * @return length of data copied on success, -1 on failure.   */ -int32_t check(uint8_t[length] data, uint64_t ping_id); +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 142640dd23..c39dc881d9 100644 --- a/protocols/Tox/libtox/src/toxcore/ping_array.c +++ b/protocols/Tox/libtox/src/toxcore/ping_array.c @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2014 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -34,7 +34,6 @@  #include "mono_time.h"  #include "util.h" -  typedef struct Ping_Array_Entry {      void *data;      uint32_t length; @@ -46,25 +45,23 @@ struct Ping_Array {      Ping_Array_Entry *entries;      uint32_t last_deleted; /* number representing the next entry to be deleted. */ -    uint32_t last_added; /* number representing the last entry to be added. */ -    uint32_t total_size; /* The length of entries */ -    uint32_t timeout; /* The timeout after which entries are cleared. */ +    uint32_t last_added;   /* number representing the last entry to be added. */ +    uint32_t total_size;   /* The length of entries */ +    uint32_t timeout;      /* The timeout after which entries are cleared. */  }; -/* Initialize a Ping_Array. - * size represents the total size of the array and should be a power of 2. - * timeout represents the maximum timeout in seconds for the entry. - * - * return 0 on success. - * return -1 on failure. - */  Ping_Array *ping_array_new(uint32_t size, uint32_t timeout)  {      if (size == 0 || timeout == 0) {          return nullptr;      } -    Ping_Array *empty_array = (Ping_Array *)calloc(1, sizeof(Ping_Array)); +    if ((size & (size - 1)) != 0) { +        // Not a power of 2. +        return nullptr; +    } + +    Ping_Array *const empty_array = (Ping_Array *)calloc(1, sizeof(Ping_Array));      if (empty_array == nullptr) {          return nullptr; @@ -86,19 +83,15 @@ Ping_Array *ping_array_new(uint32_t size, uint32_t timeout)  static void clear_entry(Ping_Array *array, uint32_t index)  { +    const Ping_Array_Entry empty = {nullptr};      free(array->entries[index].data); -    array->entries[index].data = nullptr; -    array->entries[index].length = 0; -    array->entries[index].time = 0; -    array->entries[index].ping_id = 0; +    array->entries[index] = empty;  } -/* Free all the allocated memory in a Ping_Array. - */  void ping_array_kill(Ping_Array *array)  {      while (array->last_deleted != array->last_added) { -        uint32_t index = array->last_deleted % array->total_size; +        const uint32_t index = array->last_deleted % array->total_size;          clear_entry(array, index);          ++array->last_deleted;      } @@ -109,12 +102,12 @@ void ping_array_kill(Ping_Array *array)  /* Clear timed out entries.   */ -static void ping_array_clear_timedout(Ping_Array *array) +static void ping_array_clear_timedout(Ping_Array *array, const Mono_Time *mono_time)  {      while (array->last_deleted != array->last_added) { -        uint32_t index = array->last_deleted % array->total_size; +        const uint32_t index = array->last_deleted % array->total_size; -        if (!is_timeout(array->entries[index].time, array->timeout)) { +        if (!mono_time_is_timeout(mono_time, array->entries[index].time, array->timeout)) {              break;          } @@ -123,15 +116,11 @@ static void ping_array_clear_timedout(Ping_Array *array)      }  } -/* Add a data with length to the Ping_Array list and return a ping_id. - * - * return ping_id on success. - * return 0 on failure. - */ -uint64_t ping_array_add(Ping_Array *array, const uint8_t *data, uint32_t length) +uint64_t ping_array_add(Ping_Array *array, const Mono_Time *mono_time, const uint8_t *data, +                        uint32_t length)  { -    ping_array_clear_timedout(array); -    uint32_t index = array->last_added % array->total_size; +    ping_array_clear_timedout(array, mono_time); +    const uint32_t index = array->last_added % array->total_size;      if (array->entries[index].data != nullptr) {          array->last_deleted = array->last_added - array->total_size; @@ -146,7 +135,7 @@ uint64_t ping_array_add(Ping_Array *array, const uint8_t *data, uint32_t length)      memcpy(array->entries[index].data, data, length);      array->entries[index].length = length; -    array->entries[index].time = unix_time(); +    array->entries[index].time = mono_time_get(mono_time);      ++array->last_added;      uint64_t ping_id = random_u64();      ping_id /= array->total_size; @@ -161,27 +150,20 @@ uint64_t ping_array_add(Ping_Array *array, const uint8_t *data, uint32_t length)      return ping_id;  } - -/* 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. - * return -1 on failure. - */ -int32_t ping_array_check(Ping_Array *array, uint8_t *data, size_t length, uint64_t ping_id) +int32_t ping_array_check(Ping_Array *array, const Mono_Time *mono_time, uint8_t *data, +                         size_t length, uint64_t ping_id)  {      if (ping_id == 0) {          return -1;      } -    uint32_t index = ping_id % array->total_size; +    const uint32_t index = ping_id % array->total_size;      if (array->entries[index].ping_id != ping_id) {          return -1;      } -    if (is_timeout(array->entries[index].time, array->timeout)) { +    if (mono_time_is_timeout(mono_time, array->entries[index].time, array->timeout)) {          return -1;      } @@ -189,12 +171,13 @@ int32_t ping_array_check(Ping_Array *array, uint8_t *data, size_t length, uint64          return -1;      } +    // TODO(iphydf): This can't happen? If it indeed can't, turn it into an assert.      if (array->entries[index].data == nullptr) {          return -1;      }      memcpy(data, array->entries[index].data, array->entries[index].length); -    uint32_t len = array->entries[index].length; +    const uint32_t len = array->entries[index].length;      clear_entry(array, index);      return len;  } diff --git a/protocols/Tox/libtox/src/toxcore/ping_array.h b/protocols/Tox/libtox/src/toxcore/ping_array.h index b927bbd42b..a2e57856bd 100644 --- a/protocols/Tox/libtox/src/toxcore/ping_array.h +++ b/protocols/Tox/libtox/src/toxcore/ping_array.h @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -21,10 +21,20 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef PING_ARRAY_H -#define PING_ARRAY_H +#ifndef C_TOXCORE_TOXCORE_PING_ARRAY_H +#define C_TOXCORE_TOXCORE_PING_ARRAY_H -#include "network.h" +#include <stddef.h> +#include <stdint.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 @@ -33,11 +43,11 @@ typedef struct Ping_Array Ping_Array;  /**   * Initialize a Ping_Array. - * size represents the total size of the array and should be a power of 2. - * timeout represents the maximum timeout in seconds for the entry.   * - * return 0 on success. - * return -1 on failure. + * @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.   */  struct Ping_Array *ping_array_new(uint32_t size, uint32_t timeout); @@ -49,19 +59,23 @@ void ping_array_kill(struct Ping_Array *_array);  /**   * Add a data with length to the Ping_Array list and return a ping_id.   * - * return ping_id on success. - * return 0 on failure. + * @return ping_id on success, 0 on failure.   */ -uint64_t ping_array_add(struct Ping_Array *_array, const uint8_t *data, uint32_t length); +uint64_t ping_array_add(struct Ping_Array *_array, const struct Mono_Time *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. - * return -1 on failure. + * @return length of data copied on success, -1 on failure.   */ -int32_t ping_array_check(struct Ping_Array *_array, uint8_t *data, size_t length, uint64_t ping_id); +int32_t ping_array_check(struct Ping_Array *_array, const struct Mono_Time *mono_time, uint8_t *data, size_t length, +                         uint64_t ping_id); +#ifdef __cplusplus +}  // extern "C"  #endif + +#endif // C_TOXCORE_TOXCORE_PING_ARRAY_H diff --git a/protocols/Tox/libtox/src/toxcore/state.c b/protocols/Tox/libtox/src/toxcore/state.c index 8da061f4a6..29b4af88a3 100644 --- a/protocols/Tox/libtox/src/toxcore/state.c +++ b/protocols/Tox/libtox/src/toxcore/state.c @@ -45,6 +45,7 @@ int state_load(const Logger *log, state_load_cb *state_load_callback, void *oute                  break;              case STATE_LOAD_STATUS_ERROR: +                LOGGER_ERROR(log, "Error occcured in state file (type: %u).", type);                  return -1;              case STATE_LOAD_STATUS_END: @@ -60,6 +61,15 @@ int state_load(const Logger *log, state_load_cb *state_load_callback, void *oute      return 0;  } +uint8_t *state_write_section_header(uint8_t *data, uint16_t cookie_type, uint32_t len, uint32_t section_type) +{ +    host_to_lendian32(data, len); +    data += sizeof(uint32_t); +    host_to_lendian32(data, (host_tolendian16(cookie_type) << 16) | host_tolendian16(section_type)); +    data += sizeof(uint32_t); +    return data; +} +  uint16_t lendian_to_host16(uint16_t lendian)  {  #ifdef WORDS_BIGENDIAN @@ -69,6 +79,11 @@ uint16_t lendian_to_host16(uint16_t lendian)  #endif  } +uint16_t host_tolendian16(uint16_t host) +{ +    return lendian_to_host16(host); +} +  void host_to_lendian32(uint8_t *dest,  uint32_t num)  {  #ifdef WORDS_BIGENDIAN diff --git a/protocols/Tox/libtox/src/toxcore/state.h b/protocols/Tox/libtox/src/toxcore/state.h index 3f7ff04333..2d1f62c36d 100644 --- a/protocols/Tox/libtox/src/toxcore/state.h +++ b/protocols/Tox/libtox/src/toxcore/state.h @@ -34,10 +34,12 @@ typedef State_Load_Status state_load_cb(void *outer, const uint8_t *data, uint32  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); +uint8_t *state_write_section_header(uint8_t *data, uint16_t cookie_type, uint32_t len, uint32_t section_type); +  // Utilities for state data serialisation.  uint16_t lendian_to_host16(uint16_t lendian); -#define host_tolendian16(x) lendian_to_host16(x) +uint16_t host_tolendian16(uint16_t host);  void host_to_lendian32(uint8_t *dest, uint32_t num);  void lendian_to_host32(uint32_t *dest, const uint8_t *lendian); diff --git a/protocols/Tox/libtox/src/toxcore/tox.api.h b/protocols/Tox/libtox/src/toxcore/tox.api.h index 3629bed1b4..5378847358 100644 --- a/protocols/Tox/libtox/src/toxcore/tox.api.h +++ b/protocols/Tox/libtox/src/toxcore/tox.api.h @@ -4,7 +4,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -22,8 +22,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef TOX_H -#define TOX_H +#ifndef C_TOXCORE_TOXCORE_TOX_H +#define C_TOXCORE_TOXCORE_TOX_H  #include <stdbool.h>  #include <stddef.h> @@ -182,7 +182,7 @@ const VERSION_MINOR                = 2;   * The patch or revision number. Incremented when bugfixes are applied without   * changing any functionality or API or ABI.   */ -const VERSION_PATCH                = 6; +const VERSION_PATCH                = 8;  /**   * A macro to check at preprocessing time whether the client code is compatible @@ -2772,5 +2772,5 @@ typedef TOX_CONNECTION Tox_Connection;  typedef TOX_FILE_CONTROL Tox_File_Control;  typedef TOX_CONFERENCE_TYPE Tox_Conference_Type; -#endif +#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 cd1b71f095..5258e9b6e3 100644 --- a/protocols/Tox/libtox/src/toxcore/tox.c +++ b/protocols/Tox/libtox/src/toxcore/tox.c @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -38,6 +38,7 @@  #include "Messenger.h"  #include "group.h"  #include "logger.h" +#include "mono_time.h"  #include "../toxencryptsave/defines.h" @@ -77,6 +78,8 @@  struct Tox {      Messenger *m; +    Mono_Time *mono_time; +      tox_self_connection_status_cb *self_connection_status_callback;      tox_friend_name_cb *friend_name_callback;      tox_friend_status_message_cb *friend_status_message_callback; @@ -452,13 +455,22 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)          m_options.proxy_info.ip_port.port = net_htons(tox_options_get_proxy_port(opts));      } +    tox->mono_time = mono_time_new(); + +    if (tox->mono_time == nullptr) { +        SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC); +        tox_options_free(default_options); +        free(tox); +        return nullptr; +    } +      unsigned int m_error; -    Messenger *const m = new_messenger(&m_options, &m_error); +    Messenger *const m = new_messenger(tox->mono_time, &m_options, &m_error);      tox->m = m;      // TODO(iphydf): Clarify this code, check for NULL before new_groupchats, so      // new_groupchats can assume m is non-NULL. -    if (!new_groupchats(m)) { +    if (!new_groupchats(tox->mono_time, m)) {          kill_messenger(m);          if (m_error == MESSENGER_ERROR_PORT) { @@ -469,6 +481,7 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)              SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);          } +        mono_time_free(tox->mono_time);          tox_options_free(default_options);          free(tox);          return nullptr; @@ -517,8 +530,10 @@ void tox_kill(Tox *tox)      }      Messenger *m = tox->m; +    assert(m->msi_packet == nullptr && "Attempted to kill tox while toxav is still alive");      kill_groupchats(m->conferences_object);      kill_messenger(m); +    mono_time_free(tox->mono_time);      free(tox);  } @@ -653,6 +668,8 @@ uint32_t tox_iteration_interval(const Tox *tox)  void tox_iterate(Tox *tox, void *user_data)  { +    mono_time_update(tox->mono_time); +      Messenger *m = tox->m;      struct Tox_Userdata tox_data = { tox, user_data };      do_messenger(m, &tox_data); @@ -997,7 +1014,7 @@ bool tox_friend_get_status_message(const Tox *tox, uint32_t friend_number, uint8  {      if (!status_message) {          SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_NULL); -        return 0; +        return false;      }      const Messenger *const m = tox->m; @@ -1005,14 +1022,14 @@ bool tox_friend_get_status_message(const Tox *tox, uint32_t friend_number, uint8      if (size == -1) {          SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); -        return 0; +        return false;      }      const int ret = m_copy_statusmessage(m, friend_number, status_message, size);      assert(ret == size && "concurrency problem: friend status message changed");      SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK); -    return 1; +    return ret == size;  }  void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *callback) diff --git a/protocols/Tox/libtox/src/toxcore/tox.h b/protocols/Tox/libtox/src/toxcore/tox.h index 9f3072a7bf..ee8a01cc7d 100644 --- a/protocols/Tox/libtox/src/toxcore/tox.h +++ b/protocols/Tox/libtox/src/toxcore/tox.h @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   *   * This file is part of Tox, the free peer to peer instant messenger. @@ -21,8 +21,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef TOX_H -#define TOX_H +#ifndef C_TOXCORE_TOXCORE_TOX_H +#define C_TOXCORE_TOXCORE_TOX_H  #include <stdbool.h>  #include <stddef.h> @@ -183,7 +183,7 @@ uint32_t tox_version_minor(void);   * The patch or revision number. Incremented when bugfixes are applied without   * changing any functionality or API or ABI.   */ -#define TOX_VERSION_PATCH              6 +#define TOX_VERSION_PATCH              8  uint32_t tox_version_patch(void); @@ -3167,4 +3167,4 @@ typedef TOX_CONNECTION Tox_Connection;  typedef TOX_FILE_CONTROL Tox_File_Control;  typedef TOX_CONFERENCE_TYPE Tox_Conference_Type; -#endif +#endif // C_TOXCORE_TOXCORE_TOX_H diff --git a/protocols/Tox/libtox/src/toxcore/util.c b/protocols/Tox/libtox/src/toxcore/util.c index de01625eae..adc0dc09dc 100644 --- a/protocols/Tox/libtox/src/toxcore/util.c +++ b/protocols/Tox/libtox/src/toxcore/util.c @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   * Copyright © 2013 plutooo   * diff --git a/protocols/Tox/libtox/src/toxcore/util.h b/protocols/Tox/libtox/src/toxcore/util.h index 842c97a444..8558672473 100644 --- a/protocols/Tox/libtox/src/toxcore/util.h +++ b/protocols/Tox/libtox/src/toxcore/util.h @@ -3,7 +3,7 @@   */  /* - * Copyright © 2016-2017 The TokTok team. + * Copyright © 2016-2018 The TokTok team.   * Copyright © 2013 Tox project.   * Copyright © 2013 plutooo   * @@ -23,8 +23,8 @@   * You should have received a copy of the GNU General Public License   * along with Tox.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef UTIL_H -#define UTIL_H +#ifndef C_TOXCORE_TOXCORE_UTIL_H +#define C_TOXCORE_TOXCORE_UTIL_H  #include <pthread.h>  #include <stdbool.h> @@ -55,4 +55,4 @@ uint64_t min_u64(uint64_t a, uint64_t b);  }  // extern "C"  #endif -#endif /* UTIL_H */ +#endif // C_TOXCORE_TOXCORE_UTIL_H  | 
