Coverage Report

Created: 2026-10-24 08:16

/work/toxcore/network.h
Line
Count
Source
1
/* SPDX-License-Identifier: GPL-3.0-or-later
2
 * Copyright © 2016-2026 The TokTok team.
3
 * Copyright © 2013 Tox project.
4
 */
5
6
/**
7
 * Datatypes, functions and includes for the core networking.
8
 */
9
#ifndef C_TOXCORE_TOXCORE_NETWORK_H
10
#define C_TOXCORE_TOXCORE_NETWORK_H
11
12
#include <stdbool.h>    // bool
13
#include <stddef.h>     // size_t
14
#include <stdint.h>     // uint*_t
15
16
#include "attributes.h"
17
#include "bin_pack.h"
18
#include "logger.h"
19
#include "mem.h"
20
#include "net.h"
21
#include "net_profile.h"
22
#include "os_network.h"
23
24
#ifdef __cplusplus
25
extern "C" {
26
#endif
27
28
1.16M
#define MAX_UDP_PACKET_SIZE 2048
29
30
typedef enum Net_Packet_Type {
31
    NET_PACKET_PING_REQUEST         = 0x00, /* Ping request packet ID. */
32
    NET_PACKET_PING_RESPONSE        = 0x01, /* Ping response packet ID. */
33
    NET_PACKET_NODES_REQUEST        = 0x02, /* Nodes request packet ID. */
34
    NET_PACKET_NODES_RESPONSE       = 0x04, /* Nodes response packet ID. */
35
    NET_PACKET_COOKIE_REQUEST       = 0x18, /* Cookie request packet */
36
    NET_PACKET_COOKIE_RESPONSE      = 0x19, /* Cookie response packet */
37
    NET_PACKET_CRYPTO_HS            = 0x1a, /* Crypto handshake packet */
38
    NET_PACKET_CRYPTO_DATA          = 0x1b, /* Crypto data packet */
39
    NET_PACKET_CRYPTO               = 0x20, /* Encrypted data packet ID. */
40
    NET_PACKET_LAN_DISCOVERY        = 0x21, /* LAN discovery packet ID. */
41
42
    NET_PACKET_GC_HANDSHAKE         = 0x5a, /* Group chat handshake packet ID */
43
    NET_PACKET_GC_LOSSLESS          = 0x5b, /* Group chat lossless packet ID */
44
    NET_PACKET_GC_LOSSY             = 0x5c, /* Group chat lossy packet ID */
45
46
    /* See: `docs/Prevent_Tracking.txt` and `onion.{c,h}` */
47
    NET_PACKET_ONION_SEND_INITIAL   = 0x80,
48
    NET_PACKET_ONION_SEND_1         = 0x81,
49
    NET_PACKET_ONION_SEND_2         = 0x82,
50
51
    NET_PACKET_ANNOUNCE_REQUEST_OLD  = 0x83, /* TODO: DEPRECATE */
52
    NET_PACKET_ANNOUNCE_RESPONSE_OLD = 0x84, /* TODO: DEPRECATE */
53
54
    NET_PACKET_ONION_DATA_REQUEST   = 0x85,
55
    NET_PACKET_ONION_DATA_RESPONSE  = 0x86,
56
    NET_PACKET_ANNOUNCE_REQUEST     = 0x87,
57
    NET_PACKET_ANNOUNCE_RESPONSE    = 0x88,
58
59
    NET_PACKET_ONION_RECV_3         = 0x8c,
60
    NET_PACKET_ONION_RECV_2         = 0x8d,
61
    NET_PACKET_ONION_RECV_1         = 0x8e,
62
63
    NET_PACKET_FORWARD_REQUEST      = 0x90,
64
    NET_PACKET_FORWARDING           = 0x91,
65
    NET_PACKET_FORWARD_REPLY        = 0x92,
66
67
    NET_PACKET_DATA_SEARCH_REQUEST     = 0x93,
68
    NET_PACKET_DATA_SEARCH_RESPONSE    = 0x94,
69
    NET_PACKET_DATA_RETRIEVE_REQUEST   = 0x95,
70
    NET_PACKET_DATA_RETRIEVE_RESPONSE  = 0x96,
71
    NET_PACKET_STORE_ANNOUNCE_REQUEST  = 0x97,
72
    NET_PACKET_STORE_ANNOUNCE_RESPONSE = 0x98,
73
74
    BOOTSTRAP_INFO_PACKET_ID        = 0xf0, /* Only used for bootstrap nodes */
75
76
    NET_PACKET_MAX                  = 0xff, /* This type must remain within a single uint8. */
77
} Net_Packet_Type;
78
79
3.73k
#define TOX_PORTRANGE_FROM 33445
80
1.57k
#define TOX_PORTRANGE_TO   33545
81
353
#define TOX_PORT_DEFAULT   TOX_PORTRANGE_FROM
82
83
IP4 get_ip4_loopback(void);
84
IP4 get_ip4_broadcast(void);
85
86
IP6 get_ip6_loopback(void);
87
IP6 get_ip6_broadcast(void);
88
89
Socket net_socket(const Network *_Nonnull ns, Family domain, int type, int protocol);
90
91
/**
92
 * Check if socket is valid.
93
 *
94
 * @return true if valid, false otherwise.
95
 */
96
bool sock_valid(Socket sock);
97
98
/**
99
 * Calls send(sockfd, buf, len, MSG_NOSIGNAL).
100
 *
101
 * @param ns System network object.
102
 * @param log Logger object.
103
 * @param sock Socket to send data with.
104
 * @param buf Data to send.
105
 * @param len Length of data.
106
 * @param ip_port IP and port to send data to.
107
 * @param net_profile Network profile to record the packet.
108
 */
109
int net_send(const Network *_Nonnull ns, const Logger *_Nonnull log, Socket sock, const uint8_t *_Nonnull buf, size_t len, const IP_Port *_Nonnull ip_port,
110
             Net_Profile *_Nullable net_profile);
111
/**
112
 * Calls recv(sockfd, buf, len, MSG_NOSIGNAL).
113
 *
114
 * @param ns System network object.
115
 * @param log Logger object.
116
 * @param sock Socket to receive data with.
117
 * @param buf Buffer to store received data.
118
 * @param len Length of buffer.
119
 * @param ip_port IP and port of the sender.
120
 */
121
int net_recv(const Network *_Nonnull ns, const Logger *_Nonnull log, Socket sock, uint8_t *_Nonnull buf, size_t len, const IP_Port *_Nonnull ip_port);
122
/**
123
 * Calls listen(sockfd, backlog).
124
 */
125
int net_listen(const Network *_Nonnull ns, Socket sock, int backlog);
126
/**
127
 * Calls accept(sockfd, nullptr, nullptr).
128
 */
129
Socket net_accept(const Network *_Nonnull ns, Socket sock);
130
131
/**
132
 * return the size of data in the tcp recv buffer.
133
 * return 0 on failure.
134
 */
135
uint16_t net_socket_data_recv_buffer(const Network *_Nonnull ns, Socket sock);
136
137
/** Does the IP6 struct a contain an IPv4 address in an IPv6 one? */
138
bool ipv6_ipv4_in_v6(const IP6 *_Nonnull a);
139
140
#define TOX_ENABLE_IPV6_DEFAULT true
141
142
#define TOX_INET6_ADDRSTRLEN 66
143
#define TOX_INET_ADDRSTRLEN 22
144
145
/** this would be TOX_INET6_ADDRSTRLEN, but it might be too short for the error message */
146
#define IP_NTOA_LEN 96 // TODO(irungentoo): magic number. Why not INET6_ADDRSTRLEN ?
147
148
/** Contains a null terminated string of an IP address. */
149
typedef struct Ip_Ntoa {
150
    char     buf[IP_NTOA_LEN];  // a string formatted IP address or an error message.
151
    uint16_t length;  // the length of the string (not including the null byte).
152
    bool     ip_is_valid;  // if this is false `buf` will contain an error message.
153
} Ip_Ntoa;
154
155
/** @brief Converts IP into a null terminated string.
156
 *
157
 * Writes error message into the buffer on error.
158
 *
159
 * @param ip_str contains a buffer of the required size.
160
 *
161
 * @return Pointer to the buffer inside `ip_str` containing the IP string.
162
 */
163
const char *_Nonnull net_ip_ntoa(const IP *_Nonnull ip, Ip_Ntoa *_Nonnull ip_str);
164
165
/**
166
 * Parses IP structure into an address string.
167
 *
168
 * @param ip IP of TOX_AF_INET or TOX_AF_INET6 families.
169
 * @param length length of the address buffer.
170
 *   Must be at least TOX_INET_ADDRSTRLEN for TOX_AF_INET
171
 *   and TOX_INET6_ADDRSTRLEN for TOX_AF_INET6
172
 *
173
 * @param address dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6).
174
 *
175
 * @return true on success, false on failure.
176
 */
177
bool ip_parse_addr(const IP *_Nonnull ip, char *_Nonnull address, size_t length);
178
179
/**
180
 * Directly parses the input into an IP structure.
181
 *
182
 * Tries IPv4 first, then IPv6.
183
 *
184
 * @param address dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6).
185
 * @param to family and the value is set on success.
186
 *
187
 * @return true on success, false on failure.
188
 */
189
bool addr_parse_ip(const char *_Nonnull address, IP *_Nonnull to);
190
191
/**
192
 * Compares two IP structures.
193
 *
194
 * Unset means unequal.
195
 *
196
 * @return false when not equal or when uninitialized.
197
 */
198
bool ip_equal(const IP *_Nullable a, const IP *_Nullable b);
199
/**
200
 * Compares two IP_Port structures.
201
 *
202
 * Unset means unequal.
203
 *
204
 * @return false when not equal or when uninitialized.
205
 */
206
bool ipport_equal(const IP_Port *_Nullable a, const IP_Port *_Nullable b);
207
/**
208
 * @brief IP_Port comparison function with `memcmp` signature.
209
 *
210
 * Casts the void pointers to `IP_Port *` for comparison.
211
 *
212
 * @retval -1 if `a < b`
213
 * @retval 0 if `a == b`
214
 * @retval 1 if `a > b`
215
 */
216
int ipport_cmp_handler(const void *_Nonnull a, const void *_Nonnull b, size_t size);
217
218
/** nulls out ip */
219
void ip_reset(IP *_Nonnull ip);
220
/** nulls out ip_port */
221
void ipport_reset(IP_Port *_Nonnull ipport);
222
/** nulls out ip, sets family according to flag */
223
void ip_init(IP *_Nonnull ip, bool ipv6enabled);
224
/** checks if ip is valid */
225
bool ip_isset(const IP *_Nonnull ip);
226
/** checks if ip is valid */
227
bool ipport_isset(const IP_Port *_Nonnull ipport);
228
/** copies an ip structure (careful about direction) */
229
void ip_copy(IP *_Nonnull target, const IP *_Nonnull source);
230
/** copies an ip_port structure (careful about direction) */
231
void ipport_copy(IP_Port *_Nonnull target, const IP_Port *_Nonnull source);
232
233
/**
234
 * @brief Resolves string into an IP address.
235
 *
236
 * @param[in,out] ns Network object.
237
 * @param[in] address a hostname (or something parseable to an IP address).
238
 * @param[in,out] to to.family MUST be initialized, either set to a specific IP version
239
 *   (TOX_AF_INET/TOX_AF_INET6) or to the unspecified TOX_AF_UNSPEC (0), if both
240
 *   IP versions are acceptable.
241
 * @param[out] extra can be NULL and is only set in special circumstances, see returns.
242
 * @param[in] dns_enabled if false, DNS resolution is skipped.
243
 *
244
 * Returns in `*to` a matching address (IPv6 or IPv4).
245
 * Returns in `*extra`, if not NULL, an IPv4 address, if `to->family` was `TOX_AF_UNSPEC`.
246
 *
247
 * @return true on success, false on failure
248
 */
249
bool addr_resolve_or_parse_ip(const Network *_Nonnull ns, const Memory *_Nonnull mem, const char *_Nonnull address, IP *_Nonnull to, IP *_Nullable extra, bool dns_enabled);
250
/** @brief Function to receive data, ip and port of sender is put into ip_port.
251
 * Packet data is put into data.
252
 * Packet length is put into length.
253
 */
254
typedef int packet_handler_cb(void *_Nullable object, const IP_Port *_Nonnull source, const uint8_t *_Nonnull packet, uint16_t length, void *_Nullable userdata);
255
256
typedef struct Networking_Core Networking_Core;
257
258
Family net_family(const Networking_Core *_Nonnull net);
259
uint16_t net_port(const Networking_Core *_Nonnull net);
260
261
/** Close the socket. */
262
void kill_sock(const Network *_Nonnull ns, Socket sock);
263
264
/**
265
 * Set socket as nonblocking
266
 *
267
 * @return true on success, false on failure.
268
 */
269
bool set_socket_nonblock(const Network *_Nonnull ns, Socket sock);
270
271
/**
272
 * Set socket to not emit SIGPIPE
273
 *
274
 * @return true on success, false on failure.
275
 */
276
bool set_socket_nosigpipe(const Network *_Nonnull ns, Socket sock);
277
278
/**
279
 * Enable SO_REUSEADDR on socket.
280
 *
281
 * @return true on success, false on failure.
282
 */
283
bool set_socket_reuseaddr(const Network *_Nonnull ns, Socket sock);
284
285
/**
286
 * Set socket to dual (IPv4 + IPv6 socket)
287
 *
288
 * @return true on success, false on failure.
289
 */
290
bool set_socket_dualstack(const Network *_Nonnull ns, Socket sock);
291
292
/* Basic network functions: */
293
294
/**
295
 * An outgoing network packet.
296
 *
297
 * Use `net_send_packet` to send it to an IP/port endpoint.
298
 */
299
typedef struct Net_Packet {
300
    const uint8_t *_Nonnull data;
301
    uint16_t length;
302
} Net_Packet;
303
304
/**
305
 * Check for the situation when socket TOX_AF_INET, but target IP is not. And log the error.
306
 * This function can be used for UDP sockets only.
307
 *
308
 * @return true if socket is compatible with address.
309
 */
310
bool net_socket_family_compatible(const Networking_Core *_Nonnull net, const IP_Port *_Nonnull ip_port, bool log_warning);
311
312
/**
313
 * Function to send a network packet to a given IP/port.
314
 */
315
int net_send_packet(const Networking_Core *_Nonnull net, const IP_Port *_Nonnull ip_port, Net_Packet packet);
316
317
/**
318
 * Function to send packet(data) of length length to ip_port.
319
 *
320
 * @deprecated Use net_send_packet instead.
321
 */
322
int sendpacket(const Networking_Core *_Nonnull net, const IP_Port *_Nonnull ip_port, const uint8_t *_Nonnull data, uint16_t length);
323
324
/** Function to call when packet beginning with byte is received. */
325
void networking_registerhandler(Networking_Core *_Nonnull net, uint8_t byte, packet_handler_cb *_Nullable cb, void *_Nullable object);
326
/** Call this several times a second. */
327
void networking_poll(const Networking_Core *_Nonnull net, void *_Nullable userdata);
328
typedef enum Net_Err_Connect {
329
    NET_ERR_CONNECT_OK,
330
    NET_ERR_CONNECT_INVALID_FAMILY,
331
    NET_ERR_CONNECT_FAILED,
332
} Net_Err_Connect;
333
334
const char *_Nonnull net_err_connect_to_string(Net_Err_Connect err);
335
336
/** @brief Connect a socket to the address specified by the ip_port.
337
 *
338
 * @param[out] err Set to NET_ERR_CONNECT_OK on success, otherwise an error code.
339
 *
340
 * @retval true on success, false on failure.
341
 */
342
bool net_connect(const Network *_Nonnull ns, const Memory *_Nonnull mem, const Logger *_Nonnull log, Socket sock, const IP_Port *_Nonnull ip_port, Net_Err_Connect *_Nonnull err);
343
344
/** @brief High-level getaddrinfo implementation.
345
 *
346
 * Given node, which identifies an Internet host, `net_getipport()` fills an array
347
 * with one or more IP_Port structures, each of which contains an Internet
348
 * address that can be specified by calling `net_connect()`, the port is ignored.
349
 *
350
 * Skip all addresses with socktype != type (use type = -1 to get all addresses)
351
 * To correctly deallocate array memory use `net_freeipport()`.
352
 *
353
 * @param ns Network object.
354
 * @param mem Memory allocator.
355
 * @param node The node parameter identifies the host or service on which to connect.
356
 * @param[out] res An array of IP_Port structures will be allocated into this pointer.
357
 * @param tox_type The type of socket to use (stream or datagram), only relevant for DNS lookups.
358
 * @param dns_enabled If false, DNS resolution is skipped, when passed a hostname, this function will return an error.
359
 *
360
 * @return number of elements in res array.
361
 * @retval 0 if res array empty.
362
 * @retval -1 on error.
363
 */
364
int32_t net_getipport(const Network *_Nonnull ns, const Memory *_Nonnull mem, const char *_Nonnull node, IP_Port *_Nullable *_Nonnull res, int tox_type, bool dns_enabled);
365
366
/** Deallocates memory allocated by net_getipport */
367
void net_freeipport(const Memory *_Nonnull mem, IP_Port *_Nullable ip_ports);
368
bool bin_pack_ip_port(Bin_Pack *_Nonnull bp, const Logger *_Nonnull logger, const IP_Port *_Nonnull ip_port);
369
370
/** @brief Pack an IP_Port structure into data of max size length.
371
 *
372
 * Packed_length is the offset of data currently packed.
373
 *
374
 * @return size of packed IP_Port data on success.
375
 * @retval -1 on failure.
376
 */
377
int pack_ip_port(const Logger *_Nonnull logger, uint8_t *_Nonnull data, uint16_t length, const IP_Port *_Nonnull ip_port);
378
379
/** @brief Unpack IP_Port structure from data of max size length into ip_port.
380
 *
381
 * len_processed is the offset of data currently unpacked.
382
 *
383
 * @return size of unpacked ip_port on success.
384
 * @retval -1 on failure.
385
 */
386
int unpack_ip_port(IP_Port *_Nonnull ip_port, const uint8_t *_Nonnull data, uint16_t length, bool tcp_enabled);
387
388
/**
389
 * @return true on success, false on failure.
390
 */
391
bool bind_to_port(const Network *_Nonnull ns, Socket sock, Family family, uint16_t port);
392
393
/** @brief Initialize networking.
394
 * Bind to ip and port.
395
 * ip must be in network order EX: 127.0.0.1 = (7F000001).
396
 * port is in host byte order (this means don't worry about it).
397
 *
398
 * @return Networking_Core object if no problems
399
 * @retval NULL if there are problems.
400
 *
401
 * If error is non NULL it is set to 0 if no issues, 1 if socket related error, 2 if other.
402
 */
403
Networking_Core *_Nullable new_networking_ex(
404
    const Logger *_Nonnull log, const Memory *_Nonnull mem, const Network *_Nonnull ns, const IP *_Nonnull ip,
405
    uint16_t port_from, uint16_t port_to, unsigned int *_Nullable error);
406
Networking_Core *_Nullable new_networking_no_udp(const Logger *_Nonnull log, const Memory *_Nonnull mem, const Network *_Nonnull ns);
407
408
/** Function to cleanup networking stuff (doesn't do much right now). */
409
void kill_networking(Networking_Core *_Nullable net);
410
/** @brief Returns a pointer to the network net_profile object associated with `net`.
411
 *
412
 * Returns null if `net` is null.
413
 */
414
const Net_Profile *_Nullable net_get_net_profile(const Networking_Core *_Nonnull net);
415
416
#ifdef __cplusplus
417
} /* extern "C" */
418
#endif
419
420
#endif /* C_TOXCORE_TOXCORE_NETWORK_H */