Squashed 'external/toxcore/c-toxcore/' changes from e2c01e457b..b03b571272

b03b571272 fix: flaky tcp test This only fixes the symptoms, not the real problem. Sometimes or consistently on some platforms a socket might need a moment before it can be written to.
32e67ab4c2 cleanup: use typedef for private message ID's in callback
7b1db6adc1 feat: add message IDs to private group messages
99e0bcc27d refactor: Observers/ignored peers can now send and receive custom packets
b3c3c49d26 fix: Disable IPv6 in Windows cross-compilation tests
e742deddff feat: Check hashes of Windows dependencies when cross-compiling
dfb9a0b02b fix: Test the current Windows Dockerfile, not an old Dockerhub image
14de93ccec chore: Use WineHQ's Wine as Debian Bookworm's crashes
ed37616249 docs: Update the Windows cross-compilation section
9bb79c174f cleanup: Remove a couple of unnecessary misc_tools dependencies
19475adb70 chore: Statically link OpenMP into the cracker fun util on Windows
1be311e51f feat: Build the fun utils when cross-compiling to Windows
88133f8446 chore: Strip Windows binaries
3cc0ae7535 refactor: Copy over all of the required static dependencies
c4fa8f7fb1 feat: Generate .def, .exp and .lib files when building for Windows
74bbac5363 feat: Let CMake create the dll instead of doing so ourselves
246642e9ae feat: Harden Windows cross-compilation
8d431c0d11 chore: Bump Windows build dependency versions
e519f7998b fix: Remove unnecessary wsock32 dependency on Windows
ed2b60c217 chore: Use a specific non-broken slimcc version.
d7f21010a1 chore: Update github actions.
e71a68b7f2 docs: Update the list of CMake options
77e08876ff chore: Remove mod and founder from group API naming scheme
12bc042767 docs: add the experimental api build option to INSTALL.md
e1fa5cae96 refactor: Rename Queries to Query to align with other enums.
be82a3ea30 fix: Correct type for conference offline peer numbers.
0627c36716 test: Add pkgsrc build.
92578afe4b test: Add FreeBSD VM action on GitHub.
52ece0f57b test: Build toxcore on NetBSD (VM).
3fe8ee2c11 chore: Only install tox_private.h on request.
9a8dfa06ab fix: save_compatibility_test failing on big-endian systems
86f5e55578 fix: Don't serve files from websockify.
710eb674a5 fix: Correctly pass extended public keys to group moderation code.
021db7031c refactor: Use `struct`s for extended public/secret keys.
a1e999fd80 chore: Compile libsodium reference implementation with compcert.
fbe3c19cf5 cleanup: correct a few nullable annotations
623e3ee5c3 cleanup: Don't use `memcpy` to cast arbitrary `struct`s to `uint8_t[]`.
c71567dc18 fix: Pass array, not array pointer, to `memcmp`.
9b46a08144 cleanup: Never pass `void*` directly to `memcpy`.
5d7b7a7bbc refactor: Use tox rng to seed the keypair generation.
961891d568 cleanup: Small improvements found by PVS Studio.
8201019f0d chore: Disable NGC saving by default, enable through Tox_Options.
5dd9ee3f65 cleanup: Replace pointer arithmetic with explicit `&arr[i]`.
ca4606d49d refactor: Use strong typedef for NGC peer id.
442213b722 cleanup: Simplify custom packet length check in NGC.
08d3393def fix: Correct a few potential null derefs in bootstrap daemon.
b9877b32b0 fix: Add missing memunlock of local variable when it goes out of scope.
dab5fe44b9 fix: Zero out stack-allocated secret key before return.
f058103299 refactor: Make prune_gc_sanctions_list more obviously correct.
3ba7a0dec9 docs: Add static analysis tool list to README.
8d0811a0f3 docs: Run prettier-markdown on markdown files.
969e3a2bfc refactor: Fix network test not using the strong typedef
93c83fbc7c refactor: Use strong typedef instead of struct for `Socket`.
9fe18b176f fix: Fix some false positive from PVS Studio.
7c44379ccb cleanup: Check that WINXP macro exists before comparing it.
5c93231bef refactor: Make tox mutex non-recursive.
aacff73939 docs: Fix up doxyfile.
d55fc85ff5 docs: Add more documentation to crypto_core.
5bdaaaedb6 refactor: Remove `Tox *` from `tox_dispatch`.
e202341e76 refactor: Don't rely on tox_dispatch passing tox in tests.
34df938f52 chore: Use C++ mode for clang-tidy.
8b05296a78 chore: Check that both gtest and gmock exist for tests.
42010660e1 test: Add slimcc compiler compatibility test.
b473630321 chore: Add some comments to the astyle config.
b7404f24f6 cleanup: Remove implicit bool conversions.
4e2dba4d9f chore: Reformat sources with astyle.
4359e3a6bc chore: Rename C++ headers to .hh suffixes.
0c05566e58 cleanup: Further `#include` cleanups.
8d29935b7a chore: Only check the bootstrap daemon checksum on release.
f70e588bc6 cleanup: Add more `const` where possible.
511bfe39c8 cleanup: Use Bazel modules to enforce proper `#include` hygiene.
1710a0d091 refactor: Move pack/unpack `IP_Port` from DHT into network module.
a975943564 chore: Really fix coverage docker image build.
c08409390f chore: Fix post-submit coverage image.
39aadf8922 fix: Don't use `memcmp` to compare `IP_Port`s.
d94246a906 fix: partially fix a bug that prevented group part messages from sending.
eeaa039222 chore: Fix rpm build; add a CI check for it.
8328449c1a chore: Speed up docker builds a bit by reducing layer count.
d6d67d56f3 cleanup: Add `const` where possible in auto tests.
6aa9e6850d cleanup: Minor cleanup of event unpack code.
bdf460a3a9 refactor: Rename `system_{memory,...}` to `os_{memory,...}`.
203e1af81e fix: a few off by one errors in group autotests
5c093c4888 cleanup: Remove all uses of `SIZEOF_VLA`.
662c2140f3 test: Add goblint static analyser.
8f07755834 cleanup: Use `memzero(x, s)` instead of `memset(x, 0, s)`.
a7258e40cf cleanup: Use explicit 0 instead of `PACKET_ID_PADDING`.
6370d0f15d cleanup: Expand the `Tox_Options` accessor macros.
14a1a0b9bd cleanup: Remove plan9 support.
a05dccad13 test: Add a simple new/delete test for Tox.
1cdcf938b9 cleanup: Add comment after every `#endif`.
ba99d4dc4b test: Fix comment I broke in the events test PR.
e07248debb refactor: Migrate auto_tests to new events API.
bdd42b5452 refactor: Add common msgpack array packer with callback.
3c659f5288 cleanup: Rename group to conference in groupav documentation.
89957be230 cleanup: Ensure handler params are named after callback params.
c650d9d345 refactor: Pass `this` pointer as first param to s11n callbacks.
e7fb91ddb8 refactor: Allow NULL pointers for byte arrays in events.
5e2c8cabc1 cleanup: make some improvements to group moderation test
259de4867e cleanup: Remove `bin_pack_{new,free}`.
21a8ff5895 cleanup: skip a do_gc iteration before removing peers marked for deletion
16809dc36e feat: Add dht_get_nodes_response event to the events system.

git-subtree-dir: external/toxcore/c-toxcore
git-subtree-split: b03b5712720de9a9901ea12fd741f177327a7021
This commit is contained in:
2024-03-07 23:12:55 +01:00
parent 61accfe184
commit aae086cc65
358 changed files with 8093 additions and 5229 deletions

View File

@ -9,40 +9,34 @@
#ifdef __APPLE__
#define _DARWIN_C_SOURCE
#endif
#endif /* __APPLE__ */
// For Solaris.
#ifdef __sun
#define __EXTENSIONS__ 1
#endif
#endif /* __sun */
// For Linux (and some BSDs).
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 700
#endif
#endif /* _XOPEN_SOURCE */
#if defined(_WIN32) && defined(_WIN32_WINNT) && _WIN32_WINNT >= _WIN32_WINNT_WINXP
#if defined(_WIN32) && defined(_WIN32_WINNT) && defined(_WIN32_WINNT_WINXP) && _WIN32_WINNT >= _WIN32_WINNT_WINXP
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x501
#endif
#endif /* defined(_WIN32) && defined(_WIN32_WINNT) && defined(_WIN32_WINNT_WINXP) && _WIN32_WINNT >= _WIN32_WINNT_WINXP */
#if !defined(OS_WIN32) && (defined(_WIN32) || defined(__WIN32__) || defined(WIN32))
#define OS_WIN32
#endif
#endif /* !defined(OS_WIN32) && (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) */
#if defined(OS_WIN32) && !defined(WINVER)
// Windows XP
#define WINVER 0x0501
#endif
#endif /* defined(OS_WIN32) && !defined(WINVER) */
#include "network.h"
#ifdef PLAN9
#include <u.h> // Plan 9 requires this is imported first
// Comment line here to avoid reordering by source code formatters.
#include <libc.h>
#endif
#ifdef OS_WIN32 // Put win32 includes here
// The mingw32/64 Windows library warns about including winsock2.h after
// windows.h even though with the above it's a valid thing to do. So, to make
@ -51,12 +45,12 @@
// Comment line here to avoid reordering by source code formatters.
#include <windows.h>
#include <ws2tcpip.h>
#endif
#endif /* OS_WIN32 */
#ifdef __APPLE__
#include <mach/clock.h>
#include <mach/mach.h>
#endif
#endif /* __APPLE__ */
#if !defined(OS_WIN32)
#include <arpa/inet.h>
@ -73,13 +67,13 @@
#ifdef __sun
#include <stropts.h>
#include <sys/filio.h>
#endif
#endif /* __sun */
#else
#ifndef IPV6_V6ONLY
#define IPV6_V6ONLY 27
#endif
#endif
#endif /* IPV6_V6ONLY */
#endif /* !defined(OS_WIN32) */
#include <assert.h>
#include <limits.h>
@ -87,6 +81,8 @@
#include <stdlib.h>
#include <string.h>
#include "attributes.h"
#include "bin_pack.h"
#include "ccompat.h"
#include "logger.h"
#include "mem.h"
@ -95,13 +91,13 @@
// Disable MSG_NOSIGNAL on systems not supporting it, e.g. Windows, FreeBSD
#if !defined(MSG_NOSIGNAL)
#define MSG_NOSIGNAL 0
#endif
#endif /* !defined(MSG_NOSIGNAL) */
#ifndef IPV6_ADD_MEMBERSHIP
#ifdef IPV6_JOIN_GROUP
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
#endif
#endif
#endif /* IPV6_JOIN_GROUP */
#endif /* IPV6_ADD_MEMBERSHIP */
static_assert(sizeof(IP4) == SIZE_IP4, "IP4 size must be 4");
@ -148,7 +144,7 @@ static int inet_pton6(const char *addr_string, struct in6_addr *addrbuf)
#else
#ifndef IPV6_V6ONLY
#define IPV6_V6ONLY 27
#endif
#endif /* IPV6_V6ONLY */
static bool should_ignore_recv_error(int err)
{
@ -228,7 +224,7 @@ static int inet_pton6(const char *addrString, struct in6_addr *addrbuf)
return 1;
}
#endif
#endif /* !defined(OS_WIN32) */
static_assert(TOX_INET6_ADDRSTRLEN >= INET6_ADDRSTRLEN,
"TOX_INET6_ADDRSTRLEN should be greater or equal to INET6_ADDRSTRLEN (#INET6_ADDRSTRLEN)");
@ -337,9 +333,7 @@ static void fill_addr6(const IP6 *ip, struct in6_addr *addr)
#if !defined(INADDR_LOOPBACK)
#define INADDR_LOOPBACK 0x7f000001
#endif
static const IP empty_ip = {{0}};
#endif /* !defined(INADDR_LOOPBACK) */
IP4 get_ip4_broadcast(void)
{
@ -365,19 +359,29 @@ IP4 get_ip4_loopback(void)
IP6 get_ip6_loopback(void)
{
/* in6addr_loopback isn't available everywhere, so we do it ourselves. */
IP6 loopback = empty_ip.ip.v6;
IP6 loopback = {{0}};
loopback.uint8[15] = 1;
return loopback;
}
#ifndef OS_WIN32
#define INVALID_SOCKET (-1)
#endif
#endif /* OS_WIN32 */
int net_socket_to_native(Socket sock)
{
return (force int)sock.value;
}
Socket net_socket_from_native(int sock)
{
const Socket res = {(force Socket_Value)sock};
return res;
}
Socket net_invalid_socket(void)
{
const Socket invalid_socket = { (int)INVALID_SOCKET };
return invalid_socket;
return net_socket_from_native(INVALID_SOCKET);
}
Family net_family_unspec(void)
@ -473,7 +477,7 @@ bool net_family_is_tox_tcp_ipv6(Family family)
bool sock_valid(Socket sock)
{
const Socket invalid_socket = net_invalid_socket();
return sock.sock != invalid_socket.sock;
return sock.value != invalid_socket.value;
}
struct Network_Addr {
@ -482,105 +486,107 @@ struct Network_Addr {
};
non_null()
static int sys_close(void *obj, int sock)
static int sys_close(void *obj, Socket sock)
{
#if defined(OS_WIN32)
return closesocket(sock);
return closesocket(net_socket_to_native(sock));
#else // !OS_WIN32
return close(sock);
#endif
return close(net_socket_to_native(sock));
#endif /* OS_WIN32 */
}
non_null()
static int sys_accept(void *obj, int sock)
static Socket sys_accept(void *obj, Socket sock)
{
return accept(sock, nullptr, nullptr);
return net_socket_from_native(accept(net_socket_to_native(sock), nullptr, nullptr));
}
non_null()
static int sys_bind(void *obj, int sock, const Network_Addr *addr)
static int sys_bind(void *obj, Socket sock, const Network_Addr *addr)
{
return bind(sock, (const struct sockaddr *)&addr->addr, addr->size);
return bind(net_socket_to_native(sock), (const struct sockaddr *)&addr->addr, addr->size);
}
non_null()
static int sys_listen(void *obj, int sock, int backlog)
static int sys_listen(void *obj, Socket sock, int backlog)
{
return listen(sock, backlog);
return listen(net_socket_to_native(sock), backlog);
}
non_null()
static int sys_recvbuf(void *obj, int sock)
static int sys_recvbuf(void *obj, Socket sock)
{
#ifdef OS_WIN32
u_long count = 0;
ioctlsocket(sock, FIONREAD, &count);
ioctlsocket(net_socket_to_native(sock), FIONREAD, &count);
#else
int count = 0;
ioctl(sock, FIONREAD, &count);
#endif
ioctl(net_socket_to_native(sock), FIONREAD, &count);
#endif /* OS_WIN32 */
return count;
}
non_null()
static int sys_recv(void *obj, int sock, uint8_t *buf, size_t len)
static int sys_recv(void *obj, Socket sock, uint8_t *buf, size_t len)
{
return recv(sock, (char *)buf, len, MSG_NOSIGNAL);
return recv(net_socket_to_native(sock), (char *)buf, len, MSG_NOSIGNAL);
}
non_null()
static int sys_send(void *obj, int sock, const uint8_t *buf, size_t len)
static int sys_send(void *obj, Socket sock, const uint8_t *buf, size_t len)
{
return send(sock, (const char *)buf, len, MSG_NOSIGNAL);
return send(net_socket_to_native(sock), (const char *)buf, len, MSG_NOSIGNAL);
}
non_null()
static int sys_sendto(void *obj, int sock, const uint8_t *buf, size_t len, const Network_Addr *addr) {
return sendto(sock, (const char *)buf, len, 0, (const struct sockaddr *)&addr->addr, addr->size);
static int sys_sendto(void *obj, Socket sock, const uint8_t *buf, size_t len, const Network_Addr *addr)
{
return sendto(net_socket_to_native(sock), (const char *)buf, len, 0, (const struct sockaddr *)&addr->addr, addr->size);
}
non_null()
static int sys_recvfrom(void *obj, int sock, uint8_t *buf, size_t len, Network_Addr *addr) {
static int sys_recvfrom(void *obj, Socket sock, uint8_t *buf, size_t len, Network_Addr *addr)
{
socklen_t size = addr->size;
const int ret = recvfrom(sock, (char *)buf, len, 0, (struct sockaddr *)&addr->addr, &size);
const int ret = recvfrom(net_socket_to_native(sock), (char *)buf, len, 0, (struct sockaddr *)&addr->addr, &size);
addr->size = size;
return ret;
}
non_null()
static int sys_socket(void *obj, int domain, int type, int proto)
static Socket sys_socket(void *obj, int domain, int type, int proto)
{
return (int)socket(domain, type, proto);
return net_socket_from_native(socket(domain, type, proto));
}
non_null()
static int sys_socket_nonblock(void *obj, int sock, bool nonblock)
static int sys_socket_nonblock(void *obj, Socket sock, bool nonblock)
{
#ifdef OS_WIN32
u_long mode = nonblock ? 1 : 0;
return ioctlsocket(sock, FIONBIO, &mode);
return ioctlsocket(net_socket_to_native(sock), FIONBIO, &mode);
#else
return fcntl(sock, F_SETFL, O_NONBLOCK, nonblock ? 1 : 0);
return fcntl(net_socket_to_native(sock), F_SETFL, O_NONBLOCK, nonblock ? 1 : 0);
#endif /* OS_WIN32 */
}
non_null()
static int sys_getsockopt(void *obj, int sock, int level, int optname, void *optval, size_t *optlen)
static int sys_getsockopt(void *obj, Socket sock, int level, int optname, void *optval, size_t *optlen)
{
socklen_t len = *optlen;
const int ret = getsockopt(sock, level, optname, (char *)optval, &len);
const int ret = getsockopt(net_socket_to_native(sock), level, optname, (char *)optval, &len);
*optlen = len;
return ret;
}
non_null()
static int sys_setsockopt(void *obj, int sock, int level, int optname, const void *optval, size_t optlen)
static int sys_setsockopt(void *obj, Socket sock, int level, int optname, const void *optval, size_t optlen)
{
return setsockopt(sock, level, optname, (const char *)optval, optlen);
return setsockopt(net_socket_to_native(sock), level, optname, (const char *)optval, optlen);
}
static const Network_Funcs system_network_funcs = {
static const Network_Funcs os_network_funcs = {
sys_close,
sys_accept,
sys_bind,
@ -595,45 +601,45 @@ static const Network_Funcs system_network_funcs = {
sys_getsockopt,
sys_setsockopt,
};
static const Network system_network_obj = {&system_network_funcs};
static const Network os_network_obj = {&os_network_funcs};
const Network *system_network(void)
const Network *os_network(void)
{
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if ((true)) {
return nullptr;
}
#endif
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
#ifdef OS_WIN32
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) {
return nullptr;
}
#endif
return &system_network_obj;
#endif /* OS_WIN32 */
return &os_network_obj;
}
#if 0
/* TODO(iphydf): Call this from functions that use `system_network()`. */
void system_network_deinit(const Network *ns)
/* TODO(iphydf): Call this from functions that use `os_network()`. */
void os_network_deinit(const Network *ns)
{
#ifdef OS_WIN32
WSACleanup();
#endif
#endif /* OS_WIN32 */
}
#endif
#endif /* 0 */
non_null()
static int net_setsockopt(const Network *ns, Socket sock, int level, int optname, const void *optval, size_t optlen)
{
return ns->funcs->setsockopt(ns->obj, sock.sock, level, optname, optval, optlen);
return ns->funcs->setsockopt(ns->obj, sock, level, optname, optval, optlen);
}
non_null()
static int net_getsockopt(const Network *ns, Socket sock, int level, int optname, void *optval, size_t *optlen)
{
return ns->funcs->getsockopt(ns->obj, sock.sock, level, optname, optval, optlen);
return ns->funcs->getsockopt(ns->obj, sock, level, optname, optval, optlen);
}
non_null()
@ -808,23 +814,23 @@ static void loglogdata(const Logger *log, const char *message, const uint8_t *bu
int net_send(const Network *ns, const Logger *log,
Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port)
{
const int res = ns->funcs->send(ns->obj, sock.sock, buf, len);
const int res = ns->funcs->send(ns->obj, sock, buf, len);
loglogdata(log, "T=>", buf, len, ip_port, res);
return res;
}
non_null()
static int net_sendto(
const Network *ns,
Socket sock, const uint8_t *buf, size_t len, const Network_Addr *addr, const IP_Port *ip_port)
const Network *ns,
Socket sock, const uint8_t *buf, size_t len, const Network_Addr *addr, const IP_Port *ip_port)
{
return ns->funcs->sendto(ns->obj, sock.sock, buf, len, addr);
return ns->funcs->sendto(ns->obj, sock, buf, len, addr);
}
int net_recv(const Network *ns, const Logger *log,
Socket sock, uint8_t *buf, size_t len, const IP_Port *ip_port)
{
const int res = ns->funcs->recv(ns->obj, sock.sock, buf, len);
const int res = ns->funcs->recv(ns->obj, sock, buf, len);
loglogdata(log, "=>T", buf, len, ip_port, res);
return res;
}
@ -833,35 +839,34 @@ non_null()
static int net_recvfrom(const Network *ns,
Socket sock, uint8_t *buf, size_t len, Network_Addr *addr)
{
return ns->funcs->recvfrom(ns->obj, sock.sock, buf, len, addr);
return ns->funcs->recvfrom(ns->obj, sock, buf, len, addr);
}
int net_listen(const Network *ns, Socket sock, int backlog)
{
return ns->funcs->listen(ns->obj, sock.sock, backlog);
return ns->funcs->listen(ns->obj, sock, backlog);
}
non_null()
static int net_bind(const Network *ns, Socket sock, const Network_Addr *addr)
{
return ns->funcs->bind(ns->obj, sock.sock, addr);
return ns->funcs->bind(ns->obj, sock, addr);
}
Socket net_accept(const Network *ns, Socket sock)
{
const Socket newsock = {ns->funcs->accept(ns->obj, sock.sock)};
return newsock;
return ns->funcs->accept(ns->obj, sock);
}
/** Close the socket. */
void kill_sock(const Network *ns, Socket sock)
{
ns->funcs->close(ns->obj, sock.sock);
ns->funcs->close(ns->obj, sock);
}
bool set_socket_nonblock(const Network *ns, Socket sock)
{
return ns->funcs->socket_nonblock(ns->obj, sock.sock, true) == 0;
return ns->funcs->socket_nonblock(ns->obj, sock, true) == 0;
}
bool set_socket_nosigpipe(const Network *ns, Socket sock)
@ -871,7 +876,7 @@ bool set_socket_nosigpipe(const Network *ns, Socket sock)
return net_setsockopt(ns, sock, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof(int)) == 0;
#else
return true;
#endif
#endif /* __APPLE__ */
}
bool set_socket_reuseaddr(const Network *ns, Socket sock)
@ -894,7 +899,6 @@ bool set_socket_dualstack(const Network *ns, Socket sock)
return net_setsockopt(ns, sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only)) == 0;
}
typedef struct Packet_Handler {
packet_handler_cb *function;
void *object;
@ -1123,8 +1127,8 @@ void networking_poll(const Networking_Core *net, void *userdata)
* If error is non NULL it is set to 0 if no issues, 1 if socket related error, 2 if other.
*/
Networking_Core *new_networking_ex(
const Logger *log, const Memory *mem, const Network *ns, const IP *ip,
uint16_t port_from, uint16_t port_to, unsigned int *error)
const Logger *log, const Memory *mem, const Network *ns, const IP *ip,
uint16_t port_from, uint16_t port_to, unsigned int *error)
{
/* If both from and to are 0, use default port range
* If one is 0 and the other is non-0, use the non-0 value as only port
@ -1227,9 +1231,7 @@ Networking_Core *new_networking_ex(
/* Bind our socket to port PORT and the given IP address (usually 0.0.0.0 or ::) */
uint16_t *portptr = nullptr;
Network_Addr addr;
memset(&addr.addr, 0, sizeof(struct sockaddr_storage));
Network_Addr addr = {{0}};
if (net_family_is_ipv4(temp->family)) {
struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr.addr;
@ -1268,16 +1270,15 @@ Networking_Core *new_networking_ex(
#ifndef ESP_PLATFORM
/* multicast local nodes */
struct ipv6_mreq mreq;
memset(&mreq, 0, sizeof(mreq));
mreq.ipv6mr_multiaddr.s6_addr[ 0] = 0xFF;
mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02;
struct ipv6_mreq mreq = {{{{0}}}};
mreq.ipv6mr_multiaddr.s6_addr[0] = 0xFF;
mreq.ipv6mr_multiaddr.s6_addr[1] = 0x02;
mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01;
mreq.ipv6mr_interface = 0;
const int res = net_setsockopt(ns, temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
int neterror = net_error();
const int neterror = net_error();
char *strerror = net_new_strerror(neterror);
if (res < 0) {
@ -1287,7 +1288,7 @@ Networking_Core *new_networking_ex(
}
net_kill_strerror(strerror);
#endif
#endif /* ESP_PLATFORM */
}
/* A hanging program or a different user might block the standard port.
@ -1343,7 +1344,7 @@ Networking_Core *new_networking_ex(
}
Ip_Ntoa ip_str;
int neterror = net_error();
const int neterror = net_error();
char *strerror = net_new_strerror(neterror);
LOGGER_ERROR(log, "failed to bind socket: %d, %s IP: %s port_from: %u port_to: %u",
neterror, strerror, net_ip_ntoa(ip, &ip_str), port_from, port_to);
@ -1388,7 +1389,6 @@ void kill_networking(Networking_Core *net)
mem_delete(net->mem, net);
}
bool ip_equal(const IP *a, const IP *b)
{
if (a == nullptr || b == nullptr) {
@ -1444,6 +1444,63 @@ bool ipport_equal(const IP_Port *a, const IP_Port *b)
return ip_equal(&a->ip, &b->ip);
}
non_null()
static int ip4_cmp(const IP4 *a, const IP4 *b)
{
return cmp_uint(a->uint32, b->uint32);
}
non_null()
static int ip6_cmp(const IP6 *a, const IP6 *b)
{
const int res = cmp_uint(a->uint64[0], b->uint64[0]);
if (res != 0) {
return res;
}
return cmp_uint(a->uint64[1], b->uint64[1]);
}
non_null()
static int ip_cmp(const IP *a, const IP *b)
{
const int res = cmp_uint(a->family.value, b->family.value);
if (res != 0) {
return res;
}
switch (a->family.value) {
case TOX_AF_UNSPEC:
return 0;
case TOX_AF_INET:
case TCP_INET:
case TOX_TCP_INET:
return ip4_cmp(&a->ip.v4, &b->ip.v4);
case TOX_AF_INET6:
case TCP_INET6:
case TOX_TCP_INET6:
case TCP_SERVER_FAMILY: // these happen to be ipv6 according to TCP_server.c.
case TCP_CLIENT_FAMILY:
return ip6_cmp(&a->ip.v6, &b->ip.v6);
}
// Invalid, we don't compare any further and consider them equal.
return 0;
}
int ipport_cmp_handler(const void *a, const void *b, size_t size)
{
const IP_Port *ipp_a = (const IP_Port *)a;
const IP_Port *ipp_b = (const IP_Port *)b;
assert(size == sizeof(IP_Port));
const int ip_res = ip_cmp(&ipp_a->ip, &ipp_b->ip);
if (ip_res != 0) {
return ip_res;
}
return cmp_uint(ipp_a->port, ipp_b->port);
}
static const IP empty_ip = {{0}};
/** nulls out ip */
void ip_reset(IP *ip)
{
@ -1454,6 +1511,8 @@ void ip_reset(IP *ip)
*ip = empty_ip;
}
static const IP_Port empty_ip_port = {{{0}}};
/** nulls out ip_port */
void ipport_reset(IP_Port *ipport)
{
@ -1461,7 +1520,6 @@ void ipport_reset(IP_Port *ipport)
return;
}
const IP_Port empty_ip_port = {{{0}}};
*ipport = empty_ip_port;
}
@ -1472,7 +1530,7 @@ void ip_init(IP *ip, bool ipv6enabled)
return;
}
*ip = empty_ip;
ip_reset(ip);
ip->family = ipv6enabled ? net_family_ipv6() : net_family_ipv4();
}
@ -1517,7 +1575,151 @@ void ipport_copy(IP_Port *target, const IP_Port *source)
return;
}
*target = *source;
// Write to a temporary object first, so that padding bytes are
// uninitialised and msan can catch mistakes in downstream code.
IP_Port tmp;
tmp.ip.family = source->ip.family;
tmp.ip.ip = source->ip.ip;
tmp.port = source->port;
*target = tmp;
}
/** @brief Packs an IP structure.
*
* It's the caller's responsibility to make sure `is_ipv4` tells the truth. This
* function is an implementation detail of @ref bin_pack_ip_port.
*
* @param is_ipv4 whether this IP is an IP4 or IP6.
*
* @retval true on success.
*/
non_null()
static bool bin_pack_ip(Bin_Pack *bp, const IP *ip, bool is_ipv4)
{
if (is_ipv4) {
return bin_pack_bin_b(bp, ip->ip.v4.uint8, SIZE_IP4);
} else {
return bin_pack_bin_b(bp, ip->ip.v6.uint8, SIZE_IP6);
}
}
/** @brief Packs an IP_Port structure.
*
* @retval true on success.
*/
bool bin_pack_ip_port(Bin_Pack *bp, const Logger *logger, const IP_Port *ip_port)
{
bool is_ipv4;
uint8_t family;
if (net_family_is_ipv4(ip_port->ip.family)) {
// TODO(irungentoo): use functions to convert endianness
is_ipv4 = true;
family = TOX_AF_INET;
} else if (net_family_is_tcp_ipv4(ip_port->ip.family)) {
is_ipv4 = true;
family = TOX_TCP_INET;
} else if (net_family_is_ipv6(ip_port->ip.family)) {
is_ipv4 = false;
family = TOX_AF_INET6;
} else if (net_family_is_tcp_ipv6(ip_port->ip.family)) {
is_ipv4 = false;
family = TOX_TCP_INET6;
} else {
Ip_Ntoa ip_str;
// TODO(iphydf): Find out why we're trying to pack invalid IPs, stop
// doing that, and turn this into an error.
LOGGER_TRACE(logger, "cannot pack invalid IP: %s", net_ip_ntoa(&ip_port->ip, &ip_str));
return false;
}
return bin_pack_u08_b(bp, family)
&& bin_pack_ip(bp, &ip_port->ip, is_ipv4)
&& bin_pack_u16_b(bp, net_ntohs(ip_port->port));
}
non_null()
static bool bin_pack_ip_port_handler(const void *obj, const Logger *logger, Bin_Pack *bp)
{
const IP_Port *ip_port = (const IP_Port *)obj;
return bin_pack_ip_port(bp, logger, ip_port);
}
int pack_ip_port(const Logger *logger, uint8_t *data, uint16_t length, const IP_Port *ip_port)
{
const uint32_t size = bin_pack_obj_size(bin_pack_ip_port_handler, ip_port, logger);
if (size > length) {
return -1;
}
if (!bin_pack_obj(bin_pack_ip_port_handler, ip_port, logger, data, length)) {
return -1;
}
assert(size < INT_MAX);
return (int)size;
}
int unpack_ip_port(IP_Port *ip_port, const uint8_t *data, uint16_t length, bool tcp_enabled)
{
if (data == nullptr) {
return -1;
}
bool is_ipv4;
Family host_family;
if (data[0] == TOX_AF_INET) {
is_ipv4 = true;
host_family = net_family_ipv4();
} else if (data[0] == TOX_TCP_INET) {
if (!tcp_enabled) {
return -1;
}
is_ipv4 = true;
host_family = net_family_tcp_ipv4();
} else if (data[0] == TOX_AF_INET6) {
is_ipv4 = false;
host_family = net_family_ipv6();
} else if (data[0] == TOX_TCP_INET6) {
if (!tcp_enabled) {
return -1;
}
is_ipv4 = false;
host_family = net_family_tcp_ipv6();
} else {
return -1;
}
ipport_reset(ip_port);
if (is_ipv4) {
const uint32_t size = 1 + SIZE_IP4 + sizeof(uint16_t);
if (size > length) {
return -1;
}
ip_port->ip.family = host_family;
memcpy(ip_port->ip.ip.v4.uint8, data + 1, SIZE_IP4);
memcpy(&ip_port->port, data + 1 + SIZE_IP4, sizeof(uint16_t));
return size;
} else {
const uint32_t size = 1 + SIZE_IP6 + sizeof(uint16_t);
if (size > length) {
return -1;
}
ip_port->ip.family = host_family;
memcpy(ip_port->ip.ip.v6.uint8, data + 1, SIZE_IP6);
memcpy(&ip_port->port, data + 1 + SIZE_IP6, sizeof(uint16_t));
return size;
}
}
const char *net_ip_ntoa(const IP *ip, Ip_Ntoa *ip_str)
@ -1622,7 +1824,7 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr
if ((true)) {
return 0;
}
#endif
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
if (address == nullptr || to == nullptr) {
return 0;
@ -1631,8 +1833,7 @@ 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;
memset(&hints, 0, sizeof(hints));
struct addrinfo hints = {0};
hints.ai_family = family;
hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
@ -1750,14 +1951,14 @@ bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Por
if ((true)) {
return true;
}
#endif
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
Ip_Ntoa ip_str;
LOGGER_DEBUG(log, "connecting socket %d to %s:%d",
(int)sock.sock, net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port));
net_socket_to_native(sock), net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port));
errno = 0;
if (connect(sock.sock, (struct sockaddr *)&addr, addrsize) == -1) {
if (connect(net_socket_to_native(sock), (struct sockaddr *)&addr, addrsize) == -1) {
const int error = net_error();
// Non-blocking socket: "Operation in progress" means it's connecting.
@ -1807,7 +2008,7 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to
*res = ip_port;
return 1;
}
#endif
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
// It's not an IP address, so now we try doing a DNS lookup.
struct addrinfo *infos;
@ -1823,7 +2024,7 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to
size_t count = 0;
for (struct addrinfo *cur = infos; count < max_count && cur != nullptr; cur = cur->ai_next) {
if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {
if (cur->ai_socktype != 0 && type > 0 && cur->ai_socktype != type) {
continue;
}
@ -1852,16 +2053,16 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to
*res = ip_port;
for (struct addrinfo *cur = infos; cur != nullptr; cur = cur->ai_next) {
if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {
if (cur->ai_socktype != 0 && type > 0 && cur->ai_socktype != type) {
continue;
}
if (cur->ai_family == AF_INET) {
const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)cur->ai_addr;
memcpy(&ip_port->ip.ip.v4, &addr->sin_addr, sizeof(IP4));
ip_port->ip.ip.v4.uint32 = addr->sin_addr.s_addr;
} else if (cur->ai_family == AF_INET6) {
const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(const void *)cur->ai_addr;
memcpy(&ip_port->ip.ip.v6, &addr->sin6_addr, sizeof(IP6));
memcpy(ip_port->ip.ip.v6.uint8, addr->sin6_addr.s6_addr, sizeof(IP6));
} else {
continue;
}
@ -1917,13 +2118,12 @@ Socket net_socket(const Network *ns, Family domain, int type, int protocol)
const int platform_domain = make_family(domain);
const int platform_type = make_socktype(type);
const int platform_prot = make_proto(protocol);
const Socket sock = {ns->funcs->socket(ns->obj, platform_domain, platform_type, platform_prot)};
return sock;
return ns->funcs->socket(ns->obj, platform_domain, platform_type, platform_prot);
}
uint16_t net_socket_data_recv_buffer(const Network *ns, Socket sock)
{
const int count = ns->funcs->recvbuf(ns->obj, sock.sock);
const int count = ns->funcs->recvbuf(ns->obj, sock);
return (uint16_t)max_s32(0, min_s32(count, UINT16_MAX));
}
@ -2019,14 +2219,14 @@ bool ipv6_ipv4_in_v6(const IP6 *a)
int net_error(void)
{
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#ifdef OS_WIN32
return WSAGetLastError();
#else
return errno;
#endif
#endif /* OS_WIN32 */
}
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#ifdef OS_WIN32
char *net_new_strerror(int error)
{
char *str = nullptr;
@ -2066,7 +2266,7 @@ static const char *net_strerror_r(int error, char *tmp, size_t tmp_size)
return tmp;
}
#endif
#endif /* GNU */
char *net_new_strerror(int error)
{
char tmp[256];
@ -2086,13 +2286,13 @@ char *net_new_strerror(int error)
return str;
}
#endif
#endif /* OS_WIN32 */
void net_kill_strerror(char *strerror)
{
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#ifdef OS_WIN32
LocalFree((char *)strerror);
#else
free(strerror);
#endif
#endif /* OS_WIN32 */
}