Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add groupchat API function that returns an IP address string for a peer #2446

Merged
merged 1 commit into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions auto_tests/group_general_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <string.h>

#include "auto_test_support.h"
#include "../toxcore/tox_private.h"

typedef struct State {
size_t peer_joined_count;
Expand Down Expand Up @@ -42,6 +43,22 @@ typedef struct State {

#define PEER_LIMIT 20

static void print_ip(Tox *tox, uint32_t groupnumber, uint32_t peer_id)
{
Tox_Err_Group_Peer_Query err;
size_t length = tox_group_peer_get_ip_address_size(tox, groupnumber, peer_id, &err);

ck_assert_msg(err == TOX_ERR_GROUP_PEER_QUERY_OK, "failed to get ip address size: error %d", err);

uint8_t ip_str[TOX_GROUP_PEER_IP_STRING_MAX_LENGTH];
tox_group_peer_get_ip_address(tox, groupnumber, peer_id, ip_str, &err);
ip_str[length] = '\0';

ck_assert_msg(err == TOX_ERR_GROUP_PEER_QUERY_OK, "failed to get ip address: error %d", err);

fprintf(stderr, "%s\n", ip_str);
}

static bool all_group_peers_connected(AutoTox *autotoxes, uint32_t tox_count, uint32_t groupnumber, size_t name_length)
{
for (size_t i = 0; i < tox_count; ++i) {
Expand Down Expand Up @@ -119,6 +136,9 @@ static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t pee
}
}

fprintf(stderr, "%s joined with IP: ", peer_name);
print_ip(tox, groupnumber, peer_id);

state->peer_id = peer_id;
++state->peer_joined_count;
}
Expand Down Expand Up @@ -178,6 +198,11 @@ static void group_peer_self_join_handler(Tox *tox, uint32_t groupnumber, void *u
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "%d", query_err);
ck_assert(memcmp(topic, TOPIC, TOPIC_LEN) == 0);

uint32_t peer_id = tox_group_self_get_peer_id(tox, groupnumber, nullptr);

fprintf(stderr, "self joined with IP: ");
print_ip(tox, groupnumber, peer_id);

++state->self_joined_count;
}

Expand Down Expand Up @@ -341,6 +366,7 @@ static void group_announce_test(AutoTox *autotoxes)
ck_assert(memcmp(tox0_pk_query, tox0_self_pk, TOX_GROUP_PEER_PUBLIC_KEY_SIZE) == 0);

fprintf(stderr, "Peer 0 disconnecting...\n");

// tox 0 disconnects then reconnects
Tox_Err_Group_Disconnect d_err;
tox_group_disconnect(tox0, groupnumber, &d_err);
Expand Down
2 changes: 1 addition & 1 deletion other/bootstrap_daemon/docker/tox-bootstrapd.sha256
Original file line number Diff line number Diff line change
@@ -1 +1 @@
e0fa59db7d25204f917e4b114e1607cb3819fe9da74de5f9e807bcf76abefe42 /usr/local/bin/tox-bootstrapd
8cb8b2f7bbc0ce71551365ed72ae468c731eafdce93e01d8c9a04ed5d904fcd9 /usr/local/bin/tox-bootstrapd
57 changes: 57 additions & 0 deletions toxcore/group_chats.c
Original file line number Diff line number Diff line change
Expand Up @@ -3517,6 +3517,63 @@
return 0;
}

/** @brief Puts a string of the IP associated with `ip_port` in `ip_str` if the
* connection is direct, otherwise puts a placeholder in the buffer indicating that
* the IP cannot be displayed.
*/
non_null()
static void get_gc_ip_ntoa(const IP_Port *ip_port, Ip_Ntoa *ip_str)
{
net_ip_ntoa(&ip_port->ip, ip_str);

if (!ip_str->ip_is_valid) {
ip_str->buf[0] = '-';
ip_str->buf[1] = '\0';
ip_str->length = 1;

Check warning on line 3532 in toxcore/group_chats.c

View check run for this annotation

Codecov / codecov/patch

toxcore/group_chats.c#L3530-L3532

Added lines #L3530 - L3532 were not covered by tests
}
}

int gc_get_peer_ip_address_size(const GC_Chat *chat, uint32_t peer_id)
{
const int peer_number = get_peer_number_of_peer_id(chat, peer_id);
const GC_Connection *gconn = get_gc_connection(chat, peer_number);

if (gconn == nullptr) {
return -1;

Check warning on line 3542 in toxcore/group_chats.c

View check run for this annotation

Codecov / codecov/patch

toxcore/group_chats.c#L3542

Added line #L3542 was not covered by tests
}

const IP_Port *ip_port = peer_number == 0 ? &chat->self_ip_port : &gconn->addr.ip_port;

Ip_Ntoa ip_str;
get_gc_ip_ntoa(ip_port, &ip_str);

return ip_str.length;
}

int gc_get_peer_ip_address(const GC_Chat *chat, uint32_t peer_id, uint8_t *ip_addr)
{
const int peer_number = get_peer_number_of_peer_id(chat, peer_id);
const GC_Connection *gconn = get_gc_connection(chat, peer_number);

if (gconn == nullptr) {
return -1;

Check warning on line 3559 in toxcore/group_chats.c

View check run for this annotation

Codecov / codecov/patch

toxcore/group_chats.c#L3559

Added line #L3559 was not covered by tests
}

if (ip_addr == nullptr) {
return -2;

Check warning on line 3563 in toxcore/group_chats.c

View check run for this annotation

Codecov / codecov/patch

toxcore/group_chats.c#L3563

Added line #L3563 was not covered by tests
}

const IP_Port *ip_port = peer_number == 0 ? &chat->self_ip_port : &gconn->addr.ip_port;

Ip_Ntoa ip_str;
get_gc_ip_ntoa(ip_port, &ip_str);

assert(ip_str.length <= IP_NTOA_LEN);
memcpy(ip_addr, ip_str.buf, ip_str.length);

return 0;
}

unsigned int gc_get_peer_connection_status(const GC_Chat *chat, uint32_t peer_id)
{
const int peer_number = get_peer_number_of_peer_id(chat, peer_id);
Expand Down
23 changes: 23 additions & 0 deletions toxcore/group_chats.h
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,29 @@ int gc_get_peer_nick_size(const GC_Chat *chat, uint32_t peer_id);
non_null(1) nullable(3)
int gc_get_peer_public_key_by_peer_id(const GC_Chat *chat, uint32_t peer_id, uint8_t *public_key);

/** @brief Returns the length of the IP address for the peer designated by `peer_id`.
* Returns -1 if peer_id is invalid.
*/
non_null()
int gc_get_peer_ip_address_size(const GC_Chat *chat, uint32_t peer_id);

/** @brief Copies peer_id's IP address to `ip_addr`.
*
* If the peer is forcing TCP connections this will be a placeholder value indicating
* that their real IP address is unknown to us.
*
* If `peer_id` designates ourself, it will write either our own IP address or a
* placeholder value, depending on whether or not we're forcing TCP connections.
*
* `ip_addr` should have room for at least IP_NTOA_LEN bytes.
*
* Returns 0 on success.
* Returns -1 if peer_id is invalid or doesn't correspond to a valid peer connection.
* Returns -2 if `ip_addr` is null.
*/
non_null(1) nullable(3)
int gc_get_peer_ip_address(const GC_Chat *chat, uint32_t peer_id, uint8_t *ip_addr);

/** @brief Gets the connection status for peer associated with `peer_id`.
*
* If `peer_id` designates ourself, the return value indicates whether we're capable
Expand Down
15 changes: 7 additions & 8 deletions toxcore/network.c
Original file line number Diff line number Diff line change
Expand Up @@ -1514,30 +1514,29 @@
*target = *source;
}

/** @brief Converts IP into a string.
*
* Writes error message into the buffer on error.
*
* @param ip_str contains a buffer of the required size.
*
* @return Pointer to the buffer inside `ip_str` containing the IP string.
*/
const char *net_ip_ntoa(const IP *ip, Ip_Ntoa *ip_str)
{
assert(ip_str != nullptr);

ip_str->ip_is_valid = false;

if (ip == nullptr) {
snprintf(ip_str->buf, sizeof(ip_str->buf), "(IP invalid: NULL)");
ip_str->length = (uint16_t)strlen(ip_str->buf);

Check warning on line 1525 in toxcore/network.c

View check run for this annotation

Codecov / codecov/patch

toxcore/network.c#L1525

Added line #L1525 was not covered by tests
return ip_str->buf;
}

if (!ip_parse_addr(ip, ip_str->buf, sizeof(ip_str->buf))) {
snprintf(ip_str->buf, sizeof(ip_str->buf), "(IP invalid, family %u)", ip->family.value);
ip_str->length = (uint16_t)strlen(ip_str->buf);
return ip_str->buf;
}

/* brute force protection against lacking termination */
ip_str->buf[sizeof(ip_str->buf) - 1] = '\0';
ip_str->length = (uint16_t)strlen(ip_str->buf);
ip_str->ip_is_valid = true;

return ip_str->buf;
}

Expand Down
7 changes: 5 additions & 2 deletions toxcore/network.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,11 +343,14 @@ bool ipv6_ipv4_in_v6(const IP6 *a);
/** this would be TOX_INET6_ADDRSTRLEN, but it might be too short for the error message */
#define IP_NTOA_LEN 96 // TODO(irungentoo): magic number. Why not INET6_ADDRSTRLEN ?

/** Contains a null terminated string of an IP address. */
typedef struct Ip_Ntoa {
char buf[IP_NTOA_LEN];
char buf[IP_NTOA_LEN]; // a string formatted IP address or an error message.
uint16_t length; // the length of the string (not including the null byte).
bool ip_is_valid; // if this is false `buf` will contain an error message.
} Ip_Ntoa;

/** @brief Converts IP into a string.
/** @brief Converts IP into a null terminated string.
*
* Writes error message into the buffer on error.
*
Expand Down
2 changes: 2 additions & 0 deletions toxcore/tox.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ static_assert(FILE_ID_LENGTH == CRYPTO_SYMMETRIC_KEY_SIZE,
"FILE_ID_LENGTH is assumed to be equal to CRYPTO_SYMMETRIC_KEY_SIZE");
static_assert(TOX_DHT_NODE_IP_STRING_SIZE == IP_NTOA_LEN,
"TOX_DHT_NODE_IP_STRING_SIZE is assumed to be equal to IP_NTOA_LEN");
static_assert(TOX_GROUP_PEER_IP_STRING_MAX_LENGTH == IP_NTOA_LEN,
"TOX_GROUP_PEER_IP_STRING_MAX_LENGTH is assumed to be equal to IP_NTOA_LEN");
static_assert(TOX_DHT_NODE_PUBLIC_KEY_SIZE == CRYPTO_PUBLIC_KEY_SIZE,
"TOX_DHT_NODE_PUBLIC_KEY_SIZE is assumed to be equal to CRYPTO_PUBLIC_KEY_SIZE");
static_assert(TOX_FILE_ID_LENGTH == CRYPTO_SYMMETRIC_KEY_SIZE,
Expand Down
4 changes: 4 additions & 0 deletions toxcore/tox_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@
{
return TOX_GROUP_PEER_PUBLIC_KEY_SIZE;
}
uint32_t tox_group_peer_ip_string_max_length(void)

Check warning on line 127 in toxcore/tox_api.c

View check run for this annotation

Codecov / codecov/patch

toxcore/tox_api.c#L127

Added line #L127 was not covered by tests
{
return TOX_GROUP_PEER_IP_STRING_MAX_LENGTH;

Check warning on line 129 in toxcore/tox_api.c

View check run for this annotation

Codecov / codecov/patch

toxcore/tox_api.c#L129

Added line #L129 was not covered by tests
}
uint32_t tox_dht_node_ip_string_size(void)
{
return TOX_DHT_NODE_IP_STRING_SIZE;
Expand Down
55 changes: 55 additions & 0 deletions toxcore/tox_private.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <assert.h>

#include "ccompat.h"
#include "group_chats.h"
#include "mem.h"
#include "network.h"
#include "tox_struct.h"
Expand Down Expand Up @@ -166,3 +167,57 @@
return num_cap;
}

#ifndef VANILLA_NACL
size_t tox_group_peer_get_ip_address_size(const Tox *tox, uint32_t group_number, uint32_t peer_id,
Tox_Err_Group_Peer_Query *error)
{
assert(tox != nullptr);

tox_lock(tox);
const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number);

if (chat == nullptr) {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_GROUP_NOT_FOUND);
tox_unlock(tox);
return -1;

Check warning on line 182 in toxcore/tox_private.c

View check run for this annotation

Codecov / codecov/patch

toxcore/tox_private.c#L180-L182

Added lines #L180 - L182 were not covered by tests
}

const int ret = gc_get_peer_ip_address_size(chat, peer_id);
tox_unlock(tox);

if (ret == -1) {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND);
return -1;

Check warning on line 190 in toxcore/tox_private.c

View check run for this annotation

Codecov / codecov/patch

toxcore/tox_private.c#L189-L190

Added lines #L189 - L190 were not covered by tests
} else {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_OK);
return ret;
}
}

bool tox_group_peer_get_ip_address(const Tox *tox, uint32_t group_number, uint32_t peer_id, uint8_t *ip_addr,
Tox_Err_Group_Peer_Query *error)
{
assert(tox != nullptr);

tox_lock(tox);
const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number);

if (chat == nullptr) {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_GROUP_NOT_FOUND);
tox_unlock(tox);
return false;

Check warning on line 208 in toxcore/tox_private.c

View check run for this annotation

Codecov / codecov/patch

toxcore/tox_private.c#L206-L208

Added lines #L206 - L208 were not covered by tests
}

const int ret = gc_get_peer_ip_address(chat, peer_id, ip_addr);
tox_unlock(tox);

if (ret == -1) {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND);
return false;

Check warning on line 216 in toxcore/tox_private.c

View check run for this annotation

Codecov / codecov/patch

toxcore/tox_private.c#L215-L216

Added lines #L215 - L216 were not covered by tests
}

SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_OK);
return true;
}

#endif /* VANILLA_NACL */
45 changes: 45 additions & 0 deletions toxcore/tox_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,51 @@ uint16_t tox_dht_get_num_closelist(const Tox *tox);
*/
uint16_t tox_dht_get_num_closelist_announce_capable(const Tox *tox);


/*******************************************************************************
*
* :: DHT groupchat queries.
*
******************************************************************************/

/**
* Maximum size of a peer IP address string.
*/
#define TOX_GROUP_PEER_IP_STRING_MAX_LENGTH 96

uint32_t tox_group_peer_ip_string_max_length(void);

/**
* Return the length of the peer's IP address in string form. If the group number or ID
* is invalid, the return value is unspecified.
*
* @param group_number The group number of the group we wish to query.
* @param peer_id The ID of the peer whose IP address length we want to retrieve.
*/
size_t tox_group_peer_get_ip_address_size(const Tox *tox, uint32_t group_number, uint32_t peer_id,
Tox_Err_Group_Peer_Query *error);
/**
* Write the IP address associated with the designated peer_id for the designated group number
* to ip_addr.
*
* If the peer is forcing TCP connections a placeholder value will be written instead,
* indicating that their real IP address is unknown to us.
*
* If `peer_id` designates ourself, it will write either our own IP address or a placeholder value,
* depending on whether or not we're forcing TCP connections.
*
* Call tox_group_peer_get_ip_address_size to determine the allocation size for the `ip_addr` parameter.
*
* @param group_number The group number of the group we wish to query.
* @param peer_id The ID of the peer whose public key we wish to retrieve.
* @param ip_addr A valid memory region large enough to store the IP address string.
* If this parameter is NULL, this function call has no effect.
*
* @return true on success.
*/
bool tox_group_peer_get_ip_address(const Tox *tox, uint32_t group_number, uint32_t peer_id, uint8_t *ip_addr,
Tox_Err_Group_Peer_Query *error);

#ifdef __cplusplus
}
#endif
Expand Down
Loading