Skip to content

Commit

Permalink
feat: implement the last 2 missing network struct functions
Browse files Browse the repository at this point in the history
and make use of them
  • Loading branch information
Green-Sky committed Oct 11, 2024
1 parent 03e9fbf commit 82ffefc
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 25 deletions.
119 changes: 98 additions & 21 deletions toxcore/network.c
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,84 @@ static int sys_setsockopt(void *obj, Socket sock, int level, int optname, const
return setsockopt(net_socket_to_native(sock), level, optname, (const char *)optval, optlen);
}

// sets and fills an array of addrs for address
// returns the number of entries in addrs
non_null()
int sys_getaddrinfo(void *obj, const char *address, int family, Network_Addr **addrs) {
assert(addrs != nullptr);
*addrs = nullptr;

struct addrinfo hints = {0};
hints.ai_family = family;
// hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.

struct addrinfo *infos = nullptr;

const int rc = getaddrinfo(address, nullptr, &hints, &infos);

// Lookup failed.
if (rc != 0) {
// TODO: log error
return 0;
}

int result = 0;

// we count number of "valid" results
for (struct addrinfo *walker = infos; walker != nullptr; walker = walker->ai_next) {
if (walker->ai_family == family || family == AF_UNSPEC) {
result++;
}
}

// HACK: use default memory allocator
const Memory* mem = os_memory();

*addrs = mem_valloc(mem, result, sizeof(Network_Addr));
if (*addrs == nullptr) {
freeaddrinfo(infos);
return 0;
}

// now we fill in
int i = 0;
for (struct addrinfo *walker = infos; walker != nullptr; walker = walker->ai_next) {
if (walker->ai_family == family || family == AF_UNSPEC) {
(*addrs)[i].size = sizeof(struct sockaddr_storage);
(*addrs)[i].addr.ss_family = walker->ai_family;

// according to sped, storage is supposed to be large enough (and source shows they are)
// storage is 128 bytes
assert(walker->ai_addrlen <= (*addrs)[i].size);

memcpy(&(*addrs)[i].addr, walker->ai_addr, walker->ai_addrlen);
(*addrs)[i].size = walker->ai_addrlen;

i++;
}
}

assert(i == result);

freeaddrinfo(infos);

// number of entries in addrs
return result;
}

non_null()
int sys_freeaddrinfo(void *obj, Network_Addr *addrs) {
if (addrs == nullptr) {
return 0;
}

// HACK: use default memory allocator
const Memory* mem = os_memory();
mem_delete(mem, addrs);

return 0;
}

static const Network_Funcs os_network_funcs = {
sys_close,
sys_accept,
Expand All @@ -600,8 +678,10 @@ static const Network_Funcs os_network_funcs = {
sys_socket_nonblock,
sys_getsockopt,
sys_setsockopt,
sys_getaddrinfo,
sys_freeaddrinfo
};
static const Network os_network_obj = {&os_network_funcs};
static const Network os_network_obj = {&os_network_funcs, nullptr};

const Network *os_network(void)
{
Expand Down Expand Up @@ -1833,19 +1913,16 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr
const Family tox_family = to->family;
const int family = make_family(tox_family);

struct addrinfo hints = {0};
hints.ai_family = family;
hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.

struct addrinfo *server = nullptr;

const int rc = getaddrinfo(address, nullptr, &hints, &server);
Network_Addr* addrs = nullptr;
const int rc = ns->funcs->getaddrinfo(ns->obj, address, family, &addrs);

// Lookup failed.
if (rc != 0) {
// Lookup failed / empty.
if (rc <= 0) {
return 0;
}

assert(addrs != nullptr);

IP ip4;
ip_init(&ip4, false); // ipv6enabled = false
IP ip6;
Expand All @@ -1854,16 +1931,16 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr
int result = 0;
bool done = false;

for (struct addrinfo *walker = server; walker != nullptr && !done; walker = walker->ai_next) {
switch (walker->ai_family) {
for (int i = 0; i < rc && !done; i++) {
switch (addrs[i].addr.ss_family) {
case AF_INET: {
if (walker->ai_family == family) { /* AF_INET requested, done */
const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)walker->ai_addr;
if (addrs[i].addr.ss_family == family) { /* AF_INET requested, done */
const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)&addrs[i].addr;
get_ip4(&to->ip.v4, &addr->sin_addr);
result = TOX_ADDR_RESOLVE_INET;
done = true;
} else if ((result & TOX_ADDR_RESOLVE_INET) == 0) { /* AF_UNSPEC requested, store away */
const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)walker->ai_addr;
const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)&addrs[i].addr;
get_ip4(&ip4.ip.v4, &addr->sin_addr);
result |= TOX_ADDR_RESOLVE_INET;
}
Expand All @@ -1872,16 +1949,16 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr
}

case AF_INET6: {
if (walker->ai_family == family) { /* AF_INET6 requested, done */
if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)walker->ai_addr;
if (addrs[i].addr.ss_family == family) { /* AF_INET6 requested, done */
if (addrs[i].size == sizeof(struct sockaddr_in6)) {
const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)&addrs[i].addr;
get_ip6(&to->ip.v6, &addr->sin6_addr);
result = TOX_ADDR_RESOLVE_INET6;
done = true;
}
} else if ((result & TOX_ADDR_RESOLVE_INET6) == 0) { /* AF_UNSPEC requested, store away */
if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)walker->ai_addr;
if (addrs[i].size == sizeof(struct sockaddr_in6)) {
const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)&addrs[i].addr;
get_ip6(&ip6.ip.v6, &addr->sin6_addr);
result |= TOX_ADDR_RESOLVE_INET6;
}
Expand All @@ -1906,7 +1983,7 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr
}
}

freeaddrinfo(server);
ns->funcs->freeaddrinfo(ns->obj, addrs);
return result;
}

Expand Down
2 changes: 1 addition & 1 deletion toxcore/network.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ typedef Socket net_socket_cb(void *obj, int domain, int type, int proto);
typedef int net_socket_nonblock_cb(void *obj, Socket sock, bool nonblock);
typedef int net_getsockopt_cb(void *obj, Socket sock, int level, int optname, void *optval, size_t *optlen);
typedef int net_setsockopt_cb(void *obj, Socket sock, int level, int optname, const void *optval, size_t optlen);
typedef int net_getaddrinfo_cb(void *obj, int family, Network_Addr **addrs);
typedef int net_getaddrinfo_cb(void *obj, const char *address, int family, Network_Addr **addrs);
typedef int net_freeaddrinfo_cb(void *obj, Network_Addr *addrs);

/** @brief Functions wrapping POSIX network functions.
Expand Down
4 changes: 2 additions & 2 deletions toxcore/network_test_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ int Test_Network::setsockopt(
{
return net->funcs->setsockopt(net->obj, sock, level, optname, optval, optlen);
}
int Test_Network::getaddrinfo(void *obj, int family, Network_Addr **addrs)
int Test_Network::getaddrinfo(void *obj, const char *address, int family, Network_Addr **addrs)
{
return net->funcs->getaddrinfo(net->obj, family, addrs);
return net->funcs->getaddrinfo(net->obj, address, family, addrs);
}
int Test_Network::freeaddrinfo(void *obj, Network_Addr *addrs)
{
Expand Down
2 changes: 1 addition & 1 deletion toxcore/network_test_util.hh
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class Test_Network : public Network_Class {
void *obj, Socket sock, int level, int optname, void *optval, size_t *optlen) override;
int setsockopt(
void *obj, Socket sock, int level, int optname, const void *optval, size_t optlen) override;
int getaddrinfo(void *obj, int family, Network_Addr **addrs) override;
int getaddrinfo(void *obj, const char *address, int family, Network_Addr **addrs) override;
int freeaddrinfo(void *obj, Network_Addr *addrs) override;
};

Expand Down

0 comments on commit 82ffefc

Please sign in to comment.