/work/toxcore/onion_client.h
Line | Count | Source |
1 | | /* SPDX-License-Identifier: GPL-3.0-or-later |
2 | | * Copyright © 2016-2025 The TokTok team. |
3 | | * Copyright © 2013 Tox project. |
4 | | */ |
5 | | |
6 | | /** |
7 | | * Implementation of the client part of docs/Prevent_Tracking.txt (The part that |
8 | | * uses the onion stuff to connect to the friend) |
9 | | */ |
10 | | #ifndef C_TOXCORE_TOXCORE_ONION_CLIENT_H |
11 | | #define C_TOXCORE_TOXCORE_ONION_CLIENT_H |
12 | | |
13 | | #include <stdbool.h> |
14 | | |
15 | | #include "DHT.h" |
16 | | #include "attributes.h" |
17 | | #include "crypto_core.h" |
18 | | #include "logger.h" |
19 | | #include "mem.h" |
20 | | #include "mono_time.h" |
21 | | #include "net_crypto.h" |
22 | | #include "network.h" |
23 | | #include "onion_announce.h" |
24 | | #include "ping_array.h" |
25 | | |
26 | 285k | #define MAX_ONION_CLIENTS 8 |
27 | 669k | #define MAX_ONION_CLIENTS_ANNOUNCE 12 // Number of nodes to announce ourselves to. |
28 | 325k | #define ONION_NODE_PING_INTERVAL 15 |
29 | 49.0k | #define ONION_NODE_TIMEOUT ONION_NODE_PING_INTERVAL |
30 | | |
31 | | /** The interval in seconds at which to tell our friends where we are */ |
32 | 8.27k | #define ONION_DHTPK_SEND_INTERVAL 30 |
33 | 8.27k | #define DHT_DHTPK_SEND_INTERVAL 20 |
34 | | |
35 | 716k | #define NUMBER_ONION_PATHS 6 |
36 | | |
37 | | /** |
38 | | * The timeout the first time the path is added and |
39 | | * then for all the next consecutive times |
40 | | */ |
41 | 40.3k | #define ONION_PATH_FIRST_TIMEOUT 4 |
42 | 353k | #define ONION_PATH_TIMEOUT 10 |
43 | 186k | #define ONION_PATH_MAX_LIFETIME 1200 |
44 | 388k | #define ONION_PATH_MAX_NO_RESPONSE_USES 4 |
45 | | |
46 | 192k | #define MAX_STORED_PINGED_NODES 9 |
47 | 169k | #define MIN_NODE_PING_TIME 10 |
48 | | |
49 | 1.99M | #define ONION_NODE_MAX_PINGS 3 |
50 | | |
51 | 1.68M | #define MAX_PATH_NODES 32 |
52 | | |
53 | 366 | #define GCA_MAX_DATA_LENGTH GCA_PUBLIC_ANNOUNCE_MAX_SIZE |
54 | | |
55 | | /** |
56 | | * If no announce response packets are received within this interval tox will |
57 | | * be considered offline. We give time for a node to be pinged often enough |
58 | | * that it times out, which leads to the network being thoroughly tested as it |
59 | | * is replaced. |
60 | | */ |
61 | 20.4k | #define ONION_OFFLINE_TIMEOUT (ONION_NODE_PING_INTERVAL * (ONION_NODE_MAX_PINGS+2)) |
62 | | |
63 | | /** Onion data packet ids. */ |
64 | | #define ONION_DATA_FRIEND_REQ CRYPTO_PACKET_FRIEND_REQ |
65 | 17.6k | #define ONION_DATA_DHTPK CRYPTO_PACKET_DHTPK |
66 | | |
67 | | typedef struct Onion_Client Onion_Client; |
68 | | |
69 | | DHT *_Nonnull onion_get_dht(const Onion_Client *_Nonnull onion_c); |
70 | | Net_Crypto *_Nonnull onion_get_net_crypto(const Onion_Client *_Nonnull onion_c); |
71 | | |
72 | | /** @brief Add a node to the path_nodes bootstrap array. |
73 | | * |
74 | | * If a node with the given public key was already in the bootstrap array, this function has no |
75 | | * effect and returns successfully. There is currently no way to update the IP/port for a bootstrap |
76 | | * node, so if it changes, the Onion_Client must be recreated. |
77 | | * |
78 | | * @param onion_c The onion client object. |
79 | | * @param ip_port IP/port for the bootstrap node. |
80 | | * @param public_key DHT public key for the bootstrap node. |
81 | | * |
82 | | * @retval false on failure |
83 | | * @retval true on success |
84 | | */ |
85 | | bool onion_add_bs_path_node(Onion_Client *_Nonnull onion_c, const IP_Port *_Nonnull ip_port, const uint8_t *_Nonnull public_key); |
86 | | |
87 | | /** @brief Put up to max_num nodes in nodes. |
88 | | * |
89 | | * return the number of nodes. |
90 | | */ |
91 | | uint16_t onion_backup_nodes(const Onion_Client *_Nonnull onion_c, Node_format *_Nonnull nodes, uint16_t max_num); |
92 | | |
93 | | /** @brief Get the friend_num of a friend. |
94 | | * |
95 | | * return -1 on failure. |
96 | | * return friend number on success. |
97 | | */ |
98 | | int onion_friend_num(const Onion_Client *_Nonnull onion_c, const uint8_t *_Nonnull public_key); |
99 | | |
100 | | /** @brief Add a friend who we want to connect to. |
101 | | * |
102 | | * return -1 on failure. |
103 | | * return the friend number on success or if the friend was already added. |
104 | | */ |
105 | | int onion_addfriend(Onion_Client *_Nonnull onion_c, const uint8_t *_Nonnull public_key); |
106 | | |
107 | | /** @brief Delete a friend. |
108 | | * |
109 | | * return -1 on failure. |
110 | | * return the deleted friend number on success. |
111 | | */ |
112 | | int onion_delfriend(Onion_Client *_Nonnull onion_c, int friend_num); |
113 | | |
114 | | /** @brief Set if friend is online or not. |
115 | | * |
116 | | * NOTE: This function is there and should be used so that we don't send |
117 | | * useless packets to the friend if they are online. |
118 | | * |
119 | | * return -1 on failure. |
120 | | * return 0 on success. |
121 | | */ |
122 | | int onion_set_friend_online(Onion_Client *_Nonnull onion_c, int friend_num, bool is_online); |
123 | | |
124 | | /** @brief Get the ip of friend friendnum and put it in ip_port |
125 | | * |
126 | | * @retval -1 if public_key does NOT refer to a friend |
127 | | * @retval 0 if public_key refers to a friend and we failed to find the friend (yet) |
128 | | * @retval 1 if public_key refers to a friend and we found them |
129 | | */ |
130 | | int onion_getfriendip(const Onion_Client *_Nonnull onion_c, int friend_num, IP_Port *_Nonnull ip_port); |
131 | | |
132 | | typedef int recv_tcp_relay_cb(void *_Nonnull object, uint32_t number, const IP_Port *_Nonnull ip_port, const uint8_t *_Nonnull public_key); |
133 | | |
134 | | /** @brief Set the function for this friend that will be callbacked with object and number |
135 | | * when that friend gives us one of the TCP relays they are connected to. |
136 | | * |
137 | | * object and number will be passed as argument to this function. |
138 | | * |
139 | | * return -1 on failure. |
140 | | * return 0 on success. |
141 | | */ |
142 | | int recv_tcp_relay_handler(Onion_Client *_Nonnull onion_c, int friend_num, recv_tcp_relay_cb *_Nonnull callback, void *_Nonnull object, uint32_t number); |
143 | | |
144 | | typedef void onion_dht_pk_cb(void *_Nonnull object, int32_t number, const uint8_t *_Nonnull dht_public_key, void *_Nullable userdata); |
145 | | |
146 | | /** @brief Set the function for this friend that will be callbacked with object and number |
147 | | * when that friend gives us their DHT temporary public key. |
148 | | * |
149 | | * object and number will be passed as argument to this function. |
150 | | * |
151 | | * return -1 on failure. |
152 | | * return 0 on success. |
153 | | */ |
154 | | int onion_dht_pk_callback(Onion_Client *_Nonnull onion_c, int friend_num, onion_dht_pk_cb *_Nonnull function, void *_Nonnull object, uint32_t number); |
155 | | |
156 | | /** @brief Set a friend's DHT public key. |
157 | | * |
158 | | * return -1 on failure. |
159 | | * return 0 on success. |
160 | | */ |
161 | | int onion_set_friend_dht_pubkey(Onion_Client *_Nonnull onion_c, int friend_num, const uint8_t *_Nonnull dht_key); |
162 | | |
163 | | /** @brief Copy friends DHT public key into dht_key. |
164 | | * |
165 | | * return 0 on failure (no key copied). |
166 | | * return 1 on success (key copied). |
167 | | */ |
168 | | unsigned int onion_getfriend_dht_pubkey(const Onion_Client *_Nonnull onion_c, int friend_num, uint8_t *_Nonnull dht_key); |
169 | | |
170 | 41.0k | #define ONION_DATA_IN_RESPONSE_MIN_SIZE (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE) |
171 | | |
172 | | // TODO(Jfreegman): This is not the correct value; data this large will be dropped by the onion client. |
173 | 20.8k | #define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE) |
174 | | |
175 | | /** @brief Send data of length length to friendnum. |
176 | | * Maximum length of data is ONION_CLIENT_MAX_DATA_SIZE. |
177 | | * This data will be received by the friend using the Onion_Data_Handlers callbacks. |
178 | | * |
179 | | * Even if this function succeeds, the friend might not receive any data. |
180 | | * |
181 | | * return the number of packets sent on success |
182 | | * return -1 on failure. |
183 | | */ |
184 | | int send_onion_data(Onion_Client *_Nonnull onion_c, int friend_num, const uint8_t *_Nonnull data, uint16_t length); |
185 | | |
186 | | typedef int oniondata_handler_cb(void *_Nullable object, const uint8_t *_Nonnull source_pubkey, const uint8_t *_Nonnull data, |
187 | | uint16_t length, void *_Nullable userdata); |
188 | | |
189 | | /** Function to call when onion data packet with contents beginning with byte is received. */ |
190 | | void oniondata_registerhandler(Onion_Client *_Nonnull onion_c, uint8_t byte, oniondata_handler_cb *_Nullable cb, void *_Nullable object); |
191 | | typedef bool onion_group_announce_cb(Onion_Client *_Nonnull onion_c, uint32_t sendback_num, const uint8_t *_Nonnull data, |
192 | | size_t data_length, void *_Nullable user_data); |
193 | | |
194 | | /** Function to call when the onion gets a group announce response. */ |
195 | | void onion_group_announce_register(Onion_Client *_Nonnull onion_c, onion_group_announce_cb *_Nullable func, void *_Nullable user_data); |
196 | | void do_onion_client(Onion_Client *_Nonnull onion_c); |
197 | | |
198 | | Onion_Client *_Nullable new_onion_client(const Logger *_Nonnull logger, const Memory *_Nonnull mem, const Random *_Nonnull rng, const Mono_Time *_Nonnull mono_time, Net_Crypto *_Nonnull c); |
199 | | |
200 | | void kill_onion_client(Onion_Client *_Nullable onion_c); |
201 | | typedef enum Onion_Connection_Status { |
202 | | /** We are not connected to the network. */ |
203 | | ONION_CONNECTION_STATUS_NONE = 0, |
204 | | /** We are connected with TCP only. */ |
205 | | ONION_CONNECTION_STATUS_TCP = 1, |
206 | | /** We are also connected with UDP. */ |
207 | | ONION_CONNECTION_STATUS_UDP = 2, |
208 | | } Onion_Connection_Status; |
209 | | |
210 | | Onion_Connection_Status onion_connection_status(const Onion_Client *_Nonnull onion_c); |
211 | | |
212 | | typedef struct Onion_Friend Onion_Friend; |
213 | | |
214 | | uint16_t onion_get_friend_count(const Onion_Client *_Nonnull onion_c); |
215 | | Onion_Friend *_Nullable onion_get_friend(const Onion_Client *_Nonnull onion_c, uint16_t friend_num); |
216 | | const uint8_t *_Nullable onion_friend_get_gc_public_key(const Onion_Friend *_Nonnull onion_friend); |
217 | | const uint8_t *_Nullable onion_friend_get_gc_public_key_num(const Onion_Client *_Nonnull onion_c, uint32_t num); |
218 | | void onion_friend_set_gc_public_key(Onion_Friend *_Nonnull onion_friend, const uint8_t *_Nonnull public_key); |
219 | | void onion_friend_set_gc_data(Onion_Friend *_Nonnull onion_friend, const uint8_t *_Nullable gc_data, uint16_t gc_data_length); |
220 | | bool onion_friend_is_groupchat(const Onion_Friend *_Nonnull onion_friend); |
221 | | |
222 | | #endif /* C_TOXCORE_TOXCORE_ONION_CLIENT_H */ |