summaryrefslogtreecommitdiff
path: root/toxcore
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore')
-rw-r--r--toxcore/BUILD.bazel230
-rw-r--r--toxcore/DHT.c2624
-rw-r--r--toxcore/DHT.h219
-rw-r--r--toxcore/LAN_discovery.api.h73
-rw-r--r--toxcore/LAN_discovery.c319
-rw-r--r--toxcore/LAN_discovery.h86
-rw-r--r--toxcore/Makefile.inc22
-rw-r--r--toxcore/Messenger.c1780
-rw-r--r--toxcore/Messenger.h171
-rw-r--r--toxcore/TCP_client.c519
-rw-r--r--toxcore/TCP_client.h115
-rw-r--r--toxcore/TCP_connection.c570
-rw-r--r--toxcore/TCP_connection.h89
-rw-r--r--toxcore/TCP_server.c622
-rw-r--r--toxcore/TCP_server.h124
-rw-r--r--toxcore/assoc.c1031
-rw-r--r--toxcore/assoc.h104
-rw-r--r--toxcore/ccompat.h51
-rw-r--r--toxcore/crypto_core.api.h268
-rw-r--r--toxcore/crypto_core.c280
-rw-r--r--toxcore/crypto_core.h325
-rw-r--r--toxcore/crypto_core_mem.c87
-rw-r--r--toxcore/crypto_core_test.cpp96
-rw-r--r--toxcore/friend_connection.c601
-rw-r--r--toxcore/friend_connection.h105
-rw-r--r--toxcore/friend_requests.c128
-rw-r--r--toxcore/friend_requests.h57
-rw-r--r--toxcore/group.c1251
-rw-r--r--toxcore/group.h237
-rw-r--r--toxcore/list.c69
-rw-r--r--toxcore/list.h36
-rw-r--r--toxcore/logger.c278
-rw-r--r--toxcore/logger.h115
-rw-r--r--toxcore/misc_tools.h70
-rw-r--r--toxcore/net_crypto.c1229
-rw-r--r--toxcore/net_crypto.h202
-rw-r--r--toxcore/network.c1279
-rw-r--r--toxcore/network.h419
-rw-r--r--toxcore/onion.c439
-rw-r--r--toxcore/onion.h79
-rw-r--r--toxcore/onion_announce.c327
-rw-r--r--toxcore/onion_announce.h77
-rw-r--r--toxcore/onion_client.c1010
-rw-r--r--toxcore/onion_client.h169
-rw-r--r--toxcore/ping.api.h65
-rw-r--r--toxcore/ping.c236
-rw-r--r--toxcore/ping.h74
-rw-r--r--toxcore/ping_array.api.h72
-rw-r--r--toxcore/ping_array.c172
-rw-r--r--toxcore/ping_array.h88
-rw-r--r--toxcore/tox.api.h2606
-rw-r--r--toxcore/tox.c814
-rw-r--r--toxcore/tox.h856
-rw-r--r--toxcore/tox_api.c100
-rw-r--r--toxcore/tox_old.h173
-rw-r--r--toxcore/tox_old_code.h237
-rw-r--r--toxcore/util.c182
-rw-r--r--toxcore/util.h73
-rw-r--r--toxcore/util_test.cpp55
59 files changed, 14799 insertions, 8986 deletions
diff --git a/toxcore/BUILD.bazel b/toxcore/BUILD.bazel
new file mode 100644
index 00000000..b22f9b9e
--- /dev/null
+++ b/toxcore/BUILD.bazel
@@ -0,0 +1,230 @@
1load("//tools:no_undefined.bzl", "cc_library")
2
3filegroup(
4 name = "public_headers",
5 srcs = ["tox.h"],
6 visibility = ["//c-toxcore:__pkg__"],
7)
8
9cc_library(
10 name = "ccompat",
11 hdrs = ["ccompat.h"],
12 visibility = ["//c-toxcore:__subpackages__"],
13)
14
15cc_library(
16 name = "crypto_core",
17 srcs = [
18 "crypto_core.c",
19 "crypto_core_mem.c",
20 ],
21 hdrs = [
22 "crypto_core.h",
23 ],
24 visibility = ["//c-toxcore:__subpackages__"],
25 deps = [
26 ":ccompat",
27 "@libsodium",
28 ],
29)
30
31cc_test(
32 name = "crypto_core_test",
33 srcs = ["crypto_core_test.cpp"],
34 deps = [
35 ":crypto_core",
36 "@com_google_googletest//:gtest_main",
37 ],
38)
39
40cc_library(
41 name = "list",
42 srcs = ["list.c"],
43 hdrs = ["list.h"],
44 deps = [":ccompat"],
45)
46
47cc_library(
48 name = "logger",
49 srcs = ["logger.c"],
50 hdrs = ["logger.h"],
51 deps = [":ccompat"],
52)
53
54cc_library(
55 name = "network",
56 srcs = [
57 "network.c",
58 "util.c",
59 ],
60 hdrs = [
61 "network.h",
62 "util.h",
63 ],
64 linkopts = ["-lpthread"],
65 visibility = [
66 "//c-toxcore/other:__pkg__",
67 "//c-toxcore/toxav:__pkg__",
68 ],
69 deps = [
70 ":ccompat",
71 ":crypto_core",
72 ":logger",
73 ],
74)
75
76cc_test(
77 name = "util_test",
78 srcs = ["util_test.cpp"],
79 deps = [
80 ":network",
81 "@com_google_googletest//:gtest_main",
82 ],
83)
84
85cc_library(
86 name = "ping_array",
87 srcs = ["ping_array.c"],
88 hdrs = ["ping_array.h"],
89 deps = [":network"],
90)
91
92cc_library(
93 name = "DHT",
94 srcs = [
95 "DHT.c",
96 "LAN_discovery.c",
97 "ping.c",
98 ],
99 hdrs = [
100 "DHT.h",
101 "LAN_discovery.h",
102 "ping.h",
103 ],
104 visibility = ["//c-toxcore/other/bootstrap_daemon:__pkg__"],
105 deps = [
106 ":crypto_core",
107 ":logger",
108 ":ping_array",
109 ],
110)
111
112cc_library(
113 name = "onion",
114 srcs = ["onion.c"],
115 hdrs = ["onion.h"],
116 deps = [":DHT"],
117)
118
119cc_library(
120 name = "TCP_connection",
121 srcs = [
122 "TCP_client.c",
123 "TCP_connection.c",
124 "TCP_server.c",
125 ],
126 hdrs = [
127 "TCP_client.h",
128 "TCP_connection.h",
129 "TCP_server.h",
130 ],
131 copts = select({
132 "//tools/config:freebsd": [],
133 "//tools/config:linux": ["-DTCP_SERVER_USE_EPOLL=1"],
134 "//tools/config:osx": [],
135 }),
136 deps = [
137 ":crypto_core",
138 ":list",
139 ":onion",
140 ],
141)
142
143cc_library(
144 name = "net_crypto",
145 srcs = ["net_crypto.c"],
146 hdrs = ["net_crypto.h"],
147 deps = [
148 ":DHT",
149 ":TCP_connection",
150 ],
151)
152
153cc_library(
154 name = "onion_announce",
155 srcs = ["onion_announce.c"],
156 hdrs = ["onion_announce.h"],
157 deps = [":onion"],
158)
159
160cc_library(
161 name = "onion_client",
162 srcs = ["onion_client.c"],
163 hdrs = ["onion_client.h"],
164 deps = [
165 ":net_crypto",
166 ":onion_announce",
167 ],
168)
169
170cc_library(
171 name = "friend_connection",
172 srcs = ["friend_connection.c"],
173 hdrs = ["friend_connection.h"],
174 deps = [
175 ":DHT",
176 ":net_crypto",
177 ":onion_client",
178 ],
179)
180
181cc_library(
182 name = "friend_requests",
183 srcs = ["friend_requests.c"],
184 hdrs = ["friend_requests.h"],
185 deps = [":friend_connection"],
186)
187
188cc_library(
189 name = "Messenger",
190 srcs = ["Messenger.c"],
191 hdrs = ["Messenger.h"],
192 visibility = ["//c-toxcore/toxav:__pkg__"],
193 deps = [":friend_requests"],
194)
195
196cc_library(
197 name = "group",
198 srcs = ["group.c"],
199 hdrs = ["group.h"],
200 visibility = ["//c-toxcore/toxav:__pkg__"],
201 deps = [":Messenger"],
202)
203
204cc_library(
205 name = "toxcore",
206 srcs = [
207 "tox.c",
208 "tox.h",
209 "tox_api.c",
210 ],
211 visibility = ["//c-toxcore:__subpackages__"],
212 deps = [
213 ":group",
214 "//c-toxcore/toxencryptsave:defines",
215 ],
216)
217
218cc_library(
219 name = "monolith",
220 hdrs = glob([
221 "*.c",
222 "*.h",
223 ]),
224 linkopts = ["-lpthread"],
225 visibility = ["//c-toxcore/other:__pkg__"],
226 deps = [
227 "//c-toxcore/toxencryptsave:defines",
228 "@libsodium",
229 ],
230)
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index 6d9479a6..6134f59b 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -1,51 +1,42 @@
1/* DHT.c 1/*
2 *
3 * An implementation of the DHT as seen in docs/updates/DHT.md 2 * An implementation of the DHT as seen in docs/updates/DHT.md
3 */
4
5/*
6 * Copyright © 2016-2018 The TokTok team.
7 * Copyright © 2013 Tox project.
4 * 8 *
5 * Copyright (C) 2013 Tox project All Rights Reserved. 9 * This file is part of Tox, the free peer to peer instant messenger.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23
24/*----------------------------------------------------------------------------------*/
25
26#ifdef HAVE_CONFIG_H 24#ifdef HAVE_CONFIG_H
27#include "config.h" 25#include "config.h"
28#endif 26#endif
29 27
30#ifdef DEBUG
31#include <assert.h>
32#endif
33
34#include "logger.h"
35
36#include "DHT.h" 28#include "DHT.h"
37 29
38#ifdef ENABLE_ASSOC_DHT
39#include "assoc.h"
40#endif
41
42#include "ping.h"
43
44#include "network.h"
45#include "LAN_discovery.h" 30#include "LAN_discovery.h"
46#include "misc_tools.h" 31#include "logger.h"
32#include "network.h"
33#include "ping.h"
47#include "util.h" 34#include "util.h"
48 35
36#include <assert.h>
37#include <stdlib.h>
38#include <string.h>
39
49/* The timeout after which a node is discarded completely. */ 40/* The timeout after which a node is discarded completely. */
50#define KILL_NODE_TIMEOUT (BAD_NODE_TIMEOUT + PING_INTERVAL) 41#define KILL_NODE_TIMEOUT (BAD_NODE_TIMEOUT + PING_INTERVAL)
51 42
@@ -57,6 +48,9 @@
57/* Interval in seconds between punching attempts*/ 48/* Interval in seconds between punching attempts*/
58#define PUNCH_INTERVAL 3 49#define PUNCH_INTERVAL 3
59 50
51/* Time in seconds after which punching parameters will be reset */
52#define PUNCH_RESET_TIME 40
53
60#define MAX_NORMAL_PUNCHING_TRIES 5 54#define MAX_NORMAL_PUNCHING_TRIES 5
61 55
62#define NAT_PING_REQUEST 0 56#define NAT_PING_REQUEST 0
@@ -65,6 +59,127 @@
65/* Number of get node requests to send to quickly find close nodes. */ 59/* Number of get node requests to send to quickly find close nodes. */
66#define MAX_BOOTSTRAP_TIMES 5 60#define MAX_BOOTSTRAP_TIMES 5
67 61
62#define ARRAY_SIZE(ARR) (sizeof (ARR) / sizeof (ARR)[0])
63
64struct DHT_Friend {
65 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
66 Client_data client_list[MAX_FRIEND_CLIENTS];
67
68 /* Time at which the last get_nodes request was sent. */
69 uint64_t lastgetnode;
70 /* number of times get_node packets were sent. */
71 uint32_t bootstrap_times;
72
73 /* Symetric NAT hole punching stuff. */
74 NAT nat;
75
76 uint16_t lock_count;
77 struct {
78 void (*ip_callback)(void *, int32_t, IP_Port);
79 void *data;
80 int32_t number;
81 } callbacks[DHT_FRIEND_MAX_LOCKS];
82
83 Node_format to_bootstrap[MAX_SENT_NODES];
84 unsigned int num_to_bootstrap;
85};
86
87struct DHT {
88 Logger *log;
89 Networking_Core *net;
90
91 bool hole_punching_enabled;
92
93 Client_data close_clientlist[LCLIENT_LIST];
94 uint64_t close_lastgetnodes;
95 uint32_t close_bootstrap_times;
96
97 /* DHT keypair */
98 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
99 uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
100
101 DHT_Friend *friends_list;
102 uint16_t num_friends;
103
104 Node_format *loaded_nodes_list;
105 uint32_t loaded_num_nodes;
106 unsigned int loaded_nodes_index;
107
108 Shared_Keys shared_keys_recv;
109 Shared_Keys shared_keys_sent;
110
111 struct Ping *ping;
112 Ping_Array *dht_ping_array;
113 Ping_Array *dht_harden_ping_array;
114 uint64_t last_run;
115
116 Cryptopacket_Handles cryptopackethandlers[256];
117
118 Node_format to_bootstrap[MAX_CLOSE_TO_BOOTSTRAP_NODES];
119 unsigned int num_to_bootstrap;
120};
121
122const uint8_t *dht_friend_public_key(const DHT_Friend *dht_friend)
123{
124 return dht_friend->public_key;
125}
126
127const Client_data *dht_friend_client(const DHT_Friend *dht_friend, size_t index)
128{
129 return &dht_friend->client_list[index];
130}
131
132const uint8_t *dht_get_self_public_key(const DHT *dht)
133{
134 return dht->self_public_key;
135}
136const uint8_t *dht_get_self_secret_key(const DHT *dht)
137{
138 return dht->self_secret_key;
139}
140
141void dht_set_self_public_key(DHT *dht, const uint8_t *key)
142{
143 memcpy(dht->self_public_key, key, CRYPTO_PUBLIC_KEY_SIZE);
144}
145void dht_set_self_secret_key(DHT *dht, const uint8_t *key)
146{
147 memcpy(dht->self_secret_key, key, CRYPTO_SECRET_KEY_SIZE);
148}
149
150Networking_Core *dht_get_net(const DHT *dht)
151{
152 return dht->net;
153}
154struct Ping *dht_get_ping(const DHT *dht)
155{
156 return dht->ping;
157}
158const Client_data *dht_get_close_clientlist(const DHT *dht)
159{
160 return dht->close_clientlist;
161}
162const Client_data *dht_get_close_client(const DHT *dht, uint32_t client_num)
163{
164 assert(client_num < sizeof(dht->close_clientlist) / sizeof(dht->close_clientlist[0]));
165 return &dht->close_clientlist[client_num];
166}
167uint16_t dht_get_num_friends(const DHT *dht)
168{
169 return dht->num_friends;
170}
171
172DHT_Friend *dht_get_friend(DHT *dht, uint32_t friend_num)
173{
174 assert(friend_num < dht->num_friends);
175 return &dht->friends_list[friend_num];
176}
177const uint8_t *dht_get_friend_public_key(const DHT *dht, uint32_t friend_num)
178{
179 assert(friend_num < dht->num_friends);
180 return dht->friends_list[friend_num].public_key;
181}
182
68/* Compares pk1 and pk2 with pk. 183/* Compares pk1 and pk2 with pk.
69 * 184 *
70 * return 0 if both are same distance. 185 * return 0 if both are same distance.
@@ -73,19 +188,17 @@
73 */ 188 */
74int id_closest(const uint8_t *pk, const uint8_t *pk1, const uint8_t *pk2) 189int id_closest(const uint8_t *pk, const uint8_t *pk1, const uint8_t *pk2)
75{ 190{
76 size_t i; 191 for (size_t i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; ++i) {
77 uint8_t distance1, distance2; 192 const uint8_t distance1 = pk[i] ^ pk1[i];
78 193 const uint8_t distance2 = pk[i] ^ pk2[i];
79 for (i = 0; i < crypto_box_PUBLICKEYBYTES; ++i) {
80
81 distance1 = pk[i] ^ pk1[i];
82 distance2 = pk[i] ^ pk2[i];
83 194
84 if (distance1 < distance2) 195 if (distance1 < distance2) {
85 return 1; 196 return 1;
197 }
86 198
87 if (distance1 > distance2) 199 if (distance1 > distance2) {
88 return 2; 200 return 2;
201 }
89 } 202 }
90 203
91 return 0; 204 return 0;
@@ -95,15 +208,20 @@ int id_closest(const uint8_t *pk, const uint8_t *pk1, const uint8_t *pk2)
95 */ 208 */
96static unsigned int bit_by_bit_cmp(const uint8_t *pk1, const uint8_t *pk2) 209static unsigned int bit_by_bit_cmp(const uint8_t *pk1, const uint8_t *pk2)
97{ 210{
98 unsigned int i, j = 0; 211 unsigned int i;
212 unsigned int j = 0;
99 213
100 for (i = 0; i < crypto_box_PUBLICKEYBYTES; ++i) { 214 for (i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; ++i) {
101 if (pk1[i] == pk2[i]) 215 if (pk1[i] == pk2[i]) {
102 continue; 216 continue;
217 }
103 218
104 for (j = 0; j < 8; ++j) { 219 for (j = 0; j < 8; ++j) {
105 if ((pk1[i] & (1 << (7 - j))) != (pk2[i] & (1 << (7 - j)))) 220 const uint8_t mask = 1 << (7 - j);
221
222 if ((pk1[i] & mask) != (pk2[i] & mask)) {
106 break; 223 break;
224 }
107 } 225 }
108 226
109 break; 227 break;
@@ -120,44 +238,45 @@ static unsigned int bit_by_bit_cmp(const uint8_t *pk1, const uint8_t *pk2)
120 */ 238 */
121void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t *secret_key, const uint8_t *public_key) 239void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t *secret_key, const uint8_t *public_key)
122{ 240{
123 uint32_t i, num = ~0, curr = 0; 241 uint32_t num = ~0;
242 uint32_t curr = 0;
124 243
125 for (i = 0; i < MAX_KEYS_PER_SLOT; ++i) { 244 for (uint32_t i = 0; i < MAX_KEYS_PER_SLOT; ++i) {
126 int index = public_key[30] * MAX_KEYS_PER_SLOT + i; 245 const int index = public_key[30] * MAX_KEYS_PER_SLOT + i;
246 Shared_Key *const key = &shared_keys->keys[index];
127 247
128 if (shared_keys->keys[index].stored) { 248 if (key->stored) {
129 if (public_key_cmp(public_key, shared_keys->keys[index].public_key) == 0) { 249 if (id_equal(public_key, key->public_key)) {
130 memcpy(shared_key, shared_keys->keys[index].shared_key, crypto_box_BEFORENMBYTES); 250 memcpy(shared_key, key->shared_key, CRYPTO_SHARED_KEY_SIZE);
131 ++shared_keys->keys[index].times_requested; 251 ++key->times_requested;
132 shared_keys->keys[index].time_last_requested = unix_time(); 252 key->time_last_requested = unix_time();
133 return; 253 return;
134 } 254 }
135 255
136 if (num != 0) { 256 if (num != 0) {
137 if (is_timeout(shared_keys->keys[index].time_last_requested, KEYS_TIMEOUT)) { 257 if (is_timeout(key->time_last_requested, KEYS_TIMEOUT)) {
138 num = 0; 258 num = 0;
139 curr = index; 259 curr = index;
140 } else if (num > shared_keys->keys[index].times_requested) { 260 } else if (num > key->times_requested) {
141 num = shared_keys->keys[index].times_requested; 261 num = key->times_requested;
142 curr = index; 262 curr = index;
143 } 263 }
144 } 264 }
145 } else { 265 } else if (num != 0) {
146 if (num != 0) { 266 num = 0;
147 num = 0; 267 curr = index;
148 curr = index;
149 }
150 } 268 }
151 } 269 }
152 270
153 encrypt_precompute(public_key, secret_key, shared_key); 271 encrypt_precompute(public_key, secret_key, shared_key);
154 272
155 if (num != (uint32_t)~0) { 273 if (num != UINT32_MAX) {
156 shared_keys->keys[curr].stored = 1; 274 Shared_Key *const key = &shared_keys->keys[curr];
157 shared_keys->keys[curr].times_requested = 1; 275 key->stored = 1;
158 memcpy(shared_keys->keys[curr].public_key, public_key, crypto_box_PUBLICKEYBYTES); 276 key->times_requested = 1;
159 memcpy(shared_keys->keys[curr].shared_key, shared_key, crypto_box_BEFORENMBYTES); 277 memcpy(key->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
160 shared_keys->keys[curr].time_last_requested = unix_time(); 278 memcpy(key->shared_key, shared_key, CRYPTO_SHARED_KEY_SIZE);
279 key->time_last_requested = unix_time();
161 } 280 }
162} 281}
163 282
@@ -177,48 +296,249 @@ void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *publi
177 get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, public_key); 296 get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, public_key);
178} 297}
179 298
180void to_net_family(IP *ip) 299#define CRYPTO_SIZE 1 + CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE
300
301/* Create a request to peer.
302 * send_public_key and send_secret_key are the pub/secret keys of the sender.
303 * recv_public_key is public key of receiver.
304 * packet must be an array of MAX_CRYPTO_REQUEST_SIZE big.
305 * Data represents the data we send with the request with length being the length of the data.
306 * request_id is the id of the request (32 = friend request, 254 = ping request).
307 *
308 * return -1 on failure.
309 * return the length of the created packet on success.
310 */
311int create_request(const uint8_t *send_public_key, const uint8_t *send_secret_key, uint8_t *packet,
312 const uint8_t *recv_public_key, const uint8_t *data, uint32_t length, uint8_t request_id)
181{ 313{
182 if (ip->family == AF_INET) 314 if (!send_public_key || !packet || !recv_public_key || !data) {
183 ip->family = TOX_AF_INET; 315 return -1;
184 else if (ip->family == AF_INET6) 316 }
185 ip->family = TOX_AF_INET6; 317
318 if (MAX_CRYPTO_REQUEST_SIZE < length + CRYPTO_SIZE + 1 + CRYPTO_MAC_SIZE) {
319 return -1;
320 }
321
322 uint8_t *const nonce = packet + 1 + CRYPTO_PUBLIC_KEY_SIZE * 2;
323 random_nonce(nonce);
324 uint8_t temp[MAX_CRYPTO_REQUEST_SIZE];
325 memcpy(temp + 1, data, length);
326 temp[0] = request_id;
327 const int len = encrypt_data(recv_public_key, send_secret_key, nonce, temp, length + 1,
328 CRYPTO_SIZE + packet);
329
330 if (len == -1) {
331 crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
332 return -1;
333 }
334
335 packet[0] = NET_PACKET_CRYPTO;
336 memcpy(packet + 1, recv_public_key, CRYPTO_PUBLIC_KEY_SIZE);
337 memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, send_public_key, CRYPTO_PUBLIC_KEY_SIZE);
338
339 crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
340 return len + CRYPTO_SIZE;
186} 341}
187 342
188int to_host_family(IP *ip) 343/* Puts the senders public key in the request in public_key, the data from the request
344 * in data if a friend or ping request was sent to us and returns the length of the data.
345 * packet is the request packet and length is its length.
346 *
347 * return -1 if not valid request.
348 */
349int handle_request(const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
350 uint8_t *request_id, const uint8_t *packet, uint16_t length)
189{ 351{
190 if (ip->family == TOX_AF_INET) { 352 if (!self_public_key || !public_key || !data || !request_id || !packet) {
191 ip->family = AF_INET; 353 return -1;
192 return 0; 354 }
193 } else if (ip->family == TOX_AF_INET6) { 355
194 ip->family = AF_INET6; 356 if (length <= CRYPTO_SIZE + CRYPTO_MAC_SIZE || length > MAX_CRYPTO_REQUEST_SIZE) {
195 return 0; 357 return -1;
196 } else { 358 }
359
360 if (!id_equal(packet + 1, self_public_key)) {
361 return -1;
362 }
363
364 memcpy(public_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_PUBLIC_KEY_SIZE);
365 const uint8_t *const nonce = packet + 1 + CRYPTO_PUBLIC_KEY_SIZE * 2;
366 uint8_t temp[MAX_CRYPTO_REQUEST_SIZE];
367 int len1 = decrypt_data(public_key, self_secret_key, nonce,
368 packet + CRYPTO_SIZE, length - CRYPTO_SIZE, temp);
369
370 if (len1 == -1 || len1 == 0) {
371 crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
197 return -1; 372 return -1;
198 } 373 }
374
375 request_id[0] = temp[0];
376 --len1;
377 memcpy(data, temp + 1, len1);
378 crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
379 return len1;
199} 380}
200 381
201#define PACKED_NODE_SIZE_IP4 (1 + SIZE_IP4 + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES) 382#define PACKED_NODE_SIZE_IP4 (1 + SIZE_IP4 + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE)
202#define PACKED_NODE_SIZE_IP6 (1 + SIZE_IP6 + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES) 383#define PACKED_NODE_SIZE_IP6 (1 + SIZE_IP6 + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE)
203 384
204/* Return packet size of packed node with ip_family on success. 385/* Return packet size of packed node with ip_family on success.
205 * Return -1 on failure. 386 * Return -1 on failure.
206 */ 387 */
207int packed_node_size(uint8_t ip_family) 388int packed_node_size(Family ip_family)
208{ 389{
209 if (ip_family == AF_INET) { 390 if (net_family_is_ipv4(ip_family) || net_family_is_tcp_ipv4(ip_family)) {
210 return PACKED_NODE_SIZE_IP4;
211 } else if (ip_family == TCP_INET) {
212 return PACKED_NODE_SIZE_IP4; 391 return PACKED_NODE_SIZE_IP4;
213 } else if (ip_family == AF_INET6) { 392 }
214 return PACKED_NODE_SIZE_IP6; 393
215 } else if (ip_family == TCP_INET6) { 394 if (net_family_is_ipv6(ip_family) || net_family_is_tcp_ipv6(ip_family)) {
216 return PACKED_NODE_SIZE_IP6; 395 return PACKED_NODE_SIZE_IP6;
396 }
397
398 return -1;
399}
400
401
402/* Packs an IP_Port structure into data of max size length.
403 *
404 * Returns size of packed IP_Port data on success
405 * Return -1 on failure.
406 */
407int pack_ip_port(uint8_t *data, uint16_t length, const IP_Port *ip_port)
408{
409 if (data == nullptr) {
410 return -1;
411 }
412
413 bool is_ipv4;
414 uint8_t net_family;
415
416 if (net_family_is_ipv4(ip_port->ip.family)) {
417 // TODO(irungentoo): use functions to convert endianness
418 is_ipv4 = true;
419 net_family = TOX_AF_INET;
420 } else if (net_family_is_tcp_ipv4(ip_port->ip.family)) {
421 is_ipv4 = true;
422 net_family = TOX_TCP_INET;
423 } else if (net_family_is_ipv6(ip_port->ip.family)) {
424 is_ipv4 = false;
425 net_family = TOX_AF_INET6;
426 } else if (net_family_is_tcp_ipv6(ip_port->ip.family)) {
427 is_ipv4 = false;
428 net_family = TOX_TCP_INET6;
429 } else {
430 return -1;
431 }
432
433 if (is_ipv4) {
434 const uint32_t size = 1 + SIZE_IP4 + sizeof(uint16_t);
435
436 if (size > length) {
437 return -1;
438 }
439
440 data[0] = net_family;
441 memcpy(data + 1, &ip_port->ip.ip.v4, SIZE_IP4);
442 memcpy(data + 1 + SIZE_IP4, &ip_port->port, sizeof(uint16_t));
443 return size;
217 } else { 444 } else {
445 const uint32_t size = 1 + SIZE_IP6 + sizeof(uint16_t);
446
447 if (size > length) {
448 return -1;
449 }
450
451 data[0] = net_family;
452 memcpy(data + 1, &ip_port->ip.ip.v6, SIZE_IP6);
453 memcpy(data + 1 + SIZE_IP6, &ip_port->port, sizeof(uint16_t));
454 return size;
455 }
456}
457
458static int DHT_create_packet(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
459 const uint8_t *shared_key, const uint8_t type, uint8_t *plain, size_t plain_length, uint8_t *packet)
460{
461 VLA(uint8_t, encrypted, plain_length + CRYPTO_MAC_SIZE);
462 uint8_t nonce[CRYPTO_NONCE_SIZE];
463
464 random_nonce(nonce);
465
466 const int encrypted_length = encrypt_data_symmetric(shared_key, nonce, plain, plain_length, encrypted);
467
468 if (encrypted_length == -1) {
218 return -1; 469 return -1;
219 } 470 }
471
472 packet[0] = type;
473 memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);
474 memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
475 memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, encrypted, encrypted_length);
476
477 return 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + encrypted_length;
220} 478}
221 479
480/* Unpack IP_Port structure from data of max size length into ip_port.
481 *
482 * Return size of unpacked ip_port on success.
483 * Return -1 on failure.
484 */
485int unpack_ip_port(IP_Port *ip_port, const uint8_t *data, uint16_t length, uint8_t tcp_enabled)
486{
487 if (data == nullptr) {
488 return -1;
489 }
490
491 bool is_ipv4;
492 Family host_family;
493
494 if (data[0] == TOX_AF_INET) {
495 is_ipv4 = true;
496 host_family = net_family_ipv4;
497 } else if (data[0] == TOX_TCP_INET) {
498 if (!tcp_enabled) {
499 return -1;
500 }
501
502 is_ipv4 = true;
503 host_family = net_family_tcp_ipv4;
504 } else if (data[0] == TOX_AF_INET6) {
505 is_ipv4 = false;
506 host_family = net_family_ipv6;
507 } else if (data[0] == TOX_TCP_INET6) {
508 if (!tcp_enabled) {
509 return -1;
510 }
511
512 is_ipv4 = false;
513 host_family = net_family_tcp_ipv6;
514 } else {
515 return -1;
516 }
517
518 if (is_ipv4) {
519 const uint32_t size = 1 + SIZE_IP4 + sizeof(uint16_t);
520
521 if (size > length) {
522 return -1;
523 }
524
525 ip_port->ip.family = host_family;
526 memcpy(&ip_port->ip.ip.v4, data + 1, SIZE_IP4);
527 memcpy(&ip_port->port, data + 1 + SIZE_IP4, sizeof(uint16_t));
528 return size;
529 } else {
530 const uint32_t size = 1 + SIZE_IP6 + sizeof(uint16_t);
531
532 if (size > length) {
533 return -1;
534 }
535
536 ip_port->ip.family = host_family;
537 memcpy(&ip_port->ip.ip.v6, data + 1, SIZE_IP6);
538 memcpy(&ip_port->port, data + 1 + SIZE_IP6, sizeof(uint16_t));
539 return size;
540 }
541}
222 542
223/* Pack number of nodes into data of maxlength length. 543/* Pack number of nodes into data of maxlength length.
224 * 544 *
@@ -227,54 +547,26 @@ int packed_node_size(uint8_t ip_family)
227 */ 547 */
228int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_t number) 548int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_t number)
229{ 549{
230 uint32_t i, packed_length = 0; 550 uint32_t packed_length = 0;
231
232 for (i = 0; i < number; ++i) {
233 int ipv6 = -1;
234 uint8_t net_family;
235
236 // FIXME use functions to convert endianness
237 if (nodes[i].ip_port.ip.family == AF_INET) {
238 ipv6 = 0;
239 net_family = TOX_AF_INET;
240 } else if (nodes[i].ip_port.ip.family == TCP_INET) {
241 ipv6 = 0;
242 net_family = TOX_TCP_INET;
243 } else if (nodes[i].ip_port.ip.family == AF_INET6) {
244 ipv6 = 1;
245 net_family = TOX_AF_INET6;
246 } else if (nodes[i].ip_port.ip.family == TCP_INET6) {
247 ipv6 = 1;
248 net_family = TOX_TCP_INET6;
249 } else {
250 return -1;
251 }
252 551
253 if (ipv6 == 0) { 552 for (uint32_t i = 0; i < number && packed_length < length; ++i) {
254 uint32_t size = PACKED_NODE_SIZE_IP4; 553 const int ipp_size = pack_ip_port(data + packed_length, length - packed_length, &nodes[i].ip_port);
255 554
256 if (packed_length + size > length) 555 if (ipp_size == -1) {
257 return -1; 556 return -1;
258 557 }
259 data[packed_length] = net_family;
260 memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip4, SIZE_IP4);
261 memcpy(data + packed_length + 1 + SIZE_IP4, &nodes[i].ip_port.port, sizeof(uint16_t));
262 memcpy(data + packed_length + 1 + SIZE_IP4 + sizeof(uint16_t), nodes[i].public_key, crypto_box_PUBLICKEYBYTES);
263 packed_length += size;
264 } else if (ipv6 == 1) {
265 uint32_t size = PACKED_NODE_SIZE_IP6;
266 558
267 if (packed_length + size > length) 559 packed_length += ipp_size;
268 return -1;
269 560
270 data[packed_length] = net_family; 561 if (packed_length + CRYPTO_PUBLIC_KEY_SIZE > length) {
271 memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip6, SIZE_IP6);
272 memcpy(data + packed_length + 1 + SIZE_IP6, &nodes[i].ip_port.port, sizeof(uint16_t));
273 memcpy(data + packed_length + 1 + SIZE_IP6 + sizeof(uint16_t), nodes[i].public_key, crypto_box_PUBLICKEYBYTES);
274 packed_length += size;
275 } else {
276 return -1; 562 return -1;
277 } 563 }
564
565 memcpy(data + packed_length, nodes[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
566 packed_length += CRYPTO_PUBLIC_KEY_SIZE;
567
568 const uint32_t increment = ipp_size + CRYPTO_PUBLIC_KEY_SIZE;
569 assert(increment == PACKED_NODE_SIZE_IP4 || increment == PACKED_NODE_SIZE_IP6);
278 } 570 }
279 571
280 return packed_length; 572 return packed_length;
@@ -293,200 +585,182 @@ int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed
293 uint32_t num = 0, len_processed = 0; 585 uint32_t num = 0, len_processed = 0;
294 586
295 while (num < max_num_nodes && len_processed < length) { 587 while (num < max_num_nodes && len_processed < length) {
296 int ipv6 = -1; 588 const int ipp_size = unpack_ip_port(&nodes[num].ip_port, data + len_processed, length - len_processed, tcp_enabled);
297 uint8_t host_family; 589
298 590 if (ipp_size == -1) {
299 if (data[len_processed] == TOX_AF_INET) {
300 ipv6 = 0;
301 host_family = AF_INET;
302 } else if (data[len_processed] == TOX_TCP_INET) {
303 if (!tcp_enabled)
304 return -1;
305
306 ipv6 = 0;
307 host_family = TCP_INET;
308 } else if (data[len_processed] == TOX_AF_INET6) {
309 ipv6 = 1;
310 host_family = AF_INET6;
311 } else if (data[len_processed] == TOX_TCP_INET6) {
312 if (!tcp_enabled)
313 return -1;
314
315 ipv6 = 1;
316 host_family = TCP_INET6;
317 } else {
318 return -1; 591 return -1;
319 } 592 }
320 593
321 if (ipv6 == 0) { 594 len_processed += ipp_size;
322 uint32_t size = PACKED_NODE_SIZE_IP4;
323
324 if (len_processed + size > length)
325 return -1;
326
327 nodes[num].ip_port.ip.family = host_family;
328 memcpy(&nodes[num].ip_port.ip.ip4, data + len_processed + 1, SIZE_IP4);
329 memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + SIZE_IP4, sizeof(uint16_t));
330 memcpy(nodes[num].public_key, data + len_processed + 1 + SIZE_IP4 + sizeof(uint16_t), crypto_box_PUBLICKEYBYTES);
331 len_processed += size;
332 ++num;
333 } else if (ipv6 == 1) {
334 uint32_t size = PACKED_NODE_SIZE_IP6;
335
336 if (len_processed + size > length)
337 return -1;
338 595
339 nodes[num].ip_port.ip.family = host_family; 596 if (len_processed + CRYPTO_PUBLIC_KEY_SIZE > length) {
340 memcpy(&nodes[num].ip_port.ip.ip6, data + len_processed + 1, SIZE_IP6);
341 memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + SIZE_IP6, sizeof(uint16_t));
342 memcpy(nodes[num].public_key, data + len_processed + 1 + SIZE_IP6 + sizeof(uint16_t), crypto_box_PUBLICKEYBYTES);
343 len_processed += size;
344 ++num;
345 } else {
346 return -1; 597 return -1;
347 } 598 }
599
600 memcpy(nodes[num].public_key, data + len_processed, CRYPTO_PUBLIC_KEY_SIZE);
601 len_processed += CRYPTO_PUBLIC_KEY_SIZE;
602 ++num;
603
604 const uint32_t increment = ipp_size + CRYPTO_PUBLIC_KEY_SIZE;
605 assert(increment == PACKED_NODE_SIZE_IP4 || increment == PACKED_NODE_SIZE_IP6);
348 } 606 }
349 607
350 if (processed_data_len) 608 if (processed_data_len) {
351 *processed_data_len = len_processed; 609 *processed_data_len = len_processed;
610 }
352 611
353 return num; 612 return num;
354} 613}
355 614
356 615/* Find index of ##type with public_key equal to pk.
357
358/* Check if client with public_key is already in list of length length.
359 * If it is then set its corresponding timestamp to current time.
360 * If the id is already in the list with a different ip_port, update it.
361 * TODO: Maybe optimize this.
362 * 616 *
363 * return True(1) or False(0) 617 * return index or UINT32_MAX if not found.
364 */ 618 */
365static int client_or_ip_port_in_list(Client_data *list, uint16_t length, const uint8_t *public_key, IP_Port ip_port) 619#define INDEX_OF_PK \
366{ 620 for (uint32_t i = 0; i < size; i++) { \
367 uint32_t i; 621 if (id_equal(array[i].public_key, pk)) { \
368 uint64_t temp_time = unix_time(); 622 return i; \
369 623 } \
370 /* if public_key is in list, find it and maybe overwrite ip_port */ 624 } \
371 for (i = 0; i < length; ++i) 625 \
372 if (id_equal(list[i].public_key, public_key)) { 626 return UINT32_MAX;
373 /* Refresh the client timestamp. */
374 if (ip_port.ip.family == AF_INET) {
375
376 LOGGER_SCOPE( if (!ipport_equal(&list[i].assoc4.ip_port, &ip_port)) {
377 LOGGER_TRACE("coipil[%u]: switching ipv4 from %s:%u to %s:%u", i,
378 ip_ntoa(&list[i].assoc4.ip_port.ip), ntohs(list[i].assoc4.ip_port.port),
379 ip_ntoa(&ip_port.ip), ntohs(ip_port.port));
380 }
381 );
382 627
383 if (LAN_ip(list[i].assoc4.ip_port.ip) != 0 && LAN_ip(ip_port.ip) == 0) 628static uint32_t index_of_client_pk(const Client_data *array, uint32_t size, const uint8_t *pk)
384 return 1; 629{
630 INDEX_OF_PK
631}
385 632
386 list[i].assoc4.ip_port = ip_port; 633static uint32_t index_of_friend_pk(const DHT_Friend *array, uint32_t size, const uint8_t *pk)
387 list[i].assoc4.timestamp = temp_time; 634{
388 } else if (ip_port.ip.family == AF_INET6) { 635 INDEX_OF_PK
636}
389 637
390 LOGGER_SCOPE( if (!ipport_equal(&list[i].assoc4.ip_port, &ip_port)) { 638static uint32_t index_of_node_pk(const Node_format *array, uint32_t size, const uint8_t *pk)
391 LOGGER_TRACE("coipil[%u]: switching ipv6 from %s:%u to %s:%u", i, 639{
392 ip_ntoa(&list[i].assoc6.ip_port.ip), ntohs(list[i].assoc6.ip_port.port), 640 INDEX_OF_PK
393 ip_ntoa(&ip_port.ip), ntohs(ip_port.port)); 641}
394 }
395 );
396 642
397 if (LAN_ip(list[i].assoc6.ip_port.ip) != 0 && LAN_ip(ip_port.ip) == 0) 643/* Find index of Client_data with ip_port equal to param ip_port.
398 return 1; 644 *
645 * return index or UINT32_MAX if not found.
646 */
647static uint32_t index_of_client_ip_port(const Client_data *array, uint32_t size, const IP_Port *ip_port)
648{
649 for (uint32_t i = 0; i < size; ++i) {
650 if ((net_family_is_ipv4(ip_port->ip.family) && ipport_equal(&array[i].assoc4.ip_port, ip_port)) ||
651 (net_family_is_ipv6(ip_port->ip.family) && ipport_equal(&array[i].assoc6.ip_port, ip_port))) {
652 return i;
653 }
654 }
399 655
400 list[i].assoc6.ip_port = ip_port; 656 return UINT32_MAX;
401 list[i].assoc6.timestamp = temp_time; 657}
402 }
403 658
404 return 1; 659/* Update ip_port of client if it's needed.
405 } 660 */
661static void update_client(Logger *log, int index, Client_data *client, IP_Port ip_port)
662{
663 IPPTsPng *assoc;
664 int ip_version;
406 665
407 /* public_key not in list yet: see if we can find an identical ip_port, in 666 if (net_family_is_ipv4(ip_port.ip.family)) {
408 * that case we kill the old public_key by overwriting it with the new one 667 assoc = &client->assoc4;
409 * TODO: maybe we SHOULDN'T do that if that public_key is in a friend_list 668 ip_version = 4;
410 * and the one who is the actual friend's public_key/address set? */ 669 } else if (net_family_is_ipv6(ip_port.ip.family)) {
411 for (i = 0; i < length; ++i) { 670 assoc = &client->assoc6;
412 /* MAYBE: check the other address, if valid, don't nuke? */ 671 ip_version = 6;
413 if ((ip_port.ip.family == AF_INET) && ipport_equal(&list[i].assoc4.ip_port, &ip_port)) { 672 } else {
414 /* Initialize client timestamp. */ 673 return;
415 list[i].assoc4.timestamp = temp_time; 674 }
416 memcpy(list[i].public_key, public_key, crypto_box_PUBLICKEYBYTES);
417
418 LOGGER_DEBUG("coipil[%u]: switching public_key (ipv4)", i);
419
420 /* kill the other address, if it was set */
421 memset(&list[i].assoc6, 0, sizeof(list[i].assoc6));
422 return 1;
423 } else if ((ip_port.ip.family == AF_INET6) && ipport_equal(&list[i].assoc6.ip_port, &ip_port)) {
424 /* Initialize client timestamp. */
425 list[i].assoc6.timestamp = temp_time;
426 memcpy(list[i].public_key, public_key, crypto_box_PUBLICKEYBYTES);
427 675
428 LOGGER_DEBUG("coipil[%u]: switching public_key (ipv6)", i); 676 if (!ipport_equal(&assoc->ip_port, &ip_port)) {
677 char ip_str[IP_NTOA_LEN];
678 LOGGER_TRACE(log, "coipil[%u]: switching ipv%d from %s:%u to %s:%u",
679 index, ip_version,
680 ip_ntoa(&assoc->ip_port.ip, ip_str, sizeof(ip_str)),
681 net_ntohs(assoc->ip_port.port),
682 ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)),
683 net_ntohs(ip_port.port));
684 }
429 685
430 /* kill the other address, if it was set */ 686 if (ip_is_lan(assoc->ip_port.ip) != 0 && ip_is_lan(ip_port.ip) == 0) {
431 memset(&list[i].assoc4, 0, sizeof(list[i].assoc4)); 687 return;
432 return 1;
433 }
434 } 688 }
435 689
436 return 0; 690 assoc->ip_port = ip_port;
691 assoc->timestamp = unix_time();
437} 692}
438 693
439/* Check if client with public_key is already in node format list of length length. 694/* Check if client with public_key is already in list of length length.
695 * If it is then set its corresponding timestamp to current time.
696 * If the id is already in the list with a different ip_port, update it.
697 * TODO(irungentoo): Maybe optimize this.
440 * 698 *
441 * return 1 if true. 699 * return True(1) or False(0)
442 * return 0 if false.
443 */ 700 */
444static int client_in_nodelist(const Node_format *list, uint16_t length, const uint8_t *public_key) 701static int client_or_ip_port_in_list(Logger *log, Client_data *list, uint16_t length, const uint8_t *public_key,
702 IP_Port ip_port)
445{ 703{
446 uint32_t i; 704 const uint64_t temp_time = unix_time();
705 uint32_t index = index_of_client_pk(list, length, public_key);
447 706
448 for (i = 0; i < length; ++i) { 707 /* if public_key is in list, find it and maybe overwrite ip_port */
449 if (id_equal(list[i].public_key, public_key)) 708 if (index != UINT32_MAX) {
450 return 1; 709 update_client(log, index, &list[index], ip_port);
710 return 1;
451 } 711 }
452 712
453 return 0; 713 /* public_key not in list yet: see if we can find an identical ip_port, in
454} 714 * that case we kill the old public_key by overwriting it with the new one
715 * TODO(irungentoo): maybe we SHOULDN'T do that if that public_key is in a friend_list
716 * and the one who is the actual friend's public_key/address set?
717 * MAYBE: check the other address, if valid, don't nuke? */
718 index = index_of_client_ip_port(list, length, &ip_port);
455 719
456/* return friend number from the public_key. 720 if (index == UINT32_MAX) {
457 * return -1 if a failure occurs. 721 return 0;
458 */ 722 }
459static int friend_number(const DHT *dht, const uint8_t *public_key)
460{
461 uint32_t i;
462 723
463 for (i = 0; i < dht->num_friends; ++i) { 724 IPPTsPng *assoc;
464 if (id_equal(dht->friends_list[i].public_key, public_key)) 725 int ip_version;
465 return i; 726
727 if (net_family_is_ipv4(ip_port.ip.family)) {
728 assoc = &list[index].assoc4;
729 ip_version = 4;
730 } else {
731 assoc = &list[index].assoc6;
732 ip_version = 6;
466 } 733 }
467 734
468 return -1; 735 /* Initialize client timestamp. */
736 assoc->timestamp = temp_time;
737 memcpy(list[index].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
738
739 LOGGER_DEBUG(log, "coipil[%u]: switching public_key (ipv%d)", index, ip_version);
740
741 /* kill the other address, if it was set */
742 memset(assoc, 0, sizeof(IPPTsPng));
743 return 1;
469} 744}
470 745
471/* Add node to the node list making sure only the nodes closest to cmp_pk are in the list. 746/* Add node to the node list making sure only the nodes closest to cmp_pk are in the list.
472 */ 747 */
473_Bool add_to_list(Node_format *nodes_list, unsigned int length, const uint8_t *pk, IP_Port ip_port, 748bool add_to_list(Node_format *nodes_list, unsigned int length, const uint8_t *pk, IP_Port ip_port,
474 const uint8_t *cmp_pk) 749 const uint8_t *cmp_pk)
475{ 750{
476 uint8_t pk_bak[crypto_box_PUBLICKEYBYTES]; 751 uint8_t pk_bak[CRYPTO_PUBLIC_KEY_SIZE];
477 IP_Port ip_port_bak; 752 IP_Port ip_port_bak;
478 753
479 unsigned int i; 754 for (size_t i = 0; i < length; ++i) {
480
481 for (i = 0; i < length; ++i) {
482 if (id_closest(cmp_pk, nodes_list[i].public_key, pk) == 2) { 755 if (id_closest(cmp_pk, nodes_list[i].public_key, pk) == 2) {
483 memcpy(pk_bak, nodes_list[i].public_key, crypto_box_PUBLICKEYBYTES); 756 memcpy(pk_bak, nodes_list[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
484 ip_port_bak = nodes_list[i].ip_port; 757 ip_port_bak = nodes_list[i].ip_port;
485 memcpy(nodes_list[i].public_key, pk, crypto_box_PUBLICKEYBYTES); 758 memcpy(nodes_list[i].public_key, pk, CRYPTO_PUBLIC_KEY_SIZE);
486 nodes_list[i].ip_port = ip_port; 759 nodes_list[i].ip_port = ip_port;
487 760
488 if (i != (length - 1)) 761 if (i != (length - 1)) {
489 add_to_list(nodes_list, length, pk_bak, ip_port_bak, cmp_pk); 762 add_to_list(nodes_list, length, pk_bak, ip_port_bak, cmp_pk);
763 }
490 764
491 return 1; 765 return 1;
492 } 766 }
@@ -495,7 +769,7 @@ _Bool add_to_list(Node_format *nodes_list, unsigned int length, const uint8_t *p
495 return 0; 769 return 0;
496} 770}
497 771
498/*TODO: change this to 7 when done*/ 772/* TODO(irungentoo): change this to 7 when done*/
499#define HARDENING_ALL_OK 2 773#define HARDENING_ALL_OK 2
500/* return 0 if not. 774/* return 0 if not.
501 * return 1 if route request are ok 775 * return 1 if route request are ok
@@ -511,53 +785,52 @@ static uint8_t hardening_correct(const Hardening *h)
511 * helper for get_close_nodes(). argument list is a monster :D 785 * helper for get_close_nodes(). argument list is a monster :D
512 */ 786 */
513static void get_close_nodes_inner(const uint8_t *public_key, Node_format *nodes_list, 787static void get_close_nodes_inner(const uint8_t *public_key, Node_format *nodes_list,
514 sa_family_t sa_family, const Client_data *client_list, uint32_t client_list_length, 788 Family sa_family, const Client_data *client_list, uint32_t client_list_length,
515 uint32_t *num_nodes_ptr, uint8_t is_LAN, uint8_t want_good) 789 uint32_t *num_nodes_ptr, uint8_t is_LAN, uint8_t want_good)
516{ 790{
517 if ((sa_family != AF_INET) && (sa_family != AF_INET6) && (sa_family != 0)) 791 if (!net_family_is_ipv4(sa_family) && !net_family_is_ipv6(sa_family) && !net_family_is_unspec(sa_family)) {
518 return; 792 return;
793 }
519 794
520 uint32_t num_nodes = *num_nodes_ptr; 795 uint32_t num_nodes = *num_nodes_ptr;
521 uint32_t i;
522 796
523 for (i = 0; i < client_list_length; i++) { 797 for (uint32_t i = 0; i < client_list_length; i++) {
524 const Client_data *client = &client_list[i]; 798 const Client_data *const client = &client_list[i];
525 799
526 /* node already in list? */ 800 /* node already in list? */
527 if (client_in_nodelist(nodes_list, MAX_SENT_NODES, client->public_key)) 801 if (index_of_node_pk(nodes_list, MAX_SENT_NODES, client->public_key) != UINT32_MAX) {
528 continue; 802 continue;
803 }
529 804
530 const IPPTsPng *ipptp = NULL; 805 const IPPTsPng *ipptp = nullptr;
531 806
532 if (sa_family == AF_INET) { 807 if (net_family_is_ipv4(sa_family)) {
533 ipptp = &client->assoc4; 808 ipptp = &client->assoc4;
534 } else if (sa_family == AF_INET6) { 809 } else if (net_family_is_ipv6(sa_family)) {
535 ipptp = &client->assoc6; 810 ipptp = &client->assoc6;
811 } else if (client->assoc4.timestamp >= client->assoc6.timestamp) {
812 ipptp = &client->assoc4;
536 } else { 813 } else {
537 if (client->assoc4.timestamp >= client->assoc6.timestamp) { 814 ipptp = &client->assoc6;
538 ipptp = &client->assoc4;
539 } else {
540 ipptp = &client->assoc6;
541 }
542 } 815 }
543 816
544 /* node not in a good condition? */ 817 /* node not in a good condition? */
545 if (is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT)) 818 if (is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT)) {
546 continue; 819 continue;
820 }
547 821
548 /* don't send LAN ips to non LAN peers */ 822 /* don't send LAN ips to non LAN peers */
549 if (LAN_ip(ipptp->ip_port.ip) == 0 && !is_LAN) 823 if (ip_is_lan(ipptp->ip_port.ip) == 0 && !is_LAN) {
550 continue; 824 continue;
825 }
551 826
552 if (LAN_ip(ipptp->ip_port.ip) != 0 && want_good && hardening_correct(&ipptp->hardening) != HARDENING_ALL_OK 827 if (ip_is_lan(ipptp->ip_port.ip) != 0 && want_good && hardening_correct(&ipptp->hardening) != HARDENING_ALL_OK
553 && !id_equal(public_key, client->public_key)) 828 && !id_equal(public_key, client->public_key)) {
554 continue; 829 continue;
830 }
555 831
556 if (num_nodes < MAX_SENT_NODES) { 832 if (num_nodes < MAX_SENT_NODES) {
557 memcpy(nodes_list[num_nodes].public_key, 833 memcpy(nodes_list[num_nodes].public_key, client->public_key, CRYPTO_PUBLIC_KEY_SIZE);
558 client->public_key,
559 crypto_box_PUBLICKEYBYTES );
560
561 nodes_list[num_nodes].ip_port = ipptp->ip_port; 834 nodes_list[num_nodes].ip_port = ipptp->ip_port;
562 num_nodes++; 835 num_nodes++;
563 } else { 836 } else {
@@ -571,130 +844,98 @@ static void get_close_nodes_inner(const uint8_t *public_key, Node_format *nodes_
571/* Find MAX_SENT_NODES nodes closest to the public_key for the send nodes request: 844/* Find MAX_SENT_NODES nodes closest to the public_key for the send nodes request:
572 * put them in the nodes_list and return how many were found. 845 * put them in the nodes_list and return how many were found.
573 * 846 *
574 * TODO: For the love of based <your favorite deity, in doubt use "love"> make 847 * TODO(irungentoo): For the love of based <your favorite deity, in doubt use
575 * this function cleaner and much more efficient. 848 * "love"> make this function cleaner and much more efficient.
576 * 849 *
577 * want_good : do we want only good nodes as checked with the hardening returned or not? 850 * want_good : do we want only good nodes as checked with the hardening returned or not?
578 */ 851 */
579static int get_somewhat_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, 852static int get_somewhat_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list,
580 sa_family_t sa_family, uint8_t is_LAN, uint8_t want_good) 853 Family sa_family, uint8_t is_LAN, uint8_t want_good)
581{ 854{
582 uint32_t num_nodes = 0, i; 855 uint32_t num_nodes = 0;
583 get_close_nodes_inner(public_key, nodes_list, sa_family, 856 get_close_nodes_inner(public_key, nodes_list, sa_family,
584 dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, 0); 857 dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, 0);
585 858
586 /*TODO uncomment this when hardening is added to close friend clients 859 /* TODO(irungentoo): uncomment this when hardening is added to close friend clients */
587 for (i = 0; i < dht->num_friends; ++i) 860#if 0
588 get_close_nodes_inner(dht, public_key, nodes_list, sa_family, 861
589 dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, 862 for (uint32_t i = 0; i < dht->num_friends; ++i) {
590 &num_nodes, is_LAN, want_good); 863 get_close_nodes_inner(dht, public_key, nodes_list, sa_family,
591 */ 864 dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
592 for (i = 0; i < dht->num_friends; ++i) 865 &num_nodes, is_LAN, want_good);
866 }
867
868#endif
869
870 for (uint32_t i = 0; i < dht->num_friends; ++i) {
593 get_close_nodes_inner(public_key, nodes_list, sa_family, 871 get_close_nodes_inner(public_key, nodes_list, sa_family,
594 dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, 872 dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
595 &num_nodes, is_LAN, 0); 873 &num_nodes, is_LAN, 0);
874 }
596 875
597 return num_nodes; 876 return num_nodes;
598} 877}
599 878
600int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, sa_family_t sa_family, 879int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, Family sa_family,
601 uint8_t is_LAN, uint8_t want_good) 880 uint8_t is_LAN, uint8_t want_good)
602{ 881{
603 memset(nodes_list, 0, MAX_SENT_NODES * sizeof(Node_format)); 882 memset(nodes_list, 0, MAX_SENT_NODES * sizeof(Node_format));
604#ifdef ENABLE_ASSOC_DHT 883 return get_somewhat_close_nodes(dht, public_key, nodes_list, sa_family, is_LAN, want_good);
884}
605 885
606 if (!dht->assoc) 886typedef struct {
607#endif 887 const uint8_t *base_public_key;
608 return get_somewhat_close_nodes(dht, public_key, nodes_list, sa_family, is_LAN, want_good); 888 Client_data entry;
889} DHT_Cmp_data;
609 890
610#ifdef ENABLE_ASSOC_DHT 891static int cmp_dht_entry(const void *a, const void *b)
611 //TODO: assoc, sa_family 0 (don't care if ipv4 or ipv6) support. 892{
612 Client_data *result[MAX_SENT_NODES]; 893 DHT_Cmp_data cmp1, cmp2;
894 memcpy(&cmp1, a, sizeof(DHT_Cmp_data));
895 memcpy(&cmp2, b, sizeof(DHT_Cmp_data));
896 const Client_data entry1 = cmp1.entry;
897 const Client_data entry2 = cmp2.entry;
898 const uint8_t *cmp_public_key = cmp1.base_public_key;
613 899
614 Assoc_close_entries request; 900#define ASSOC_TIMEOUT(assoc) is_timeout((assoc).timestamp, BAD_NODE_TIMEOUT)
615 memset(&request, 0, sizeof(request));
616 request.count = MAX_SENT_NODES;
617 request.count_good = MAX_SENT_NODES - 2; /* allow 2 'indirect' nodes */
618 request.result = result;
619 request.wanted_id = public_key;
620 request.flags = (is_LAN ? LANOk : 0) + (sa_family == AF_INET ? ProtoIPv4 : ProtoIPv6);
621 901
622 uint8_t num_found = Assoc_get_close_entries(dht->assoc, &request); 902 bool t1 = ASSOC_TIMEOUT(entry1.assoc4) && ASSOC_TIMEOUT(entry1.assoc6);
903 bool t2 = ASSOC_TIMEOUT(entry2.assoc4) && ASSOC_TIMEOUT(entry2.assoc6);
623 904
624 if (!num_found) { 905 if (t1 && t2) {
625 LOGGER_DEBUG("get_close_nodes(): Assoc_get_close_entries() returned zero nodes"); 906 return 0;
626 return get_somewhat_close_nodes(dht, public_key, nodes_list, sa_family, is_LAN, want_good);
627 } 907 }
628 908
629 LOGGER_DEBUG("get_close_nodes(): Assoc_get_close_entries() returned %i 'direct' and %i 'indirect' nodes", 909 if (t1) {
630 request.count_good, num_found - request.count_good); 910 return -1;
631
632 uint8_t i, num_returned = 0;
633
634 for (i = 0; i < num_found; i++) {
635 Client_data *client = result[i];
636
637 if (client) {
638 id_copy(nodes_list[num_returned].public_key, client->public_key);
639
640 if (sa_family == AF_INET)
641 if (ipport_isset(&client->assoc4.ip_port)) {
642 nodes_list[num_returned].ip_port = client->assoc4.ip_port;
643 num_returned++;
644 continue;
645 }
646
647 if (sa_family == AF_INET6)
648 if (ipport_isset(&client->assoc6.ip_port)) {
649 nodes_list[num_returned].ip_port = client->assoc6.ip_port;
650 num_returned++;
651 continue;
652 }
653 }
654 } 911 }
655 912
656 return num_returned; 913 if (t2) {
657#endif 914 return 1;
658} 915 }
659 916
660static uint8_t cmp_public_key[crypto_box_PUBLICKEYBYTES]; 917#define INCORRECT_HARDENING(assoc) hardening_correct(&(assoc).hardening) != HARDENING_ALL_OK
661static int cmp_dht_entry(const void *a, const void *b)
662{
663 Client_data entry1, entry2;
664 memcpy(&entry1, a, sizeof(Client_data));
665 memcpy(&entry2, b, sizeof(Client_data));
666 int t1 = is_timeout(entry1.assoc4.timestamp, BAD_NODE_TIMEOUT) && is_timeout(entry1.assoc6.timestamp, BAD_NODE_TIMEOUT);
667 int t2 = is_timeout(entry2.assoc4.timestamp, BAD_NODE_TIMEOUT) && is_timeout(entry2.assoc6.timestamp, BAD_NODE_TIMEOUT);
668 918
669 if (t1 && t2) 919 t1 = INCORRECT_HARDENING(entry1.assoc4) && INCORRECT_HARDENING(entry1.assoc6);
670 return 0; 920 t2 = INCORRECT_HARDENING(entry2.assoc4) && INCORRECT_HARDENING(entry2.assoc6);
671 921
672 if (t1) 922 if (t1 && !t2) {
673 return -1; 923 return -1;
924 }
674 925
675 if (t2) 926 if (!t1 && t2) {
676 return 1; 927 return 1;
677
678 t1 = hardening_correct(&entry1.assoc4.hardening) != HARDENING_ALL_OK
679 && hardening_correct(&entry1.assoc6.hardening) != HARDENING_ALL_OK;
680 t2 = hardening_correct(&entry2.assoc4.hardening) != HARDENING_ALL_OK
681 && hardening_correct(&entry2.assoc6.hardening) != HARDENING_ALL_OK;
682
683 if (t1 != t2) {
684 if (t1)
685 return -1;
686
687 if (t2)
688 return 1;
689 } 928 }
690 929
691 int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key); 930 const int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key);
692 931
693 if (close == 1) 932 if (close == 1) {
694 return 1; 933 return 1;
934 }
695 935
696 if (close == 2) 936 if (close == 2) {
697 return -1; 937 return -1;
938 }
698 939
699 return 0; 940 return 0;
700} 941}
@@ -706,18 +947,51 @@ static int cmp_dht_entry(const void *a, const void *b)
706 */ 947 */
707static unsigned int store_node_ok(const Client_data *client, const uint8_t *public_key, const uint8_t *comp_public_key) 948static unsigned int store_node_ok(const Client_data *client, const uint8_t *public_key, const uint8_t *comp_public_key)
708{ 949{
709 if ((is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) && is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) 950 return (is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT)
710 || (id_closest(comp_public_key, client->public_key, public_key) == 2)) { 951 && is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT))
711 return 1; 952 || id_closest(comp_public_key, client->public_key, public_key) == 2;
712 } else {
713 return 0;
714 }
715} 953}
716 954
717static void sort_client_list(Client_data *list, unsigned int length, const uint8_t *comp_public_key) 955static void sort_client_list(Client_data *list, unsigned int length, const uint8_t *comp_public_key)
718{ 956{
719 memcpy(cmp_public_key, comp_public_key, crypto_box_PUBLICKEYBYTES); 957 // Pass comp_public_key to qsort with each Client_data entry, so the
720 qsort(list, length, sizeof(Client_data), cmp_dht_entry); 958 // comparison function can use it as the base of comparison.
959 VLA(DHT_Cmp_data, cmp_list, length);
960
961 for (uint32_t i = 0; i < length; i++) {
962 cmp_list[i].base_public_key = comp_public_key;
963 cmp_list[i].entry = list[i];
964 }
965
966 qsort(cmp_list, length, sizeof(DHT_Cmp_data), cmp_dht_entry);
967
968 for (uint32_t i = 0; i < length; i++) {
969 list[i] = cmp_list[i].entry;
970 }
971}
972
973static void update_client_with_reset(Client_data *client, const IP_Port *ip_port)
974{
975 IPPTsPng *ipptp_write = nullptr;
976 IPPTsPng *ipptp_clear = nullptr;
977
978 if (net_family_is_ipv4(ip_port->ip.family)) {
979 ipptp_write = &client->assoc4;
980 ipptp_clear = &client->assoc6;
981 } else {
982 ipptp_write = &client->assoc6;
983 ipptp_clear = &client->assoc4;
984 }
985
986 ipptp_write->ip_port = *ip_port;
987 ipptp_write->timestamp = unix_time();
988
989 ip_reset(&ipptp_write->ret_ip_port.ip);
990 ipptp_write->ret_ip_port.port = 0;
991 ipptp_write->ret_timestamp = 0;
992
993 /* zero out other address */
994 memset(ipptp_clear, 0, sizeof(*ipptp_clear));
721} 995}
722 996
723/* Replace a first bad (or empty) node with this one 997/* Replace a first bad (or empty) node with this one
@@ -732,47 +1006,29 @@ static void sort_client_list(Client_data *list, unsigned int length, const uint8
732 * and all nodes in the list are closer to comp_public_key 1006 * and all nodes in the list are closer to comp_public_key
733 * than public_key. 1007 * than public_key.
734 * 1008 *
735 * returns True(1) when the item was stored, False(0) otherwise */ 1009 * returns true when the item was stored, false otherwise */
736static int replace_all( Client_data *list, 1010static bool replace_all(Client_data *list,
737 uint16_t length, 1011 uint16_t length,
738 const uint8_t *public_key, 1012 const uint8_t *public_key,
739 IP_Port ip_port, 1013 IP_Port ip_port,
740 const uint8_t *comp_public_key ) 1014 const uint8_t *comp_public_key)
741{ 1015{
742 if ((ip_port.ip.family != AF_INET) && (ip_port.ip.family != AF_INET6)) 1016 if (!net_family_is_ipv4(ip_port.ip.family) && !net_family_is_ipv6(ip_port.ip.family)) {
743 return 0; 1017 return false;
744 1018 }
745 if (store_node_ok(&list[1], public_key, comp_public_key) || store_node_ok(&list[0], public_key, comp_public_key)) {
746 sort_client_list(list, length, comp_public_key);
747
748 IPPTsPng *ipptp_write = NULL;
749 IPPTsPng *ipptp_clear = NULL;
750
751 Client_data *client = &list[0];
752
753 if (ip_port.ip.family == AF_INET) {
754 ipptp_write = &client->assoc4;
755 ipptp_clear = &client->assoc6;
756 } else {
757 ipptp_write = &client->assoc6;
758 ipptp_clear = &client->assoc4;
759 }
760
761 id_copy(client->public_key, public_key);
762 ipptp_write->ip_port = ip_port;
763 ipptp_write->timestamp = unix_time();
764 1019
765 ip_reset(&ipptp_write->ret_ip_port.ip); 1020 if (!store_node_ok(&list[1], public_key, comp_public_key) &&
766 ipptp_write->ret_ip_port.port = 0; 1021 !store_node_ok(&list[0], public_key, comp_public_key)) {
767 ipptp_write->ret_timestamp = 0; 1022 return false;
1023 }
768 1024
769 /* zero out other address */ 1025 sort_client_list(list, length, comp_public_key);
770 memset(ipptp_clear, 0, sizeof(*ipptp_clear));
771 1026
772 return 1; 1027 Client_data *const client = &list[0];
773 } 1028 id_copy(client->public_key, public_key);
774 1029
775 return 0; 1030 update_client_with_reset(client, &ip_port);
1031 return true;
776} 1032}
777 1033
778/* Add node to close list. 1034/* Add node to close list.
@@ -782,45 +1038,31 @@ static int replace_all( Client_data *list,
782 * return -1 on failure. 1038 * return -1 on failure.
783 * return 0 on success. 1039 * return 0 on success.
784 */ 1040 */
785static int add_to_close(DHT *dht, const uint8_t *public_key, IP_Port ip_port, _Bool simulate) 1041static int add_to_close(DHT *dht, const uint8_t *public_key, IP_Port ip_port, bool simulate)
786{ 1042{
787 unsigned int i;
788
789 unsigned int index = bit_by_bit_cmp(public_key, dht->self_public_key); 1043 unsigned int index = bit_by_bit_cmp(public_key, dht->self_public_key);
790 1044
791 if (index > LCLIENT_LENGTH) 1045 if (index >= LCLIENT_LENGTH) {
792 index = LCLIENT_LENGTH - 1; 1046 index = LCLIENT_LENGTH - 1;
1047 }
793 1048
794 for (i = 0; i < LCLIENT_NODES; ++i) { 1049 for (uint32_t i = 0; i < LCLIENT_NODES; ++i) {
795 Client_data *client = &dht->close_clientlist[(index * LCLIENT_NODES) + i]; 1050 /* TODO(iphydf): write bounds checking test to catch the case that
796 1051 * index is left as >= LCLIENT_LENGTH */
797 if (is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) && is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) { 1052 Client_data *const client = &dht->close_clientlist[(index * LCLIENT_NODES) + i];
798 if (!simulate) {
799 IPPTsPng *ipptp_write = NULL;
800 IPPTsPng *ipptp_clear = NULL;
801
802 if (ip_port.ip.family == AF_INET) {
803 ipptp_write = &client->assoc4;
804 ipptp_clear = &client->assoc6;
805 } else {
806 ipptp_write = &client->assoc6;
807 ipptp_clear = &client->assoc4;
808 }
809
810 id_copy(client->public_key, public_key);
811 ipptp_write->ip_port = ip_port;
812 ipptp_write->timestamp = unix_time();
813
814 ip_reset(&ipptp_write->ret_ip_port.ip);
815 ipptp_write->ret_ip_port.port = 0;
816 ipptp_write->ret_timestamp = 0;
817 1053
818 /* zero out other address */ 1054 if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) ||
819 memset(ipptp_clear, 0, sizeof(*ipptp_clear)); 1055 !is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) {
820 } 1056 continue;
1057 }
821 1058
1059 if (simulate) {
822 return 0; 1060 return 0;
823 } 1061 }
1062
1063 id_copy(client->public_key, public_key);
1064 update_client_with_reset(client, &ip_port);
1065 return 0;
824 } 1066 }
825 1067
826 return -1; 1068 return -1;
@@ -828,83 +1070,97 @@ static int add_to_close(DHT *dht, const uint8_t *public_key, IP_Port ip_port, _B
828 1070
829/* Return 1 if node can be added to close list, 0 if it can't. 1071/* Return 1 if node can be added to close list, 0 if it can't.
830 */ 1072 */
831_Bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port) 1073bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port)
832{ 1074{
833 if (add_to_close(dht, public_key, ip_port, 1) == 0) { 1075 return add_to_close(dht, public_key, ip_port, 1) == 0;
834 return 1; 1076}
1077
1078static bool is_pk_in_client_list(const Client_data *list, unsigned int client_list_length, const uint8_t *public_key,
1079 IP_Port ip_port)
1080{
1081 const uint32_t index = index_of_client_pk(list, client_list_length, public_key);
1082
1083 if (index == UINT32_MAX) {
1084 return 0;
835 } 1085 }
836 1086
837 return 0; 1087 const IPPTsPng *assoc = net_family_is_ipv4(ip_port.ip.family)
1088 ? &list[index].assoc4
1089 : &list[index].assoc6;
1090
1091 return !is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT);
838} 1092}
839 1093
840static _Bool is_pk_in_client_list(Client_data *list, unsigned int client_list_length, const uint8_t *public_key, 1094static bool is_pk_in_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port)
841 IP_Port ip_port)
842{ 1095{
843 unsigned int i; 1096 unsigned int index = bit_by_bit_cmp(public_key, dht->self_public_key);
844 1097
845 for (i = 0; i < client_list_length; ++i) { 1098 if (index >= LCLIENT_LENGTH) {
846 if ((ip_port.ip.family == AF_INET && !is_timeout(list[i].assoc4.timestamp, BAD_NODE_TIMEOUT)) 1099 index = LCLIENT_LENGTH - 1;
847 || (ip_port.ip.family == AF_INET6 && !is_timeout(list[i].assoc6.timestamp, BAD_NODE_TIMEOUT))) {
848 if (public_key_cmp(list[i].public_key, public_key) == 0) {
849 return 1;
850 }
851 }
852 } 1100 }
853 1101
854 return 0; 1102 return is_pk_in_client_list(dht->close_clientlist + index * LCLIENT_NODES, LCLIENT_NODES, public_key, ip_port);
855} 1103}
856 1104
857/* Check if the node obtained with a get_nodes with public_key should be pinged. 1105/* Check if the node obtained with a get_nodes with public_key should be pinged.
858 * NOTE: for best results call it after addto_lists; 1106 * NOTE: for best results call it after addto_lists;
859 * 1107 *
860 * return 0 if the node should not be pinged. 1108 * return false if the node should not be pinged.
861 * return 1 if it should. 1109 * return true if it should.
862 */ 1110 */
863static unsigned int ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_key, IP_Port ip_port) 1111static bool ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_key, IP_Port ip_port)
864{ 1112{
865 _Bool ret = 0; 1113 bool ret = false;
866 1114
867 if (add_to_close(dht, public_key, ip_port, 1) == 0) { 1115 if (add_to_close(dht, public_key, ip_port, 1) == 0) {
868 ret = 1; 1116 ret = true;
869 } 1117 }
870 1118
871 if (ret && !client_in_nodelist(dht->to_bootstrap, dht->num_to_bootstrap, public_key)) { 1119 {
872 if (dht->num_to_bootstrap < MAX_CLOSE_TO_BOOTSTRAP_NODES) { 1120 unsigned int *const num = &dht->num_to_bootstrap;
873 memcpy(dht->to_bootstrap[dht->num_to_bootstrap].public_key, public_key, crypto_box_PUBLICKEYBYTES); 1121 const uint32_t index = index_of_node_pk(dht->to_bootstrap, *num, public_key);
874 dht->to_bootstrap[dht->num_to_bootstrap].ip_port = ip_port; 1122 const bool in_close_list = is_pk_in_close_list(dht, public_key, ip_port);
875 ++dht->num_to_bootstrap; 1123
876 } else { 1124 if (ret && index == UINT32_MAX && !in_close_list) {
877 //TODO: ipv6 vs v4 1125 if (*num < MAX_CLOSE_TO_BOOTSTRAP_NODES) {
878 add_to_list(dht->to_bootstrap, MAX_CLOSE_TO_BOOTSTRAP_NODES, public_key, ip_port, dht->self_public_key); 1126 memcpy(dht->to_bootstrap[*num].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
1127 dht->to_bootstrap[*num].ip_port = ip_port;
1128 ++*num;
1129 } else {
1130 // TODO(irungentoo): ipv6 vs v4
1131 add_to_list(dht->to_bootstrap, MAX_CLOSE_TO_BOOTSTRAP_NODES, public_key, ip_port, dht->self_public_key);
1132 }
879 } 1133 }
880 } 1134 }
881 1135
882 unsigned int i; 1136 for (uint32_t i = 0; i < dht->num_friends; ++i) {
883 1137 DHT_Friend *dht_friend = &dht->friends_list[i];
884 for (i = 0; i < dht->num_friends; ++i) {
885 _Bool store_ok = 0;
886 1138
887 DHT_Friend *friend = &dht->friends_list[i]; 1139 bool store_ok = false;
888 1140
889 if (store_node_ok(&friend->client_list[1], public_key, friend->public_key)) { 1141 if (store_node_ok(&dht_friend->client_list[1], public_key, dht_friend->public_key)) {
890 store_ok = 1; 1142 store_ok = true;
891 } 1143 }
892 1144
893 if (store_node_ok(&friend->client_list[0], public_key, friend->public_key)) { 1145 if (store_node_ok(&dht_friend->client_list[0], public_key, dht_friend->public_key)) {
894 store_ok = 1; 1146 store_ok = true;
895 } 1147 }
896 1148
897 if (store_ok && !client_in_nodelist(friend->to_bootstrap, friend->num_to_bootstrap, public_key) 1149 unsigned int *const friend_num = &dht_friend->num_to_bootstrap;
898 && !is_pk_in_client_list(friend->client_list, MAX_FRIEND_CLIENTS, public_key, ip_port)) { 1150 const uint32_t index = index_of_node_pk(dht_friend->to_bootstrap, *friend_num, public_key);
899 if (friend->num_to_bootstrap < MAX_SENT_NODES) { 1151 const bool pk_in_list = is_pk_in_client_list(dht_friend->client_list, MAX_FRIEND_CLIENTS, public_key, ip_port);
900 memcpy(friend->to_bootstrap[friend->num_to_bootstrap].public_key, public_key, crypto_box_PUBLICKEYBYTES); 1152
901 friend->to_bootstrap[friend->num_to_bootstrap].ip_port = ip_port; 1153 if (store_ok && index == UINT32_MAX && !pk_in_list) {
902 ++friend->num_to_bootstrap; 1154 if (*friend_num < MAX_SENT_NODES) {
1155 Node_format *const format = &dht_friend->to_bootstrap[*friend_num];
1156 memcpy(format->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
1157 format->ip_port = ip_port;
1158 ++*friend_num;
903 } else { 1159 } else {
904 add_to_list(friend->to_bootstrap, MAX_SENT_NODES, public_key, ip_port, friend->public_key); 1160 add_to_list(dht_friend->to_bootstrap, MAX_SENT_NODES, public_key, ip_port, dht_friend->public_key);
905 } 1161 }
906 1162
907 ret = 1; 1163 ret = true;
908 } 1164 }
909 } 1165 }
910 1166
@@ -916,143 +1172,110 @@ static unsigned int ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_k
916 * 1172 *
917 * returns 1+ if the item is used in any list, 0 else 1173 * returns 1+ if the item is used in any list, 0 else
918 */ 1174 */
919int addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key) 1175uint32_t addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key)
920{ 1176{
921 uint32_t i, used = 0; 1177 uint32_t used = 0;
922 1178
923 /* convert IPv4-in-IPv6 to IPv4 */ 1179 /* convert IPv4-in-IPv6 to IPv4 */
924 if ((ip_port.ip.family == AF_INET6) && IPV6_IPV4_IN_V6(ip_port.ip.ip6)) { 1180 if (net_family_is_ipv6(ip_port.ip.family) && IPV6_IPV4_IN_V6(ip_port.ip.ip.v6)) {
925 ip_port.ip.family = AF_INET; 1181 ip_port.ip.family = net_family_ipv4;
926 ip_port.ip.ip4.uint32 = ip_port.ip.ip6.uint32[3]; 1182 ip_port.ip.ip.v4.uint32 = ip_port.ip.ip.v6.uint32[3];
927 } 1183 }
928 1184
929 /* NOTE: Current behavior if there are two clients with the same id is 1185 /* NOTE: Current behavior if there are two clients with the same id is
930 * to replace the first ip by the second. 1186 * to replace the first ip by the second.
931 */ 1187 */
932 if (!client_or_ip_port_in_list(dht->close_clientlist, LCLIENT_LIST, public_key, ip_port)) { 1188 const bool in_close_list = client_or_ip_port_in_list(dht->log, dht->close_clientlist,
933 if (add_to_close(dht, public_key, ip_port, 0)) 1189 LCLIENT_LIST, public_key, ip_port);
934 used++;
935 } else
936 used++;
937
938 DHT_Friend *friend_foundip = 0;
939 1190
940 for (i = 0; i < dht->num_friends; ++i) { 1191 /* add_to_close should be called only if !in_list (don't extract to variable) */
941 if (!client_or_ip_port_in_list(dht->friends_list[i].client_list, 1192 if (in_close_list || add_to_close(dht, public_key, ip_port, 0)) {
942 MAX_FRIEND_CLIENTS, public_key, ip_port)) { 1193 used++;
943 if (replace_all(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, 1194 }
944 public_key, ip_port, dht->friends_list[i].public_key)) {
945 1195
946 DHT_Friend *friend = &dht->friends_list[i]; 1196 DHT_Friend *friend_foundip = nullptr;
947 1197
948 if (public_key_cmp(public_key, friend->public_key) == 0) { 1198 for (uint32_t i = 0; i < dht->num_friends; ++i) {
949 friend_foundip = friend; 1199 const bool in_list = client_or_ip_port_in_list(dht->log, dht->friends_list[i].client_list,
950 } 1200 MAX_FRIEND_CLIENTS, public_key, ip_port);
951 1201
952 used++; 1202 /* replace_all should be called only if !in_list (don't extract to variable) */
953 } 1203 if (in_list || replace_all(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, public_key,
954 } else { 1204 ip_port, dht->friends_list[i].public_key)) {
955 DHT_Friend *friend = &dht->friends_list[i]; 1205 DHT_Friend *dht_friend = &dht->friends_list[i];
956 1206
957 if (public_key_cmp(public_key, friend->public_key) == 0) { 1207 if (id_equal(public_key, dht_friend->public_key)) {
958 friend_foundip = friend; 1208 friend_foundip = dht_friend;
959 } 1209 }
960 1210
961 used++; 1211 used++;
962 } 1212 }
963 } 1213 }
964 1214
965 if (friend_foundip) { 1215 if (!friend_foundip) {
966 uint32_t j; 1216 return used;
1217 }
967 1218
968 for (j = 0; j < friend_foundip->lock_count; ++j) { 1219 for (uint32_t i = 0; i < friend_foundip->lock_count; ++i) {
969 if (friend_foundip->callbacks[j].ip_callback) 1220 if (friend_foundip->callbacks[i].ip_callback) {
970 friend_foundip->callbacks[j].ip_callback(friend_foundip->callbacks[j].data, friend_foundip->callbacks[j].number, 1221 friend_foundip->callbacks[i].ip_callback(friend_foundip->callbacks[i].data,
971 ip_port); 1222 friend_foundip->callbacks[i].number, ip_port);
972 } 1223 }
973 } 1224 }
974 1225
975#ifdef ENABLE_ASSOC_DHT 1226 return used;
1227}
976 1228
977 if (dht->assoc) { 1229static bool update_client_data(Client_data *array, size_t size, IP_Port ip_port, const uint8_t *pk)
978 IPPTs ippts; 1230{
1231 const uint64_t temp_time = unix_time();
1232 const uint32_t index = index_of_client_pk(array, size, pk);
1233
1234 if (index == UINT32_MAX) {
1235 return false;
1236 }
979 1237
980 ippts.ip_port = ip_port; 1238 Client_data *const data = &array[index];
981 ippts.timestamp = unix_time(); 1239 IPPTsPng *assoc;
982 1240
983 Assoc_add_entry(dht->assoc, public_key, &ippts, NULL, used ? 1 : 0); 1241 if (net_family_is_ipv4(ip_port.ip.family)) {
1242 assoc = &data->assoc4;
1243 } else if (net_family_is_ipv6(ip_port.ip.family)) {
1244 assoc = &data->assoc6;
1245 } else {
1246 return true;
984 } 1247 }
985 1248
986#endif 1249 assoc->ret_ip_port = ip_port;
987 return used; 1250 assoc->ret_timestamp = temp_time;
1251 return true;
988} 1252}
989 1253
990/* If public_key is a friend or us, update ret_ip_port 1254/* If public_key is a friend or us, update ret_ip_port
991 * nodepublic_key is the id of the node that sent us this info. 1255 * nodepublic_key is the id of the node that sent us this info.
992 */ 1256 */
993static int returnedip_ports(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const uint8_t *nodepublic_key) 1257static void returnedip_ports(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const uint8_t *nodepublic_key)
994{ 1258{
995 uint32_t i, j;
996 uint64_t temp_time = unix_time();
997
998 uint32_t used = 0;
999
1000 /* convert IPv4-in-IPv6 to IPv4 */ 1259 /* convert IPv4-in-IPv6 to IPv4 */
1001 if ((ip_port.ip.family == AF_INET6) && IPV6_IPV4_IN_V6(ip_port.ip.ip6)) { 1260 if (net_family_is_ipv6(ip_port.ip.family) && IPV6_IPV4_IN_V6(ip_port.ip.ip.v6)) {
1002 ip_port.ip.family = AF_INET; 1261 ip_port.ip.family = net_family_ipv4;
1003 ip_port.ip.ip4.uint32 = ip_port.ip.ip6.uint32[3]; 1262 ip_port.ip.ip.v4.uint32 = ip_port.ip.ip.v6.uint32[3];
1004 } 1263 }
1005 1264
1006 if (id_equal(public_key, dht->self_public_key)) { 1265 if (id_equal(public_key, dht->self_public_key)) {
1007 for (i = 0; i < LCLIENT_LIST; ++i) { 1266 update_client_data(dht->close_clientlist, LCLIENT_LIST, ip_port, nodepublic_key);
1008 if (id_equal(nodepublic_key, dht->close_clientlist[i].public_key)) { 1267 return;
1009 if (ip_port.ip.family == AF_INET) {
1010 dht->close_clientlist[i].assoc4.ret_ip_port = ip_port;
1011 dht->close_clientlist[i].assoc4.ret_timestamp = temp_time;
1012 } else if (ip_port.ip.family == AF_INET6) {
1013 dht->close_clientlist[i].assoc6.ret_ip_port = ip_port;
1014 dht->close_clientlist[i].assoc6.ret_timestamp = temp_time;
1015 }
1016
1017 ++used;
1018 break;
1019 }
1020 }
1021 } else {
1022 for (i = 0; i < dht->num_friends; ++i) {
1023 if (id_equal(public_key, dht->friends_list[i].public_key)) {
1024 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
1025 if (id_equal(nodepublic_key, dht->friends_list[i].client_list[j].public_key)) {
1026 if (ip_port.ip.family == AF_INET) {
1027 dht->friends_list[i].client_list[j].assoc4.ret_ip_port = ip_port;
1028 dht->friends_list[i].client_list[j].assoc4.ret_timestamp = temp_time;
1029 } else if (ip_port.ip.family == AF_INET6) {
1030 dht->friends_list[i].client_list[j].assoc6.ret_ip_port = ip_port;
1031 dht->friends_list[i].client_list[j].assoc6.ret_timestamp = temp_time;
1032 }
1033
1034 ++used;
1035 goto end;
1036 }
1037 }
1038 }
1039 }
1040 } 1268 }
1041 1269
1042end: 1270 for (uint32_t i = 0; i < dht->num_friends; ++i) {
1043#ifdef ENABLE_ASSOC_DHT 1271 if (id_equal(public_key, dht->friends_list[i].public_key)) {
1272 Client_data *const client_list = dht->friends_list[i].client_list;
1044 1273
1045 if (dht->assoc) { 1274 if (update_client_data(client_list, MAX_FRIEND_CLIENTS, ip_port, nodepublic_key)) {
1046 IPPTs ippts; 1275 return;
1047 ippts.ip_port = ip_port; 1276 }
1048 ippts.timestamp = temp_time; 1277 }
1049 /* this is only a hear-say entry, so ret-ipp is NULL, but used is required
1050 * to decide how valuable it is ("used" may throw an "unused" entry out) */
1051 Assoc_add_entry(dht->assoc, public_key, &ippts, NULL, used ? 1 : 0);
1052 } 1278 }
1053
1054#endif
1055 return 0;
1056} 1279}
1057 1280
1058/* Send a getnodes request. 1281/* Send a getnodes request.
@@ -1061,56 +1284,47 @@ static int getnodes(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const
1061 const Node_format *sendback_node) 1284 const Node_format *sendback_node)
1062{ 1285{
1063 /* Check if packet is going to be sent to ourself. */ 1286 /* Check if packet is going to be sent to ourself. */
1064 if (id_equal(public_key, dht->self_public_key)) 1287 if (id_equal(public_key, dht->self_public_key)) {
1065 return -1; 1288 return -1;
1289 }
1066 1290
1067 uint8_t plain_message[sizeof(Node_format) * 2] = {0}; 1291 uint8_t plain_message[sizeof(Node_format) * 2] = {0};
1068 1292
1069 Node_format receiver; 1293 Node_format receiver;
1070 memcpy(receiver.public_key, public_key, crypto_box_PUBLICKEYBYTES); 1294 memcpy(receiver.public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
1071 receiver.ip_port = ip_port; 1295 receiver.ip_port = ip_port;
1072 memcpy(plain_message, &receiver, sizeof(receiver)); 1296 memcpy(plain_message, &receiver, sizeof(receiver));
1073 1297
1074 uint64_t ping_id = 0; 1298 uint64_t ping_id = 0;
1075 1299
1076 if (sendback_node != NULL) { 1300 if (sendback_node != nullptr) {
1077 memcpy(plain_message + sizeof(receiver), sendback_node, sizeof(Node_format)); 1301 memcpy(plain_message + sizeof(receiver), sendback_node, sizeof(Node_format));
1078 ping_id = ping_array_add(&dht->dht_harden_ping_array, plain_message, sizeof(plain_message)); 1302 ping_id = ping_array_add(dht->dht_harden_ping_array, plain_message, sizeof(plain_message));
1079 } else { 1303 } else {
1080 ping_id = ping_array_add(&dht->dht_ping_array, plain_message, sizeof(receiver)); 1304 ping_id = ping_array_add(dht->dht_ping_array, plain_message, sizeof(receiver));
1081 } 1305 }
1082 1306
1083 if (ping_id == 0) 1307 if (ping_id == 0) {
1084 return -1; 1308 return -1;
1309 }
1085 1310
1086 uint8_t plain[crypto_box_PUBLICKEYBYTES + sizeof(ping_id)]; 1311 uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + sizeof(ping_id)];
1087 uint8_t encrypt[sizeof(plain) + crypto_box_MACBYTES]; 1312 uint8_t data[1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + sizeof(plain) + CRYPTO_MAC_SIZE];
1088 uint8_t data[1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + sizeof(encrypt)];
1089 1313
1090 memcpy(plain, client_id, crypto_box_PUBLICKEYBYTES); 1314 memcpy(plain, client_id, CRYPTO_PUBLIC_KEY_SIZE);
1091 memcpy(plain + crypto_box_PUBLICKEYBYTES, &ping_id, sizeof(ping_id)); 1315 memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, &ping_id, sizeof(ping_id));
1092 1316
1093 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 1317 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
1094 DHT_get_shared_key_sent(dht, shared_key, public_key); 1318 DHT_get_shared_key_sent(dht, shared_key, public_key);
1095 1319
1096 uint8_t nonce[crypto_box_NONCEBYTES]; 1320 const int len = DHT_create_packet(dht->self_public_key, shared_key, NET_PACKET_GET_NODES,
1097 new_nonce(nonce); 1321 plain, sizeof(plain), data);
1098 1322
1099 int len = encrypt_data_symmetric( shared_key, 1323 if (len != sizeof(data)) {
1100 nonce,
1101 plain,
1102 sizeof(plain),
1103 encrypt );
1104
1105 if (len != sizeof(encrypt))
1106 return -1; 1324 return -1;
1325 }
1107 1326
1108 data[0] = NET_PACKET_GET_NODES; 1327 return sendpacket(dht->net, ip_port, data, len);
1109 memcpy(data + 1, dht->self_public_key, crypto_box_PUBLICKEYBYTES);
1110 memcpy(data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES);
1111 memcpy(data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, encrypt, len);
1112
1113 return sendpacket(dht->net, ip_port, data, sizeof(data));
1114} 1328}
1115 1329
1116/* Send a send nodes response: message for IPv6 nodes */ 1330/* Send a send nodes response: message for IPv6 nodes */
@@ -1118,105 +1332,108 @@ static int sendnodes_ipv6(const DHT *dht, IP_Port ip_port, const uint8_t *public
1118 const uint8_t *sendback_data, uint16_t length, const uint8_t *shared_encryption_key) 1332 const uint8_t *sendback_data, uint16_t length, const uint8_t *shared_encryption_key)
1119{ 1333{
1120 /* Check if packet is going to be sent to ourself. */ 1334 /* Check if packet is going to be sent to ourself. */
1121 if (id_equal(public_key, dht->self_public_key)) 1335 if (id_equal(public_key, dht->self_public_key)) {
1122 return -1; 1336 return -1;
1337 }
1123 1338
1124 if (length != sizeof(uint64_t)) 1339 if (length != sizeof(uint64_t)) {
1125 return -1; 1340 return -1;
1341 }
1126 1342
1127 size_t Node_format_size = sizeof(Node_format); 1343 const size_t node_format_size = sizeof(Node_format);
1128 uint8_t data[1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES
1129 + Node_format_size * MAX_SENT_NODES + length + crypto_box_MACBYTES];
1130 1344
1131 Node_format nodes_list[MAX_SENT_NODES]; 1345 Node_format nodes_list[MAX_SENT_NODES];
1132 uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, 0, LAN_ip(ip_port.ip) == 0, 1); 1346 const uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, net_family_unspec, ip_is_lan(ip_port.ip) == 0,
1347 1);
1133 1348
1134 uint8_t plain[1 + Node_format_size * MAX_SENT_NODES + length]; 1349 VLA(uint8_t, plain, 1 + node_format_size * MAX_SENT_NODES + length);
1135 uint8_t encrypt[sizeof(plain) + crypto_box_MACBYTES];
1136 uint8_t nonce[crypto_box_NONCEBYTES];
1137 new_nonce(nonce);
1138 1350
1139 int nodes_length = 0; 1351 int nodes_length = 0;
1140 1352
1141 if (num_nodes) { 1353 if (num_nodes) {
1142 nodes_length = pack_nodes(plain + 1, Node_format_size * MAX_SENT_NODES, nodes_list, num_nodes); 1354 nodes_length = pack_nodes(plain + 1, node_format_size * MAX_SENT_NODES, nodes_list, num_nodes);
1143 1355
1144 if (nodes_length <= 0) 1356 if (nodes_length <= 0) {
1145 return -1; 1357 return -1;
1358 }
1146 } 1359 }
1147 1360
1148 plain[0] = num_nodes; 1361 plain[0] = num_nodes;
1149 memcpy(plain + 1 + nodes_length, sendback_data, length); 1362 memcpy(plain + 1 + nodes_length, sendback_data, length);
1150 int len = encrypt_data_symmetric( shared_encryption_key,
1151 nonce,
1152 plain,
1153 1 + nodes_length + length,
1154 encrypt );
1155 1363
1156 if (len != 1 + nodes_length + length + crypto_box_MACBYTES) 1364 const uint32_t crypto_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE;
1157 return -1; 1365 VLA(uint8_t, data, 1 + nodes_length + length + crypto_size);
1158 1366
1159 data[0] = NET_PACKET_SEND_NODES_IPV6; 1367 const int len = DHT_create_packet(dht->self_public_key, shared_encryption_key, NET_PACKET_SEND_NODES_IPV6,
1160 memcpy(data + 1, dht->self_public_key, crypto_box_PUBLICKEYBYTES); 1368 plain, 1 + nodes_length + length, data);
1161 memcpy(data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES);
1162 memcpy(data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, encrypt, len);
1163 1369
1164 return sendpacket(dht->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + len); 1370 if (len != SIZEOF_VLA(data)) {
1371 return -1;
1372 }
1373
1374 return sendpacket(dht->net, ip_port, data, len);
1165} 1375}
1166 1376
1167static int handle_getnodes(void *object, IP_Port source, const uint8_t *packet, uint16_t length) 1377#define CRYPTO_NODE_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint64_t))
1378
1379static int handle_getnodes(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
1168{ 1380{
1169 if (length != (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + sizeof( 1381 if (length != (CRYPTO_SIZE + CRYPTO_MAC_SIZE + sizeof(uint64_t))) {
1170 uint64_t) + crypto_box_MACBYTES)) 1382 return true;
1171 return 1; 1383 }
1172 1384
1173 DHT *dht = object; 1385 DHT *const dht = (DHT *)object;
1174 1386
1175 /* Check if packet is from ourself. */ 1387 /* Check if packet is from ourself. */
1176 if (id_equal(packet + 1, dht->self_public_key)) 1388 if (id_equal(packet + 1, dht->self_public_key)) {
1177 return 1; 1389 return true;
1390 }
1178 1391
1179 uint8_t plain[crypto_box_PUBLICKEYBYTES + sizeof(uint64_t)]; 1392 uint8_t plain[CRYPTO_NODE_SIZE];
1180 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 1393 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
1181 1394
1182 DHT_get_shared_key_recv(dht, shared_key, packet + 1); 1395 DHT_get_shared_key_recv(dht, shared_key, packet + 1);
1183 int len = decrypt_data_symmetric( shared_key, 1396 const int len = decrypt_data_symmetric(
1184 packet + 1 + crypto_box_PUBLICKEYBYTES, 1397 shared_key,
1185 packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, 1398 packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
1186 crypto_box_PUBLICKEYBYTES + sizeof(uint64_t) + crypto_box_MACBYTES, 1399 packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
1187 plain ); 1400 CRYPTO_NODE_SIZE + CRYPTO_MAC_SIZE,
1401 plain);
1188 1402
1189 if (len != crypto_box_PUBLICKEYBYTES + sizeof(uint64_t)) 1403 if (len != CRYPTO_NODE_SIZE) {
1190 return 1; 1404 return true;
1405 }
1191 1406
1192 sendnodes_ipv6(dht, source, packet + 1, plain, plain + crypto_box_PUBLICKEYBYTES, sizeof(uint64_t), shared_key); 1407 sendnodes_ipv6(dht, source, packet + 1, plain, plain + CRYPTO_PUBLIC_KEY_SIZE, sizeof(uint64_t), shared_key);
1193 1408
1194 add_to_ping(dht->ping, packet + 1, source); 1409 ping_add(dht->ping, packet + 1, source);
1195 1410
1196 return 0; 1411 return false;
1197} 1412}
1198/* return 0 if no 1413
1199 return 1 if yes */ 1414/* return false if no
1200static uint8_t sent_getnode_to_node(DHT *dht, const uint8_t *public_key, IP_Port node_ip_port, uint64_t ping_id, 1415 return true if yes */
1201 Node_format *sendback_node) 1416static bool sent_getnode_to_node(DHT *dht, const uint8_t *public_key, IP_Port node_ip_port, uint64_t ping_id,
1417 Node_format *sendback_node)
1202{ 1418{
1203 uint8_t data[sizeof(Node_format) * 2]; 1419 uint8_t data[sizeof(Node_format) * 2];
1204 1420
1205 if (ping_array_check(data, sizeof(data), &dht->dht_ping_array, ping_id) == sizeof(Node_format)) { 1421 if (ping_array_check(dht->dht_ping_array, data, sizeof(data), ping_id) == sizeof(Node_format)) {
1206 memset(sendback_node, 0, sizeof(Node_format)); 1422 memset(sendback_node, 0, sizeof(Node_format));
1207 } else if (ping_array_check(data, sizeof(data), &dht->dht_harden_ping_array, ping_id) == sizeof(data)) { 1423 } else if (ping_array_check(dht->dht_harden_ping_array, data, sizeof(data), ping_id) == sizeof(data)) {
1208 memcpy(sendback_node, data + sizeof(Node_format), sizeof(Node_format)); 1424 memcpy(sendback_node, data + sizeof(Node_format), sizeof(Node_format));
1209 } else { 1425 } else {
1210 return 0; 1426 return false;
1211 } 1427 }
1212 1428
1213 Node_format test; 1429 Node_format test;
1214 memcpy(&test, data, sizeof(Node_format)); 1430 memcpy(&test, data, sizeof(Node_format));
1215 1431
1216 if (!ipport_equal(&test.ip_port, &node_ip_port) || public_key_cmp(test.public_key, public_key) != 0) 1432 if (!ipport_equal(&test.ip_port, &node_ip_port) || !id_equal(test.public_key, public_key)) {
1217 return 0; 1433 return false;
1434 }
1218 1435
1219 return 1; 1436 return true;
1220} 1437}
1221 1438
1222/* Function is needed in following functions. */ 1439/* Function is needed in following functions. */
@@ -1226,55 +1443,64 @@ static int send_hardening_getnode_res(const DHT *dht, const Node_format *sendto,
1226static int handle_sendnodes_core(void *object, IP_Port source, const uint8_t *packet, uint16_t length, 1443static int handle_sendnodes_core(void *object, IP_Port source, const uint8_t *packet, uint16_t length,
1227 Node_format *plain_nodes, uint16_t size_plain_nodes, uint32_t *num_nodes_out) 1444 Node_format *plain_nodes, uint16_t size_plain_nodes, uint32_t *num_nodes_out)
1228{ 1445{
1229 DHT *dht = object; 1446 DHT *const dht = (DHT *)object;
1230 uint32_t cid_size = 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + 1 + sizeof(uint64_t) + crypto_box_MACBYTES; 1447 const uint32_t cid_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + 1 + sizeof(uint64_t) + CRYPTO_MAC_SIZE;
1231 1448
1232 if (length < cid_size) /* too short */ 1449 if (length < cid_size) { /* too short */
1233 return 1; 1450 return 1;
1451 }
1234 1452
1235 uint32_t data_size = length - cid_size; 1453 const uint32_t data_size = length - cid_size;
1236 1454
1237 if (data_size == 0) 1455 if (data_size == 0) {
1238 return 1; 1456 return 1;
1457 }
1239 1458
1240 if (data_size > sizeof(Node_format) * MAX_SENT_NODES) /* invalid length */ 1459 if (data_size > sizeof(Node_format) * MAX_SENT_NODES) { /* invalid length */
1241 return 1; 1460 return 1;
1461 }
1242 1462
1243 uint8_t plain[1 + data_size + sizeof(uint64_t)]; 1463 VLA(uint8_t, plain, 1 + data_size + sizeof(uint64_t));
1244 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 1464 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
1245 DHT_get_shared_key_sent(dht, shared_key, packet + 1); 1465 DHT_get_shared_key_sent(dht, shared_key, packet + 1);
1246 int len = decrypt_data_symmetric( 1466 const int len = decrypt_data_symmetric(
1247 shared_key, 1467 shared_key,
1248 packet + 1 + crypto_box_PUBLICKEYBYTES, 1468 packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
1249 packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, 1469 packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
1250 1 + data_size + sizeof(uint64_t) + crypto_box_MACBYTES, 1470 1 + data_size + sizeof(uint64_t) + CRYPTO_MAC_SIZE,
1251 plain); 1471 plain);
1252 1472
1253 if ((unsigned int)len != sizeof(plain)) 1473 if ((unsigned int)len != SIZEOF_VLA(plain)) {
1254 return 1; 1474 return 1;
1475 }
1255 1476
1256 if (plain[0] > size_plain_nodes) 1477 if (plain[0] > size_plain_nodes) {
1257 return 1; 1478 return 1;
1479 }
1258 1480
1259 Node_format sendback_node; 1481 Node_format sendback_node;
1260 1482
1261 uint64_t ping_id; 1483 uint64_t ping_id;
1262 memcpy(&ping_id, plain + 1 + data_size, sizeof(ping_id)); 1484 memcpy(&ping_id, plain + 1 + data_size, sizeof(ping_id));
1263 1485
1264 if (!sent_getnode_to_node(dht, packet + 1, source, ping_id, &sendback_node)) 1486 if (!sent_getnode_to_node(dht, packet + 1, source, ping_id, &sendback_node)) {
1265 return 1; 1487 return 1;
1488 }
1266 1489
1267 uint16_t length_nodes = 0; 1490 uint16_t length_nodes = 0;
1268 int num_nodes = unpack_nodes(plain_nodes, plain[0], &length_nodes, plain + 1, data_size, 0); 1491 const int num_nodes = unpack_nodes(plain_nodes, plain[0], &length_nodes, plain + 1, data_size, 0);
1269 1492
1270 if (length_nodes != data_size) 1493 if (length_nodes != data_size) {
1271 return 1; 1494 return 1;
1495 }
1272 1496
1273 if (num_nodes != plain[0]) 1497 if (num_nodes != plain[0]) {
1274 return 1; 1498 return 1;
1499 }
1275 1500
1276 if (num_nodes < 0) 1501 if (num_nodes < 0) {
1277 return 1; 1502 return 1;
1503 }
1278 1504
1279 /* store the address the *request* was sent to */ 1505 /* store the address the *request* was sent to */
1280 addto_lists(dht, source, packet + 1); 1506 addto_lists(dht, source, packet + 1);
@@ -1285,22 +1511,21 @@ static int handle_sendnodes_core(void *object, IP_Port source, const uint8_t *pa
1285 return 0; 1511 return 0;
1286} 1512}
1287 1513
1288static int handle_sendnodes_ipv6(void *object, IP_Port source, const uint8_t *packet, uint16_t length) 1514static int handle_sendnodes_ipv6(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
1289{ 1515{
1290 DHT *dht = object; 1516 DHT *const dht = (DHT *)object;
1291 Node_format plain_nodes[MAX_SENT_NODES]; 1517 Node_format plain_nodes[MAX_SENT_NODES];
1292 uint32_t num_nodes; 1518 uint32_t num_nodes;
1293 1519
1294 if (handle_sendnodes_core(object, source, packet, length, plain_nodes, MAX_SENT_NODES, &num_nodes)) 1520 if (handle_sendnodes_core(object, source, packet, length, plain_nodes, MAX_SENT_NODES, &num_nodes)) {
1295 return 1; 1521 return 1;
1522 }
1296 1523
1297 if (num_nodes == 0) 1524 if (num_nodes == 0) {
1298 return 0; 1525 return 0;
1526 }
1299 1527
1300 uint32_t i; 1528 for (uint32_t i = 0; i < num_nodes; i++) {
1301
1302 for (i = 0; i < num_nodes; i++) {
1303
1304 if (ipport_isset(&plain_nodes[i].ip_port)) { 1529 if (ipport_isset(&plain_nodes[i].ip_port)) {
1305 ping_node_from_getnodes_ok(dht, plain_nodes[i].public_key, plain_nodes[i].ip_port); 1530 ping_node_from_getnodes_ok(dht, plain_nodes[i].public_key, plain_nodes[i].ip_port);
1306 returnedip_ports(dht, plain_nodes[i].ip_port, plain_nodes[i].public_key, packet + 1); 1531 returnedip_ports(dht, plain_nodes[i].ip_port, plain_nodes[i].public_key, packet + 1);
@@ -1316,127 +1541,131 @@ static int handle_sendnodes_ipv6(void *object, IP_Port source, const uint8_t *pa
1316int DHT_addfriend(DHT *dht, const uint8_t *public_key, void (*ip_callback)(void *data, int32_t number, IP_Port), 1541int DHT_addfriend(DHT *dht, const uint8_t *public_key, void (*ip_callback)(void *data, int32_t number, IP_Port),
1317 void *data, int32_t number, uint16_t *lock_count) 1542 void *data, int32_t number, uint16_t *lock_count)
1318{ 1543{
1319 int friend_num = friend_number(dht, public_key); 1544 const uint32_t friend_num = index_of_friend_pk(dht->friends_list, dht->num_friends, public_key);
1320 1545
1321 uint16_t lock_num; 1546 uint16_t lock_num;
1322 1547
1323 if (friend_num != -1) { /* Is friend already in DHT? */ 1548 if (friend_num != UINT32_MAX) { /* Is friend already in DHT? */
1324 DHT_Friend *friend = &dht->friends_list[friend_num]; 1549 DHT_Friend *const dht_friend = &dht->friends_list[friend_num];
1325 1550
1326 if (friend->lock_count == DHT_FRIEND_MAX_LOCKS) 1551 if (dht_friend->lock_count == DHT_FRIEND_MAX_LOCKS) {
1327 return -1; 1552 return -1;
1553 }
1328 1554
1329 lock_num = friend->lock_count; 1555 lock_num = dht_friend->lock_count;
1330 ++friend->lock_count; 1556 ++dht_friend->lock_count;
1331 friend->callbacks[lock_num].ip_callback = ip_callback; 1557 dht_friend->callbacks[lock_num].ip_callback = ip_callback;
1332 friend->callbacks[lock_num].data = data; 1558 dht_friend->callbacks[lock_num].data = data;
1333 friend->callbacks[lock_num].number = number; 1559 dht_friend->callbacks[lock_num].number = number;
1334 1560
1335 if (lock_count) 1561 if (lock_count) {
1336 *lock_count = lock_num + 1; 1562 *lock_count = lock_num + 1;
1563 }
1337 1564
1338 return 0; 1565 return 0;
1339 } 1566 }
1340 1567
1341 DHT_Friend *temp; 1568 DHT_Friend *const temp = (DHT_Friend *)realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends + 1));
1342 temp = realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends + 1));
1343 1569
1344 if (temp == NULL) 1570 if (temp == nullptr) {
1345 return -1; 1571 return -1;
1572 }
1346 1573
1347 dht->friends_list = temp; 1574 dht->friends_list = temp;
1348 DHT_Friend *friend = &dht->friends_list[dht->num_friends]; 1575 DHT_Friend *const dht_friend = &dht->friends_list[dht->num_friends];
1349 memset(friend, 0, sizeof(DHT_Friend)); 1576 memset(dht_friend, 0, sizeof(DHT_Friend));
1350 memcpy(friend->public_key, public_key, crypto_box_PUBLICKEYBYTES); 1577 memcpy(dht_friend->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
1351 1578
1352 friend->nat.NATping_id = random_64b(); 1579 dht_friend->nat.NATping_id = random_u64();
1353 ++dht->num_friends; 1580 ++dht->num_friends;
1354 1581
1355 lock_num = friend->lock_count; 1582 lock_num = dht_friend->lock_count;
1356 ++friend->lock_count; 1583 ++dht_friend->lock_count;
1357 friend->callbacks[lock_num].ip_callback = ip_callback; 1584 dht_friend->callbacks[lock_num].ip_callback = ip_callback;
1358 friend->callbacks[lock_num].data = data; 1585 dht_friend->callbacks[lock_num].data = data;
1359 friend->callbacks[lock_num].number = number; 1586 dht_friend->callbacks[lock_num].number = number;
1360 1587
1361 if (lock_count) 1588 if (lock_count) {
1362 *lock_count = lock_num + 1; 1589 *lock_count = lock_num + 1;
1590 }
1363 1591
1364 friend->num_to_bootstrap = get_close_nodes(dht, friend->public_key, friend->to_bootstrap, 0, 1, 0); 1592 dht_friend->num_to_bootstrap = get_close_nodes(dht, dht_friend->public_key, dht_friend->to_bootstrap, net_family_unspec,
1593 1, 0);
1365 1594
1366 return 0; 1595 return 0;
1367} 1596}
1368 1597
1369int DHT_delfriend(DHT *dht, const uint8_t *public_key, uint16_t lock_count) 1598int DHT_delfriend(DHT *dht, const uint8_t *public_key, uint16_t lock_count)
1370{ 1599{
1371 int friend_num = friend_number(dht, public_key); 1600 const uint32_t friend_num = index_of_friend_pk(dht->friends_list, dht->num_friends, public_key);
1372 1601
1373 if (friend_num == -1) { 1602 if (friend_num == UINT32_MAX) {
1374 return -1; 1603 return -1;
1375 } 1604 }
1376 1605
1377 DHT_Friend *friend = &dht->friends_list[friend_num]; 1606 DHT_Friend *const dht_friend = &dht->friends_list[friend_num];
1378 --friend->lock_count; 1607 --dht_friend->lock_count;
1379 1608
1380 if (friend->lock_count && lock_count) { /* DHT friend is still in use.*/ 1609 if (dht_friend->lock_count && lock_count) { /* DHT friend is still in use.*/
1381 --lock_count; 1610 --lock_count;
1382 friend->callbacks[lock_count].ip_callback = NULL; 1611 dht_friend->callbacks[lock_count].ip_callback = nullptr;
1383 friend->callbacks[lock_count].data = NULL; 1612 dht_friend->callbacks[lock_count].data = nullptr;
1384 friend->callbacks[lock_count].number = 0; 1613 dht_friend->callbacks[lock_count].number = 0;
1385 return 0; 1614 return 0;
1386 } 1615 }
1387 1616
1388 DHT_Friend *temp;
1389
1390 --dht->num_friends; 1617 --dht->num_friends;
1391 1618
1392 if (dht->num_friends != friend_num) { 1619 if (dht->num_friends != friend_num) {
1393 memcpy( &dht->friends_list[friend_num], 1620 memcpy(&dht->friends_list[friend_num],
1394 &dht->friends_list[dht->num_friends], 1621 &dht->friends_list[dht->num_friends],
1395 sizeof(DHT_Friend) ); 1622 sizeof(DHT_Friend));
1396 } 1623 }
1397 1624
1398 if (dht->num_friends == 0) { 1625 if (dht->num_friends == 0) {
1399 free(dht->friends_list); 1626 free(dht->friends_list);
1400 dht->friends_list = NULL; 1627 dht->friends_list = nullptr;
1401 return 0; 1628 return 0;
1402 } 1629 }
1403 1630
1404 temp = realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends)); 1631 DHT_Friend *const temp = (DHT_Friend *)realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends));
1405 1632
1406 if (temp == NULL) 1633 if (temp == nullptr) {
1407 return -1; 1634 return -1;
1635 }
1408 1636
1409 dht->friends_list = temp; 1637 dht->friends_list = temp;
1410 return 0; 1638 return 0;
1411} 1639}
1412 1640
1413/* TODO: Optimize this. */ 1641/* TODO(irungentoo): Optimize this. */
1414int DHT_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port) 1642int DHT_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port)
1415{ 1643{
1416 uint32_t i, j;
1417
1418 ip_reset(&ip_port->ip); 1644 ip_reset(&ip_port->ip);
1419 ip_port->port = 0; 1645 ip_port->port = 0;
1420 1646
1421 for (i = 0; i < dht->num_friends; ++i) { 1647 const uint32_t friend_index = index_of_friend_pk(dht->friends_list, dht->num_friends, public_key);
1422 /* Equal */
1423 if (id_equal(dht->friends_list[i].public_key, public_key)) {
1424 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
1425 Client_data *client = &dht->friends_list[i].client_list[j];
1426
1427 if (id_equal(client->public_key, public_key)) {
1428 IPPTsPng *assoc = NULL;
1429 uint32_t a;
1430
1431 for (a = 0, assoc = &client->assoc6; a < 2; a++, assoc = &client->assoc4)
1432 if (!is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT)) {
1433 *ip_port = assoc->ip_port;
1434 return 1;
1435 }
1436 }
1437 }
1438 1648
1439 return 0; 1649 if (friend_index == UINT32_MAX) {
1650 return -1;
1651 }
1652
1653 DHT_Friend *const frnd = &dht->friends_list[friend_index];
1654 const uint32_t client_index = index_of_client_pk(frnd->client_list, MAX_FRIEND_CLIENTS, public_key);
1655
1656 if (client_index == -1) {
1657 return 0;
1658 }
1659
1660 const Client_data *const client = &frnd->client_list[client_index];
1661 const IPPTsPng *const assocs[] = { &client->assoc6, &client->assoc4 };
1662
1663 for (size_t i = 0; i < ARRAY_SIZE(assocs); i++) {
1664 const IPPTsPng *const assoc = assocs[i];
1665
1666 if (!is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT)) {
1667 *ip_port = assoc->ip_port;
1668 return 1;
1440 } 1669 }
1441 } 1670 }
1442 1671
@@ -1445,31 +1674,32 @@ int DHT_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port)
1445 1674
1446/* returns number of nodes not in kill-timeout */ 1675/* returns number of nodes not in kill-timeout */
1447static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, const uint8_t *public_key, 1676static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, const uint8_t *public_key,
1448 Client_data *list, uint32_t list_count, uint32_t *bootstrap_times, _Bool sortable) 1677 Client_data *list, uint32_t list_count, uint32_t *bootstrap_times, bool sortable)
1449{ 1678{
1450 uint32_t i;
1451 uint8_t not_kill = 0; 1679 uint8_t not_kill = 0;
1452 uint64_t temp_time = unix_time(); 1680 const uint64_t temp_time = unix_time();
1453 1681
1454 uint32_t num_nodes = 0; 1682 uint32_t num_nodes = 0;
1455 Client_data *client_list[list_count * 2]; 1683 VLA(Client_data *, client_list, list_count * 2);
1456 IPPTsPng *assoc_list[list_count * 2]; 1684 VLA(IPPTsPng *, assoc_list, list_count * 2);
1457 unsigned int sort = 0; 1685 unsigned int sort = 0;
1458 _Bool sort_ok = 0; 1686 bool sort_ok = false;
1459 1687
1460 for (i = 0; i < list_count; i++) { 1688 for (uint32_t i = 0; i < list_count; i++) {
1461 /* If node is not dead. */ 1689 /* If node is not dead. */
1462 Client_data *client = &list[i]; 1690 Client_data *client = &list[i];
1463 IPPTsPng *assoc;
1464 uint32_t a;
1465 1691
1466 for (a = 0, assoc = &client->assoc6; a < 2; a++, assoc = &client->assoc4) 1692 IPPTsPng *assocs[] = { &client->assoc6, &client->assoc4 };
1693
1694 for (size_t j = 0; j < ARRAY_SIZE(assocs); j++) {
1695 IPPTsPng *assoc = assocs[j];
1696
1467 if (!is_timeout(assoc->timestamp, KILL_NODE_TIMEOUT)) { 1697 if (!is_timeout(assoc->timestamp, KILL_NODE_TIMEOUT)) {
1468 sort = 0; 1698 sort = 0;
1469 not_kill++; 1699 not_kill++;
1470 1700
1471 if (is_timeout(assoc->last_pinged, PING_INTERVAL)) { 1701 if (is_timeout(assoc->last_pinged, PING_INTERVAL)) {
1472 getnodes(dht, assoc->ip_port, client->public_key, public_key, NULL); 1702 getnodes(dht, assoc->ip_port, client->public_key, public_key, nullptr);
1473 assoc->last_pinged = temp_time; 1703 assoc->last_pinged = temp_time;
1474 } 1704 }
1475 1705
@@ -1483,10 +1713,11 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
1483 ++sort; 1713 ++sort;
1484 1714
1485 /* Timed out should be at beginning, if they are not, sort the list. */ 1715 /* Timed out should be at beginning, if they are not, sort the list. */
1486 if (sort > 1 && sort < (((i + 1) * 2) - 1)) { 1716 if (sort > 1 && sort < (((j + 1) * 2) - 1)) {
1487 sort_ok = 1; 1717 sort_ok = true;
1488 } 1718 }
1489 } 1719 }
1720 }
1490 } 1721 }
1491 1722
1492 if (sortable && sort_ok) { 1723 if (sortable && sort_ok) {
@@ -1494,13 +1725,13 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
1494 } 1725 }
1495 1726
1496 if ((num_nodes != 0) && (is_timeout(*lastgetnode, GET_NODE_INTERVAL) || *bootstrap_times < MAX_BOOTSTRAP_TIMES)) { 1727 if ((num_nodes != 0) && (is_timeout(*lastgetnode, GET_NODE_INTERVAL) || *bootstrap_times < MAX_BOOTSTRAP_TIMES)) {
1497 uint32_t rand_node = rand() % (num_nodes); 1728 uint32_t rand_node = rand() % num_nodes;
1498 1729
1499 if ((num_nodes - 1) != rand_node) { 1730 if ((num_nodes - 1) != rand_node) {
1500 rand_node += rand() % (num_nodes - (rand_node + 1)); 1731 rand_node += rand() % (num_nodes - (rand_node + 1));
1501 } 1732 }
1502 1733
1503 getnodes(dht, assoc_list[rand_node]->ip_port, client_list[rand_node]->public_key, public_key, NULL); 1734 getnodes(dht, assoc_list[rand_node]->ip_port, client_list[rand_node]->public_key, public_key, nullptr);
1504 1735
1505 *lastgetnode = temp_time; 1736 *lastgetnode = temp_time;
1506 ++*bootstrap_times; 1737 ++*bootstrap_times;
@@ -1514,19 +1745,19 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
1514 */ 1745 */
1515static void do_DHT_friends(DHT *dht) 1746static void do_DHT_friends(DHT *dht)
1516{ 1747{
1517 unsigned int i, j; 1748 for (size_t i = 0; i < dht->num_friends; ++i) {
1518 1749 DHT_Friend *const dht_friend = &dht->friends_list[i];
1519 for (i = 0; i < dht->num_friends; ++i) {
1520 DHT_Friend *friend = &dht->friends_list[i];
1521 1750
1522 for (j = 0; j < friend->num_to_bootstrap; ++j) { 1751 for (size_t j = 0; j < dht_friend->num_to_bootstrap; ++j) {
1523 getnodes(dht, friend->to_bootstrap[j].ip_port, friend->to_bootstrap[j].public_key, friend->public_key, NULL); 1752 getnodes(dht, dht_friend->to_bootstrap[j].ip_port, dht_friend->to_bootstrap[j].public_key, dht_friend->public_key,
1753 nullptr);
1524 } 1754 }
1525 1755
1526 friend->num_to_bootstrap = 0; 1756 dht_friend->num_to_bootstrap = 0;
1527 1757
1528 do_ping_and_sendnode_requests(dht, &friend->lastgetnode, friend->public_key, friend->client_list, MAX_FRIEND_CLIENTS, 1758 do_ping_and_sendnode_requests(dht, &dht_friend->lastgetnode, dht_friend->public_key, dht_friend->client_list,
1529 &friend->bootstrap_times, 1); 1759 MAX_FRIEND_CLIENTS,
1760 &dht_friend->bootstrap_times, 1);
1530 } 1761 }
1531} 1762}
1532 1763
@@ -1535,68 +1766,63 @@ static void do_DHT_friends(DHT *dht)
1535 */ 1766 */
1536static void do_Close(DHT *dht) 1767static void do_Close(DHT *dht)
1537{ 1768{
1538 unsigned int i; 1769 for (size_t i = 0; i < dht->num_to_bootstrap; ++i) {
1539 1770 getnodes(dht, dht->to_bootstrap[i].ip_port, dht->to_bootstrap[i].public_key, dht->self_public_key, nullptr);
1540 for (i = 0; i < dht->num_to_bootstrap; ++i) {
1541 getnodes(dht, dht->to_bootstrap[i].ip_port, dht->to_bootstrap[i].public_key, dht->self_public_key, NULL);
1542 } 1771 }
1543 1772
1544 dht->num_to_bootstrap = 0; 1773 dht->num_to_bootstrap = 0;
1545 1774
1546 uint8_t not_killed = do_ping_and_sendnode_requests(dht, &dht->close_lastgetnodes, dht->self_public_key, 1775 uint8_t not_killed = do_ping_and_sendnode_requests(
1547 dht->close_clientlist, LCLIENT_LIST, &dht->close_bootstrap_times, 0); 1776 dht, &dht->close_lastgetnodes, dht->self_public_key, dht->close_clientlist, LCLIENT_LIST, &dht->close_bootstrap_times,
1777 0);
1778
1779 if (not_killed != 0) {
1780 return;
1781 }
1782
1783 /* all existing nodes are at least KILL_NODE_TIMEOUT,
1784 * which means we are mute, as we only send packets to
1785 * nodes NOT in KILL_NODE_TIMEOUT
1786 *
1787 * so: reset all nodes to be BAD_NODE_TIMEOUT, but not
1788 * KILL_NODE_TIMEOUT, so we at least keep trying pings */
1789 const uint64_t badonly = unix_time() - BAD_NODE_TIMEOUT;
1790
1791 for (size_t i = 0; i < LCLIENT_LIST; i++) {
1792 Client_data *const client = &dht->close_clientlist[i];
1548 1793
1549 if (!not_killed) { 1794 IPPTsPng *const assocs[] = { &client->assoc6, &client->assoc4 };
1550 /* all existing nodes are at least KILL_NODE_TIMEOUT,
1551 * which means we are mute, as we only send packets to
1552 * nodes NOT in KILL_NODE_TIMEOUT
1553 *
1554 * so: reset all nodes to be BAD_NODE_TIMEOUT, but not
1555 * KILL_NODE_TIMEOUT, so we at least keep trying pings */
1556 uint64_t badonly = unix_time() - BAD_NODE_TIMEOUT;
1557 size_t i, a;
1558 1795
1559 for (i = 0; i < LCLIENT_LIST; i++) { 1796 for (size_t j = 0; j < ARRAY_SIZE(assocs); j++) {
1560 Client_data *client = &dht->close_clientlist[i]; 1797 IPPTsPng *const assoc = assocs[j];
1561 IPPTsPng *assoc;
1562 1798
1563 for (a = 0, assoc = &client->assoc4; a < 2; a++, assoc = &client->assoc6) 1799 if (assoc->timestamp) {
1564 if (assoc->timestamp) 1800 assoc->timestamp = badonly;
1565 assoc->timestamp = badonly; 1801 }
1566 } 1802 }
1567 } 1803 }
1568} 1804}
1569 1805
1570void DHT_getnodes(DHT *dht, const IP_Port *from_ipp, const uint8_t *from_id, const uint8_t *which_id) 1806void DHT_getnodes(DHT *dht, const IP_Port *from_ipp, const uint8_t *from_id, const uint8_t *which_id)
1571{ 1807{
1572 getnodes(dht, *from_ipp, from_id, which_id, NULL); 1808 getnodes(dht, *from_ipp, from_id, which_id, nullptr);
1573} 1809}
1574 1810
1575void DHT_bootstrap(DHT *dht, IP_Port ip_port, const uint8_t *public_key) 1811void DHT_bootstrap(DHT *dht, IP_Port ip_port, const uint8_t *public_key)
1576{ 1812{
1577 /*#ifdef ENABLE_ASSOC_DHT 1813 getnodes(dht, ip_port, public_key, dht->self_public_key, nullptr);
1578 if (dht->assoc) {
1579 IPPTs ippts;
1580 ippts.ip_port = ip_port;
1581 ippts.timestamp = 0;
1582
1583 Assoc_add_entry(dht->assoc, public_key, &ippts, NULL, 0);
1584 }
1585 #endif*/
1586
1587 getnodes(dht, ip_port, public_key, dht->self_public_key, NULL);
1588} 1814}
1589int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled, 1815int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled,
1590 uint16_t port, const uint8_t *public_key) 1816 uint16_t port, const uint8_t *public_key)
1591{ 1817{
1592 IP_Port ip_port_v64; 1818 IP_Port ip_port_v64;
1593 IP *ip_extra = NULL; 1819 IP *ip_extra = nullptr;
1594 IP_Port ip_port_v4; 1820 IP_Port ip_port_v4;
1595 ip_init(&ip_port_v64.ip, ipv6enabled); 1821 ip_init(&ip_port_v64.ip, ipv6enabled);
1596 1822
1597 if (ipv6enabled) { 1823 if (ipv6enabled) {
1598 /* setup for getting BOTH: an IPv6 AND an IPv4 address */ 1824 /* setup for getting BOTH: an IPv6 AND an IPv4 address */
1599 ip_port_v64.ip.family = AF_UNSPEC; 1825 ip_port_v64.ip.family = net_family_unspec;
1600 ip_reset(&ip_port_v4.ip); 1826 ip_reset(&ip_port_v4.ip);
1601 ip_extra = &ip_port_v4.ip; 1827 ip_extra = &ip_port_v4.ip;
1602 } 1828 }
@@ -1605,14 +1831,15 @@ int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enable
1605 ip_port_v64.port = port; 1831 ip_port_v64.port = port;
1606 DHT_bootstrap(dht, ip_port_v64, public_key); 1832 DHT_bootstrap(dht, ip_port_v64, public_key);
1607 1833
1608 if ((ip_extra != NULL) && ip_isset(ip_extra)) { 1834 if ((ip_extra != nullptr) && ip_isset(ip_extra)) {
1609 ip_port_v4.port = port; 1835 ip_port_v4.port = port;
1610 DHT_bootstrap(dht, ip_port_v4, public_key); 1836 DHT_bootstrap(dht, ip_port_v4, public_key);
1611 } 1837 }
1612 1838
1613 return 1; 1839 return 1;
1614 } else 1840 }
1615 return 0; 1841
1842 return 0;
1616} 1843}
1617 1844
1618/* Send the given packet to node with public_key 1845/* Send the given packet to node with public_key
@@ -1621,18 +1848,20 @@ int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enable
1621 */ 1848 */
1622int route_packet(const DHT *dht, const uint8_t *public_key, const uint8_t *packet, uint16_t length) 1849int route_packet(const DHT *dht, const uint8_t *public_key, const uint8_t *packet, uint16_t length)
1623{ 1850{
1624 uint32_t i; 1851 for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
1625
1626 for (i = 0; i < LCLIENT_LIST; ++i) {
1627 if (id_equal(public_key, dht->close_clientlist[i].public_key)) { 1852 if (id_equal(public_key, dht->close_clientlist[i].public_key)) {
1628 const Client_data *client = &dht->close_clientlist[i]; 1853 const Client_data *const client = &dht->close_clientlist[i];
1854 const IPPTsPng *const assocs[] = { &client->assoc6, &client->assoc4 };
1629 1855
1630 if (ip_isset(&client->assoc6.ip_port.ip)) 1856 for (size_t j = 0; j < ARRAY_SIZE(assocs); j++) {
1631 return sendpacket(dht->net, client->assoc6.ip_port, packet, length); 1857 const IPPTsPng *const assoc = assocs[j];
1632 else if (ip_isset(&client->assoc4.ip_port.ip)) 1858
1633 return sendpacket(dht->net, client->assoc4.ip_port, packet, length); 1859 if (ip_isset(&assoc->ip_port.ip)) {
1634 else 1860 return sendpacket(dht->net, assoc->ip_port, packet, length);
1635 break; 1861 }
1862 }
1863
1864 break;
1636 } 1865 }
1637 } 1866 }
1638 1867
@@ -1648,19 +1877,18 @@ int route_packet(const DHT *dht, const uint8_t *public_key, const uint8_t *packe
1648 */ 1877 */
1649static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) 1878static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_num)
1650{ 1879{
1651 if (friend_num >= dht->num_friends) 1880 if (friend_num >= dht->num_friends) {
1652 return -1; 1881 return -1;
1882 }
1653 1883
1654 DHT_Friend *friend = &dht->friends_list[friend_num]; 1884 const DHT_Friend *const dht_friend = &dht->friends_list[friend_num];
1655 Client_data *client;
1656 IP_Port ipv4s[MAX_FRIEND_CLIENTS]; 1885 IP_Port ipv4s[MAX_FRIEND_CLIENTS];
1657 int num_ipv4s = 0; 1886 int num_ipv4s = 0;
1658 IP_Port ipv6s[MAX_FRIEND_CLIENTS]; 1887 IP_Port ipv6s[MAX_FRIEND_CLIENTS];
1659 int num_ipv6s = 0; 1888 int num_ipv6s = 0;
1660 int i;
1661 1889
1662 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { 1890 for (size_t i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
1663 client = &(friend->client_list[i]); 1891 const Client_data *const client = &dht_friend->client_list[i];
1664 1892
1665 /* If ip is not zero and node is good. */ 1893 /* If ip is not zero and node is good. */
1666 if (ip_isset(&client->assoc4.ret_ip_port.ip) && !is_timeout(client->assoc4.ret_timestamp, BAD_NODE_TIMEOUT)) { 1894 if (ip_isset(&client->assoc4.ret_ip_port.ip) && !is_timeout(client->assoc4.ret_timestamp, BAD_NODE_TIMEOUT)) {
@@ -1673,21 +1901,26 @@ static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_n
1673 ++num_ipv6s; 1901 ++num_ipv6s;
1674 } 1902 }
1675 1903
1676 if (id_equal(client->public_key, friend->public_key)) 1904 if (id_equal(client->public_key, dht_friend->public_key)) {
1677 if (!is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT) || !is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT)) 1905 if (!is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)
1906 || !is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT)) {
1678 return 0; /* direct connectivity */ 1907 return 0; /* direct connectivity */
1908 }
1909 }
1679 } 1910 }
1680 1911
1681#ifdef FRIEND_IPLIST_PAD 1912#ifdef FRIEND_IPLIST_PAD
1682 memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port)); 1913 memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port));
1683 1914
1684 if (num_ipv6s == MAX_FRIEND_CLIENTS) 1915 if (num_ipv6s == MAX_FRIEND_CLIENTS) {
1685 return MAX_FRIEND_CLIENTS; 1916 return MAX_FRIEND_CLIENTS;
1917 }
1686 1918
1687 int num_ipv4s_used = MAX_FRIEND_CLIENTS - num_ipv6s; 1919 int num_ipv4s_used = MAX_FRIEND_CLIENTS - num_ipv6s;
1688 1920
1689 if (num_ipv4s_used > num_ipv4s) 1921 if (num_ipv4s_used > num_ipv4s) {
1690 num_ipv4s_used = num_ipv4s; 1922 num_ipv4s_used = num_ipv4s;
1923 }
1691 1924
1692 memcpy(&ip_portlist[num_ipv6s], ipv4s, num_ipv4s_used * sizeof(IP_Port)); 1925 memcpy(&ip_portlist[num_ipv6s], ipv4s, num_ipv4s_used * sizeof(IP_Port));
1693 return num_ipv6s + num_ipv4s_used; 1926 return num_ipv6s + num_ipv4s_used;
@@ -1716,44 +1949,41 @@ static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_n
1716 */ 1949 */
1717int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint16_t length) 1950int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint16_t length)
1718{ 1951{
1719 int num = friend_number(dht, friend_id); 1952 const uint32_t num = index_of_friend_pk(dht->friends_list, dht->num_friends, friend_id);
1720 1953
1721 if (num == -1) 1954 if (num == UINT32_MAX) {
1722 return 0; 1955 return 0;
1956 }
1723 1957
1724 uint32_t i, sent = 0; 1958 uint32_t sent = 0;
1725 uint8_t friend_sent[MAX_FRIEND_CLIENTS] = {0}; 1959 uint8_t friend_sent[MAX_FRIEND_CLIENTS] = {0};
1726 1960
1727 IP_Port ip_list[MAX_FRIEND_CLIENTS]; 1961 IP_Port ip_list[MAX_FRIEND_CLIENTS];
1728 int ip_num = friend_iplist(dht, ip_list, num); 1962 const int ip_num = friend_iplist(dht, ip_list, num);
1729 1963
1730 if (ip_num < (MAX_FRIEND_CLIENTS / 4)) 1964 if (ip_num < (MAX_FRIEND_CLIENTS / 4)) {
1731 return 0; /* Reason for that? */ 1965 return 0; /* Reason for that? */
1966 }
1732 1967
1733 DHT_Friend *friend = &dht->friends_list[num]; 1968 const DHT_Friend *const dht_friend = &dht->friends_list[num];
1734 Client_data *client;
1735 1969
1736 /* extra legwork, because having the outside allocating the space for us 1970 /* extra legwork, because having the outside allocating the space for us
1737 * is *usually* good(tm) (bites us in the behind in this case though) */ 1971 * is *usually* good(tm) (bites us in the behind in this case though) */
1738 uint32_t a;
1739 1972
1740 for (a = 0; a < 2; a++) 1973 for (uint32_t i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
1741 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { 1974 if (friend_sent[i]) {/* Send one packet per client.*/
1742 if (friend_sent[i])/* Send one packet per client.*/ 1975 continue;
1743 continue; 1976 }
1744 1977
1745 client = &friend->client_list[i]; 1978 const Client_data *const client = &dht_friend->client_list[i];
1746 IPPTsPng *assoc = NULL; 1979 const IPPTsPng *const assocs[] = { &client->assoc4, &client->assoc6 };
1747 1980
1748 if (!a) 1981 for (size_t j = 0; j < ARRAY_SIZE(assocs); j++) {
1749 assoc = &client->assoc4; 1982 const IPPTsPng *const assoc = assocs[j];
1750 else
1751 assoc = &client->assoc6;
1752 1983
1753 /* If ip is not zero and node is good. */ 1984 /* If ip is not zero and node is good. */
1754 if (ip_isset(&assoc->ret_ip_port.ip) && 1985 if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) {
1755 !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { 1986 const int retval = sendpacket(dht->net, assoc->ip_port, packet, length);
1756 int retval = sendpacket(dht->net, assoc->ip_port, packet, length);
1757 1987
1758 if ((unsigned int)retval == length) { 1988 if ((unsigned int)retval == length) {
1759 ++sent; 1989 ++sent;
@@ -1761,6 +1991,7 @@ int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *pack
1761 } 1991 }
1762 } 1992 }
1763 } 1993 }
1994 }
1764 1995
1765 return sent; 1996 return sent;
1766} 1997}
@@ -1771,31 +2002,26 @@ int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *pack
1771 */ 2002 */
1772static int routeone_tofriend(DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint16_t length) 2003static int routeone_tofriend(DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint16_t length)
1773{ 2004{
1774 int num = friend_number(dht, friend_id); 2005 const uint32_t num = index_of_friend_pk(dht->friends_list, dht->num_friends, friend_id);
1775 2006
1776 if (num == -1) 2007 if (num == UINT32_MAX) {
1777 return 0; 2008 return 0;
2009 }
1778 2010
1779 DHT_Friend *friend = &dht->friends_list[num]; 2011 const DHT_Friend *const dht_friend = &dht->friends_list[num];
1780 Client_data *client;
1781 2012
1782 IP_Port ip_list[MAX_FRIEND_CLIENTS * 2]; 2013 IP_Port ip_list[MAX_FRIEND_CLIENTS * 2];
1783 int n = 0; 2014 int n = 0;
1784 uint32_t i;
1785 2015
1786 /* extra legwork, because having the outside allocating the space for us 2016 /* extra legwork, because having the outside allocating the space for us
1787 * is *usually* good(tm) (bites us in the behind in this case though) */ 2017 * is *usually* good(tm) (bites us in the behind in this case though) */
1788 uint32_t a;
1789 2018
1790 for (a = 0; a < 2; a++) 2019 for (uint32_t i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
1791 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { 2020 const Client_data *const client = &dht_friend->client_list[i];
1792 client = &friend->client_list[i]; 2021 const IPPTsPng *const assocs[] = { &client->assoc4, &client->assoc6 };
1793 IPPTsPng *assoc = NULL;
1794 2022
1795 if (!a) 2023 for (size_t j = 0; j < ARRAY_SIZE(assocs); j++) {
1796 assoc = &client->assoc4; 2024 const IPPTsPng *assoc = assocs[j];
1797 else
1798 assoc = &client->assoc6;
1799 2025
1800 /* If ip is not zero and node is good. */ 2026 /* If ip is not zero and node is good. */
1801 if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { 2027 if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) {
@@ -1803,14 +2029,17 @@ static int routeone_tofriend(DHT *dht, const uint8_t *friend_id, const uint8_t *
1803 ++n; 2029 ++n;
1804 } 2030 }
1805 } 2031 }
2032 }
1806 2033
1807 if (n < 1) 2034 if (n < 1) {
1808 return 0; 2035 return 0;
2036 }
1809 2037
1810 int retval = sendpacket(dht->net, ip_list[rand() % n], packet, length); 2038 const int retval = sendpacket(dht->net, ip_list[rand() % n], packet, length);
1811 2039
1812 if ((unsigned int)retval == length) 2040 if ((unsigned int)retval == length) {
1813 return 1; 2041 return 1;
2042 }
1814 2043
1815 return 0; 2044 return 0;
1816} 2045}
@@ -1828,50 +2057,58 @@ static int send_NATping(DHT *dht, const uint8_t *public_key, uint64_t ping_id, u
1828 data[0] = type; 2057 data[0] = type;
1829 memcpy(data + 1, &ping_id, sizeof(uint64_t)); 2058 memcpy(data + 1, &ping_id, sizeof(uint64_t));
1830 /* 254 is NAT ping request packet id */ 2059 /* 254 is NAT ping request packet id */
1831 int len = create_request(dht->self_public_key, dht->self_secret_key, packet, public_key, data, 2060 const int len = create_request(
1832 sizeof(uint64_t) + 1, CRYPTO_PACKET_NAT_PING); 2061 dht->self_public_key, dht->self_secret_key, packet, public_key, data,
2062 sizeof(uint64_t) + 1, CRYPTO_PACKET_NAT_PING);
1833 2063
1834 if (len == -1) 2064 if (len == -1) {
1835 return -1; 2065 return -1;
2066 }
1836 2067
1837 if (type == 0) /* If packet is request use many people to route it. */ 2068 if (type == 0) { /* If packet is request use many people to route it. */
1838 num = route_tofriend(dht, public_key, packet, len); 2069 num = route_tofriend(dht, public_key, packet, len);
1839 else if (type == 1) /* If packet is response use only one person to route it */ 2070 } else if (type == 1) { /* If packet is response use only one person to route it */
1840 num = routeone_tofriend(dht, public_key, packet, len); 2071 num = routeone_tofriend(dht, public_key, packet, len);
2072 }
1841 2073
1842 if (num == 0) 2074 if (num == 0) {
1843 return -1; 2075 return -1;
2076 }
1844 2077
1845 return num; 2078 return num;
1846} 2079}
1847 2080
1848/* Handle a received ping request for. */ 2081/* Handle a received ping request for. */
1849static int handle_NATping(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet, 2082static int handle_NATping(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet,
1850 uint16_t length) 2083 uint16_t length, void *userdata)
1851{ 2084{
1852 if (length != sizeof(uint64_t) + 1) 2085 if (length != sizeof(uint64_t) + 1) {
1853 return 1; 2086 return 1;
2087 }
1854 2088
1855 DHT *dht = object; 2089 DHT *const dht = (DHT *)object;
1856 uint64_t ping_id; 2090 uint64_t ping_id;
1857 memcpy(&ping_id, packet + 1, sizeof(uint64_t)); 2091 memcpy(&ping_id, packet + 1, sizeof(uint64_t));
1858 2092
1859 int friendnumber = friend_number(dht, source_pubkey); 2093 uint32_t friendnumber = index_of_friend_pk(dht->friends_list, dht->num_friends, source_pubkey);
1860 2094
1861 if (friendnumber == -1) 2095 if (friendnumber == UINT32_MAX) {
1862 return 1; 2096 return 1;
2097 }
1863 2098
1864 DHT_Friend *friend = &dht->friends_list[friendnumber]; 2099 DHT_Friend *const dht_friend = &dht->friends_list[friendnumber];
1865 2100
1866 if (packet[0] == NAT_PING_REQUEST) { 2101 if (packet[0] == NAT_PING_REQUEST) {
1867 /* 1 is reply */ 2102 /* 1 is reply */
1868 send_NATping(dht, source_pubkey, ping_id, NAT_PING_RESPONSE); 2103 send_NATping(dht, source_pubkey, ping_id, NAT_PING_RESPONSE);
1869 friend->nat.recvNATping_timestamp = unix_time(); 2104 dht_friend->nat.recvNATping_timestamp = unix_time();
1870 return 0; 2105 return 0;
1871 } else if (packet[0] == NAT_PING_RESPONSE) { 2106 }
1872 if (friend->nat.NATping_id == ping_id) { 2107
1873 friend->nat.NATping_id = random_64b(); 2108 if (packet[0] == NAT_PING_RESPONSE) {
1874 friend->nat.hole_punching = 1; 2109 if (dht_friend->nat.NATping_id == ping_id) {
2110 dht_friend->nat.NATping_id = random_u64();
2111 dht_friend->nat.hole_punching = 1;
1875 return 0; 2112 return 0;
1876 } 2113 }
1877 } 2114 }
@@ -1890,20 +2127,22 @@ static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)
1890 IP zero; 2127 IP zero;
1891 ip_reset(&zero); 2128 ip_reset(&zero);
1892 2129
1893 if (len > MAX_FRIEND_CLIENTS) 2130 if (len > MAX_FRIEND_CLIENTS) {
1894 return zero; 2131 return zero;
2132 }
1895 2133
1896 uint32_t i, j;
1897 uint16_t numbers[MAX_FRIEND_CLIENTS] = {0}; 2134 uint16_t numbers[MAX_FRIEND_CLIENTS] = {0};
1898 2135
1899 for (i = 0; i < len; ++i) { 2136 for (uint32_t i = 0; i < len; ++i) {
1900 for (j = 0; j < len; ++j) { 2137 for (uint32_t j = 0; j < len; ++j) {
1901 if (ip_equal(&ip_portlist[i].ip, &ip_portlist[j].ip)) 2138 if (ip_equal(&ip_portlist[i].ip, &ip_portlist[j].ip)) {
1902 ++numbers[i]; 2139 ++numbers[i];
2140 }
1903 } 2141 }
1904 2142
1905 if (numbers[i] >= min_num) 2143 if (numbers[i] >= min_num) {
1906 return ip_portlist[i].ip; 2144 return ip_portlist[i].ip;
2145 }
1907 } 2146 }
1908 2147
1909 return zero; 2148 return zero;
@@ -1917,12 +2156,11 @@ static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)
1917 */ 2156 */
1918static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t len, IP ip) 2157static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t len, IP ip)
1919{ 2158{
1920 uint32_t i;
1921 uint16_t num = 0; 2159 uint16_t num = 0;
1922 2160
1923 for (i = 0; i < len; ++i) { 2161 for (uint32_t i = 0; i < len; ++i) {
1924 if (ip_equal(&ip_portlist[i].ip, &ip)) { 2162 if (ip_equal(&ip_portlist[i].ip, &ip)) {
1925 portlist[num] = ntohs(ip_portlist[i].port); 2163 portlist[num] = net_ntohs(ip_portlist[i].port);
1926 ++num; 2164 ++num;
1927 } 2165 }
1928 } 2166 }
@@ -1932,48 +2170,57 @@ static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t
1932 2170
1933static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports, uint16_t friend_num) 2171static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports, uint16_t friend_num)
1934{ 2172{
1935 if (numports > MAX_FRIEND_CLIENTS || numports == 0) 2173 if (!dht->hole_punching_enabled) {
1936 return; 2174 return;
2175 }
1937 2176
2177 if (numports > MAX_FRIEND_CLIENTS || numports == 0) {
2178 return;
2179 }
2180
2181 const uint16_t first_port = port_list[0];
1938 uint32_t i; 2182 uint32_t i;
1939 uint32_t top = dht->friends_list[friend_num].nat.punching_index + MAX_PUNCHING_PORTS;
1940 uint16_t firstport = port_list[0];
1941 2183
1942 for (i = 0; i < numports; ++i) { 2184 for (i = 0; i < numports; ++i) {
1943 if (firstport != port_list[i]) 2185 if (first_port != port_list[i]) {
1944 break; 2186 break;
2187 }
1945 } 2188 }
1946 2189
1947 if (i == numports) { /* If all ports are the same, only try that one port. */ 2190 if (i == numports) { /* If all ports are the same, only try that one port. */
1948 IP_Port pinging; 2191 IP_Port pinging;
1949 ip_copy(&pinging.ip, &ip); 2192 ip_copy(&pinging.ip, &ip);
1950 pinging.port = htons(firstport); 2193 pinging.port = net_htons(first_port);
1951 send_ping_request(dht->ping, pinging, dht->friends_list[friend_num].public_key); 2194 ping_send_request(dht->ping, pinging, dht->friends_list[friend_num].public_key);
1952 } else { 2195 } else {
1953 for (i = dht->friends_list[friend_num].nat.punching_index; i != top; ++i) { 2196 for (i = 0; i < MAX_PUNCHING_PORTS; ++i) {
1954 /* TODO: Improve port guessing algorithm. */ 2197 /* TODO(irungentoo): Improve port guessing algorithm. */
1955 uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); 2198 const uint32_t it = i + dht->friends_list[friend_num].nat.punching_index;
2199 const int8_t sign = (it % 2) ? -1 : 1;
2200 const uint32_t delta = sign * (it / (2 * numports));
2201 const uint32_t index = (it / 2) % numports;
2202 const uint16_t port = port_list[index] + delta;
1956 IP_Port pinging; 2203 IP_Port pinging;
1957 ip_copy(&pinging.ip, &ip); 2204 ip_copy(&pinging.ip, &ip);
1958 pinging.port = htons(port); 2205 pinging.port = net_htons(port);
1959 send_ping_request(dht->ping, pinging, dht->friends_list[friend_num].public_key); 2206 ping_send_request(dht->ping, pinging, dht->friends_list[friend_num].public_key);
1960 } 2207 }
1961 2208
1962 dht->friends_list[friend_num].nat.punching_index = i; 2209 dht->friends_list[friend_num].nat.punching_index += i;
1963 } 2210 }
1964 2211
1965 if (dht->friends_list[friend_num].nat.tries > MAX_NORMAL_PUNCHING_TRIES) { 2212 if (dht->friends_list[friend_num].nat.tries > MAX_NORMAL_PUNCHING_TRIES) {
1966 top = dht->friends_list[friend_num].nat.punching_index2 + MAX_PUNCHING_PORTS; 2213 const uint16_t port = 1024;
1967 uint16_t port = 1024;
1968 IP_Port pinging; 2214 IP_Port pinging;
1969 ip_copy(&pinging.ip, &ip); 2215 ip_copy(&pinging.ip, &ip);
1970 2216
1971 for (i = dht->friends_list[friend_num].nat.punching_index2; i != top; ++i) { 2217 for (i = 0; i < MAX_PUNCHING_PORTS; ++i) {
1972 pinging.port = htons(port + i); 2218 uint32_t it = i + dht->friends_list[friend_num].nat.punching_index2;
1973 send_ping_request(dht->ping, pinging, dht->friends_list[friend_num].public_key); 2219 pinging.port = net_htons(port + it);
2220 ping_send_request(dht->ping, pinging, dht->friends_list[friend_num].public_key);
1974 } 2221 }
1975 2222
1976 dht->friends_list[friend_num].nat.punching_index2 = i - (MAX_PUNCHING_PORTS / 2); 2223 dht->friends_list[friend_num].nat.punching_index2 += i - (MAX_PUNCHING_PORTS / 2);
1977 } 2224 }
1978 2225
1979 ++dht->friends_list[friend_num].nat.tries; 2226 ++dht->friends_list[friend_num].nat.tries;
@@ -1981,16 +2228,16 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports,
1981 2228
1982static void do_NAT(DHT *dht) 2229static void do_NAT(DHT *dht)
1983{ 2230{
1984 uint32_t i; 2231 const uint64_t temp_time = unix_time();
1985 uint64_t temp_time = unix_time();
1986 2232
1987 for (i = 0; i < dht->num_friends; ++i) { 2233 for (uint32_t i = 0; i < dht->num_friends; ++i) {
1988 IP_Port ip_list[MAX_FRIEND_CLIENTS]; 2234 IP_Port ip_list[MAX_FRIEND_CLIENTS];
1989 int num = friend_iplist(dht, ip_list, i); 2235 const int num = friend_iplist(dht, ip_list, i);
1990 2236
1991 /* If already connected or friend is not online don't try to hole punch. */ 2237 /* If already connected or friend is not online don't try to hole punch. */
1992 if (num < MAX_FRIEND_CLIENTS / 2) 2238 if (num < MAX_FRIEND_CLIENTS / 2) {
1993 continue; 2239 continue;
2240 }
1994 2241
1995 if (dht->friends_list[i].nat.NATping_timestamp + PUNCH_INTERVAL < temp_time) { 2242 if (dht->friends_list[i].nat.NATping_timestamp + PUNCH_INTERVAL < temp_time) {
1996 send_NATping(dht, dht->friends_list[i].public_key, dht->friends_list[i].nat.NATping_id, NAT_PING_REQUEST); 2243 send_NATping(dht, dht->friends_list[i].public_key, dht->friends_list[i].nat.NATping_id, NAT_PING_REQUEST);
@@ -2001,13 +2248,20 @@ static void do_NAT(DHT *dht)
2001 dht->friends_list[i].nat.punching_timestamp + PUNCH_INTERVAL < temp_time && 2248 dht->friends_list[i].nat.punching_timestamp + PUNCH_INTERVAL < temp_time &&
2002 dht->friends_list[i].nat.recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { 2249 dht->friends_list[i].nat.recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) {
2003 2250
2004 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); 2251 const IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2);
2005 2252
2006 if (!ip_isset(&ip)) 2253 if (!ip_isset(&ip)) {
2007 continue; 2254 continue;
2255 }
2256
2257 if (dht->friends_list[i].nat.punching_timestamp + PUNCH_RESET_TIME < temp_time) {
2258 dht->friends_list[i].nat.tries = 0;
2259 dht->friends_list[i].nat.punching_index = 0;
2260 dht->friends_list[i].nat.punching_index2 = 0;
2261 }
2008 2262
2009 uint16_t port_list[MAX_FRIEND_CLIENTS]; 2263 uint16_t port_list[MAX_FRIEND_CLIENTS];
2010 uint16_t numports = NAT_getports(port_list, ip_list, num, ip); 2264 const uint16_t numports = NAT_getports(port_list, ip_list, num, ip);
2011 punch_holes(dht, ip, port_list, numports, i); 2265 punch_holes(dht, ip, port_list, numports, i);
2012 2266
2013 dht->friends_list[i].nat.punching_timestamp = temp_time; 2267 dht->friends_list[i].nat.punching_timestamp = temp_time;
@@ -2019,29 +2273,36 @@ static void do_NAT(DHT *dht)
2019/*----------------------------------------------------------------------------------*/ 2273/*----------------------------------------------------------------------------------*/
2020/*-----------------------END OF NAT PUNCHING FUNCTIONS------------------------------*/ 2274/*-----------------------END OF NAT PUNCHING FUNCTIONS------------------------------*/
2021 2275
2276#define DHT_HARDENING 0
2022#define HARDREQ_DATA_SIZE 384 /* Attempt to prevent amplification/other attacks*/ 2277#define HARDREQ_DATA_SIZE 384 /* Attempt to prevent amplification/other attacks*/
2023 2278
2024#define CHECK_TYPE_ROUTE_REQ 0 2279enum {
2025#define CHECK_TYPE_ROUTE_RES 1 2280 CHECK_TYPE_ROUTE_REQ = 0,
2026#define CHECK_TYPE_GETNODE_REQ 2 2281 CHECK_TYPE_ROUTE_RES = 1,
2027#define CHECK_TYPE_GETNODE_RES 3 2282 CHECK_TYPE_GETNODE_REQ = 2,
2028#define CHECK_TYPE_TEST_REQ 4 2283 CHECK_TYPE_GETNODE_RES = 3,
2029#define CHECK_TYPE_TEST_RES 5 2284 CHECK_TYPE_TEST_REQ = 4,
2285 CHECK_TYPE_TEST_RES = 5,
2286};
2030 2287
2288#if DHT_HARDENING
2031static int send_hardening_req(DHT *dht, Node_format *sendto, uint8_t type, uint8_t *contents, uint16_t length) 2289static int send_hardening_req(DHT *dht, Node_format *sendto, uint8_t type, uint8_t *contents, uint16_t length)
2032{ 2290{
2033 if (length > HARDREQ_DATA_SIZE - 1) 2291 if (length > HARDREQ_DATA_SIZE - 1) {
2034 return -1; 2292 return -1;
2293 }
2035 2294
2036 uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; 2295 uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
2037 uint8_t data[HARDREQ_DATA_SIZE] = {0}; 2296 uint8_t data[HARDREQ_DATA_SIZE] = {0};
2038 data[0] = type; 2297 data[0] = type;
2039 memcpy(data + 1, contents, length); 2298 memcpy(data + 1, contents, length);
2040 int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->public_key, data, 2299 const int len = create_request(
2041 sizeof(data), CRYPTO_PACKET_HARDENING); 2300 dht->self_public_key, dht->self_secret_key, packet, sendto->public_key,
2301 data, sizeof(data), CRYPTO_PACKET_HARDENING);
2042 2302
2043 if (len == -1) 2303 if (len == -1) {
2044 return -1; 2304 return -1;
2305 }
2045 2306
2046 return sendpacket(dht->net, sendto->ip_port, packet, len); 2307 return sendpacket(dht->net, sendto->ip_port, packet, len);
2047} 2308}
@@ -2049,67 +2310,72 @@ static int send_hardening_req(DHT *dht, Node_format *sendto, uint8_t type, uint8
2049/* Send a get node hardening request */ 2310/* Send a get node hardening request */
2050static int send_hardening_getnode_req(DHT *dht, Node_format *dest, Node_format *node_totest, uint8_t *search_id) 2311static int send_hardening_getnode_req(DHT *dht, Node_format *dest, Node_format *node_totest, uint8_t *search_id)
2051{ 2312{
2052 uint8_t data[sizeof(Node_format) + crypto_box_PUBLICKEYBYTES]; 2313 uint8_t data[sizeof(Node_format) + CRYPTO_PUBLIC_KEY_SIZE];
2053 memcpy(data, node_totest, sizeof(Node_format)); 2314 memcpy(data, node_totest, sizeof(Node_format));
2054 memcpy(data + sizeof(Node_format), search_id, crypto_box_PUBLICKEYBYTES); 2315 memcpy(data + sizeof(Node_format), search_id, CRYPTO_PUBLIC_KEY_SIZE);
2055 return send_hardening_req(dht, dest, CHECK_TYPE_GETNODE_REQ, data, sizeof(Node_format) + crypto_box_PUBLICKEYBYTES); 2316 return send_hardening_req(dht, dest, CHECK_TYPE_GETNODE_REQ, data, sizeof(Node_format) + CRYPTO_PUBLIC_KEY_SIZE);
2056} 2317}
2318#endif
2057 2319
2058/* Send a get node hardening response */ 2320/* Send a get node hardening response */
2059static int send_hardening_getnode_res(const DHT *dht, const Node_format *sendto, const uint8_t *queried_client_id, 2321static int send_hardening_getnode_res(const DHT *dht, const Node_format *sendto, const uint8_t *queried_client_id,
2060 const uint8_t *nodes_data, uint16_t nodes_data_length) 2322 const uint8_t *nodes_data, uint16_t nodes_data_length)
2061{ 2323{
2062 if (!ip_isset(&sendto->ip_port.ip)) 2324 if (!ip_isset(&sendto->ip_port.ip)) {
2063 return -1; 2325 return -1;
2326 }
2064 2327
2065 uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; 2328 uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
2066 uint8_t data[1 + crypto_box_PUBLICKEYBYTES + nodes_data_length]; 2329 VLA(uint8_t, data, 1 + CRYPTO_PUBLIC_KEY_SIZE + nodes_data_length);
2067 data[0] = CHECK_TYPE_GETNODE_RES; 2330 data[0] = CHECK_TYPE_GETNODE_RES;
2068 memcpy(data + 1, queried_client_id, crypto_box_PUBLICKEYBYTES); 2331 memcpy(data + 1, queried_client_id, CRYPTO_PUBLIC_KEY_SIZE);
2069 memcpy(data + 1 + crypto_box_PUBLICKEYBYTES, nodes_data, nodes_data_length); 2332 memcpy(data + 1 + CRYPTO_PUBLIC_KEY_SIZE, nodes_data, nodes_data_length);
2070 int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->public_key, data, 2333 const int len = create_request(
2071 sizeof(data), CRYPTO_PACKET_HARDENING); 2334 dht->self_public_key, dht->self_secret_key, packet, sendto->public_key,
2335 data, SIZEOF_VLA(data), CRYPTO_PACKET_HARDENING);
2072 2336
2073 if (len == -1) 2337 if (len == -1) {
2074 return -1; 2338 return -1;
2339 }
2075 2340
2076 return sendpacket(dht->net, sendto->ip_port, packet, len); 2341 return sendpacket(dht->net, sendto->ip_port, packet, len);
2077} 2342}
2078 2343
2079/* TODO: improve */ 2344/* TODO(irungentoo): improve */
2080static IPPTsPng *get_closelist_IPPTsPng(DHT *dht, const uint8_t *public_key, sa_family_t sa_family) 2345static IPPTsPng *get_closelist_IPPTsPng(DHT *dht, const uint8_t *public_key, Family sa_family)
2081{ 2346{
2082 uint32_t i; 2347 for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
2083 2348 if (!id_equal(dht->close_clientlist[i].public_key, public_key)) {
2084 for (i = 0; i < LCLIENT_LIST; ++i) {
2085 if (public_key_cmp(dht->close_clientlist[i].public_key, public_key) != 0)
2086 continue; 2349 continue;
2350 }
2087 2351
2088 if (sa_family == AF_INET) 2352 if (net_family_is_ipv4(sa_family)) {
2089 return &dht->close_clientlist[i].assoc4; 2353 return &dht->close_clientlist[i].assoc4;
2090 else if (sa_family == AF_INET6) 2354 }
2355
2356 if (net_family_is_ipv6(sa_family)) {
2091 return &dht->close_clientlist[i].assoc6; 2357 return &dht->close_clientlist[i].assoc6;
2358 }
2092 } 2359 }
2093 2360
2094 return NULL; 2361 return nullptr;
2095} 2362}
2096 2363
2097/* 2364/*
2098 * check how many nodes in nodes are also present in the closelist. 2365 * check how many nodes in nodes are also present in the closelist.
2099 * TODO: make this function better. 2366 * TODO(irungentoo): make this function better.
2100 */ 2367 */
2101static uint32_t have_nodes_closelist(DHT *dht, Node_format *nodes, uint16_t num) 2368static uint32_t have_nodes_closelist(DHT *dht, Node_format *nodes, uint16_t num)
2102{ 2369{
2103 uint32_t counter = 0; 2370 uint32_t counter = 0;
2104 uint32_t i;
2105 2371
2106 for (i = 0; i < num; ++i) { 2372 for (uint32_t i = 0; i < num; ++i) {
2107 if (id_equal(nodes[i].public_key, dht->self_public_key)) { 2373 if (id_equal(nodes[i].public_key, dht->self_public_key)) {
2108 ++counter; 2374 ++counter;
2109 continue; 2375 continue;
2110 } 2376 }
2111 2377
2112 IPPTsPng *temp = get_closelist_IPPTsPng(dht, nodes[i].public_key, nodes[i].ip_port.ip.family); 2378 const IPPTsPng *const temp = get_closelist_IPPTsPng(dht, nodes[i].public_key, nodes[i].ip_port.ip.family);
2113 2379
2114 if (temp) { 2380 if (temp) {
2115 if (!is_timeout(temp->timestamp, BAD_NODE_TIMEOUT)) { 2381 if (!is_timeout(temp->timestamp, BAD_NODE_TIMEOUT)) {
@@ -2123,13 +2389,12 @@ static uint32_t have_nodes_closelist(DHT *dht, Node_format *nodes, uint16_t num)
2123 2389
2124/* Interval in seconds between hardening checks */ 2390/* Interval in seconds between hardening checks */
2125#define HARDENING_INTERVAL 120 2391#define HARDENING_INTERVAL 120
2126#define HARDEN_TIMEOUT 1200
2127 2392
2128/* Handle a received hardening packet */ 2393/* Handle a received hardening packet */
2129static int handle_hardening(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet, 2394static int handle_hardening(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet,
2130 uint16_t length) 2395 uint16_t length, void *userdata)
2131{ 2396{
2132 DHT *dht = object; 2397 DHT *const dht = (DHT *)object;
2133 2398
2134 if (length < 2) { 2399 if (length < 2) {
2135 return 1; 2400 return 1;
@@ -2137,50 +2402,60 @@ static int handle_hardening(void *object, IP_Port source, const uint8_t *source_
2137 2402
2138 switch (packet[0]) { 2403 switch (packet[0]) {
2139 case CHECK_TYPE_GETNODE_REQ: { 2404 case CHECK_TYPE_GETNODE_REQ: {
2140 if (length != HARDREQ_DATA_SIZE) 2405 if (length != HARDREQ_DATA_SIZE) {
2141 return 1; 2406 return 1;
2407 }
2142 2408
2143 Node_format node, tocheck_node; 2409 Node_format node, tocheck_node;
2144 node.ip_port = source; 2410 node.ip_port = source;
2145 memcpy(node.public_key, source_pubkey, crypto_box_PUBLICKEYBYTES); 2411 memcpy(node.public_key, source_pubkey, CRYPTO_PUBLIC_KEY_SIZE);
2146 memcpy(&tocheck_node, packet + 1, sizeof(Node_format)); 2412 memcpy(&tocheck_node, packet + 1, sizeof(Node_format));
2147 2413
2148 if (getnodes(dht, tocheck_node.ip_port, tocheck_node.public_key, packet + 1 + sizeof(Node_format), &node) == -1) 2414 if (getnodes(dht, tocheck_node.ip_port, tocheck_node.public_key, packet + 1 + sizeof(Node_format), &node) == -1) {
2149 return 1; 2415 return 1;
2416 }
2150 2417
2151 return 0; 2418 return 0;
2152 } 2419 }
2153 2420
2154 case CHECK_TYPE_GETNODE_RES: { 2421 case CHECK_TYPE_GETNODE_RES: {
2155 if (length <= crypto_box_PUBLICKEYBYTES + 1) 2422 if (length <= CRYPTO_PUBLIC_KEY_SIZE + 1) {
2156 return 1; 2423 return 1;
2424 }
2157 2425
2158 if (length > 1 + crypto_box_PUBLICKEYBYTES + sizeof(Node_format) * MAX_SENT_NODES) 2426 if (length > 1 + CRYPTO_PUBLIC_KEY_SIZE + sizeof(Node_format) * MAX_SENT_NODES) {
2159 return 1; 2427 return 1;
2428 }
2160 2429
2161 uint16_t length_nodes = length - 1 - crypto_box_PUBLICKEYBYTES; 2430 uint16_t length_nodes = length - 1 - CRYPTO_PUBLIC_KEY_SIZE;
2162 Node_format nodes[MAX_SENT_NODES]; 2431 Node_format nodes[MAX_SENT_NODES];
2163 int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, packet + 1 + crypto_box_PUBLICKEYBYTES, length_nodes, 0); 2432 const int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, nullptr, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
2433 length_nodes, 0);
2164 2434
2165 /* TODO: MAX_SENT_NODES nodes should be returned at all times 2435 /* TODO(irungentoo): MAX_SENT_NODES nodes should be returned at all times
2166 (right now we have a small network size so it could cause problems for testing and etc..) */ 2436 (right now we have a small network size so it could cause problems for testing and etc..) */
2167 if (num_nodes <= 0) 2437 if (num_nodes <= 0) {
2168 return 1; 2438 return 1;
2439 }
2169 2440
2170 /* NOTE: This should work for now but should be changed to something better. */ 2441 /* NOTE: This should work for now but should be changed to something better. */
2171 if (have_nodes_closelist(dht, nodes, num_nodes) < (uint32_t)((num_nodes + 2) / 2)) 2442 if (have_nodes_closelist(dht, nodes, num_nodes) < (uint32_t)((num_nodes + 2) / 2)) {
2172 return 1; 2443 return 1;
2444 }
2173 2445
2174 IPPTsPng *temp = get_closelist_IPPTsPng(dht, packet + 1, nodes[0].ip_port.ip.family); 2446 IPPTsPng *const temp = get_closelist_IPPTsPng(dht, packet + 1, nodes[0].ip_port.ip.family);
2175 2447
2176 if (temp == NULL) 2448 if (temp == nullptr) {
2177 return 1; 2449 return 1;
2450 }
2178 2451
2179 if (is_timeout(temp->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) 2452 if (is_timeout(temp->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) {
2180 return 1; 2453 return 1;
2454 }
2181 2455
2182 if (public_key_cmp(temp->hardening.send_nodes_pingedid, source_pubkey) != 0) 2456 if (!id_equal(temp->hardening.send_nodes_pingedid, source_pubkey)) {
2183 return 1; 2457 return 1;
2458 }
2184 2459
2185 /* If Nodes look good and the request checks out */ 2460 /* If Nodes look good and the request checks out */
2186 temp->hardening.send_nodes_ok = 1; 2461 temp->hardening.send_nodes_ok = 1;
@@ -2191,62 +2466,68 @@ static int handle_hardening(void *object, IP_Port source, const uint8_t *source_
2191 return 1; 2466 return 1;
2192} 2467}
2193 2468
2469#if DHT_HARDENING
2470#define HARDEN_TIMEOUT 1200
2471
2194/* Return a random node from all the nodes we are connected to. 2472/* Return a random node from all the nodes we are connected to.
2195 * TODO: improve this function. 2473 * TODO(irungentoo): improve this function.
2196 */ 2474 */
2197Node_format random_node(DHT *dht, sa_family_t sa_family) 2475static Node_format random_node(DHT *dht, Family sa_family)
2198{ 2476{
2199 uint8_t id[crypto_box_PUBLICKEYBYTES]; 2477 uint8_t id[CRYPTO_PUBLIC_KEY_SIZE];
2200 uint32_t i;
2201 2478
2202 for (i = 0; i < crypto_box_PUBLICKEYBYTES / 4; ++i) { /* populate the id with pseudorandom bytes.*/ 2479 for (uint32_t i = 0; i < CRYPTO_PUBLIC_KEY_SIZE / 4; ++i) { /* populate the id with pseudorandom bytes.*/
2203 uint32_t t = rand(); 2480 const uint32_t t = rand();
2204 memcpy(id + i * sizeof(t), &t, sizeof(t)); 2481 memcpy(id + i * sizeof(t), &t, sizeof(t));
2205 } 2482 }
2206 2483
2207 Node_format nodes_list[MAX_SENT_NODES]; 2484 Node_format nodes_list[MAX_SENT_NODES];
2208 memset(nodes_list, 0, sizeof(nodes_list)); 2485 memset(nodes_list, 0, sizeof(nodes_list));
2209 uint32_t num_nodes = get_close_nodes(dht, id, nodes_list, sa_family, 1, 0); 2486 const uint32_t num_nodes = get_close_nodes(dht, id, nodes_list, sa_family, 1, 0);
2210 2487
2211 if (num_nodes == 0) 2488 if (num_nodes == 0) {
2212 return nodes_list[0]; 2489 return nodes_list[0];
2213 else 2490 }
2214 return nodes_list[rand() % num_nodes]; 2491
2492 return nodes_list[rand() % num_nodes];
2215} 2493}
2494#endif
2216 2495
2217/* Put up to max_num nodes in nodes from the closelist. 2496/* Put up to max_num nodes in nodes from the closelist.
2218 * 2497 *
2219 * return the number of nodes. 2498 * return the number of nodes.
2220 */ 2499 */
2221uint16_t list_nodes(Client_data *list, unsigned int length, Node_format *nodes, uint16_t max_num) 2500static uint16_t list_nodes(Client_data *list, size_t length, Node_format *nodes, uint16_t max_num)
2222{ 2501{
2223 if (max_num == 0) 2502 if (max_num == 0) {
2224 return 0; 2503 return 0;
2504 }
2225 2505
2226 uint16_t count = 0; 2506 uint16_t count = 0;
2227 2507
2228 unsigned int i; 2508 for (size_t i = length; i != 0; --i) {
2229 2509 const IPPTsPng *assoc = nullptr;
2230 for (i = length; i != 0; --i) {
2231 IPPTsPng *assoc = NULL;
2232 2510
2233 if (!is_timeout(list[i - 1].assoc4.timestamp, BAD_NODE_TIMEOUT)) 2511 if (!is_timeout(list[i - 1].assoc4.timestamp, BAD_NODE_TIMEOUT)) {
2234 assoc = &list[i - 1].assoc4; 2512 assoc = &list[i - 1].assoc4;
2513 }
2235 2514
2236 if (!is_timeout(list[i - 1].assoc6.timestamp, BAD_NODE_TIMEOUT)) { 2515 if (!is_timeout(list[i - 1].assoc6.timestamp, BAD_NODE_TIMEOUT)) {
2237 if (assoc == NULL) 2516 if (assoc == nullptr) {
2238 assoc = &list[i - 1].assoc6; 2517 assoc = &list[i - 1].assoc6;
2239 else if (rand() % 2) 2518 } else if (rand() % 2) {
2240 assoc = &list[i - 1].assoc6; 2519 assoc = &list[i - 1].assoc6;
2520 }
2241 } 2521 }
2242 2522
2243 if (assoc != NULL) { 2523 if (assoc != nullptr) {
2244 memcpy(nodes[count].public_key, list[i - 1].public_key, crypto_box_PUBLICKEYBYTES); 2524 memcpy(nodes[count].public_key, list[i - 1].public_key, CRYPTO_PUBLIC_KEY_SIZE);
2245 nodes[count].ip_port = assoc->ip_port; 2525 nodes[count].ip_port = assoc->ip_port;
2246 ++count; 2526 ++count;
2247 2527
2248 if (count >= max_num) 2528 if (count >= max_num) {
2249 return count; 2529 return count;
2530 }
2250 } 2531 }
2251 } 2532 }
2252 2533
@@ -2259,18 +2540,20 @@ uint16_t list_nodes(Client_data *list, unsigned int length, Node_format *nodes,
2259 */ 2540 */
2260uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num) 2541uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)
2261{ 2542{
2262 if (max_num == 0) 2543 if (max_num == 0) {
2263 return 0; 2544 return 0;
2545 }
2264 2546
2265 uint16_t count = 0; 2547 uint16_t count = 0;
2266 unsigned int i, r = rand(); 2548 const unsigned int r = rand();
2267 2549
2268 for (i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) { 2550 for (size_t i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) {
2269 count += list_nodes(dht->friends_list[(i + r) % DHT_FAKE_FRIEND_NUMBER].client_list, MAX_FRIEND_CLIENTS, nodes + count, 2551 count += list_nodes(dht->friends_list[(i + r) % DHT_FAKE_FRIEND_NUMBER].client_list, MAX_FRIEND_CLIENTS, nodes + count,
2270 max_num - count); 2552 max_num - count);
2271 2553
2272 if (count >= max_num) 2554 if (count >= max_num) {
2273 break; 2555 break;
2556 }
2274 } 2557 }
2275 2558
2276 return count; 2559 return count;
@@ -2285,43 +2568,45 @@ uint16_t closelist_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)
2285 return list_nodes(dht->close_clientlist, LCLIENT_LIST, nodes, max_num); 2568 return list_nodes(dht->close_clientlist, LCLIENT_LIST, nodes, max_num);
2286} 2569}
2287 2570
2288void do_hardening(DHT *dht) 2571#if DHT_HARDENING
2572static void do_hardening(DHT *dht)
2289{ 2573{
2290 uint32_t i; 2574 for (uint32_t i = 0; i < LCLIENT_LIST * 2; ++i) {
2291 2575 IPPTsPng *cur_iptspng;
2292 for (i = 0; i < LCLIENT_LIST * 2; ++i) { 2576 Family sa_family;
2293 IPPTsPng *cur_iptspng; 2577 const uint8_t *const public_key = dht->close_clientlist[i / 2].public_key;
2294 sa_family_t sa_family;
2295 uint8_t *public_key = dht->close_clientlist[i / 2].public_key;
2296 2578
2297 if (i % 2 == 0) { 2579 if (i % 2 == 0) {
2298 cur_iptspng = &dht->close_clientlist[i / 2].assoc4; 2580 cur_iptspng = &dht->close_clientlist[i / 2].assoc4;
2299 sa_family = AF_INET; 2581 sa_family = net_family_ipv4;
2300 } else { 2582 } else {
2301 cur_iptspng = &dht->close_clientlist[i / 2].assoc6; 2583 cur_iptspng = &dht->close_clientlist[i / 2].assoc6;
2302 sa_family = AF_INET6; 2584 sa_family = net_family_ipv6;
2303 } 2585 }
2304 2586
2305 if (is_timeout(cur_iptspng->timestamp, BAD_NODE_TIMEOUT)) 2587 if (is_timeout(cur_iptspng->timestamp, BAD_NODE_TIMEOUT)) {
2306 continue; 2588 continue;
2589 }
2307 2590
2308 if (cur_iptspng->hardening.send_nodes_ok == 0) { 2591 if (cur_iptspng->hardening.send_nodes_ok == 0) {
2309 if (is_timeout(cur_iptspng->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) { 2592 if (is_timeout(cur_iptspng->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) {
2310 Node_format rand_node = random_node(dht, sa_family); 2593 Node_format rand_node = random_node(dht, sa_family);
2311 2594
2312 if (!ipport_isset(&rand_node.ip_port)) 2595 if (!ipport_isset(&rand_node.ip_port)) {
2313 continue; 2596 continue;
2597 }
2314 2598
2315 if (id_equal(public_key, rand_node.public_key)) 2599 if (id_equal(public_key, rand_node.public_key)) {
2316 continue; 2600 continue;
2601 }
2317 2602
2318 Node_format to_test; 2603 Node_format to_test;
2319 to_test.ip_port = cur_iptspng->ip_port; 2604 to_test.ip_port = cur_iptspng->ip_port;
2320 memcpy(to_test.public_key, public_key, crypto_box_PUBLICKEYBYTES); 2605 memcpy(to_test.public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
2321 2606
2322 //TODO: The search id should maybe not be ours? 2607 // TODO(irungentoo): The search id should maybe not be ours?
2323 if (send_hardening_getnode_req(dht, &rand_node, &to_test, dht->self_public_key) > 0) { 2608 if (send_hardening_getnode_req(dht, &rand_node, &to_test, dht->self_public_key) > 0) {
2324 memcpy(cur_iptspng->hardening.send_nodes_pingedid, rand_node.public_key, crypto_box_PUBLICKEYBYTES); 2609 memcpy(cur_iptspng->hardening.send_nodes_pingedid, rand_node.public_key, CRYPTO_PUBLIC_KEY_SIZE);
2325 cur_iptspng->hardening.send_nodes_timestamp = unix_time(); 2610 cur_iptspng->hardening.send_nodes_timestamp = unix_time();
2326 } 2611 }
2327 } 2612 }
@@ -2331,9 +2616,10 @@ void do_hardening(DHT *dht)
2331 } 2616 }
2332 } 2617 }
2333 2618
2334 //TODO: add the 2 other testers. 2619 // TODO(irungentoo): add the 2 other testers.
2335 } 2620 }
2336} 2621}
2622#endif
2337 2623
2338/*----------------------------------------------------------------------------------*/ 2624/*----------------------------------------------------------------------------------*/
2339 2625
@@ -2343,35 +2629,43 @@ void cryptopacket_registerhandler(DHT *dht, uint8_t byte, cryptopacket_handler_c
2343 dht->cryptopackethandlers[byte].object = object; 2629 dht->cryptopackethandlers[byte].object = object;
2344} 2630}
2345 2631
2346static int cryptopacket_handle(void *object, IP_Port source, const uint8_t *packet, uint16_t length) 2632static int cryptopacket_handle(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
2347{ 2633{
2348 DHT *dht = object; 2634 DHT *const dht = (DHT *)object;
2349 2635
2350 if (packet[0] == NET_PACKET_CRYPTO) { 2636 assert(packet[0] == NET_PACKET_CRYPTO);
2351 if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + crypto_box_MACBYTES || 2637
2352 length > MAX_CRYPTO_REQUEST_SIZE + crypto_box_MACBYTES) 2638 if (length <= CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE + 1 + CRYPTO_MAC_SIZE ||
2353 return 1; 2639 length > MAX_CRYPTO_REQUEST_SIZE + CRYPTO_MAC_SIZE) {
2640 return 1;
2641 }
2354 2642
2355 if (public_key_cmp(packet + 1, dht->self_public_key) == 0) { // Check if request is for us. 2643 // Check if request is for us.
2356 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 2644 if (id_equal(packet + 1, dht->self_public_key)) {
2357 uint8_t data[MAX_CRYPTO_REQUEST_SIZE]; 2645 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
2358 uint8_t number; 2646 uint8_t data[MAX_CRYPTO_REQUEST_SIZE];
2359 int len = handle_request(dht->self_public_key, dht->self_secret_key, public_key, data, &number, packet, length); 2647 uint8_t number;
2648 const int len = handle_request(dht->self_public_key, dht->self_secret_key, public_key,
2649 data, &number, packet, length);
2360 2650
2361 if (len == -1 || len == 0) 2651 if (len == -1 || len == 0) {
2362 return 1; 2652 return 1;
2653 }
2363 2654
2364 if (!dht->cryptopackethandlers[number].function) return 1; 2655 if (!dht->cryptopackethandlers[number].function) {
2656 return 1;
2657 }
2365 2658
2366 return dht->cryptopackethandlers[number].function(dht->cryptopackethandlers[number].object, source, public_key, 2659 return dht->cryptopackethandlers[number].function(
2367 data, len); 2660 dht->cryptopackethandlers[number].object, source, public_key,
2661 data, len, userdata);
2662 }
2368 2663
2369 } else { /* If request is not for us, try routing it. */ 2664 /* If request is not for us, try routing it. */
2370 int retval = route_packet(dht, packet + 1, packet, length); 2665 const int retval = route_packet(dht, packet + 1, packet, length);
2371 2666
2372 if ((unsigned int)retval == length) 2667 if ((unsigned int)retval == length) {
2373 return 0; 2668 return 0;
2374 }
2375 } 2669 }
2376 2670
2377 return 1; 2671 return 1;
@@ -2379,25 +2673,31 @@ static int cryptopacket_handle(void *object, IP_Port source, const uint8_t *pack
2379 2673
2380/*----------------------------------------------------------------------------------*/ 2674/*----------------------------------------------------------------------------------*/
2381 2675
2382DHT *new_DHT(Networking_Core *net) 2676DHT *new_DHT(Logger *log, Networking_Core *net, bool holepunching_enabled)
2383{ 2677{
2384 /* init time */ 2678 /* init time */
2385 unix_time_update(); 2679 unix_time_update();
2386 2680
2387 if (net == NULL) 2681 if (net == nullptr) {
2388 return NULL; 2682 return nullptr;
2683 }
2389 2684
2390 DHT *dht = calloc(1, sizeof(DHT)); 2685 DHT *const dht = (DHT *)calloc(1, sizeof(DHT));
2391 2686
2392 if (dht == NULL) 2687 if (dht == nullptr) {
2393 return NULL; 2688 return nullptr;
2689 }
2394 2690
2691 dht->log = log;
2395 dht->net = net; 2692 dht->net = net;
2396 dht->ping = new_ping(dht);
2397 2693
2398 if (dht->ping == NULL) { 2694 dht->hole_punching_enabled = holepunching_enabled;
2695
2696 dht->ping = ping_new(dht);
2697
2698 if (dht->ping == nullptr) {
2399 kill_DHT(dht); 2699 kill_DHT(dht);
2400 return NULL; 2700 return nullptr;
2401 } 2701 }
2402 2702
2403 networking_registerhandler(dht->net, NET_PACKET_GET_NODES, &handle_getnodes, dht); 2703 networking_registerhandler(dht->net, NET_PACKET_GET_NODES, &handle_getnodes, dht);
@@ -2406,23 +2706,18 @@ DHT *new_DHT(Networking_Core *net)
2406 cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht); 2706 cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht);
2407 cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, &handle_hardening, dht); 2707 cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, &handle_hardening, dht);
2408 2708
2409 new_symmetric_key(dht->secret_symmetric_key); 2709 crypto_new_keypair(dht->self_public_key, dht->self_secret_key);
2410 crypto_box_keypair(dht->self_public_key, dht->self_secret_key);
2411 2710
2412 ping_array_init(&dht->dht_ping_array, DHT_PING_ARRAY_SIZE, PING_TIMEOUT); 2711 dht->dht_ping_array = ping_array_new(DHT_PING_ARRAY_SIZE, PING_TIMEOUT);
2413 ping_array_init(&dht->dht_harden_ping_array, DHT_PING_ARRAY_SIZE, PING_TIMEOUT); 2712 dht->dht_harden_ping_array = ping_array_new(DHT_PING_ARRAY_SIZE, PING_TIMEOUT);
2414#ifdef ENABLE_ASSOC_DHT
2415 dht->assoc = new_Assoc_default(dht->self_public_key);
2416#endif
2417 uint32_t i;
2418 2713
2419 for (i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) { 2714 for (uint32_t i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) {
2420 uint8_t random_key_bytes[crypto_box_PUBLICKEYBYTES]; 2715 uint8_t random_key_bytes[CRYPTO_PUBLIC_KEY_SIZE];
2421 randombytes(random_key_bytes, sizeof(random_key_bytes)); 2716 random_bytes(random_key_bytes, sizeof(random_key_bytes));
2422 2717
2423 if (DHT_addfriend(dht, random_key_bytes, 0, 0, 0, 0) != 0) { 2718 if (DHT_addfriend(dht, random_key_bytes, nullptr, nullptr, 0, nullptr) != 0) {
2424 kill_DHT(dht); 2719 kill_DHT(dht);
2425 return NULL; 2720 return nullptr;
2426 } 2721 }
2427 } 2722 }
2428 2723
@@ -2445,35 +2740,29 @@ void do_DHT(DHT *dht)
2445 do_Close(dht); 2740 do_Close(dht);
2446 do_DHT_friends(dht); 2741 do_DHT_friends(dht);
2447 do_NAT(dht); 2742 do_NAT(dht);
2448 do_to_ping(dht->ping); 2743 ping_iterate(dht->ping);
2449 //do_hardening(dht); 2744#if DHT_HARDENING
2450#ifdef ENABLE_ASSOC_DHT 2745 do_hardening(dht);
2451
2452 if (dht->assoc)
2453 do_Assoc(dht->assoc, dht);
2454
2455#endif 2746#endif
2456 dht->last_run = unix_time(); 2747 dht->last_run = unix_time();
2457} 2748}
2749
2458void kill_DHT(DHT *dht) 2750void kill_DHT(DHT *dht)
2459{ 2751{
2460#ifdef ENABLE_ASSOC_DHT 2752 networking_registerhandler(dht->net, NET_PACKET_GET_NODES, nullptr, nullptr);
2461 kill_Assoc(dht->assoc); 2753 networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, nullptr, nullptr);
2462#endif 2754 cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, nullptr, nullptr);
2463 networking_registerhandler(dht->net, NET_PACKET_GET_NODES, NULL, NULL); 2755 cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, nullptr, nullptr);
2464 networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, NULL, NULL); 2756 ping_array_kill(dht->dht_ping_array);
2465 cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, NULL, NULL); 2757 ping_array_kill(dht->dht_harden_ping_array);
2466 cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, NULL, NULL); 2758 ping_kill(dht->ping);
2467 ping_array_free_all(&dht->dht_ping_array);
2468 ping_array_free_all(&dht->dht_harden_ping_array);
2469 kill_ping(dht->ping);
2470 free(dht->friends_list); 2759 free(dht->friends_list);
2471 free(dht->loaded_nodes_list); 2760 free(dht->loaded_nodes_list);
2472 free(dht); 2761 free(dht);
2473} 2762}
2474 2763
2475/* new DHT format for load/save, more robust and forward compatible */ 2764/* new DHT format for load/save, more robust and forward compatible */
2476//TODO: Move this closer to Messenger. 2765// TODO(irungentoo): Move this closer to Messenger.
2477#define DHT_STATE_COOKIE_GLOBAL 0x159000d 2766#define DHT_STATE_COOKIE_GLOBAL 0x159000d
2478 2767
2479#define DHT_STATE_COOKIE_TYPE 0x11ce 2768#define DHT_STATE_COOKIE_TYPE 0x11ce
@@ -2484,28 +2773,30 @@ void kill_DHT(DHT *dht)
2484/* Get the size of the DHT (for saving). */ 2773/* Get the size of the DHT (for saving). */
2485uint32_t DHT_size(const DHT *dht) 2774uint32_t DHT_size(const DHT *dht)
2486{ 2775{
2487 uint32_t numv4 = 0, numv6 = 0, i, j; 2776 uint32_t numv4 = 0;
2777 uint32_t numv6 = 0;
2488 2778
2489 for (i = 0; i < LCLIENT_LIST; ++i) { 2779 for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
2490 numv4 += (dht->close_clientlist[i].assoc4.timestamp != 0); 2780 numv4 += (dht->close_clientlist[i].assoc4.timestamp != 0);
2491 numv6 += (dht->close_clientlist[i].assoc6.timestamp != 0); 2781 numv6 += (dht->close_clientlist[i].assoc6.timestamp != 0);
2492 } 2782 }
2493 2783
2494 for (i = 0; i < DHT_FAKE_FRIEND_NUMBER && i < dht->num_friends; ++i) { 2784 for (uint32_t i = 0; i < DHT_FAKE_FRIEND_NUMBER && i < dht->num_friends; ++i) {
2495 DHT_Friend *fr = &dht->friends_list[i]; 2785 const DHT_Friend *const fr = &dht->friends_list[i];
2496 2786
2497 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 2787 for (uint32_t j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
2498 numv4 += (fr->client_list[j].assoc4.timestamp != 0); 2788 numv4 += (fr->client_list[j].assoc4.timestamp != 0);
2499 numv6 += (fr->client_list[j].assoc6.timestamp != 0); 2789 numv6 += (fr->client_list[j].assoc6.timestamp != 0);
2500 } 2790 }
2501 } 2791 }
2502 2792
2503 uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2; 2793 const uint32_t size32 = sizeof(uint32_t);
2794 const uint32_t sizesubhead = size32 * 2;
2504 2795
2505 return size32 + sizesubhead + (packed_node_size(AF_INET) * numv4) + (packed_node_size(AF_INET6) * numv6); 2796 return size32 + sizesubhead + packed_node_size(net_family_ipv4) * numv4 + packed_node_size(net_family_ipv6) * numv6;
2506} 2797}
2507 2798
2508static uint8_t *z_state_save_subheader(uint8_t *data, uint32_t len, uint16_t type) 2799static uint8_t *DHT_save_subheader(uint8_t *data, uint32_t len, uint16_t type)
2509{ 2800{
2510 host_to_lendian32(data, len); 2801 host_to_lendian32(data, len);
2511 data += sizeof(uint32_t); 2802 data += sizeof(uint32_t);
@@ -2516,53 +2807,53 @@ static uint8_t *z_state_save_subheader(uint8_t *data, uint32_t len, uint16_t typ
2516 2807
2517 2808
2518/* Save the DHT in data where data is an array of size DHT_size(). */ 2809/* Save the DHT in data where data is an array of size DHT_size(). */
2519void DHT_save(DHT *dht, uint8_t *data) 2810void DHT_save(const DHT *dht, uint8_t *data)
2520{ 2811{
2521 host_to_lendian32(data, DHT_STATE_COOKIE_GLOBAL); 2812 host_to_lendian32(data, DHT_STATE_COOKIE_GLOBAL);
2522 data += sizeof(uint32_t); 2813 data += sizeof(uint32_t);
2523 2814
2524 uint32_t num, i, j; 2815 uint8_t *const old_data = data;
2525
2526 uint8_t *old_data = data;
2527 2816
2528 /* get right offset. we write the actual header later. */ 2817 /* get right offset. we write the actual header later. */
2529 data = z_state_save_subheader(data, 0, 0); 2818 data = DHT_save_subheader(data, 0, 0);
2530 2819
2531 Node_format clients[MAX_SAVED_DHT_NODES]; 2820 Node_format clients[MAX_SAVED_DHT_NODES];
2532 2821
2533 for (num = 0, i = 0; i < LCLIENT_LIST; ++i) { 2822 uint32_t num = 0;
2823
2824 for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
2534 if (dht->close_clientlist[i].assoc4.timestamp != 0) { 2825 if (dht->close_clientlist[i].assoc4.timestamp != 0) {
2535 memcpy(clients[num].public_key, dht->close_clientlist[i].public_key, crypto_box_PUBLICKEYBYTES); 2826 memcpy(clients[num].public_key, dht->close_clientlist[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
2536 clients[num].ip_port = dht->close_clientlist[i].assoc4.ip_port; 2827 clients[num].ip_port = dht->close_clientlist[i].assoc4.ip_port;
2537 ++num; 2828 ++num;
2538 } 2829 }
2539 2830
2540 if (dht->close_clientlist[i].assoc6.timestamp != 0) { 2831 if (dht->close_clientlist[i].assoc6.timestamp != 0) {
2541 memcpy(clients[num].public_key, dht->close_clientlist[i].public_key, crypto_box_PUBLICKEYBYTES); 2832 memcpy(clients[num].public_key, dht->close_clientlist[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
2542 clients[num].ip_port = dht->close_clientlist[i].assoc6.ip_port; 2833 clients[num].ip_port = dht->close_clientlist[i].assoc6.ip_port;
2543 ++num; 2834 ++num;
2544 } 2835 }
2545 } 2836 }
2546 2837
2547 for (i = 0; i < DHT_FAKE_FRIEND_NUMBER && i < dht->num_friends; ++i) { 2838 for (uint32_t i = 0; i < DHT_FAKE_FRIEND_NUMBER && i < dht->num_friends; ++i) {
2548 DHT_Friend *fr = &dht->friends_list[i]; 2839 const DHT_Friend *const fr = &dht->friends_list[i];
2549 2840
2550 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 2841 for (uint32_t j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
2551 if (fr->client_list[j].assoc4.timestamp != 0) { 2842 if (fr->client_list[j].assoc4.timestamp != 0) {
2552 memcpy(clients[num].public_key, fr->client_list[j].public_key, crypto_box_PUBLICKEYBYTES); 2843 memcpy(clients[num].public_key, fr->client_list[j].public_key, CRYPTO_PUBLIC_KEY_SIZE);
2553 clients[num].ip_port = fr->client_list[j].assoc4.ip_port; 2844 clients[num].ip_port = fr->client_list[j].assoc4.ip_port;
2554 ++num; 2845 ++num;
2555 } 2846 }
2556 2847
2557 if (fr->client_list[j].assoc6.timestamp != 0) { 2848 if (fr->client_list[j].assoc6.timestamp != 0) {
2558 memcpy(clients[num].public_key, fr->client_list[j].public_key, crypto_box_PUBLICKEYBYTES); 2849 memcpy(clients[num].public_key, fr->client_list[j].public_key, CRYPTO_PUBLIC_KEY_SIZE);
2559 clients[num].ip_port = fr->client_list[j].assoc6.ip_port; 2850 clients[num].ip_port = fr->client_list[j].assoc6.ip_port;
2560 ++num; 2851 ++num;
2561 } 2852 }
2562 } 2853 }
2563 } 2854 }
2564 2855
2565 z_state_save_subheader(old_data, pack_nodes(data, sizeof(Node_format) * num, clients, num), DHT_STATE_TYPE_NODES); 2856 DHT_save_subheader(old_data, pack_nodes(data, sizeof(Node_format) * num, clients, num), DHT_STATE_TYPE_NODES);
2566} 2857}
2567 2858
2568/* Bootstrap from this number of nodes every time DHT_connect_after_load() is called */ 2859/* Bootstrap from this number of nodes every time DHT_connect_after_load() is called */
@@ -2571,24 +2862,24 @@ void DHT_save(DHT *dht, uint8_t *data)
2571/* Start sending packets after DHT loaded_friends_list and loaded_clients_list are set */ 2862/* Start sending packets after DHT loaded_friends_list and loaded_clients_list are set */
2572int DHT_connect_after_load(DHT *dht) 2863int DHT_connect_after_load(DHT *dht)
2573{ 2864{
2574 if (dht == NULL) 2865 if (dht == nullptr) {
2575 return -1; 2866 return -1;
2867 }
2576 2868
2577 if (!dht->loaded_nodes_list) 2869 if (!dht->loaded_nodes_list) {
2578 return -1; 2870 return -1;
2871 }
2579 2872
2580 /* DHT is connected, stop. */ 2873 /* DHT is connected, stop. */
2581 if (DHT_non_lan_connected(dht)) { 2874 if (DHT_non_lan_connected(dht)) {
2582 free(dht->loaded_nodes_list); 2875 free(dht->loaded_nodes_list);
2583 dht->loaded_nodes_list = NULL; 2876 dht->loaded_nodes_list = nullptr;
2584 dht->loaded_num_nodes = 0; 2877 dht->loaded_num_nodes = 0;
2585 return 0; 2878 return 0;
2586 } 2879 }
2587 2880
2588 unsigned int i; 2881 for (uint32_t i = 0; i < dht->loaded_num_nodes && i < SAVE_BOOTSTAP_FREQUENCY; ++i) {
2589 2882 const unsigned int index = dht->loaded_nodes_index % dht->loaded_num_nodes;
2590 for (i = 0; i < dht->loaded_num_nodes && i < SAVE_BOOTSTAP_FREQUENCY; ++i) {
2591 unsigned int index = dht->loaded_nodes_index % dht->loaded_num_nodes;
2592 DHT_bootstrap(dht, dht->loaded_nodes_list[index].ip_port, dht->loaded_nodes_list[index].public_key); 2883 DHT_bootstrap(dht, dht->loaded_nodes_list[index].ip_port, dht->loaded_nodes_list[index].public_key);
2593 ++dht->loaded_nodes_index; 2884 ++dht->loaded_nodes_index;
2594 } 2885 }
@@ -2598,37 +2889,33 @@ int DHT_connect_after_load(DHT *dht)
2598 2889
2599static int dht_load_state_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type) 2890static int dht_load_state_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type)
2600{ 2891{
2601 DHT *dht = outer; 2892 DHT *dht = (DHT *)outer;
2602 2893
2603 switch (type) { 2894 switch (type) {
2604 case DHT_STATE_TYPE_NODES: 2895 case DHT_STATE_TYPE_NODES: {
2605 if (length == 0) 2896 if (length == 0) {
2606 break; 2897 break;
2898 }
2607 2899
2608 { 2900 free(dht->loaded_nodes_list);
2609 free(dht->loaded_nodes_list); 2901 // Copy to loaded_clients_list
2610 // Copy to loaded_clients_list 2902 dht->loaded_nodes_list = (Node_format *)calloc(MAX_SAVED_DHT_NODES, sizeof(Node_format));
2611 dht->loaded_nodes_list = calloc(MAX_SAVED_DHT_NODES, sizeof(Node_format));
2612
2613 int num = unpack_nodes(dht->loaded_nodes_list, MAX_SAVED_DHT_NODES, NULL, data, length, 0);
2614 2903
2615 if (num > 0) { 2904 const int num = unpack_nodes(dht->loaded_nodes_list, MAX_SAVED_DHT_NODES, nullptr, data, length, 0);
2616 dht->loaded_num_nodes = num;
2617 } else {
2618 dht->loaded_num_nodes = 0;
2619 }
2620 2905
2621 } /* localize declarations */ 2906 if (num > 0) {
2907 dht->loaded_num_nodes = num;
2908 } else {
2909 dht->loaded_num_nodes = 0;
2910 }
2622 2911
2623 break; 2912 break;
2624 2913 }
2625#ifdef DEBUG
2626 2914
2627 default: 2915 default:
2628 fprintf(stderr, "Load state (DHT): contains unrecognized part (len %u, type %u)\n", 2916 LOGGER_ERROR(dht->log, "Load state (DHT): contains unrecognized part (len %u, type %u)\n",
2629 length, type); 2917 length, type);
2630 break; 2918 break;
2631#endif
2632 } 2919 }
2633 2920
2634 return 0; 2921 return 0;
@@ -2641,57 +2928,58 @@ static int dht_load_state_callback(void *outer, const uint8_t *data, uint32_t le
2641 */ 2928 */
2642int DHT_load(DHT *dht, const uint8_t *data, uint32_t length) 2929int DHT_load(DHT *dht, const uint8_t *data, uint32_t length)
2643{ 2930{
2644 uint32_t cookie_len = sizeof(uint32_t); 2931 const uint32_t cookie_len = sizeof(uint32_t);
2645 2932
2646 if (length > cookie_len) { 2933 if (length > cookie_len) {
2647 uint32_t data32; 2934 uint32_t data32;
2648 lendian_to_host32(&data32, data); 2935 lendian_to_host32(&data32, data);
2649 2936
2650 if (data32 == DHT_STATE_COOKIE_GLOBAL) 2937 if (data32 == DHT_STATE_COOKIE_GLOBAL) {
2651 return load_state(dht_load_state_callback, dht, data + cookie_len, 2938 return load_state(dht_load_state_callback, dht->log, dht, data + cookie_len,
2652 length - cookie_len, DHT_STATE_COOKIE_TYPE); 2939 length - cookie_len, DHT_STATE_COOKIE_TYPE);
2940 }
2653 } 2941 }
2654 2942
2655 return -1; 2943 return -1;
2656} 2944}
2657 2945
2658/* return 0 if we are not connected to the DHT. 2946/* return false if we are not connected to the DHT.
2659 * return 1 if we are. 2947 * return true if we are.
2660 */ 2948 */
2661int DHT_isconnected(const DHT *dht) 2949bool DHT_isconnected(const DHT *dht)
2662{ 2950{
2663 uint32_t i;
2664 unix_time_update(); 2951 unix_time_update();
2665 2952
2666 for (i = 0; i < LCLIENT_LIST; ++i) { 2953 for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
2667 const Client_data *client = &dht->close_clientlist[i]; 2954 const Client_data *const client = &dht->close_clientlist[i];
2668 2955
2669 if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) || 2956 if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) ||
2670 !is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) 2957 !is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) {
2671 return 1; 2958 return true;
2959 }
2672 } 2960 }
2673 2961
2674 return 0; 2962 return false;
2675} 2963}
2676 2964
2677/* return 0 if we are not connected or only connected to lan peers with the DHT. 2965/* return false if we are not connected or only connected to lan peers with the DHT.
2678 * return 1 if we are. 2966 * return true if we are.
2679 */ 2967 */
2680int DHT_non_lan_connected(const DHT *dht) 2968bool DHT_non_lan_connected(const DHT *dht)
2681{ 2969{
2682 uint32_t i;
2683 unix_time_update(); 2970 unix_time_update();
2684 2971
2685 for (i = 0; i < LCLIENT_LIST; ++i) { 2972 for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
2686 const Client_data *client = &dht->close_clientlist[i]; 2973 const Client_data *const client = &dht->close_clientlist[i];
2687
2688 if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) && LAN_ip(client->assoc4.ip_port.ip) == -1)
2689 return 1;
2690 2974
2691 if (!is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT) && LAN_ip(client->assoc6.ip_port.ip) == -1) 2975 if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) && ip_is_lan(client->assoc4.ip_port.ip) == -1) {
2692 return 1; 2976 return true;
2977 }
2693 2978
2979 if (!is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT) && ip_is_lan(client->assoc6.ip_port.ip) == -1) {
2980 return true;
2981 }
2694 } 2982 }
2695 2983
2696 return 0; 2984 return false;
2697} 2985}
diff --git a/toxcore/DHT.h b/toxcore/DHT.h
index aea3d73b..3ad28d8c 100644
--- a/toxcore/DHT.h
+++ b/toxcore/DHT.h
@@ -1,33 +1,36 @@
1/* DHT.h 1/*
2 *
3 * An implementation of the DHT as seen in docs/updates/DHT.md 2 * An implementation of the DHT as seen in docs/updates/DHT.md
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2013 Tox project.
4 * 8 *
5 * Copyright (C) 2013 Tox project All Rights Reserved. 9 * This file is part of Tox, the free peer to peer instant messenger.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23
24#ifndef DHT_H 24#ifndef DHT_H
25#define DHT_H 25#define DHT_H
26 26
27#include "crypto_core.h" 27#include "crypto_core.h"
28#include "logger.h"
28#include "network.h" 29#include "network.h"
29#include "ping_array.h" 30#include "ping_array.h"
30 31
32#include <stdbool.h>
33
31/* Maximum number of clients stored per friend. */ 34/* Maximum number of clients stored per friend. */
32#define MAX_FRIEND_CLIENTS 8 35#define MAX_FRIEND_CLIENTS 8
33 36
@@ -56,20 +59,35 @@
56#define PING_ROUNDTRIP 2 59#define PING_ROUNDTRIP 2
57#define BAD_NODE_TIMEOUT (PING_INTERVAL + PINGS_MISSED_NODE_GOES_BAD * (PING_INTERVAL + PING_ROUNDTRIP)) 60#define BAD_NODE_TIMEOUT (PING_INTERVAL + PINGS_MISSED_NODE_GOES_BAD * (PING_INTERVAL + PING_ROUNDTRIP))
58 61
59/* Redefinitions of variables for safe transfer over wire. */
60#define TOX_AF_INET 2
61#define TOX_AF_INET6 10
62#define TOX_TCP_INET 130
63#define TOX_TCP_INET6 138
64
65/* The number of "fake" friends to add (for optimization purposes and so our paths for the onion part are more random) */ 62/* The number of "fake" friends to add (for optimization purposes and so our paths for the onion part are more random) */
66#define DHT_FAKE_FRIEND_NUMBER 2 63#define DHT_FAKE_FRIEND_NUMBER 2
67 64
68/* Functions to transfer ips safely across wire. */ 65#define MAX_CRYPTO_REQUEST_SIZE 1024
69void to_net_family(IP *ip); 66
67#define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */
68#define CRYPTO_PACKET_HARDENING 48 /* Hardening crypto packet ID. */
69#define CRYPTO_PACKET_DHTPK 156
70#define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID. */
70 71
71/* return 0 on success, -1 on failure. */ 72/* Create a request to peer.
72int to_host_family(IP *ip); 73 * send_public_key and send_secret_key are the pub/secret keys of the sender.
74 * recv_public_key is public key of receiver.
75 * packet must be an array of MAX_CRYPTO_REQUEST_SIZE big.
76 * Data represents the data we send with the request with length being the length of the data.
77 * request_id is the id of the request (32 = friend request, 254 = ping request).
78 *
79 * return -1 on failure.
80 * return the length of the created packet on success.
81 */
82int create_request(const uint8_t *send_public_key, const uint8_t *send_secret_key, uint8_t *packet,
83 const uint8_t *recv_public_key, const uint8_t *data, uint32_t length, uint8_t request_id);
84
85/* puts the senders public key in the request in public_key, the data from the request
86 in data if a friend or ping request was sent to us and returns the length of the data.
87 packet is the request packet and length is its length
88 return -1 if not valid request. */
89int handle_request(const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
90 uint8_t *request_id, const uint8_t *packet, uint16_t length);
73 91
74typedef struct { 92typedef struct {
75 IP_Port ip_port; 93 IP_Port ip_port;
@@ -81,17 +99,17 @@ typedef struct {
81 uint8_t routes_requests_ok; 99 uint8_t routes_requests_ok;
82 /* Time which we last checked this.*/ 100 /* Time which we last checked this.*/
83 uint64_t routes_requests_timestamp; 101 uint64_t routes_requests_timestamp;
84 uint8_t routes_requests_pingedid[crypto_box_PUBLICKEYBYTES]; 102 uint8_t routes_requests_pingedid[CRYPTO_PUBLIC_KEY_SIZE];
85 /* Node sends correct send_node (true (1) or false/didn't check (0)) */ 103 /* Node sends correct send_node (true (1) or false/didn't check (0)) */
86 uint8_t send_nodes_ok; 104 uint8_t send_nodes_ok;
87 /* Time which we last checked this.*/ 105 /* Time which we last checked this.*/
88 uint64_t send_nodes_timestamp; 106 uint64_t send_nodes_timestamp;
89 uint8_t send_nodes_pingedid[crypto_box_PUBLICKEYBYTES]; 107 uint8_t send_nodes_pingedid[CRYPTO_PUBLIC_KEY_SIZE];
90 /* Node can be used to test other nodes (true (1) or false/didn't check (0)) */ 108 /* Node can be used to test other nodes (true (1) or false/didn't check (0)) */
91 uint8_t testing_requests; 109 uint8_t testing_requests;
92 /* Time which we last checked this.*/ 110 /* Time which we last checked this.*/
93 uint64_t testing_timestamp; 111 uint64_t testing_timestamp;
94 uint8_t testing_pingedid[crypto_box_PUBLICKEYBYTES]; 112 uint8_t testing_pingedid[CRYPTO_PUBLIC_KEY_SIZE];
95} Hardening; 113} Hardening;
96 114
97typedef struct { 115typedef struct {
@@ -106,7 +124,7 @@ typedef struct {
106} IPPTsPng; 124} IPPTsPng;
107 125
108typedef struct { 126typedef struct {
109 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 127 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
110 IPPTsPng assoc4; 128 IPPTsPng assoc4;
111 IPPTsPng assoc6; 129 IPPTsPng assoc6;
112} Client_data; 130} Client_data;
@@ -129,38 +147,34 @@ typedef struct {
129#define DHT_FRIEND_MAX_LOCKS 32 147#define DHT_FRIEND_MAX_LOCKS 32
130 148
131typedef struct { 149typedef struct {
132 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 150 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
133 IP_Port ip_port; 151 IP_Port ip_port;
134} 152}
135Node_format; 153Node_format;
136 154
137typedef struct { 155typedef struct DHT_Friend DHT_Friend;
138 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
139 Client_data client_list[MAX_FRIEND_CLIENTS];
140
141 /* Time at which the last get_nodes request was sent. */
142 uint64_t lastgetnode;
143 /* number of times get_node packets were sent. */
144 uint32_t bootstrap_times;
145 156
146 /* Symetric NAT hole punching stuff. */ 157const uint8_t *dht_friend_public_key(const DHT_Friend *dht_friend);
147 NAT nat; 158const Client_data *dht_friend_client(const DHT_Friend *dht_friend, size_t index);
148 159
149 uint16_t lock_count; 160/* Return packet size of packed node with ip_family on success.
150 struct { 161 * Return -1 on failure.
151 void (*ip_callback)(void *, int32_t, IP_Port); 162 */
152 void *data; 163int packed_node_size(Family ip_family);
153 int32_t number;
154 } callbacks[DHT_FRIEND_MAX_LOCKS];
155 164
156 Node_format to_bootstrap[MAX_SENT_NODES]; 165/* Packs an IP_Port structure into data of max size length.
157 unsigned int num_to_bootstrap; 166 *
158} DHT_Friend; 167 * Returns size of packed IP_Port data on success
168 * Return -1 on failure.
169 */
170int pack_ip_port(uint8_t *data, uint16_t length, const IP_Port *ip_port);
159 171
160/* Return packet size of packed node with ip_family on success. 172/* Unpack IP_Port structure from data of max size length into ip_port.
173 *
174 * Return size of unpacked ip_port on success.
161 * Return -1 on failure. 175 * Return -1 on failure.
162 */ 176 */
163int packed_node_size(uint8_t ip_family); 177int unpack_ip_port(IP_Port *ip_port, const uint8_t *data, uint16_t length, uint8_t tcp_enabled);
164 178
165/* Pack number of nodes into data of maxlength length. 179/* Pack number of nodes into data of maxlength length.
166 * 180 *
@@ -184,62 +198,46 @@ int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed
184/* struct to store some shared keys so we don't have to regenerate them for each request. */ 198/* struct to store some shared keys so we don't have to regenerate them for each request. */
185#define MAX_KEYS_PER_SLOT 4 199#define MAX_KEYS_PER_SLOT 4
186#define KEYS_TIMEOUT 600 200#define KEYS_TIMEOUT 600
201
187typedef struct { 202typedef struct {
188 struct { 203 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
189 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 204 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
190 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 205 uint32_t times_requested;
191 uint32_t times_requested; 206 uint8_t stored; /* 0 if not, 1 if is */
192 uint8_t stored; /* 0 if not, 1 if is */ 207 uint64_t time_last_requested;
193 uint64_t time_last_requested; 208} Shared_Key;
194 } keys[256 * MAX_KEYS_PER_SLOT]; 209
210typedef struct {
211 Shared_Key keys[256 * MAX_KEYS_PER_SLOT];
195} Shared_Keys; 212} Shared_Keys;
196 213
197/*----------------------------------------------------------------------------------*/ 214/*----------------------------------------------------------------------------------*/
198 215
199typedef int (*cryptopacket_handler_callback)(void *object, IP_Port ip_port, const uint8_t *source_pubkey, 216typedef int (*cryptopacket_handler_callback)(void *object, IP_Port ip_port, const uint8_t *source_pubkey,
200 const uint8_t *data, uint16_t len); 217 const uint8_t *data, uint16_t len, void *userdata);
201 218
202typedef struct { 219typedef struct {
203 cryptopacket_handler_callback function; 220 cryptopacket_handler_callback function;
204 void *object; 221 void *object;
205} Cryptopacket_Handles; 222} Cryptopacket_Handles;
206 223
207typedef struct { 224#define DHT_DEFINED
208 Networking_Core *net; 225typedef struct DHT DHT;
209
210 Client_data close_clientlist[LCLIENT_LIST];
211 uint64_t close_lastgetnodes;
212 uint32_t close_bootstrap_times;
213
214 /* Note: this key should not be/is not used to transmit any sensitive materials */
215 uint8_t secret_symmetric_key[crypto_box_KEYBYTES];
216 /* DHT keypair */
217 uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
218 uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
219 226
220 DHT_Friend *friends_list; 227const uint8_t *dht_get_self_public_key(const DHT *dht);
221 uint16_t num_friends; 228const uint8_t *dht_get_self_secret_key(const DHT *dht);
229void dht_set_self_public_key(DHT *dht, const uint8_t *key);
230void dht_set_self_secret_key(DHT *dht, const uint8_t *key);
222 231
223 Node_format *loaded_nodes_list; 232Networking_Core *dht_get_net(const DHT *dht);
224 uint32_t loaded_num_nodes; 233struct Ping *dht_get_ping(const DHT *dht);
225 unsigned int loaded_nodes_index; 234const Client_data *dht_get_close_clientlist(const DHT *dht);
235const Client_data *dht_get_close_client(const DHT *dht, uint32_t client_num);
236uint16_t dht_get_num_friends(const DHT *dht);
226 237
227 Shared_Keys shared_keys_recv; 238DHT_Friend *dht_get_friend(DHT *dht, uint32_t friend_num);
228 Shared_Keys shared_keys_sent; 239const uint8_t *dht_get_friend_public_key(const DHT *dht, uint32_t friend_num);
229 240
230 struct PING *ping;
231 Ping_Array dht_ping_array;
232 Ping_Array dht_harden_ping_array;
233#ifdef ENABLE_ASSOC_DHT
234 struct Assoc *assoc;
235#endif
236 uint64_t last_run;
237
238 Cryptopacket_Handles cryptopackethandlers[256];
239
240 Node_format to_bootstrap[MAX_CLOSE_TO_BOOTSTRAP_NODES];
241 unsigned int num_to_bootstrap;
242} DHT;
243/*----------------------------------------------------------------------------------*/ 241/*----------------------------------------------------------------------------------*/
244 242
245/* Shared key generations are costly, it is therefor smart to store commonly used 243/* Shared key generations are costly, it is therefor smart to store commonly used
@@ -264,7 +262,7 @@ void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *publi
264void DHT_getnodes(DHT *dht, const IP_Port *from_ipp, const uint8_t *from_id, const uint8_t *which_id); 262void DHT_getnodes(DHT *dht, const IP_Port *from_ipp, const uint8_t *from_id, const uint8_t *which_id);
265 263
266/* Add a new friend to the friends list. 264/* Add a new friend to the friends list.
267 * public_key must be crypto_box_PUBLICKEYBYTES bytes long. 265 * public_key must be CRYPTO_PUBLIC_KEY_SIZE bytes long.
268 * 266 *
269 * ip_callback is the callback of a function that will be called when the ip address 267 * ip_callback is the callback of a function that will be called when the ip address
270 * is found along with arguments data and number. 268 * is found along with arguments data and number.
@@ -279,7 +277,7 @@ int DHT_addfriend(DHT *dht, const uint8_t *public_key, void (*ip_callback)(void
279 void *data, int32_t number, uint16_t *lock_count); 277 void *data, int32_t number, uint16_t *lock_count);
280 278
281/* Delete a friend from the friends list. 279/* Delete a friend from the friends list.
282 * public_key must be crypto_box_PUBLICKEYBYTES bytes long. 280 * public_key must be CRYPTO_PUBLIC_KEY_SIZE bytes long.
283 * 281 *
284 * return 0 if success. 282 * return 0 if success.
285 * return -1 if failure (public_key not in friends list). 283 * return -1 if failure (public_key not in friends list).
@@ -287,7 +285,7 @@ int DHT_addfriend(DHT *dht, const uint8_t *public_key, void (*ip_callback)(void
287int DHT_delfriend(DHT *dht, const uint8_t *public_key, uint16_t lock_count); 285int DHT_delfriend(DHT *dht, const uint8_t *public_key, uint16_t lock_count);
288 286
289/* Get ip of friend. 287/* Get ip of friend.
290 * public_key must be crypto_box_PUBLICKEYBYTES bytes long. 288 * public_key must be CRYPTO_PUBLIC_KEY_SIZE bytes long.
291 * ip must be 4 bytes long. 289 * ip must be 4 bytes long.
292 * port must be 2 bytes long. 290 * port must be 2 bytes long.
293 * 291 *
@@ -309,24 +307,24 @@ int id_closest(const uint8_t *pk, const uint8_t *pk1, const uint8_t *pk2);
309 307
310/* Add node to the node list making sure only the nodes closest to cmp_pk are in the list. 308/* Add node to the node list making sure only the nodes closest to cmp_pk are in the list.
311 */ 309 */
312_Bool add_to_list(Node_format *nodes_list, unsigned int length, const uint8_t *pk, IP_Port ip_port, 310bool add_to_list(Node_format *nodes_list, unsigned int length, const uint8_t *pk, IP_Port ip_port,
313 const uint8_t *cmp_pk); 311 const uint8_t *cmp_pk);
314 312
315/* Return 1 if node can be added to close list, 0 if it can't. 313/* Return 1 if node can be added to close list, 0 if it can't.
316 */ 314 */
317_Bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port); 315bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port);
318 316
319/* Get the (maximum MAX_SENT_NODES) closest nodes to public_key we know 317/* Get the (maximum MAX_SENT_NODES) closest nodes to public_key we know
320 * and put them in nodes_list (must be MAX_SENT_NODES big). 318 * and put them in nodes_list (must be MAX_SENT_NODES big).
321 * 319 *
322 * sa_family = family (IPv4 or IPv6) (0 if we don't care)? 320 * sa_family = family (IPv4 or IPv6) (0 if we don't care)?
323 * is_LAN = return some LAN ips (true or false) 321 * is_LAN = return some LAN ips (true or false)
324 * want_good = do we want tested nodes or not? (TODO) 322 * want_good = do we want tested nodes or not? (TODO(irungentoo))
325 * 323 *
326 * return the number of nodes returned. 324 * return the number of nodes returned.
327 * 325 *
328 */ 326 */
329int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, sa_family_t sa_family, 327int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, Family sa_family,
330 uint8_t is_LAN, uint8_t want_good); 328 uint8_t is_LAN, uint8_t want_good);
331 329
332 330
@@ -397,7 +395,7 @@ void cryptopacket_registerhandler(DHT *dht, uint8_t byte, cryptopacket_handler_c
397uint32_t DHT_size(const DHT *dht); 395uint32_t DHT_size(const DHT *dht);
398 396
399/* Save the DHT in data where data is an array of size DHT_size(). */ 397/* Save the DHT in data where data is an array of size DHT_size(). */
400void DHT_save(DHT *dht, uint8_t *data); 398void DHT_save(const DHT *dht, uint8_t *data);
401 399
402/* Load the DHT from data of size size. 400/* Load the DHT from data of size size.
403 * 401 *
@@ -407,22 +405,21 @@ void DHT_save(DHT *dht, uint8_t *data);
407int DHT_load(DHT *dht, const uint8_t *data, uint32_t length); 405int DHT_load(DHT *dht, const uint8_t *data, uint32_t length);
408 406
409/* Initialize DHT. */ 407/* Initialize DHT. */
410DHT *new_DHT(Networking_Core *net); 408DHT *new_DHT(Logger *log, Networking_Core *net, bool holepunching_enabled);
411 409
412void kill_DHT(DHT *dht); 410void kill_DHT(DHT *dht);
413 411
414/* return 0 if we are not connected to the DHT. 412/* return false if we are not connected to the DHT.
415 * return 1 if we are. 413 * return true if we are.
416 */ 414 */
417int DHT_isconnected(const DHT *dht); 415bool DHT_isconnected(const DHT *dht);
418 416
419/* return 0 if we are not connected or only connected to lan peers with the DHT. 417/* return false if we are not connected or only connected to lan peers with the DHT.
420 * return 1 if we are. 418 * return true if we are.
421 */ 419 */
422int DHT_non_lan_connected(const DHT *dht); 420bool DHT_non_lan_connected(const DHT *dht);
423 421
424 422
425int addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key); 423uint32_t addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key);
426 424
427#endif 425#endif
428
diff --git a/toxcore/LAN_discovery.api.h b/toxcore/LAN_discovery.api.h
new file mode 100644
index 00000000..9e6c6481
--- /dev/null
+++ b/toxcore/LAN_discovery.api.h
@@ -0,0 +1,73 @@
1%{
2/*
3 * LAN discovery implementation.
4 */
5
6/*
7 * Copyright © 2016-2017 The TokTok team.
8 * Copyright © 2013 Tox project.
9 *
10 * This file is part of Tox, the free peer to peer instant messenger.
11 *
12 * Tox is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * Tox is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
24 */
25#ifndef LAN_DISCOVERY_H
26#define LAN_DISCOVERY_H
27
28#include "DHT.h"
29%}
30
31class dHT { struct this; }
32class iP { struct this; }
33
34namespace lan_discovery {
35
36/**
37 * Interval in seconds between LAN discovery packet sending.
38 */
39const INTERVAL = 10;
40
41/**
42 * Send a LAN discovery pcaket to the broadcast address with port port.
43 */
44static int32_t send(uint16_t port, dHT::this *dht);
45
46/**
47 * Sets up packet handlers.
48 */
49static void init(dHT::this *dht);
50
51/**
52 * Clear packet handlers.
53 */
54static void kill(dHT::this *dht);
55
56}
57
58/**
59 * Is IP a local ip or not.
60 */
61static bool ip_is_local(iP::this ip);
62
63/**
64 * checks if a given IP isn't routable
65 *
66 * return 0 if ip is a LAN ip.
67 * return -1 if it is not.
68 */
69static int32_t ip_is_lan(iP::this ip);
70
71%{
72#endif
73%}
diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c
index 3ea09eb9..d25aace3 100644
--- a/toxcore/LAN_discovery.c
+++ b/toxcore/LAN_discovery.c
@@ -1,70 +1,81 @@
1/* LAN_discovery.c 1/*
2 * 2 * LAN discovery implementation.
3 * LAN discovery implementation. 3 */
4 * 4
5 * Copyright (C) 2013 Tox project All Rights Reserved. 5/*
6 * 6 * Copyright © 2016-2017 The TokTok team.
7 * This file is part of Tox. 7 * Copyright © 2013 Tox project.
8 * 8 *
9 * Tox is free software: you can redistribute it and/or modify 9 * This file is part of Tox, the free peer to peer instant messenger.
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23
24#ifdef HAVE_CONFIG_H 24#ifdef HAVE_CONFIG_H
25#include "config.h" 25#include "config.h"
26#endif 26#endif
27 27
28#include "LAN_discovery.h" 28#include "LAN_discovery.h"
29#include "util.h"
30 29
31/* Used for get_broadcast(). */ 30#include <string.h>
32#ifdef __linux 31
33#include <sys/ioctl.h> 32#include "util.h"
34#include <arpa/inet.h>
35#include <linux/netdevice.h>
36#endif
37 33
38#define MAX_INTERFACES 16 34#define MAX_INTERFACES 16
39 35
40 36
37/* TODO: multiple threads might concurrently try to set these, and it isn't clear that this couldn't lead to undesirable
38 * behaviour. Consider storing the data in per-instance variables instead. */
41static int broadcast_count = -1; 39static int broadcast_count = -1;
42static IP_Port broadcast_ip_port[MAX_INTERFACES]; 40static IP_Port broadcast_ip_ports[MAX_INTERFACES];
43 41
44#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) 42#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
43
44// The mingw32/64 Windows library warns about including winsock2.h after
45// windows.h even though with the above it's a valid thing to do. So, to make
46// mingw32 headers happy, we include winsock2.h first.
47#include <winsock2.h>
48
49#include <windows.h>
50#include <ws2tcpip.h>
45 51
46#include <iphlpapi.h> 52#include <iphlpapi.h>
47 53
48static void fetch_broadcast_info(uint16_t port) 54static void fetch_broadcast_info(uint16_t port)
49{ 55{
50 broadcast_count = 0; 56 IP_ADAPTER_INFO *pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
51
52 IP_ADAPTER_INFO *pAdapterInfo = malloc(sizeof(IP_ADAPTER_INFO));
53 unsigned long ulOutBufLen = sizeof(IP_ADAPTER_INFO); 57 unsigned long ulOutBufLen = sizeof(IP_ADAPTER_INFO);
54 58
55 if (pAdapterInfo == NULL) { 59 if (pAdapterInfo == nullptr) {
56 return; 60 return;
57 } 61 }
58 62
59 if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { 63 if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {
60 free(pAdapterInfo); 64 free(pAdapterInfo);
61 pAdapterInfo = malloc(ulOutBufLen); 65 pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
62 66
63 if (pAdapterInfo == NULL) { 67 if (pAdapterInfo == nullptr) {
64 return; 68 return;
65 } 69 }
66 } 70 }
67 71
72 /* We copy these to the static variables broadcast_* only at the end of fetch_broadcast_info().
73 * The intention is to ensure that even if multiple threads enter fetch_broadcast_info() concurrently, only valid
74 * interfaces will be set to be broadcast to.
75 * */
76 int count = 0;
77 IP_Port ip_ports[MAX_INTERFACES];
78
68 int ret; 79 int ret;
69 80
70 if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { 81 if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) {
@@ -75,17 +86,17 @@ static void fetch_broadcast_info(uint16_t port)
75 86
76 if (addr_parse_ip(pAdapter->IpAddressList.IpMask.String, &subnet_mask) 87 if (addr_parse_ip(pAdapter->IpAddressList.IpMask.String, &subnet_mask)
77 && addr_parse_ip(pAdapter->GatewayList.IpAddress.String, &gateway)) { 88 && addr_parse_ip(pAdapter->GatewayList.IpAddress.String, &gateway)) {
78 if (gateway.family == AF_INET && subnet_mask.family == AF_INET) { 89 if (net_family_is_ipv4(gateway.family) && net_family_is_ipv4(subnet_mask.family)) {
79 IP_Port *ip_port = &broadcast_ip_port[broadcast_count]; 90 IP_Port *ip_port = &ip_ports[count];
80 ip_port->ip.family = AF_INET; 91 ip_port->ip.family = net_family_ipv4;
81 uint32_t gateway_ip = ntohl(gateway.ip4.uint32), subnet_ip = ntohl(subnet_mask.ip4.uint32); 92 uint32_t gateway_ip = net_ntohl(gateway.ip.v4.uint32), subnet_ip = net_ntohl(subnet_mask.ip.v4.uint32);
82 uint32_t broadcast_ip = gateway_ip + ~subnet_ip - 1; 93 uint32_t broadcast_ip = gateway_ip + ~subnet_ip - 1;
83 ip_port->ip.ip4.uint32 = htonl(broadcast_ip); 94 ip_port->ip.ip.v4.uint32 = net_htonl(broadcast_ip);
84 ip_port->port = port; 95 ip_port->port = port;
85 broadcast_count++; 96 count++;
86 97
87 if (broadcast_count >= MAX_INTERFACES) { 98 if (count >= MAX_INTERFACES) {
88 return; 99 break;
89 } 100 }
90 } 101 }
91 } 102 }
@@ -97,9 +108,29 @@ static void fetch_broadcast_info(uint16_t port)
97 if (pAdapterInfo) { 108 if (pAdapterInfo) {
98 free(pAdapterInfo); 109 free(pAdapterInfo);
99 } 110 }
111
112 broadcast_count = count;
113
114 for (uint32_t i = 0; i < count; i++) {
115 broadcast_ip_ports[i] = ip_ports[i];
116 }
100} 117}
101 118
102#elif defined(__linux__) 119#elif defined(__linux__) || defined(__FreeBSD__)
120
121#include <netinet/in.h>
122#include <sys/ioctl.h>
123#include <sys/socket.h>
124#include <sys/types.h>
125#include <unistd.h>
126
127#ifdef __linux__
128#include <linux/netdevice.h>
129#endif
130
131#ifdef __FreeBSD__
132#include <net/if.h>
133#endif
103 134
104static void fetch_broadcast_info(uint16_t port) 135static void fetch_broadcast_info(uint16_t port)
105{ 136{
@@ -108,10 +139,11 @@ static void fetch_broadcast_info(uint16_t port)
108 * Definitely won't work like this on Windows... 139 * Definitely won't work like this on Windows...
109 */ 140 */
110 broadcast_count = 0; 141 broadcast_count = 0;
111 sock_t sock = 0; 142 const Socket sock = net_socket(net_family_ipv4, TOX_SOCK_STREAM, 0);
112 143
113 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 144 if (!sock_valid(sock)) {
114 return; 145 return;
146 }
115 147
116 /* Configure ifconf for the ioctl call. */ 148 /* Configure ifconf for the ioctl call. */
117 struct ifreq i_faces[MAX_INTERFACES]; 149 struct ifreq i_faces[MAX_INTERFACES];
@@ -121,50 +153,64 @@ static void fetch_broadcast_info(uint16_t port)
121 ifconf.ifc_buf = (char *)i_faces; 153 ifconf.ifc_buf = (char *)i_faces;
122 ifconf.ifc_len = sizeof(i_faces); 154 ifconf.ifc_len = sizeof(i_faces);
123 155
124 if (ioctl(sock, SIOCGIFCONF, &ifconf) < 0) { 156 if (ioctl(sock.socket, SIOCGIFCONF, &ifconf) < 0) {
125 close(sock); 157 kill_sock(sock);
126 return; 158 return;
127 } 159 }
128 160
161 /* We copy these to the static variables broadcast_* only at the end of fetch_broadcast_info().
162 * The intention is to ensure that even if multiple threads enter fetch_broadcast_info() concurrently, only valid
163 * interfaces will be set to be broadcast to.
164 * */
165 int count = 0;
166 IP_Port ip_ports[MAX_INTERFACES];
167
129 /* ifconf.ifc_len is set by the ioctl() to the actual length used; 168 /* ifconf.ifc_len is set by the ioctl() to the actual length used;
130 * on usage of the complete array the call should be repeated with 169 * on usage of the complete array the call should be repeated with
131 * a larger array, not done (640kB and 16 interfaces shall be 170 * a larger array, not done (640kB and 16 interfaces shall be
132 * enough, for everybody!) 171 * enough, for everybody!)
133 */ 172 */
134 int i, count = ifconf.ifc_len / sizeof(struct ifreq); 173 int n = ifconf.ifc_len / sizeof(struct ifreq);
135 174
136 for (i = 0; i < count; i++) { 175 for (int i = 0; i < n; i++) {
137 /* there are interfaces with are incapable of broadcast */ 176 /* there are interfaces with are incapable of broadcast */
138 if (ioctl(sock, SIOCGIFBRDADDR, &i_faces[i]) < 0) 177 if (ioctl(sock.socket, SIOCGIFBRDADDR, &i_faces[i]) < 0) {
139 continue; 178 continue;
179 }
140 180
141 /* moot check: only AF_INET returned (backwards compat.) */ 181 /* moot check: only AF_INET returned (backwards compat.) */
142 if (i_faces[i].ifr_broadaddr.sa_family != AF_INET) 182 if (i_faces[i].ifr_broadaddr.sa_family != AF_INET) {
143 continue; 183 continue;
184 }
144 185
145 struct sockaddr_in *sock4 = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr; 186 struct sockaddr_in *sock4 = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr;
146 187
147 if (broadcast_count >= MAX_INTERFACES) { 188 if (count >= MAX_INTERFACES) {
148 close(sock); 189 break;
149 return;
150 } 190 }
151 191
152 IP_Port *ip_port = &broadcast_ip_port[broadcast_count]; 192 IP_Port *ip_port = &ip_ports[count];
153 ip_port->ip.family = AF_INET; 193 ip_port->ip.family = net_family_ipv4;
154 ip_port->ip.ip4.in_addr = sock4->sin_addr; 194 ip_port->ip.ip.v4.uint32 = sock4->sin_addr.s_addr;
155 195
156 if (ip_port->ip.ip4.uint32 == 0) { 196 if (ip_port->ip.ip.v4.uint32 == 0) {
157 continue; 197 continue;
158 } 198 }
159 199
160 ip_port->port = port; 200 ip_port->port = port;
161 broadcast_count++; 201 count++;
162 } 202 }
163 203
164 close(sock); 204 kill_sock(sock);
205
206 broadcast_count = count;
207
208 for (uint32_t i = 0; i < count; i++) {
209 broadcast_ip_ports[i] = ip_ports[i];
210 }
165} 211}
166 212
167#else //TODO: Other platforms? 213#else // TODO(irungentoo): Other platforms?
168 214
169static void fetch_broadcast_info(uint16_t port) 215static void fetch_broadcast_info(uint16_t port)
170{ 216{
@@ -181,73 +227,71 @@ static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, const uint8
181{ 227{
182 /* fetch only once? on every packet? every X seconds? 228 /* fetch only once? on every packet? every X seconds?
183 * old: every packet, new: once */ 229 * old: every packet, new: once */
184 if (broadcast_count < 0) 230 if (broadcast_count < 0) {
185 fetch_broadcast_info(port); 231 fetch_broadcast_info(port);
232 }
186 233
187 if (!broadcast_count) 234 if (!broadcast_count) {
188 return 0; 235 return 0;
236 }
189 237
190 int i; 238 for (int i = 0; i < broadcast_count; i++) {
191 239 sendpacket(net, broadcast_ip_ports[i], data, length);
192 for (i = 0; i < broadcast_count; i++) 240 }
193 sendpacket(net, broadcast_ip_port[i], data, length);
194 241
195 return 1; 242 return 1;
196} 243}
197 244
198/* Return the broadcast ip. */ 245/* Return the broadcast ip. */
199static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast) 246static IP broadcast_ip(Family family_socket, Family family_broadcast)
200{ 247{
201 IP ip; 248 IP ip;
202 ip_reset(&ip); 249 ip_reset(&ip);
203 250
204 if (family_socket == AF_INET6) { 251 if (net_family_is_ipv6(family_socket)) {
205 if (family_broadcast == AF_INET6) { 252 if (net_family_is_ipv6(family_broadcast)) {
206 ip.family = AF_INET6; 253 ip.family = net_family_ipv6;
207 /* FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */ 254 /* FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */
208 /* FE80::*: MUST be exact, for that we would need to look over all 255 /* FE80::*: MUST be exact, for that we would need to look over all
209 * interfaces and check in which status they are */ 256 * interfaces and check in which status they are */
210 ip.ip6.uint8[ 0] = 0xFF; 257 ip.ip.v6.uint8[ 0] = 0xFF;
211 ip.ip6.uint8[ 1] = 0x02; 258 ip.ip.v6.uint8[ 1] = 0x02;
212 ip.ip6.uint8[15] = 0x01; 259 ip.ip.v6.uint8[15] = 0x01;
213 } else if (family_broadcast == AF_INET) { 260 } else if (net_family_is_ipv4(family_broadcast)) {
214 ip.family = AF_INET6; 261 ip.family = net_family_ipv6;
215 ip.ip6.uint32[0] = 0; 262 ip.ip.v6 = IP6_BROADCAST;
216 ip.ip6.uint32[1] = 0;
217 ip.ip6.uint32[2] = htonl(0xFFFF);
218 ip.ip6.uint32[3] = INADDR_BROADCAST;
219 }
220 } else if (family_socket == AF_INET) {
221 if (family_broadcast == AF_INET) {
222 ip.family = AF_INET;
223 ip.ip4.uint32 = INADDR_BROADCAST;
224 } 263 }
264 } else if (net_family_is_ipv4(family_socket) && net_family_is_ipv4(family_broadcast)) {
265 ip.family = net_family_ipv4;
266 ip.ip.v4 = IP4_BROADCAST;
225 } 267 }
226 268
227 return ip; 269 return ip;
228} 270}
229 271
230/* Is IP a local ip or not. */ 272/* Is IP a local ip or not. */
231_Bool Local_ip(IP ip) 273bool ip_is_local(IP ip)
232{ 274{
233 if (ip.family == AF_INET) { 275 if (net_family_is_ipv4(ip.family)) {
234 IP4 ip4 = ip.ip4; 276 IP4 ip4 = ip.ip.v4;
235 277
236 /* Loopback. */ 278 /* Loopback. */
237 if (ip4.uint8[0] == 127) 279 if (ip4.uint8[0] == 127) {
238 return 1; 280 return 1;
281 }
239 } else { 282 } else {
240 /* embedded IPv4-in-IPv6 */ 283 /* embedded IPv4-in-IPv6 */
241 if (IPV6_IPV4_IN_V6(ip.ip6)) { 284 if (IPV6_IPV4_IN_V6(ip.ip.v6)) {
242 IP ip4; 285 IP ip4;
243 ip4.family = AF_INET; 286 ip4.family = net_family_ipv4;
244 ip4.ip4.uint32 = ip.ip6.uint32[3]; 287 ip4.ip.v4.uint32 = ip.ip.v6.uint32[3];
245 return Local_ip(ip4); 288 return ip_is_local(ip4);
246 } 289 }
247 290
248 /* localhost in IPv6 (::1) */ 291 /* localhost in IPv6 (::1) */
249 if (ip.ip6.uint64[0] == 0 && ip.ip6.uint32[2] == 0 && ip.ip6.uint32[3] == htonl(1)) 292 if (ip.ip.v6.uint64[0] == 0 && ip.ip.v6.uint32[2] == 0 && ip.ip.v6.uint32[3] == net_htonl(1)) {
250 return 1; 293 return 1;
294 }
251 } 295 }
252 296
253 return 0; 297 return 0;
@@ -256,109 +300,124 @@ _Bool Local_ip(IP ip)
256/* return 0 if ip is a LAN ip. 300/* return 0 if ip is a LAN ip.
257 * return -1 if it is not. 301 * return -1 if it is not.
258 */ 302 */
259int LAN_ip(IP ip) 303int ip_is_lan(IP ip)
260{ 304{
261 if (Local_ip(ip)) 305 if (ip_is_local(ip)) {
262 return 0; 306 return 0;
307 }
263 308
264 if (ip.family == AF_INET) { 309 if (net_family_is_ipv4(ip.family)) {
265 IP4 ip4 = ip.ip4; 310 IP4 ip4 = ip.ip.v4;
266 311
267 /* 10.0.0.0 to 10.255.255.255 range. */ 312 /* 10.0.0.0 to 10.255.255.255 range. */
268 if (ip4.uint8[0] == 10) 313 if (ip4.uint8[0] == 10) {
269 return 0; 314 return 0;
315 }
270 316
271 /* 172.16.0.0 to 172.31.255.255 range. */ 317 /* 172.16.0.0 to 172.31.255.255 range. */
272 if (ip4.uint8[0] == 172 && ip4.uint8[1] >= 16 && ip4.uint8[1] <= 31) 318 if (ip4.uint8[0] == 172 && ip4.uint8[1] >= 16 && ip4.uint8[1] <= 31) {
273 return 0; 319 return 0;
320 }
274 321
275 /* 192.168.0.0 to 192.168.255.255 range. */ 322 /* 192.168.0.0 to 192.168.255.255 range. */
276 if (ip4.uint8[0] == 192 && ip4.uint8[1] == 168) 323 if (ip4.uint8[0] == 192 && ip4.uint8[1] == 168) {
277 return 0; 324 return 0;
325 }
278 326
279 /* 169.254.1.0 to 169.254.254.255 range. */ 327 /* 169.254.1.0 to 169.254.254.255 range. */
280 if (ip4.uint8[0] == 169 && ip4.uint8[1] == 254 && ip4.uint8[2] != 0 328 if (ip4.uint8[0] == 169 && ip4.uint8[1] == 254 && ip4.uint8[2] != 0
281 && ip4.uint8[2] != 255) 329 && ip4.uint8[2] != 255) {
282 return 0; 330 return 0;
331 }
283 332
284 /* RFC 6598: 100.64.0.0 to 100.127.255.255 (100.64.0.0/10) 333 /* RFC 6598: 100.64.0.0 to 100.127.255.255 (100.64.0.0/10)
285 * (shared address space to stack another layer of NAT) */ 334 * (shared address space to stack another layer of NAT) */
286 if ((ip4.uint8[0] == 100) && ((ip4.uint8[1] & 0xC0) == 0x40)) 335 if ((ip4.uint8[0] == 100) && ((ip4.uint8[1] & 0xC0) == 0x40)) {
287 return 0; 336 return 0;
288 337 }
289 } else if (ip.family == AF_INET6) { 338 } else if (net_family_is_ipv6(ip.family)) {
290 339
291 /* autogenerated for each interface: FE80::* (up to FEBF::*) 340 /* autogenerated for each interface: FE80::* (up to FEBF::*)
292 FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */ 341 FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */
293 if (((ip.ip6.uint8[0] == 0xFF) && (ip.ip6.uint8[1] < 3) && (ip.ip6.uint8[15] == 1)) || 342 if (((ip.ip.v6.uint8[0] == 0xFF) && (ip.ip.v6.uint8[1] < 3) && (ip.ip.v6.uint8[15] == 1)) ||
294 ((ip.ip6.uint8[0] == 0xFE) && ((ip.ip6.uint8[1] & 0xC0) == 0x80))) 343 ((ip.ip.v6.uint8[0] == 0xFE) && ((ip.ip.v6.uint8[1] & 0xC0) == 0x80))) {
295 return 0; 344 return 0;
345 }
296 346
297 /* embedded IPv4-in-IPv6 */ 347 /* embedded IPv4-in-IPv6 */
298 if (IPV6_IPV4_IN_V6(ip.ip6)) { 348 if (IPV6_IPV4_IN_V6(ip.ip.v6)) {
299 IP ip4; 349 IP ip4;
300 ip4.family = AF_INET; 350 ip4.family = net_family_ipv4;
301 ip4.ip4.uint32 = ip.ip6.uint32[3]; 351 ip4.ip.v4.uint32 = ip.ip.v6.uint32[3];
302 return LAN_ip(ip4); 352 return ip_is_lan(ip4);
303 } 353 }
304 } 354 }
305 355
306 return -1; 356 return -1;
307} 357}
308 358
309static int handle_LANdiscovery(void *object, IP_Port source, const uint8_t *packet, uint16_t length) 359static int handle_LANdiscovery(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
310{ 360{
311 DHT *dht = object; 361 DHT *dht = (DHT *)object;
312 362
313 if (LAN_ip(source.ip) == -1) 363 char ip_str[IP_NTOA_LEN] = { 0 };
364 ip_ntoa(&source.ip, ip_str, sizeof(ip_str));
365
366 if (ip_is_lan(source.ip) == -1) {
314 return 1; 367 return 1;
368 }
315 369
316 if (length != crypto_box_PUBLICKEYBYTES + 1) 370 if (length != CRYPTO_PUBLIC_KEY_SIZE + 1) {
317 return 1; 371 return 1;
372 }
318 373
319 DHT_bootstrap(dht, source, packet + 1); 374 DHT_bootstrap(dht, source, packet + 1);
320 return 0; 375 return 0;
321} 376}
322 377
323 378
324int send_LANdiscovery(uint16_t port, DHT *dht) 379int lan_discovery_send(uint16_t port, DHT *dht)
325{ 380{
326 uint8_t data[crypto_box_PUBLICKEYBYTES + 1]; 381 uint8_t data[CRYPTO_PUBLIC_KEY_SIZE + 1];
327 data[0] = NET_PACKET_LAN_DISCOVERY; 382 data[0] = NET_PACKET_LAN_DISCOVERY;
328 id_copy(data + 1, dht->self_public_key); 383 id_copy(data + 1, dht_get_self_public_key(dht));
329 384
330 send_broadcasts(dht->net, port, data, 1 + crypto_box_PUBLICKEYBYTES); 385 send_broadcasts(dht_get_net(dht), port, data, 1 + CRYPTO_PUBLIC_KEY_SIZE);
331 386
332 int res = -1; 387 int res = -1;
333 IP_Port ip_port; 388 IP_Port ip_port;
334 ip_port.port = port; 389 ip_port.port = port;
335 390
336 /* IPv6 multicast */ 391 /* IPv6 multicast */
337 if (dht->net->family == AF_INET6) { 392 if (net_family_is_ipv6(net_family(dht_get_net(dht)))) {
338 ip_port.ip = broadcast_ip(AF_INET6, AF_INET6); 393 ip_port.ip = broadcast_ip(net_family_ipv6, net_family_ipv6);
339 394
340 if (ip_isset(&ip_port.ip)) 395 if (ip_isset(&ip_port.ip)) {
341 if (sendpacket(dht->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES) > 0) 396 if (sendpacket(dht_get_net(dht), ip_port, data, 1 + CRYPTO_PUBLIC_KEY_SIZE) > 0) {
342 res = 1; 397 res = 1;
398 }
399 }
343 } 400 }
344 401
345 /* IPv4 broadcast (has to be IPv4-in-IPv6 mapping if socket is AF_INET6 */ 402 /* IPv4 broadcast (has to be IPv4-in-IPv6 mapping if socket is IPv6 */
346 ip_port.ip = broadcast_ip(dht->net->family, AF_INET); 403 ip_port.ip = broadcast_ip(net_family(dht_get_net(dht)), net_family_ipv4);
347 404
348 if (ip_isset(&ip_port.ip)) 405 if (ip_isset(&ip_port.ip)) {
349 if (sendpacket(dht->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES)) 406 if (sendpacket(dht_get_net(dht), ip_port, data, 1 + CRYPTO_PUBLIC_KEY_SIZE)) {
350 res = 1; 407 res = 1;
408 }
409 }
351 410
352 return res; 411 return res;
353} 412}
354 413
355 414
356void LANdiscovery_init(DHT *dht) 415void lan_discovery_init(DHT *dht)
357{ 416{
358 networking_registerhandler(dht->net, NET_PACKET_LAN_DISCOVERY, &handle_LANdiscovery, dht); 417 networking_registerhandler(dht_get_net(dht), NET_PACKET_LAN_DISCOVERY, &handle_LANdiscovery, dht);
359} 418}
360 419
361void LANdiscovery_kill(DHT *dht) 420void lan_discovery_kill(DHT *dht)
362{ 421{
363 networking_registerhandler(dht->net, NET_PACKET_LAN_DISCOVERY, NULL, NULL); 422 networking_registerhandler(dht_get_net(dht), NET_PACKET_LAN_DISCOVERY, nullptr, nullptr);
364} 423}
diff --git a/toxcore/LAN_discovery.h b/toxcore/LAN_discovery.h
index 358bea2f..6d9d17b6 100644
--- a/toxcore/LAN_discovery.h
+++ b/toxcore/LAN_discovery.h
@@ -1,54 +1,74 @@
1/* LAN_discovery.h 1/*
2 * 2 * LAN discovery implementation.
3 * LAN discovery implementation. 3 */
4 * 4
5 * Copyright (C) 2013 Tox project All Rights Reserved. 5/*
6 * 6 * Copyright © 2016-2017 The TokTok team.
7 * This file is part of Tox. 7 * Copyright © 2013 Tox project.
8 * 8 *
9 * Tox is free software: you can redistribute it and/or modify 9 * This file is part of Tox, the free peer to peer instant messenger.
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23
24
25#ifndef LAN_DISCOVERY_H 24#ifndef LAN_DISCOVERY_H
26#define LAN_DISCOVERY_H 25#define LAN_DISCOVERY_H
27 26
28
29#include "DHT.h" 27#include "DHT.h"
30 28
31/* Interval in seconds between LAN discovery packet sending. */ 29#ifndef DHT_DEFINED
32#define LAN_DISCOVERY_INTERVAL 10 30#define DHT_DEFINED
31typedef struct DHT DHT;
32#endif /* DHT_DEFINED */
33 33
34/* Send a LAN discovery pcaket to the broadcast address with port port. */ 34#ifndef IP_DEFINED
35int send_LANdiscovery(uint16_t port, DHT *dht); 35#define IP_DEFINED
36typedef struct IP IP;
37#endif /* IP_DEFINED */
36 38
37/* Sets up packet handlers. */ 39/**
38void LANdiscovery_init(DHT *dht); 40 * Interval in seconds between LAN discovery packet sending.
41 */
42#define LAN_DISCOVERY_INTERVAL 10
39 43
40/* Clear packet handlers. */ 44uint32_t lan_discovery_interval(void);
41void LANdiscovery_kill(DHT *dht);
42 45
43/* Is IP a local ip or not. */ 46/**
44_Bool Local_ip(IP ip); 47 * Send a LAN discovery pcaket to the broadcast address with port port.
48 */
49int32_t lan_discovery_send(uint16_t port, DHT *dht);
50
51/**
52 * Sets up packet handlers.
53 */
54void lan_discovery_init(DHT *dht);
55
56/**
57 * Clear packet handlers.
58 */
59void lan_discovery_kill(DHT *dht);
60
61/**
62 * Is IP a local ip or not.
63 */
64bool ip_is_local(IP ip);
45 65
46/* checks if a given IP isn't routable 66/**
67 * checks if a given IP isn't routable
47 * 68 *
48 * return 0 if ip is a LAN ip. 69 * return 0 if ip is a LAN ip.
49 * return -1 if it is not. 70 * return -1 if it is not.
50 */ 71 */
51int LAN_ip(IP ip); 72int32_t ip_is_lan(IP ip);
52
53 73
54#endif 74#endif
diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc
index d6b67eb2..2ca25650 100644
--- a/toxcore/Makefile.inc
+++ b/toxcore/Makefile.inc
@@ -1,17 +1,18 @@
1lib_LTLIBRARIES += libtoxcore.la 1lib_LTLIBRARIES += libtoxcore.la
2 2
3libtoxcore_la_include_HEADERS = \ 3libtoxcore_la_include_HEADERS = \
4 ../toxcore/tox.h \ 4 ../toxcore/tox.h
5 ../toxcore/tox_old.h
6 5
7libtoxcore_la_includedir = $(includedir)/tox 6libtoxcore_la_includedir = $(includedir)/tox
8 7
9libtoxcore_la_SOURCES = ../toxcore/DHT.h \ 8libtoxcore_la_SOURCES = ../toxcore/ccompat.h \
9 ../toxcore/DHT.h \
10 ../toxcore/DHT.c \ 10 ../toxcore/DHT.c \
11 ../toxcore/network.h \ 11 ../toxcore/network.h \
12 ../toxcore/network.c \ 12 ../toxcore/network.c \
13 ../toxcore/crypto_core.h \ 13 ../toxcore/crypto_core.h \
14 ../toxcore/crypto_core.c \ 14 ../toxcore/crypto_core.c \
15 ../toxcore/crypto_core_mem.c \
15 ../toxcore/ping_array.h \ 16 ../toxcore/ping_array.h \
16 ../toxcore/ping_array.c \ 17 ../toxcore/ping_array.c \
17 ../toxcore/net_crypto.h \ 18 ../toxcore/net_crypto.h \
@@ -28,12 +29,11 @@ libtoxcore_la_SOURCES = ../toxcore/DHT.h \
28 ../toxcore/ping.c \ 29 ../toxcore/ping.c \
29 ../toxcore/tox.h \ 30 ../toxcore/tox.h \
30 ../toxcore/tox.c \ 31 ../toxcore/tox.c \
32 ../toxcore/tox_api.c \
31 ../toxcore/util.h \ 33 ../toxcore/util.h \
32 ../toxcore/util.c \ 34 ../toxcore/util.c \
33 ../toxcore/group.h \ 35 ../toxcore/group.h \
34 ../toxcore/group.c \ 36 ../toxcore/group.c \
35 ../toxcore/assoc.h \
36 ../toxcore/assoc.c \
37 ../toxcore/onion.h \ 37 ../toxcore/onion.h \
38 ../toxcore/onion.c \ 38 ../toxcore/onion.c \
39 ../toxcore/logger.h \ 39 ../toxcore/logger.h \
@@ -49,9 +49,7 @@ libtoxcore_la_SOURCES = ../toxcore/DHT.h \
49 ../toxcore/TCP_connection.h \ 49 ../toxcore/TCP_connection.h \
50 ../toxcore/TCP_connection.c \ 50 ../toxcore/TCP_connection.c \
51 ../toxcore/list.c \ 51 ../toxcore/list.c \
52 ../toxcore/list.h \ 52 ../toxcore/list.h
53 ../toxcore/misc_tools.h \
54 ../toxcore/tox_old_code.h
55 53
56libtoxcore_la_CFLAGS = -I$(top_srcdir) \ 54libtoxcore_la_CFLAGS = -I$(top_srcdir) \
57 -I$(top_srcdir)/toxcore \ 55 -I$(top_srcdir)/toxcore \
@@ -59,7 +57,7 @@ libtoxcore_la_CFLAGS = -I$(top_srcdir) \
59 $(NACL_CFLAGS) \ 57 $(NACL_CFLAGS) \
60 $(PTHREAD_CFLAGS) 58 $(PTHREAD_CFLAGS)
61 59
62libtoxcore_la_LDFLAGS = $(TOXCORE_LT_LDFLAGS) \ 60libtoxcore_la_LDFLAGS = $(LT_LDFLAGS) \
63 $(EXTRA_LT_LDFLAGS) \ 61 $(EXTRA_LT_LDFLAGS) \
64 $(LIBSODIUM_LDFLAGS) \ 62 $(LIBSODIUM_LDFLAGS) \
65 $(NACL_LDFLAGS) \ 63 $(NACL_LDFLAGS) \
@@ -71,3 +69,9 @@ libtoxcore_la_LIBADD = $(LIBSODIUM_LIBS) \
71 $(NACL_OBJECTS) \ 69 $(NACL_OBJECTS) \
72 $(NAC_LIBS) \ 70 $(NAC_LIBS) \
73 $(PTHREAD_LIBS) 71 $(PTHREAD_LIBS)
72
73if SET_SO_VERSION
74
75EXTRA_libtoxcore_la_DEPENDENCIES = ../so.version
76
77endif
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index 34296c24..11109815 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -1,42 +1,42 @@
1/* Messenger.c 1/*
2 *
3 * An implementation of a simple text chat only messenger on the tox network core. 2 * An implementation of a simple text chat only messenger on the tox network core.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2013 Tox project.
4 * 8 *
5 * Copyright (C) 2013 Tox project All Rights Reserved. 9 * This file is part of Tox, the free peer to peer instant messenger.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23
24#ifdef HAVE_CONFIG_H 24#ifdef HAVE_CONFIG_H
25#include "config.h" 25#include "config.h"
26#endif 26#endif
27 27
28#ifdef DEBUG 28#include "Messenger.h"
29
29#include <assert.h> 30#include <assert.h>
30#endif 31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <time.h>
31 35
32#include "logger.h" 36#include "logger.h"
33#include "Messenger.h"
34#include "assoc.h"
35#include "network.h" 37#include "network.h"
36#include "util.h" 38#include "util.h"
37 39
38
39static void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status);
40static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data, 40static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data,
41 uint32_t length, uint8_t congestion_control); 41 uint32_t length, uint8_t congestion_control);
42 42
@@ -56,18 +56,19 @@ static uint8_t friend_not_valid(const Messenger *m, int32_t friendnumber)
56 * 56 *
57 * return -1 if realloc fails. 57 * return -1 if realloc fails.
58 */ 58 */
59int realloc_friendlist(Messenger *m, uint32_t num) 59static int realloc_friendlist(Messenger *m, uint32_t num)
60{ 60{
61 if (num == 0) { 61 if (num == 0) {
62 free(m->friendlist); 62 free(m->friendlist);
63 m->friendlist = NULL; 63 m->friendlist = nullptr;
64 return 0; 64 return 0;
65 } 65 }
66 66
67 Friend *newfriendlist = realloc(m->friendlist, num * sizeof(Friend)); 67 Friend *newfriendlist = (Friend *)realloc(m->friendlist, num * sizeof(Friend));
68 68
69 if (newfriendlist == NULL) 69 if (newfriendlist == nullptr) {
70 return -1; 70 return -1;
71 }
71 72
72 m->friendlist = newfriendlist; 73 m->friendlist = newfriendlist;
73 return 0; 74 return 0;
@@ -81,26 +82,29 @@ int32_t getfriend_id(const Messenger *m, const uint8_t *real_pk)
81 uint32_t i; 82 uint32_t i;
82 83
83 for (i = 0; i < m->numfriends; ++i) { 84 for (i = 0; i < m->numfriends; ++i) {
84 if (m->friendlist[i].status > 0) 85 if (m->friendlist[i].status > 0) {
85 if (id_equal(real_pk, m->friendlist[i].real_pk)) 86 if (id_equal(real_pk, m->friendlist[i].real_pk)) {
86 return i; 87 return i;
88 }
89 }
87 } 90 }
88 91
89 return -1; 92 return -1;
90} 93}
91 94
92/* Copies the public key associated to that friend id into real_pk buffer. 95/* Copies the public key associated to that friend id into real_pk buffer.
93 * Make sure that real_pk is of size crypto_box_PUBLICKEYBYTES. 96 * Make sure that real_pk is of size CRYPTO_PUBLIC_KEY_SIZE.
94 * 97 *
95 * return 0 if success. 98 * return 0 if success.
96 * return -1 if failure. 99 * return -1 if failure.
97 */ 100 */
98int get_real_pk(const Messenger *m, int32_t friendnumber, uint8_t *real_pk) 101int get_real_pk(const Messenger *m, int32_t friendnumber, uint8_t *real_pk)
99{ 102{
100 if (friend_not_valid(m, friendnumber)) 103 if (friend_not_valid(m, friendnumber)) {
101 return -1; 104 return -1;
105 }
102 106
103 memcpy(real_pk, m->friendlist[friendnumber].real_pk, crypto_box_PUBLICKEYBYTES); 107 memcpy(real_pk, m->friendlist[friendnumber].real_pk, CRYPTO_PUBLIC_KEY_SIZE);
104 return 0; 108 return 0;
105} 109}
106 110
@@ -109,8 +113,9 @@ int get_real_pk(const Messenger *m, int32_t friendnumber, uint8_t *real_pk)
109 */ 113 */
110int getfriendcon_id(const Messenger *m, int32_t friendnumber) 114int getfriendcon_id(const Messenger *m, int32_t friendnumber)
111{ 115{
112 if (friend_not_valid(m, friendnumber)) 116 if (friend_not_valid(m, friendnumber)) {
113 return -1; 117 return -1;
118 }
114 119
115 return m->friendlist[friendnumber].friendcon_id; 120 return m->friendlist[friendnumber].friendcon_id;
116} 121}
@@ -124,8 +129,9 @@ static uint16_t address_checksum(const uint8_t *address, uint32_t len)
124 uint16_t check; 129 uint16_t check;
125 uint32_t i; 130 uint32_t i;
126 131
127 for (i = 0; i < len; ++i) 132 for (i = 0; i < len; ++i) {
128 checksum[i % 2] ^= address[i]; 133 checksum[i % 2] ^= address[i];
134 }
129 135
130 memcpy(&check, checksum, sizeof(check)); 136 memcpy(&check, checksum, sizeof(check));
131 return check; 137 return check;
@@ -137,17 +143,18 @@ static uint16_t address_checksum(const uint8_t *address, uint32_t len)
137 */ 143 */
138void getaddress(const Messenger *m, uint8_t *address) 144void getaddress(const Messenger *m, uint8_t *address)
139{ 145{
140 id_copy(address, m->net_crypto->self_public_key); 146 id_copy(address, nc_get_self_public_key(m->net_crypto));
141 uint32_t nospam = get_nospam(&(m->fr)); 147 uint32_t nospam = get_nospam(m->fr);
142 memcpy(address + crypto_box_PUBLICKEYBYTES, &nospam, sizeof(nospam)); 148 memcpy(address + CRYPTO_PUBLIC_KEY_SIZE, &nospam, sizeof(nospam));
143 uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); 149 uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum));
144 memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(nospam), &checksum, sizeof(checksum)); 150 memcpy(address + CRYPTO_PUBLIC_KEY_SIZE + sizeof(nospam), &checksum, sizeof(checksum));
145} 151}
146 152
147static int send_online_packet(Messenger *m, int32_t friendnumber) 153static int send_online_packet(Messenger *m, int32_t friendnumber)
148{ 154{
149 if (friend_not_valid(m, friendnumber)) 155 if (friend_not_valid(m, friendnumber)) {
150 return 0; 156 return 0;
157 }
151 158
152 uint8_t packet = PACKET_ID_ONLINE; 159 uint8_t packet = PACKET_ID_ONLINE;
153 return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, 160 return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
@@ -161,22 +168,25 @@ static int send_offline_packet(Messenger *m, int friendcon_id)
161 sizeof(packet), 0) != -1; 168 sizeof(packet), 0) != -1;
162} 169}
163 170
164static int handle_status(void *object, int i, uint8_t status); 171static int m_handle_status(void *object, int i, uint8_t status, void *userdata);
165static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len); 172static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t len, void *userdata);
166static int handle_custom_lossy_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length); 173static int m_handle_custom_lossy_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length,
174 void *userdata);
167 175
168static int32_t init_new_friend(Messenger *m, const uint8_t *real_pk, uint8_t status) 176static int32_t init_new_friend(Messenger *m, const uint8_t *real_pk, uint8_t status)
169{ 177{
170 /* Resize the friend list if necessary. */ 178 /* Resize the friend list if necessary. */
171 if (realloc_friendlist(m, m->numfriends + 1) != 0) 179 if (realloc_friendlist(m, m->numfriends + 1) != 0) {
172 return FAERR_NOMEM; 180 return FAERR_NOMEM;
181 }
173 182
174 memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend)); 183 memset(&m->friendlist[m->numfriends], 0, sizeof(Friend));
175 184
176 int friendcon_id = new_friend_connection(m->fr_c, real_pk); 185 int friendcon_id = new_friend_connection(m->fr_c, real_pk);
177 186
178 if (friendcon_id == -1) 187 if (friendcon_id == -1) {
179 return FAERR_NOMEM; 188 return FAERR_NOMEM;
189 }
180 190
181 uint32_t i; 191 uint32_t i;
182 192
@@ -190,11 +200,12 @@ static int32_t init_new_friend(Messenger *m, const uint8_t *real_pk, uint8_t sta
190 m->friendlist[i].userstatus = USERSTATUS_NONE; 200 m->friendlist[i].userstatus = USERSTATUS_NONE;
191 m->friendlist[i].is_typing = 0; 201 m->friendlist[i].is_typing = 0;
192 m->friendlist[i].message_id = 0; 202 m->friendlist[i].message_id = 0;
193 friend_connection_callbacks(m->fr_c, friendcon_id, MESSENGER_CALLBACK_INDEX, &handle_status, &handle_packet, 203 friend_connection_callbacks(m->fr_c, friendcon_id, MESSENGER_CALLBACK_INDEX, &m_handle_status, &m_handle_packet,
194 &handle_custom_lossy_packet, m, i); 204 &m_handle_custom_lossy_packet, m, i);
195 205
196 if (m->numfriends == i) 206 if (m->numfriends == i) {
197 ++m->numfriends; 207 ++m->numfriends;
208 }
198 209
199 if (friend_con_connected(m->fr_c, friendcon_id) == FRIENDCONN_STATUS_CONNECTED) { 210 if (friend_con_connected(m->fr_c, friendcon_id) == FRIENDCONN_STATUS_CONNECTED) {
200 send_online_packet(m, i); 211 send_online_packet(m, i);
@@ -225,38 +236,45 @@ static int32_t init_new_friend(Messenger *m, const uint8_t *real_pk, uint8_t sta
225 */ 236 */
226int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, uint16_t length) 237int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, uint16_t length)
227{ 238{
228 if (length > MAX_FRIEND_REQUEST_DATA_SIZE) 239 if (length > MAX_FRIEND_REQUEST_DATA_SIZE) {
229 return FAERR_TOOLONG; 240 return FAERR_TOOLONG;
241 }
230 242
231 uint8_t real_pk[crypto_box_PUBLICKEYBYTES]; 243 uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
232 id_copy(real_pk, address); 244 id_copy(real_pk, address);
233 245
234 if (!public_key_valid(real_pk)) 246 if (!public_key_valid(real_pk)) {
235 return FAERR_BADCHECKSUM; 247 return FAERR_BADCHECKSUM;
248 }
236 249
237 uint16_t check, checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); 250 uint16_t check, checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum));
238 memcpy(&check, address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), sizeof(check)); 251 memcpy(&check, address + CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint32_t), sizeof(check));
239 252
240 if (check != checksum) 253 if (check != checksum) {
241 return FAERR_BADCHECKSUM; 254 return FAERR_BADCHECKSUM;
255 }
242 256
243 if (length < 1) 257 if (length < 1) {
244 return FAERR_NOMESSAGE; 258 return FAERR_NOMESSAGE;
259 }
245 260
246 if (id_equal(real_pk, m->net_crypto->self_public_key)) 261 if (id_equal(real_pk, nc_get_self_public_key(m->net_crypto))) {
247 return FAERR_OWNKEY; 262 return FAERR_OWNKEY;
263 }
248 264
249 int32_t friend_id = getfriend_id(m, real_pk); 265 int32_t friend_id = getfriend_id(m, real_pk);
250 266
251 if (friend_id != -1) { 267 if (friend_id != -1) {
252 if (m->friendlist[friend_id].status >= FRIEND_CONFIRMED) 268 if (m->friendlist[friend_id].status >= FRIEND_CONFIRMED) {
253 return FAERR_ALREADYSENT; 269 return FAERR_ALREADYSENT;
270 }
254 271
255 uint32_t nospam; 272 uint32_t nospam;
256 memcpy(&nospam, address + crypto_box_PUBLICKEYBYTES, sizeof(nospam)); 273 memcpy(&nospam, address + CRYPTO_PUBLIC_KEY_SIZE, sizeof(nospam));
257 274
258 if (m->friendlist[friend_id].friendrequest_nospam == nospam) 275 if (m->friendlist[friend_id].friendrequest_nospam == nospam) {
259 return FAERR_ALREADYSENT; 276 return FAERR_ALREADYSENT;
277 }
260 278
261 m->friendlist[friend_id].friendrequest_nospam = nospam; 279 m->friendlist[friend_id].friendrequest_nospam = nospam;
262 return FAERR_SETNEWNOSPAM; 280 return FAERR_SETNEWNOSPAM;
@@ -271,29 +289,33 @@ int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, u
271 m->friendlist[ret].friendrequest_timeout = FRIENDREQUEST_TIMEOUT; 289 m->friendlist[ret].friendrequest_timeout = FRIENDREQUEST_TIMEOUT;
272 memcpy(m->friendlist[ret].info, data, length); 290 memcpy(m->friendlist[ret].info, data, length);
273 m->friendlist[ret].info_size = length; 291 m->friendlist[ret].info_size = length;
274 memcpy(&(m->friendlist[ret].friendrequest_nospam), address + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t)); 292 memcpy(&m->friendlist[ret].friendrequest_nospam, address + CRYPTO_PUBLIC_KEY_SIZE, sizeof(uint32_t));
275 293
276 return ret; 294 return ret;
277} 295}
278 296
279int32_t m_addfriend_norequest(Messenger *m, const uint8_t *real_pk) 297int32_t m_addfriend_norequest(Messenger *m, const uint8_t *real_pk)
280{ 298{
281 if (getfriend_id(m, real_pk) != -1) 299 if (getfriend_id(m, real_pk) != -1) {
282 return FAERR_ALREADYSENT; 300 return FAERR_ALREADYSENT;
301 }
283 302
284 if (!public_key_valid(real_pk)) 303 if (!public_key_valid(real_pk)) {
285 return FAERR_BADCHECKSUM; 304 return FAERR_BADCHECKSUM;
305 }
286 306
287 if (id_equal(real_pk, m->net_crypto->self_public_key)) 307 if (id_equal(real_pk, nc_get_self_public_key(m->net_crypto))) {
288 return FAERR_OWNKEY; 308 return FAERR_OWNKEY;
309 }
289 310
290 return init_new_friend(m, real_pk, FRIEND_CONFIRMED); 311 return init_new_friend(m, real_pk, FRIEND_CONFIRMED);
291} 312}
292 313
293static int clear_receipts(Messenger *m, int32_t friendnumber) 314static int clear_receipts(Messenger *m, int32_t friendnumber)
294{ 315{
295 if (friend_not_valid(m, friendnumber)) 316 if (friend_not_valid(m, friendnumber)) {
296 return -1; 317 return -1;
318 }
297 319
298 struct Receipts *receipts = m->friendlist[friendnumber].receipts_start; 320 struct Receipts *receipts = m->friendlist[friendnumber].receipts_start;
299 321
@@ -303,32 +325,34 @@ static int clear_receipts(Messenger *m, int32_t friendnumber)
303 receipts = temp_r; 325 receipts = temp_r;
304 } 326 }
305 327
306 m->friendlist[friendnumber].receipts_start = NULL; 328 m->friendlist[friendnumber].receipts_start = nullptr;
307 m->friendlist[friendnumber].receipts_end = NULL; 329 m->friendlist[friendnumber].receipts_end = nullptr;
308 return 0; 330 return 0;
309} 331}
310 332
311static int add_receipt(Messenger *m, int32_t friendnumber, uint32_t packet_num, uint32_t msg_id) 333static int add_receipt(Messenger *m, int32_t friendnumber, uint32_t packet_num, uint32_t msg_id)
312{ 334{
313 if (friend_not_valid(m, friendnumber)) 335 if (friend_not_valid(m, friendnumber)) {
314 return -1; 336 return -1;
337 }
315 338
316 struct Receipts *new = calloc(1, sizeof(struct Receipts)); 339 struct Receipts *new_receipts = (struct Receipts *)calloc(1, sizeof(struct Receipts));
317 340
318 if (!new) 341 if (!new_receipts) {
319 return -1; 342 return -1;
343 }
320 344
321 new->packet_num = packet_num; 345 new_receipts->packet_num = packet_num;
322 new->msg_id = msg_id; 346 new_receipts->msg_id = msg_id;
323 347
324 if (!m->friendlist[friendnumber].receipts_start) { 348 if (!m->friendlist[friendnumber].receipts_start) {
325 m->friendlist[friendnumber].receipts_start = new; 349 m->friendlist[friendnumber].receipts_start = new_receipts;
326 } else { 350 } else {
327 m->friendlist[friendnumber].receipts_end->next = new; 351 m->friendlist[friendnumber].receipts_end->next = new_receipts;
328 } 352 }
329 353
330 m->friendlist[friendnumber].receipts_end = new; 354 m->friendlist[friendnumber].receipts_end = new_receipts;
331 new->next = NULL; 355 new_receipts->next = nullptr;
332 return 0; 356 return 0;
333} 357}
334/* 358/*
@@ -337,36 +361,43 @@ static int add_receipt(Messenger *m, int32_t friendnumber, uint32_t packet_num,
337 */ 361 */
338static int friend_received_packet(const Messenger *m, int32_t friendnumber, uint32_t number) 362static int friend_received_packet(const Messenger *m, int32_t friendnumber, uint32_t number)
339{ 363{
340 if (friend_not_valid(m, friendnumber)) 364 if (friend_not_valid(m, friendnumber)) {
341 return -1; 365 return -1;
366 }
342 367
343 return cryptpacket_received(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, 368 return cryptpacket_received(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
344 m->friendlist[friendnumber].friendcon_id), number); 369 m->friendlist[friendnumber].friendcon_id), number);
345} 370}
346 371
347static int do_receipts(Messenger *m, int32_t friendnumber) 372static int do_receipts(Messenger *m, int32_t friendnumber, void *userdata)
348{ 373{
349 if (friend_not_valid(m, friendnumber)) 374 if (friend_not_valid(m, friendnumber)) {
350 return -1; 375 return -1;
376 }
351 377
352 struct Receipts *receipts = m->friendlist[friendnumber].receipts_start; 378 struct Receipts *receipts = m->friendlist[friendnumber].receipts_start;
353 379
354 while (receipts) { 380 while (receipts) {
355 struct Receipts *temp_r = receipts->next; 381 if (friend_received_packet(m, friendnumber, receipts->packet_num) == -1) {
356
357 if (friend_received_packet(m, friendnumber, receipts->packet_num) == -1)
358 break; 382 break;
383 }
384
385 if (m->read_receipt) {
386 (*m->read_receipt)(m, friendnumber, receipts->msg_id, userdata);
387 }
359 388
360 if (m->read_receipt) 389 struct Receipts *r_next = receipts->next;
361 (*m->read_receipt)(m, friendnumber, receipts->msg_id, m->read_receipt_userdata);
362 390
363 free(receipts); 391 free(receipts);
364 m->friendlist[friendnumber].receipts_start = temp_r; 392
365 receipts = temp_r; 393 m->friendlist[friendnumber].receipts_start = r_next;
394
395 receipts = r_next;
366 } 396 }
367 397
368 if (!m->friendlist[friendnumber].receipts_start) 398 if (!m->friendlist[friendnumber].receipts_start) {
369 m->friendlist[friendnumber].receipts_end = NULL; 399 m->friendlist[friendnumber].receipts_end = nullptr;
400 }
370 401
371 return 0; 402 return 0;
372} 403}
@@ -378,66 +409,73 @@ static int do_receipts(Messenger *m, int32_t friendnumber)
378 */ 409 */
379int m_delfriend(Messenger *m, int32_t friendnumber) 410int m_delfriend(Messenger *m, int32_t friendnumber)
380{ 411{
381 if (friend_not_valid(m, friendnumber)) 412 if (friend_not_valid(m, friendnumber)) {
382 return -1; 413 return -1;
414 }
383 415
384 if (m->friend_connectionstatuschange_internal) 416 if (m->friend_connectionstatuschange_internal) {
385 m->friend_connectionstatuschange_internal(m, friendnumber, 0, m->friend_connectionstatuschange_internal_userdata); 417 m->friend_connectionstatuschange_internal(m, friendnumber, 0, m->friend_connectionstatuschange_internal_userdata);
418 }
386 419
387 clear_receipts(m, friendnumber); 420 clear_receipts(m, friendnumber);
388 remove_request_received(&(m->fr), m->friendlist[friendnumber].real_pk); 421 remove_request_received(m->fr, m->friendlist[friendnumber].real_pk);
389 friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, 0, 0, 0, 0, 0); 422 friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, nullptr,
423 nullptr, nullptr, nullptr, 0);
390 424
391 if (friend_con_connected(m->fr_c, m->friendlist[friendnumber].friendcon_id) == FRIENDCONN_STATUS_CONNECTED) { 425 if (friend_con_connected(m->fr_c, m->friendlist[friendnumber].friendcon_id) == FRIENDCONN_STATUS_CONNECTED) {
392 send_offline_packet(m, m->friendlist[friendnumber].friendcon_id); 426 send_offline_packet(m, m->friendlist[friendnumber].friendcon_id);
393 } 427 }
394 428
395 kill_friend_connection(m->fr_c, m->friendlist[friendnumber].friendcon_id); 429 kill_friend_connection(m->fr_c, m->friendlist[friendnumber].friendcon_id);
396 memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend)); 430 memset(&m->friendlist[friendnumber], 0, sizeof(Friend));
397 uint32_t i; 431 uint32_t i;
398 432
399 for (i = m->numfriends; i != 0; --i) { 433 for (i = m->numfriends; i != 0; --i) {
400 if (m->friendlist[i - 1].status != NOFRIEND) 434 if (m->friendlist[i - 1].status != NOFRIEND) {
401 break; 435 break;
436 }
402 } 437 }
403 438
404 m->numfriends = i; 439 m->numfriends = i;
405 440
406 if (realloc_friendlist(m, m->numfriends) != 0) 441 if (realloc_friendlist(m, m->numfriends) != 0) {
407 return FAERR_NOMEM; 442 return FAERR_NOMEM;
443 }
408 444
409 return 0; 445 return 0;
410} 446}
411 447
412int m_get_friend_connectionstatus(const Messenger *m, int32_t friendnumber) 448int m_get_friend_connectionstatus(const Messenger *m, int32_t friendnumber)
413{ 449{
414 if (friend_not_valid(m, friendnumber)) 450 if (friend_not_valid(m, friendnumber)) {
415 return -1; 451 return -1;
452 }
416 453
417 if (m->friendlist[friendnumber].status == FRIEND_ONLINE) { 454 if (m->friendlist[friendnumber].status == FRIEND_ONLINE) {
418 _Bool direct_connected = 0; 455 bool direct_connected = 0;
419 unsigned int num_online_relays = 0; 456 unsigned int num_online_relays = 0;
420 crypto_connection_status(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, 457 int crypt_conn_id = friend_connection_crypt_connection_id(m->fr_c, m->friendlist[friendnumber].friendcon_id);
421 m->friendlist[friendnumber].friendcon_id), &direct_connected, &num_online_relays); 458 crypto_connection_status(m->net_crypto, crypt_conn_id, &direct_connected, &num_online_relays);
422 459
423 if (direct_connected) { 460 if (direct_connected) {
424 return CONNECTION_UDP; 461 return CONNECTION_UDP;
425 } else {
426 if (num_online_relays) {
427 return CONNECTION_TCP;
428 } else {
429 return CONNECTION_UNKNOWN;
430 }
431 } 462 }
432 } else { 463
433 return CONNECTION_NONE; 464 if (num_online_relays) {
465 return CONNECTION_TCP;
466 }
467
468 return CONNECTION_UNKNOWN;
434 } 469 }
470
471 return CONNECTION_NONE;
435} 472}
436 473
437int m_friend_exists(const Messenger *m, int32_t friendnumber) 474int m_friend_exists(const Messenger *m, int32_t friendnumber)
438{ 475{
439 if (friend_not_valid(m, friendnumber)) 476 if (friend_not_valid(m, friendnumber)) {
440 return 0; 477 return 0;
478 }
441 479
442 return 1; 480 return 1;
443} 481}
@@ -454,36 +492,43 @@ int m_friend_exists(const Messenger *m, int32_t friendnumber)
454int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, const uint8_t *message, uint32_t length, 492int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, const uint8_t *message, uint32_t length,
455 uint32_t *message_id) 493 uint32_t *message_id)
456{ 494{
457 if (type > MESSAGE_ACTION) 495 if (type > MESSAGE_ACTION) {
458 return -5; 496 return -5;
497 }
459 498
460 if (friend_not_valid(m, friendnumber)) 499 if (friend_not_valid(m, friendnumber)) {
461 return -1; 500 return -1;
501 }
462 502
463 if (length >= MAX_CRYPTO_DATA_SIZE) 503 if (length >= MAX_CRYPTO_DATA_SIZE) {
464 return -2; 504 return -2;
505 }
465 506
466 if (m->friendlist[friendnumber].status != FRIEND_ONLINE) 507 if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
467 return -3; 508 return -3;
509 }
468 510
469 uint8_t packet[length + 1]; 511 VLA(uint8_t, packet, length + 1);
470 packet[0] = type + PACKET_ID_MESSAGE; 512 packet[0] = type + PACKET_ID_MESSAGE;
471 513
472 if (length != 0) 514 if (length != 0) {
473 memcpy(packet + 1, message, length); 515 memcpy(packet + 1, message, length);
516 }
474 517
475 int64_t packet_num = write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, 518 int64_t packet_num = write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
476 m->friendlist[friendnumber].friendcon_id), packet, length + 1, 0); 519 m->friendlist[friendnumber].friendcon_id), packet, length + 1, 0);
477 520
478 if (packet_num == -1) 521 if (packet_num == -1) {
479 return -4; 522 return -4;
523 }
480 524
481 uint32_t msg_id = ++m->friendlist[friendnumber].message_id; 525 uint32_t msg_id = ++m->friendlist[friendnumber].message_id;
482 526
483 add_receipt(m, friendnumber, packet_num, msg_id); 527 add_receipt(m, friendnumber, packet_num, msg_id);
484 528
485 if (message_id) 529 if (message_id) {
486 *message_id = msg_id; 530 *message_id = msg_id;
531 }
487 532
488 return 0; 533 return 0;
489} 534}
@@ -493,8 +538,9 @@ int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, con
493 */ 538 */
494static int m_sendname(const Messenger *m, int32_t friendnumber, const uint8_t *name, uint16_t length) 539static int m_sendname(const Messenger *m, int32_t friendnumber, const uint8_t *name, uint16_t length)
495{ 540{
496 if (length > MAX_NAME_LENGTH) 541 if (length > MAX_NAME_LENGTH) {
497 return 0; 542 return 0;
543 }
498 544
499 return write_cryptpacket_id(m, friendnumber, PACKET_ID_NICKNAME, name, length, 0); 545 return write_cryptpacket_id(m, friendnumber, PACKET_ID_NICKNAME, name, length, 0);
500} 546}
@@ -506,11 +552,13 @@ static int m_sendname(const Messenger *m, int32_t friendnumber, const uint8_t *n
506 */ 552 */
507int setfriendname(Messenger *m, int32_t friendnumber, const uint8_t *name, uint16_t length) 553int setfriendname(Messenger *m, int32_t friendnumber, const uint8_t *name, uint16_t length)
508{ 554{
509 if (friend_not_valid(m, friendnumber)) 555 if (friend_not_valid(m, friendnumber)) {
510 return -1; 556 return -1;
557 }
511 558
512 if (length > MAX_NAME_LENGTH || length == 0) 559 if (length > MAX_NAME_LENGTH || length == 0) {
513 return -1; 560 return -1;
561 }
514 562
515 m->friendlist[friendnumber].name_length = length; 563 m->friendlist[friendnumber].name_length = length;
516 memcpy(m->friendlist[friendnumber].name, name, length); 564 memcpy(m->friendlist[friendnumber].name, name, length);
@@ -527,20 +575,24 @@ int setfriendname(Messenger *m, int32_t friendnumber, const uint8_t *name, uint1
527 */ 575 */
528int setname(Messenger *m, const uint8_t *name, uint16_t length) 576int setname(Messenger *m, const uint8_t *name, uint16_t length)
529{ 577{
530 if (length > MAX_NAME_LENGTH) 578 if (length > MAX_NAME_LENGTH) {
531 return -1; 579 return -1;
580 }
532 581
533 if (m->name_length == length && (length == 0 || memcmp(name, m->name, length) == 0)) 582 if (m->name_length == length && (length == 0 || memcmp(name, m->name, length) == 0)) {
534 return 0; 583 return 0;
584 }
535 585
536 if (length) 586 if (length) {
537 memcpy(m->name, name, length); 587 memcpy(m->name, name, length);
588 }
538 589
539 m->name_length = length; 590 m->name_length = length;
540 uint32_t i; 591 uint32_t i;
541 592
542 for (i = 0; i < m->numfriends; ++i) 593 for (i = 0; i < m->numfriends; ++i) {
543 m->friendlist[i].name_sent = 0; 594 m->friendlist[i].name_sent = 0;
595 }
544 596
545 return 0; 597 return 0;
546} 598}
@@ -552,7 +604,7 @@ int setname(Messenger *m, const uint8_t *name, uint16_t length)
552 */ 604 */
553uint16_t getself_name(const Messenger *m, uint8_t *name) 605uint16_t getself_name(const Messenger *m, uint8_t *name)
554{ 606{
555 if (name == NULL) { 607 if (name == nullptr) {
556 return 0; 608 return 0;
557 } 609 }
558 610
@@ -569,8 +621,9 @@ uint16_t getself_name(const Messenger *m, uint8_t *name)
569 */ 621 */
570int getname(const Messenger *m, int32_t friendnumber, uint8_t *name) 622int getname(const Messenger *m, int32_t friendnumber, uint8_t *name)
571{ 623{
572 if (friend_not_valid(m, friendnumber)) 624 if (friend_not_valid(m, friendnumber)) {
573 return -1; 625 return -1;
626 }
574 627
575 memcpy(name, m->friendlist[friendnumber].name, m->friendlist[friendnumber].name_length); 628 memcpy(name, m->friendlist[friendnumber].name, m->friendlist[friendnumber].name_length);
576 return m->friendlist[friendnumber].name_length; 629 return m->friendlist[friendnumber].name_length;
@@ -578,8 +631,9 @@ int getname(const Messenger *m, int32_t friendnumber, uint8_t *name)
578 631
579int m_get_name_size(const Messenger *m, int32_t friendnumber) 632int m_get_name_size(const Messenger *m, int32_t friendnumber)
580{ 633{
581 if (friend_not_valid(m, friendnumber)) 634 if (friend_not_valid(m, friendnumber)) {
582 return -1; 635 return -1;
636 }
583 637
584 return m->friendlist[friendnumber].name_length; 638 return m->friendlist[friendnumber].name_length;
585} 639}
@@ -591,38 +645,45 @@ int m_get_self_name_size(const Messenger *m)
591 645
592int m_set_statusmessage(Messenger *m, const uint8_t *status, uint16_t length) 646int m_set_statusmessage(Messenger *m, const uint8_t *status, uint16_t length)
593{ 647{
594 if (length > MAX_STATUSMESSAGE_LENGTH) 648 if (length > MAX_STATUSMESSAGE_LENGTH) {
595 return -1; 649 return -1;
650 }
596 651
597 if (m->statusmessage_length == length && (length == 0 || memcmp(m->statusmessage, status, length) == 0)) 652 if (m->statusmessage_length == length && (length == 0 || memcmp(m->statusmessage, status, length) == 0)) {
598 return 0; 653 return 0;
654 }
599 655
600 if (length) 656 if (length) {
601 memcpy(m->statusmessage, status, length); 657 memcpy(m->statusmessage, status, length);
658 }
602 659
603 m->statusmessage_length = length; 660 m->statusmessage_length = length;
604 661
605 uint32_t i; 662 uint32_t i;
606 663
607 for (i = 0; i < m->numfriends; ++i) 664 for (i = 0; i < m->numfriends; ++i) {
608 m->friendlist[i].statusmessage_sent = 0; 665 m->friendlist[i].statusmessage_sent = 0;
666 }
609 667
610 return 0; 668 return 0;
611} 669}
612 670
613int m_set_userstatus(Messenger *m, uint8_t status) 671int m_set_userstatus(Messenger *m, uint8_t status)
614{ 672{
615 if (status >= USERSTATUS_INVALID) 673 if (status >= USERSTATUS_INVALID) {
616 return -1; 674 return -1;
675 }
617 676
618 if (m->userstatus == status) 677 if (m->userstatus == status) {
619 return 0; 678 return 0;
679 }
620 680
621 m->userstatus = status; 681 m->userstatus = (USERSTATUS)status;
622 uint32_t i; 682 uint32_t i;
623 683
624 for (i = 0; i < m->numfriends; ++i) 684 for (i = 0; i < m->numfriends; ++i) {
625 m->friendlist[i].userstatus_sent = 0; 685 m->friendlist[i].userstatus_sent = 0;
686 }
626 687
627 return 0; 688 return 0;
628} 689}
@@ -632,8 +693,9 @@ int m_set_userstatus(Messenger *m, uint8_t status)
632 */ 693 */
633int m_get_statusmessage_size(const Messenger *m, int32_t friendnumber) 694int m_get_statusmessage_size(const Messenger *m, int32_t friendnumber)
634{ 695{
635 if (friend_not_valid(m, friendnumber)) 696 if (friend_not_valid(m, friendnumber)) {
636 return -1; 697 return -1;
698 }
637 699
638 return m->friendlist[friendnumber].statusmessage_length; 700 return m->friendlist[friendnumber].statusmessage_length;
639} 701}
@@ -643,8 +705,9 @@ int m_get_statusmessage_size(const Messenger *m, int32_t friendnumber)
643 */ 705 */
644int m_copy_statusmessage(const Messenger *m, int32_t friendnumber, uint8_t *buf, uint32_t maxlen) 706int m_copy_statusmessage(const Messenger *m, int32_t friendnumber, uint8_t *buf, uint32_t maxlen)
645{ 707{
646 if (friend_not_valid(m, friendnumber)) 708 if (friend_not_valid(m, friendnumber)) {
647 return -1; 709 return -1;
710 }
648 711
649 int msglen = MIN(maxlen, m->friendlist[friendnumber].statusmessage_length); 712 int msglen = MIN(maxlen, m->friendlist[friendnumber].statusmessage_length);
650 713
@@ -669,8 +732,9 @@ int m_copy_self_statusmessage(const Messenger *m, uint8_t *buf)
669 732
670uint8_t m_get_userstatus(const Messenger *m, int32_t friendnumber) 733uint8_t m_get_userstatus(const Messenger *m, int32_t friendnumber)
671{ 734{
672 if (friend_not_valid(m, friendnumber)) 735 if (friend_not_valid(m, friendnumber)) {
673 return USERSTATUS_INVALID; 736 return USERSTATUS_INVALID;
737 }
674 738
675 uint8_t status = m->friendlist[friendnumber].userstatus; 739 uint8_t status = m->friendlist[friendnumber].userstatus;
676 740
@@ -688,23 +752,26 @@ uint8_t m_get_self_userstatus(const Messenger *m)
688 752
689uint64_t m_get_last_online(const Messenger *m, int32_t friendnumber) 753uint64_t m_get_last_online(const Messenger *m, int32_t friendnumber)
690{ 754{
691 if (friend_not_valid(m, friendnumber)) 755 if (friend_not_valid(m, friendnumber)) {
692 return UINT64_MAX; 756 return UINT64_MAX;
757 }
693 758
694 return m->friendlist[friendnumber].last_seen_time; 759 return m->friendlist[friendnumber].last_seen_time;
695} 760}
696 761
697int m_set_usertyping(Messenger *m, int32_t friendnumber, uint8_t is_typing) 762int m_set_usertyping(Messenger *m, int32_t friendnumber, uint8_t is_typing)
698
699{ 763{
700 if (is_typing != 0 && is_typing != 1) 764 if (is_typing != 0 && is_typing != 1) {
701 return -1; 765 return -1;
766 }
702 767
703 if (friend_not_valid(m, friendnumber)) 768 if (friend_not_valid(m, friendnumber)) {
704 return -1; 769 return -1;
770 }
705 771
706 if (m->friendlist[friendnumber].user_istyping == is_typing) 772 if (m->friendlist[friendnumber].user_istyping == is_typing) {
707 return 0; 773 return 0;
774 }
708 775
709 m->friendlist[friendnumber].user_istyping = is_typing; 776 m->friendlist[friendnumber].user_istyping = is_typing;
710 m->friendlist[friendnumber].user_istyping_sent = 0; 777 m->friendlist[friendnumber].user_istyping_sent = 0;
@@ -714,8 +781,9 @@ int m_set_usertyping(Messenger *m, int32_t friendnumber, uint8_t is_typing)
714 781
715int m_get_istyping(const Messenger *m, int32_t friendnumber) 782int m_get_istyping(const Messenger *m, int32_t friendnumber)
716{ 783{
717 if (friend_not_valid(m, friendnumber)) 784 if (friend_not_valid(m, friendnumber)) {
718 return -1; 785 return -1;
786 }
719 787
720 return m->friendlist[friendnumber].is_typing; 788 return m->friendlist[friendnumber].is_typing;
721} 789}
@@ -738,14 +806,17 @@ static int send_user_istyping(const Messenger *m, int32_t friendnumber, uint8_t
738 806
739static int set_friend_statusmessage(const Messenger *m, int32_t friendnumber, const uint8_t *status, uint16_t length) 807static int set_friend_statusmessage(const Messenger *m, int32_t friendnumber, const uint8_t *status, uint16_t length)
740{ 808{
741 if (friend_not_valid(m, friendnumber)) 809 if (friend_not_valid(m, friendnumber)) {
742 return -1; 810 return -1;
811 }
743 812
744 if (length > MAX_STATUSMESSAGE_LENGTH) 813 if (length > MAX_STATUSMESSAGE_LENGTH) {
745 return -1; 814 return -1;
815 }
746 816
747 if (length) 817 if (length) {
748 memcpy(m->friendlist[friendnumber].statusmessage, status, length); 818 memcpy(m->friendlist[friendnumber].statusmessage, status, length);
819 }
749 820
750 m->friendlist[friendnumber].statusmessage_length = length; 821 m->friendlist[friendnumber].statusmessage_length = length;
751 return 0; 822 return 0;
@@ -753,7 +824,7 @@ static int set_friend_statusmessage(const Messenger *m, int32_t friendnumber, co
753 824
754static void set_friend_userstatus(const Messenger *m, int32_t friendnumber, uint8_t status) 825static void set_friend_userstatus(const Messenger *m, int32_t friendnumber, uint8_t status)
755{ 826{
756 m->friendlist[friendnumber].userstatus = status; 827 m->friendlist[friendnumber].userstatus = (USERSTATUS)status;
757} 828}
758 829
759static void set_friend_typing(const Messenger *m, int32_t friendnumber, uint8_t is_typing) 830static void set_friend_typing(const Messenger *m, int32_t friendnumber, uint8_t is_typing)
@@ -761,65 +832,58 @@ static void set_friend_typing(const Messenger *m, int32_t friendnumber, uint8_t
761 m->friendlist[friendnumber].is_typing = is_typing; 832 m->friendlist[friendnumber].is_typing = is_typing;
762} 833}
763 834
835void m_callback_log(Messenger *m, logger_cb *function, void *context, void *userdata)
836{
837 logger_callback_log(m->log, function, context, userdata);
838}
839
764/* Set the function that will be executed when a friend request is received. */ 840/* Set the function that will be executed when a friend request is received. */
765void m_callback_friendrequest(Messenger *m, void (*function)(Messenger *m, const uint8_t *, const uint8_t *, size_t, 841void m_callback_friendrequest(Messenger *m, void (*function)(Messenger *m, const uint8_t *, const uint8_t *, size_t,
766 void *), void *userdata) 842 void *))
767{ 843{
768 void (*handle_friendrequest)(void *, const uint8_t *, const uint8_t *, size_t, void *) = (void *)function; 844 callback_friendrequest(m->fr, (void (*)(void *, const uint8_t *, const uint8_t *, size_t, void *))function, m);
769 callback_friendrequest(&(m->fr), handle_friendrequest, m, userdata);
770} 845}
771 846
772/* Set the function that will be executed when a message from a friend is received. */ 847/* Set the function that will be executed when a message from a friend is received. */
773void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, const uint8_t *, 848void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, const uint8_t *,
774 size_t, void *), void *userdata) 849 size_t, void *))
775{ 850{
776 m->friend_message = function; 851 m->friend_message = function;
777 m->friend_message_userdata = userdata;
778} 852}
779 853
780void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *), 854void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *))
781 void *userdata)
782{ 855{
783 m->friend_namechange = function; 856 m->friend_namechange = function;
784 m->friend_namechange_userdata = userdata;
785} 857}
786 858
787void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *), 859void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *))
788 void *userdata)
789{ 860{
790 m->friend_statusmessagechange = function; 861 m->friend_statusmessagechange = function;
791 m->friend_statusmessagechange_userdata = userdata;
792} 862}
793 863
794void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *), void *userdata) 864void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *))
795{ 865{
796 m->friend_userstatuschange = function; 866 m->friend_userstatuschange = function;
797 m->friend_userstatuschange_userdata = userdata;
798} 867}
799 868
800void m_callback_typingchange(Messenger *m, void(*function)(Messenger *m, uint32_t, _Bool, void *), void *userdata) 869void m_callback_typingchange(Messenger *m, void(*function)(Messenger *m, uint32_t, bool, void *))
801{ 870{
802 m->friend_typingchange = function; 871 m->friend_typingchange = function;
803 m->friend_typingchange_userdata = userdata;
804} 872}
805 873
806void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, void *), void *userdata) 874void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, void *))
807{ 875{
808 m->read_receipt = function; 876 m->read_receipt = function;
809 m->read_receipt_userdata = userdata;
810} 877}
811 878
812void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *), 879void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *))
813 void *userdata)
814{ 880{
815 m->friend_connectionstatuschange = function; 881 m->friend_connectionstatuschange = function;
816 m->friend_connectionstatuschange_userdata = userdata;
817} 882}
818 883
819void m_callback_core_connection(Messenger *m, void (*function)(Messenger *m, unsigned int, void *), void *userdata) 884void m_callback_core_connection(Messenger *m, void (*function)(Messenger *m, unsigned int, void *))
820{ 885{
821 m->core_connection_change = function; 886 m->core_connection_change = function;
822 m->core_connection_change_userdata = userdata;
823} 887}
824 888
825void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, void *), 889void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, void *),
@@ -829,36 +893,39 @@ void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Mess
829 m->friend_connectionstatuschange_internal_userdata = userdata; 893 m->friend_connectionstatuschange_internal_userdata = userdata;
830} 894}
831 895
832static void check_friend_tcp_udp(Messenger *m, int32_t friendnumber) 896static void check_friend_tcp_udp(Messenger *m, int32_t friendnumber, void *userdata)
833{ 897{
834 int last_connection_udp_tcp = m->friendlist[friendnumber].last_connection_udp_tcp; 898 int last_connection_udp_tcp = m->friendlist[friendnumber].last_connection_udp_tcp;
835 899
836 int ret = m_get_friend_connectionstatus(m, friendnumber); 900 int ret = m_get_friend_connectionstatus(m, friendnumber);
837 901
838 if (ret == -1) 902 if (ret == -1) {
839 return; 903 return;
904 }
840 905
841 if (ret == CONNECTION_UNKNOWN) { 906 if (ret == CONNECTION_UNKNOWN) {
842 if (last_connection_udp_tcp == CONNECTION_UDP) { 907 if (last_connection_udp_tcp == CONNECTION_UDP) {
843 return; 908 return;
844 } else {
845 ret = CONNECTION_TCP;
846 } 909 }
910
911 ret = CONNECTION_TCP;
847 } 912 }
848 913
849 if (last_connection_udp_tcp != ret) { 914 if (last_connection_udp_tcp != ret) {
850 if (m->friend_connectionstatuschange) 915 if (m->friend_connectionstatuschange) {
851 m->friend_connectionstatuschange(m, friendnumber, ret, m->friend_connectionstatuschange_userdata); 916 m->friend_connectionstatuschange(m, friendnumber, ret, userdata);
917 }
852 } 918 }
853 919
854 m->friendlist[friendnumber].last_connection_udp_tcp = ret; 920 m->friendlist[friendnumber].last_connection_udp_tcp = ret;
855} 921}
856 922
857static void break_files(const Messenger *m, int32_t friendnumber); 923static void break_files(const Messenger *m, int32_t friendnumber);
858static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, uint8_t status) 924static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, uint8_t status, void *userdata)
859{ 925{
860 if (status == NOFRIEND) 926 if (status == NOFRIEND) {
861 return; 927 return;
928 }
862 929
863 const uint8_t was_online = m->friendlist[friendnumber].status == FRIEND_ONLINE; 930 const uint8_t was_online = m->friendlist[friendnumber].status == FRIEND_ONLINE;
864 const uint8_t is_online = status == FRIEND_ONLINE; 931 const uint8_t is_online = status == FRIEND_ONLINE;
@@ -876,60 +943,65 @@ static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, ui
876 943
877 m->friendlist[friendnumber].status = status; 944 m->friendlist[friendnumber].status = status;
878 945
879 check_friend_tcp_udp(m, friendnumber); 946 check_friend_tcp_udp(m, friendnumber, userdata);
880 947
881 if (m->friend_connectionstatuschange_internal) 948 if (m->friend_connectionstatuschange_internal) {
882 m->friend_connectionstatuschange_internal(m, friendnumber, is_online, 949 m->friend_connectionstatuschange_internal(m, friendnumber, is_online,
883 m->friend_connectionstatuschange_internal_userdata); 950 m->friend_connectionstatuschange_internal_userdata);
951 }
884 } 952 }
885} 953}
886 954
887void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status) 955static void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status, void *userdata)
888{ 956{
889 check_friend_connectionstatus(m, friendnumber, status); 957 check_friend_connectionstatus(m, friendnumber, status, userdata);
890 m->friendlist[friendnumber].status = status; 958 m->friendlist[friendnumber].status = status;
891} 959}
892 960
893static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data, 961static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data,
894 uint32_t length, uint8_t congestion_control) 962 uint32_t length, uint8_t congestion_control)
895{ 963{
896 if (friend_not_valid(m, friendnumber)) 964 if (friend_not_valid(m, friendnumber)) {
897 return 0; 965 return 0;
966 }
898 967
899 if (length >= MAX_CRYPTO_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE) 968 if (length >= MAX_CRYPTO_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE) {
900 return 0; 969 return 0;
970 }
901 971
902 uint8_t packet[length + 1]; 972 VLA(uint8_t, packet, length + 1);
903 packet[0] = packet_id; 973 packet[0] = packet_id;
904 974
905 if (length != 0) 975 if (length != 0) {
906 memcpy(packet + 1, data, length); 976 memcpy(packet + 1, data, length);
977 }
907 978
908 return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, 979 return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
909 m->friendlist[friendnumber].friendcon_id), packet, length + 1, congestion_control) != -1; 980 m->friendlist[friendnumber].friendcon_id), packet, length + 1, congestion_control) != -1;
910} 981}
911 982
912/**********GROUP CHATS************/ 983/**********CONFERENCES************/
913 984
914 985
915/* Set the callback for group invites. 986/* Set the callback for conference invites.
916 * 987 *
917 * Function(Messenger *m, uint32_t friendnumber, uint8_t *data, uint16_t length) 988 * Function(Messenger *m, uint32_t friendnumber, uint8_t *data, uint16_t length, void *userdata)
918 */ 989 */
919void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, uint16_t)) 990void m_callback_conference_invite(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, uint16_t,
991 void *))
920{ 992{
921 m->group_invite = function; 993 m->conference_invite = function;
922} 994}
923 995
924 996
925/* Send a group invite packet. 997/* Send a conference invite packet.
926 * 998 *
927 * return 1 on success 999 * return 1 on success
928 * return 0 on failure 1000 * return 0 on failure
929 */ 1001 */
930int send_group_invite_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length) 1002int send_conference_invite_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length)
931{ 1003{
932 return write_cryptpacket_id(m, friendnumber, PACKET_ID_INVITE_GROUPCHAT, data, length, 0); 1004 return write_cryptpacket_id(m, friendnumber, PACKET_ID_INVITE_CONFERENCE, data, length, 0);
933} 1005}
934 1006
935/****************FILE SENDING*****************/ 1007/****************FILE SENDING*****************/
@@ -940,10 +1012,9 @@ int send_group_invite_packet(const Messenger *m, int32_t friendnumber, const uin
940 * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint32_t filetype, uint64_t filesize, uint8_t *filename, size_t filename_length, void *userdata) 1012 * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint32_t filetype, uint64_t filesize, uint8_t *filename, size_t filename_length, void *userdata)
941 */ 1013 */
942void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint32_t, uint64_t, 1014void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint32_t, uint64_t,
943 const uint8_t *, size_t, void *), void *userdata) 1015 const uint8_t *, size_t, void *))
944{ 1016{
945 m->file_sendrequest = function; 1017 m->file_sendrequest = function;
946 m->file_sendrequest_userdata = userdata;
947} 1018}
948 1019
949/* Set the callback for file control requests. 1020/* Set the callback for file control requests.
@@ -951,11 +1022,9 @@ void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, uin
951 * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, unsigned int control_type, void *userdata) 1022 * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, unsigned int control_type, void *userdata)
952 * 1023 *
953 */ 1024 */
954void callback_file_control(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, unsigned int, void *), 1025void callback_file_control(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, unsigned int, void *))
955 void *userdata)
956{ 1026{
957 m->file_filecontrol = function; 1027 m->file_filecontrol = function;
958 m->file_filecontrol_userdata = userdata;
959} 1028}
960 1029
961/* Set the callback for file data. 1030/* Set the callback for file data.
@@ -964,10 +1033,9 @@ void callback_file_control(Messenger *m, void (*function)(Messenger *m, uint32_t
964 * 1033 *
965 */ 1034 */
966void callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, const uint8_t *, 1035void callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, const uint8_t *,
967 size_t, void *), void *userdata) 1036 size_t, void *))
968{ 1037{
969 m->file_filedata = function; 1038 m->file_filedata = function;
970 m->file_filedata_userdata = userdata;
971} 1039}
972 1040
973/* Set the callback for file request chunk. 1041/* Set the callback for file request chunk.
@@ -975,11 +1043,9 @@ void callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, u
975 * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length, void *userdata) 1043 * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length, void *userdata)
976 * 1044 *
977 */ 1045 */
978void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *), 1046void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *))
979 void *userdata)
980{ 1047{
981 m->file_reqchunk = function; 1048 m->file_reqchunk = function;
982 m->file_reqchunk_userdata = userdata;
983} 1049}
984 1050
985#define MAX_FILENAME_LENGTH 255 1051#define MAX_FILENAME_LENGTH 255
@@ -992,11 +1058,13 @@ void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_
992 */ 1058 */
993int file_get_id(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint8_t *file_id) 1059int file_get_id(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint8_t *file_id)
994{ 1060{
995 if (friend_not_valid(m, friendnumber)) 1061 if (friend_not_valid(m, friendnumber)) {
996 return -1; 1062 return -1;
1063 }
997 1064
998 if (m->friendlist[friendnumber].status != FRIEND_ONLINE) 1065 if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
999 return -2; 1066 return -2;
1067 }
1000 1068
1001 uint32_t temp_filenum; 1069 uint32_t temp_filenum;
1002 uint8_t send_receive, file_number; 1070 uint8_t send_receive, file_number;
@@ -1009,8 +1077,9 @@ int file_get_id(const Messenger *m, int32_t friendnumber, uint32_t filenumber, u
1009 temp_filenum = filenumber; 1077 temp_filenum = filenumber;
1010 } 1078 }
1011 1079
1012 if (temp_filenum >= MAX_CONCURRENT_FILE_PIPES) 1080 if (temp_filenum >= MAX_CONCURRENT_FILE_PIPES) {
1013 return -2; 1081 return -2;
1082 }
1014 1083
1015 file_number = temp_filenum; 1084 file_number = temp_filenum;
1016 1085
@@ -1022,8 +1091,9 @@ int file_get_id(const Messenger *m, int32_t friendnumber, uint32_t filenumber, u
1022 ft = &m->friendlist[friendnumber].file_sending[file_number]; 1091 ft = &m->friendlist[friendnumber].file_sending[file_number];
1023 } 1092 }
1024 1093
1025 if (ft->status == FILESTATUS_NONE) 1094 if (ft->status == FILESTATUS_NONE) {
1026 return -2; 1095 return -2;
1096 }
1027 1097
1028 memcpy(file_id, ft->id, FILE_ID_LENGTH); 1098 memcpy(file_id, ft->id, FILE_ID_LENGTH);
1029 return 0; 1099 return 0;
@@ -1037,15 +1107,17 @@ int file_get_id(const Messenger *m, int32_t friendnumber, uint32_t filenumber, u
1037static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint32_t file_type, 1107static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint32_t file_type,
1038 uint64_t filesize, const uint8_t *file_id, const uint8_t *filename, uint16_t filename_length) 1108 uint64_t filesize, const uint8_t *file_id, const uint8_t *filename, uint16_t filename_length)
1039{ 1109{
1040 if (friend_not_valid(m, friendnumber)) 1110 if (friend_not_valid(m, friendnumber)) {
1041 return 0; 1111 return 0;
1112 }
1042 1113
1043 if (filename_length > MAX_FILENAME_LENGTH) 1114 if (filename_length > MAX_FILENAME_LENGTH) {
1044 return 0; 1115 return 0;
1116 }
1045 1117
1046 uint8_t packet[1 + sizeof(file_type) + sizeof(filesize) + FILE_ID_LENGTH + filename_length]; 1118 VLA(uint8_t, packet, 1 + sizeof(file_type) + sizeof(filesize) + FILE_ID_LENGTH + filename_length);
1047 packet[0] = filenumber; 1119 packet[0] = filenumber;
1048 file_type = htonl(file_type); 1120 file_type = net_htonl(file_type);
1049 memcpy(packet + 1, &file_type, sizeof(file_type)); 1121 memcpy(packet + 1, &file_type, sizeof(file_type));
1050 host_to_net((uint8_t *)&filesize, sizeof(filesize)); 1122 host_to_net((uint8_t *)&filesize, sizeof(filesize));
1051 memcpy(packet + 1 + sizeof(file_type), &filesize, sizeof(filesize)); 1123 memcpy(packet + 1 + sizeof(file_type), &filesize, sizeof(filesize));
@@ -1055,7 +1127,7 @@ static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t fi
1055 memcpy(packet + 1 + sizeof(file_type) + sizeof(filesize) + FILE_ID_LENGTH, filename, filename_length); 1127 memcpy(packet + 1 + sizeof(file_type) + sizeof(filesize) + FILE_ID_LENGTH, filename, filename_length);
1056 } 1128 }
1057 1129
1058 return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_SENDREQUEST, packet, sizeof(packet), 0); 1130 return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_SENDREQUEST, packet, SIZEOF_VLA(packet), 0);
1059} 1131}
1060 1132
1061/* Send a file send request. 1133/* Send a file send request.
@@ -1070,32 +1142,44 @@ static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t fi
1070long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_type, uint64_t filesize, 1142long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_type, uint64_t filesize,
1071 const uint8_t *file_id, const uint8_t *filename, uint16_t filename_length) 1143 const uint8_t *file_id, const uint8_t *filename, uint16_t filename_length)
1072{ 1144{
1073 if (friend_not_valid(m, friendnumber)) 1145 if (friend_not_valid(m, friendnumber)) {
1074 return -1; 1146 return -1;
1147 }
1075 1148
1076 if (filename_length > MAX_FILENAME_LENGTH) 1149 if (filename_length > MAX_FILENAME_LENGTH) {
1077 return -2; 1150 return -2;
1151 }
1078 1152
1079 uint32_t i; 1153 uint32_t i;
1080 1154
1081 for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) { 1155 for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) {
1082 if (m->friendlist[friendnumber].file_sending[i].status == FILESTATUS_NONE) 1156 if (m->friendlist[friendnumber].file_sending[i].status == FILESTATUS_NONE) {
1083 break; 1157 break;
1158 }
1084 } 1159 }
1085 1160
1086 if (i == MAX_CONCURRENT_FILE_PIPES) 1161 if (i == MAX_CONCURRENT_FILE_PIPES) {
1087 return -3; 1162 return -3;
1163 }
1088 1164
1089 if (file_sendrequest(m, friendnumber, i, file_type, filesize, file_id, filename, filename_length) == 0) 1165 if (file_sendrequest(m, friendnumber, i, file_type, filesize, file_id, filename, filename_length) == 0) {
1090 return -4; 1166 return -4;
1167 }
1091 1168
1092 struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[i]; 1169 struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[i];
1170
1093 ft->status = FILESTATUS_NOT_ACCEPTED; 1171 ft->status = FILESTATUS_NOT_ACCEPTED;
1172
1094 ft->size = filesize; 1173 ft->size = filesize;
1174
1095 ft->transferred = 0; 1175 ft->transferred = 0;
1176
1096 ft->requested = 0; 1177 ft->requested = 0;
1178
1097 ft->slots_allocated = 0; 1179 ft->slots_allocated = 0;
1180
1098 ft->paused = FILE_PAUSE_NOT; 1181 ft->paused = FILE_PAUSE_NOT;
1182
1099 memcpy(ft->id, file_id, FILE_ID_LENGTH); 1183 memcpy(ft->id, file_id, FILE_ID_LENGTH);
1100 1184
1101 ++m->friendlist[friendnumber].num_sending_files; 1185 ++m->friendlist[friendnumber].num_sending_files;
@@ -1103,13 +1187,14 @@ long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_
1103 return i; 1187 return i;
1104} 1188}
1105 1189
1106int send_file_control_packet(const Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber, 1190static int send_file_control_packet(const Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber,
1107 uint8_t control_type, uint8_t *data, uint16_t data_length) 1191 uint8_t control_type, uint8_t *data, uint16_t data_length)
1108{ 1192{
1109 if ((unsigned int)(1 + 3 + data_length) > MAX_CRYPTO_DATA_SIZE) 1193 if ((unsigned int)(1 + 3 + data_length) > MAX_CRYPTO_DATA_SIZE) {
1110 return -1; 1194 return -1;
1195 }
1111 1196
1112 uint8_t packet[3 + data_length]; 1197 VLA(uint8_t, packet, 3 + data_length);
1113 1198
1114 packet[0] = send_receive; 1199 packet[0] = send_receive;
1115 packet[1] = filenumber; 1200 packet[1] = filenumber;
@@ -1119,7 +1204,7 @@ int send_file_control_packet(const Messenger *m, int32_t friendnumber, uint8_t s
1119 memcpy(packet + 3, data, data_length); 1204 memcpy(packet + 3, data, data_length);
1120 } 1205 }
1121 1206
1122 return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_CONTROL, packet, sizeof(packet), 0); 1207 return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_CONTROL, packet, SIZEOF_VLA(packet), 0);
1123} 1208}
1124 1209
1125/* Send a file control request. 1210/* Send a file control request.
@@ -1136,11 +1221,13 @@ int send_file_control_packet(const Messenger *m, int32_t friendnumber, uint8_t s
1136 */ 1221 */
1137int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber, unsigned int control) 1222int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber, unsigned int control)
1138{ 1223{
1139 if (friend_not_valid(m, friendnumber)) 1224 if (friend_not_valid(m, friendnumber)) {
1140 return -1; 1225 return -1;
1226 }
1141 1227
1142 if (m->friendlist[friendnumber].status != FRIEND_ONLINE) 1228 if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
1143 return -2; 1229 return -2;
1230 }
1144 1231
1145 uint32_t temp_filenum; 1232 uint32_t temp_filenum;
1146 uint8_t send_receive, file_number; 1233 uint8_t send_receive, file_number;
@@ -1153,8 +1240,9 @@ int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber,
1153 temp_filenum = filenumber; 1240 temp_filenum = filenumber;
1154 } 1241 }
1155 1242
1156 if (temp_filenum >= MAX_CONCURRENT_FILE_PIPES) 1243 if (temp_filenum >= MAX_CONCURRENT_FILE_PIPES) {
1157 return -3; 1244 return -3;
1245 }
1158 1246
1159 file_number = temp_filenum; 1247 file_number = temp_filenum;
1160 1248
@@ -1166,34 +1254,39 @@ int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber,
1166 ft = &m->friendlist[friendnumber].file_sending[file_number]; 1254 ft = &m->friendlist[friendnumber].file_sending[file_number];
1167 } 1255 }
1168 1256
1169 if (ft->status == FILESTATUS_NONE) 1257 if (ft->status == FILESTATUS_NONE) {
1170 return -3; 1258 return -3;
1259 }
1171 1260
1172 if (control > FILECONTROL_KILL) 1261 if (control > FILECONTROL_KILL) {
1173 return -4; 1262 return -4;
1263 }
1174 1264
1175 if (control == FILECONTROL_PAUSE && ((ft->paused & FILE_PAUSE_US) || ft->status != FILESTATUS_TRANSFERRING)) 1265 if (control == FILECONTROL_PAUSE && ((ft->paused & FILE_PAUSE_US) || ft->status != FILESTATUS_TRANSFERRING)) {
1176 return -5; 1266 return -5;
1267 }
1177 1268
1178 if (control == FILECONTROL_ACCEPT) { 1269 if (control == FILECONTROL_ACCEPT) {
1179 if (ft->status == FILESTATUS_TRANSFERRING) { 1270 if (ft->status == FILESTATUS_TRANSFERRING) {
1180 if (!(ft->paused & FILE_PAUSE_US)) { 1271 if (!(ft->paused & FILE_PAUSE_US)) {
1181 if (ft->paused & FILE_PAUSE_OTHER) { 1272 if (ft->paused & FILE_PAUSE_OTHER) {
1182 return -6; 1273 return -6;
1183 } else {
1184 return -7;
1185 } 1274 }
1275
1276 return -7;
1186 } 1277 }
1187 } else { 1278 } else {
1188 if (ft->status != FILESTATUS_NOT_ACCEPTED) 1279 if (ft->status != FILESTATUS_NOT_ACCEPTED) {
1189 return -7; 1280 return -7;
1281 }
1190 1282
1191 if (!send_receive) 1283 if (!send_receive) {
1192 return -6; 1284 return -6;
1285 }
1193 } 1286 }
1194 } 1287 }
1195 1288
1196 if (send_file_control_packet(m, friendnumber, send_receive, file_number, control, 0, 0)) { 1289 if (send_file_control_packet(m, friendnumber, send_receive, file_number, control, nullptr, 0)) {
1197 if (control == FILECONTROL_KILL) { 1290 if (control == FILECONTROL_KILL) {
1198 ft->status = FILESTATUS_NONE; 1291 ft->status = FILESTATUS_NONE;
1199 1292
@@ -1229,40 +1322,38 @@ int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber,
1229 */ 1322 */
1230int file_seek(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position) 1323int file_seek(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position)
1231{ 1324{
1232 if (friend_not_valid(m, friendnumber)) 1325 if (friend_not_valid(m, friendnumber)) {
1233 return -1; 1326 return -1;
1327 }
1234 1328
1235 if (m->friendlist[friendnumber].status != FRIEND_ONLINE) 1329 if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
1236 return -2; 1330 return -2;
1331 }
1237 1332
1238 uint32_t temp_filenum; 1333 if (filenumber < (1 << 16)) {
1239 uint8_t send_receive, file_number; 1334 // Not receiving.
1240
1241 if (filenumber >= (1 << 16)) {
1242 send_receive = 1;
1243 temp_filenum = (filenumber >> 16) - 1;
1244 } else {
1245 return -4; 1335 return -4;
1246 } 1336 }
1247 1337
1248 if (temp_filenum >= MAX_CONCURRENT_FILE_PIPES) 1338 uint32_t temp_filenum = (filenumber >> 16) - 1;
1249 return -3;
1250 1339
1251 file_number = temp_filenum; 1340 if (temp_filenum >= MAX_CONCURRENT_FILE_PIPES) {
1341 return -3;
1342 }
1252 1343
1253 struct File_Transfers *ft; 1344 assert(temp_filenum <= UINT8_MAX);
1345 uint8_t file_number = temp_filenum;
1254 1346
1255 if (send_receive) { 1347 // We're always receiving at this point.
1256 ft = &m->friendlist[friendnumber].file_receiving[file_number]; 1348 struct File_Transfers *ft = &m->friendlist[friendnumber].file_receiving[file_number];
1257 } else {
1258 ft = &m->friendlist[friendnumber].file_sending[file_number];
1259 }
1260 1349
1261 if (ft->status == FILESTATUS_NONE) 1350 if (ft->status == FILESTATUS_NONE) {
1262 return -3; 1351 return -3;
1352 }
1263 1353
1264 if (ft->status != FILESTATUS_NOT_ACCEPTED) 1354 if (ft->status != FILESTATUS_NOT_ACCEPTED) {
1265 return -5; 1355 return -5;
1356 }
1266 1357
1267 if (position >= ft->size) { 1358 if (position >= ft->size) {
1268 return -6; 1359 return -6;
@@ -1271,7 +1362,7 @@ int file_seek(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uin
1271 uint64_t sending_pos = position; 1362 uint64_t sending_pos = position;
1272 host_to_net((uint8_t *)&sending_pos, sizeof(sending_pos)); 1363 host_to_net((uint8_t *)&sending_pos, sizeof(sending_pos));
1273 1364
1274 if (send_file_control_packet(m, friendnumber, send_receive, file_number, FILECONTROL_SEEK, (uint8_t *)&sending_pos, 1365 if (send_file_control_packet(m, friendnumber, 1, file_number, FILECONTROL_SEEK, (uint8_t *)&sending_pos,
1275 sizeof(sending_pos))) { 1366 sizeof(sending_pos))) {
1276 ft->transferred = position; 1367 ft->transferred = position;
1277 } else { 1368 } else {
@@ -1287,10 +1378,11 @@ int file_seek(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uin
1287static int64_t send_file_data_packet(const Messenger *m, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, 1378static int64_t send_file_data_packet(const Messenger *m, int32_t friendnumber, uint8_t filenumber, const uint8_t *data,
1288 uint16_t length) 1379 uint16_t length)
1289{ 1380{
1290 if (friend_not_valid(m, friendnumber)) 1381 if (friend_not_valid(m, friendnumber)) {
1291 return -1; 1382 return -1;
1383 }
1292 1384
1293 uint8_t packet[2 + length]; 1385 VLA(uint8_t, packet, 2 + length);
1294 packet[0] = PACKET_ID_FILE_DATA; 1386 packet[0] = PACKET_ID_FILE_DATA;
1295 packet[1] = filenumber; 1387 packet[1] = filenumber;
1296 1388
@@ -1299,7 +1391,7 @@ static int64_t send_file_data_packet(const Messenger *m, int32_t friendnumber, u
1299 } 1391 }
1300 1392
1301 return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, 1393 return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
1302 m->friendlist[friendnumber].friendcon_id), packet, sizeof(packet), 1); 1394 m->friendlist[friendnumber].friendcon_id), packet, SIZEOF_VLA(packet), 1);
1303} 1395}
1304 1396
1305#define MAX_FILE_DATA_SIZE (MAX_CRYPTO_DATA_SIZE - 2) 1397#define MAX_FILE_DATA_SIZE (MAX_CRYPTO_DATA_SIZE - 2)
@@ -1318,22 +1410,27 @@ static int64_t send_file_data_packet(const Messenger *m, int32_t friendnumber, u
1318int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data, 1410int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
1319 uint16_t length) 1411 uint16_t length)
1320{ 1412{
1321 if (friend_not_valid(m, friendnumber)) 1413 if (friend_not_valid(m, friendnumber)) {
1322 return -1; 1414 return -1;
1415 }
1323 1416
1324 if (m->friendlist[friendnumber].status != FRIEND_ONLINE) 1417 if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
1325 return -2; 1418 return -2;
1419 }
1326 1420
1327 if (filenumber >= MAX_CONCURRENT_FILE_PIPES) 1421 if (filenumber >= MAX_CONCURRENT_FILE_PIPES) {
1328 return -3; 1422 return -3;
1423 }
1329 1424
1330 struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[filenumber]; 1425 struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[filenumber];
1331 1426
1332 if (ft->status != FILESTATUS_TRANSFERRING) 1427 if (ft->status != FILESTATUS_TRANSFERRING) {
1333 return -4; 1428 return -4;
1429 }
1334 1430
1335 if (length > MAX_FILE_DATA_SIZE) 1431 if (length > MAX_FILE_DATA_SIZE) {
1336 return -5; 1432 return -5;
1433 }
1337 1434
1338 if (ft->size - ft->transferred < length) { 1435 if (ft->size - ft->transferred < length) {
1339 return -5; 1436 return -5;
@@ -1347,15 +1444,17 @@ int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uin
1347 return -7; 1444 return -7;
1348 } 1445 }
1349 1446
1350 /* Prevent file sending from filling up the entire buffer preventing messages from being sent. TODO: remove */ 1447 /* Prevent file sending from filling up the entire buffer preventing messages from being sent.
1448 * TODO(irungentoo): remove */
1351 if (crypto_num_free_sendqueue_slots(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, 1449 if (crypto_num_free_sendqueue_slots(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
1352 m->friendlist[friendnumber].friendcon_id)) < MIN_SLOTS_FREE) 1450 m->friendlist[friendnumber].friendcon_id)) < MIN_SLOTS_FREE) {
1353 return -6; 1451 return -6;
1452 }
1354 1453
1355 int64_t ret = send_file_data_packet(m, friendnumber, filenumber, data, length); 1454 int64_t ret = send_file_data_packet(m, friendnumber, filenumber, data, length);
1356 1455
1357 if (ret != -1) { 1456 if (ret != -1) {
1358 //TODO record packet ids to check if other received complete file. 1457 // TODO(irungentoo): record packet ids to check if other received complete file.
1359 ft->transferred += length; 1458 ft->transferred += length;
1360 1459
1361 if (ft->slots_allocated) { 1460 if (ft->slots_allocated) {
@@ -1371,7 +1470,6 @@ int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uin
1371 } 1470 }
1372 1471
1373 return -6; 1472 return -6;
1374
1375} 1473}
1376 1474
1377/* Give the number of bytes left to be sent/received. 1475/* Give the number of bytes left to be sent/received.
@@ -1383,210 +1481,302 @@ int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uin
1383 */ 1481 */
1384uint64_t file_dataremaining(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t send_receive) 1482uint64_t file_dataremaining(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t send_receive)
1385{ 1483{
1386 if (friend_not_valid(m, friendnumber)) 1484 if (friend_not_valid(m, friendnumber)) {
1387 return 0; 1485 return 0;
1486 }
1487
1488 const struct File_Transfers *const sending = &m->friendlist[friendnumber].file_sending[filenumber];
1388 1489
1389 if (send_receive == 0) { 1490 if (send_receive == 0) {
1390 if (m->friendlist[friendnumber].file_sending[filenumber].status == FILESTATUS_NONE) 1491 if (sending->status == FILESTATUS_NONE) {
1391 return 0; 1492 return 0;
1493 }
1392 1494
1393 return m->friendlist[friendnumber].file_sending[filenumber].size - 1495 return sending->size - sending->transferred;
1394 m->friendlist[friendnumber].file_sending[filenumber].transferred; 1496 }
1395 } else {
1396 if (m->friendlist[friendnumber].file_receiving[filenumber].status == FILESTATUS_NONE)
1397 return 0;
1398 1497
1399 return m->friendlist[friendnumber].file_receiving[filenumber].size - 1498 const struct File_Transfers *const receiving = &m->friendlist[friendnumber].file_receiving[filenumber];
1400 m->friendlist[friendnumber].file_receiving[filenumber].transferred; 1499
1500 if (receiving->status == FILESTATUS_NONE) {
1501 return 0;
1401 } 1502 }
1503
1504 return receiving->size - receiving->transferred;
1402} 1505}
1403 1506
1404static void do_reqchunk_filecb(Messenger *m, int32_t friendnumber) 1507/**
1508 * Iterate over all file transfers and request chunks (from the client) for each
1509 * of them.
1510 *
1511 * The free_slots parameter is updated by this function.
1512 *
1513 * @param m Our messenger object.
1514 * @param friendnumber The friend we're sending files to.
1515 * @param userdata The client userdata to pass along to chunk request callbacks.
1516 * @param free_slots A pointer to the number of free send queue slots in the
1517 * crypto connection.
1518 *
1519 * @return true if there are still file transfers ongoing, false if all file
1520 * transfers are complete.
1521 */
1522static bool do_all_filetransfers(Messenger *m, int32_t friendnumber, void *userdata, uint32_t *free_slots)
1405{ 1523{
1406 if (!m->friendlist[friendnumber].num_sending_files) 1524 Friend *const friendcon = &m->friendlist[friendnumber];
1407 return; 1525 uint32_t num = friendcon->num_sending_files;
1408
1409 int free_slots = crypto_num_free_sendqueue_slots(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
1410 m->friendlist[friendnumber].friendcon_id));
1411
1412 if (free_slots < MIN_SLOTS_FREE) {
1413 free_slots = 0;
1414 } else {
1415 free_slots -= MIN_SLOTS_FREE;
1416 }
1417 1526
1418 unsigned int i, num = m->friendlist[friendnumber].num_sending_files; 1527 bool any_active_fts = false;
1419 1528
1420 for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) { 1529 // Iterate over all file transfers, including inactive ones. I.e. we always
1421 struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[i]; 1530 // iterate exactly MAX_CONCURRENT_FILE_PIPES times.
1531 for (uint32_t i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) {
1532 struct File_Transfers *const ft = &friendcon->file_sending[i];
1422 1533
1534 // Any status other than NONE means the file transfer is active.
1423 if (ft->status != FILESTATUS_NONE) { 1535 if (ft->status != FILESTATUS_NONE) {
1536 any_active_fts = true;
1424 --num; 1537 --num;
1425 1538
1426 if (ft->status == FILESTATUS_FINISHED) { 1539 // If the file transfer is complete, we request a chunk of size 0.
1427 /* Check if file was entirely sent. */ 1540 if (ft->status == FILESTATUS_FINISHED && friend_received_packet(m, friendnumber, ft->last_packet_number) == 0) {
1428 if (friend_received_packet(m, friendnumber, ft->last_packet_number) == 0) { 1541 if (m->file_reqchunk) {
1429 if (m->file_reqchunk) 1542 m->file_reqchunk(m, friendnumber, i, ft->transferred, 0, userdata);
1430 (*m->file_reqchunk)(m, friendnumber, i, ft->transferred, 0, m->file_reqchunk_userdata);
1431
1432 ft->status = FILESTATUS_NONE;
1433 --m->friendlist[friendnumber].num_sending_files;
1434 } 1543 }
1435 }
1436 1544
1437 /* TODO: if file is too slow, switch to the next. */ 1545 // Now it's inactive, we're no longer sending this.
1438 if (ft->slots_allocated > (unsigned int)free_slots) { 1546 ft->status = FILESTATUS_NONE;
1439 free_slots = 0; 1547 --friendcon->num_sending_files;
1440 } else {
1441 free_slots -= ft->slots_allocated;
1442 } 1548 }
1549
1550 // Decrease free slots by the number of slots this FT uses.
1551 *free_slots = max_s32(0, (int32_t) * free_slots - ft->slots_allocated);
1443 } 1552 }
1444 1553
1445 while (ft->status == FILESTATUS_TRANSFERRING && (ft->paused == FILE_PAUSE_NOT)) { 1554 if (ft->status == FILESTATUS_TRANSFERRING && ft->paused == FILE_PAUSE_NOT) {
1446 if (max_speed_reached(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, 1555 if (max_speed_reached(m->net_crypto, friend_connection_crypt_connection_id(
1447 m->friendlist[friendnumber].friendcon_id))) { 1556 m->fr_c, friendcon->friendcon_id))) {
1448 free_slots = 0; 1557 *free_slots = 0;
1449 } 1558 }
1450 1559
1451 if (free_slots == 0) 1560 if (*free_slots == 0) {
1452 break; 1561 continue;
1453 1562 }
1454 uint16_t length = MAX_FILE_DATA_SIZE;
1455 1563
1456 if (ft->size == 0) { 1564 if (ft->size == 0) {
1457 /* Send 0 data to friend if file is 0 length. */ 1565 /* Send 0 data to friend if file is 0 length. */
1458 file_data(m, friendnumber, i, 0, 0, 0); 1566 file_data(m, friendnumber, i, 0, nullptr, 0);
1459 break; 1567 continue;
1460 } 1568 }
1461 1569
1462 if (ft->size == ft->requested) { 1570 if (ft->size == ft->requested) {
1463 break; 1571 // This file transfer is done.
1464 } 1572 continue;
1465
1466 if (ft->size - ft->requested < length) {
1467 length = ft->size - ft->requested;
1468 } 1573 }
1469 1574
1470 ++ft->slots_allocated; 1575 // Allocate 1 slot to this file transfer.
1576 ft->slots_allocated++;
1471 1577
1472 uint64_t position = ft->requested; 1578 const uint16_t length = min_u64(ft->size - ft->requested, MAX_FILE_DATA_SIZE);
1579 const uint64_t position = ft->requested;
1473 ft->requested += length; 1580 ft->requested += length;
1474 1581
1475 if (m->file_reqchunk) 1582 if (m->file_reqchunk) {
1476 (*m->file_reqchunk)(m, friendnumber, i, position, length, m->file_reqchunk_userdata); 1583 m->file_reqchunk(m, friendnumber, i, position, length, userdata);
1584 }
1477 1585
1478 --free_slots; 1586 // The allocated slot is no longer free.
1587 --*free_slots;
1588 }
1479 1589
1590 if (num == 0) {
1591 continue;
1480 } 1592 }
1593 }
1481 1594
1482 if (num == 0) 1595 return any_active_fts;
1483 break; 1596}
1597
1598static void do_reqchunk_filecb(Messenger *m, int32_t friendnumber, void *userdata)
1599{
1600 // We're not currently doing any file transfers.
1601 if (m->friendlist[friendnumber].num_sending_files == 0) {
1602 return;
1603 }
1604
1605 // The number of packet slots left in the sendbuffer.
1606 // This is a per friend count (CRYPTO_PACKET_BUFFER_SIZE).
1607 uint32_t free_slots = crypto_num_free_sendqueue_slots(
1608 m->net_crypto,
1609 friend_connection_crypt_connection_id(
1610 m->fr_c,
1611 m->friendlist[friendnumber].friendcon_id));
1612
1613 // We keep MIN_SLOTS_FREE slots free for other packets, otherwise file
1614 // transfers might block other traffic for a long time.
1615 free_slots = max_s32(0, (int32_t)free_slots - MIN_SLOTS_FREE);
1616
1617 bool any_active_fts = true;
1618 uint32_t loop_counter = 0;
1619 // Maximum number of outer loops below. If the client doesn't send file
1620 // chunks from within the chunk request callback handler, we never realise
1621 // that the file transfer has finished and may end up in an infinite loop.
1622 //
1623 // TODO(zoff99): Fix this to exit the loop properly when we're done
1624 // requesting all chunks for all file transfers.
1625 const uint32_t MAX_FT_LOOPS = 16;
1626
1627 while (((free_slots > 0) || loop_counter == 0) && any_active_fts && (loop_counter < MAX_FT_LOOPS)) {
1628 any_active_fts = do_all_filetransfers(m, friendnumber, userdata, &free_slots);
1629 loop_counter++;
1484 } 1630 }
1485} 1631}
1486 1632
1633
1487/* Run this when the friend disconnects. 1634/* Run this when the friend disconnects.
1488 * Kill all current file transfers. 1635 * Kill all current file transfers.
1489 */ 1636 */
1490static void break_files(const Messenger *m, int32_t friendnumber) 1637static void break_files(const Messenger *m, int32_t friendnumber)
1491{ 1638{
1492 uint32_t i; 1639 // TODO(irungentoo): Inform the client which file transfers get killed with a callback?
1493 1640 for (uint32_t i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) {
1494 //TODO: Inform the client which file transfers get killed with a callback? 1641 if (m->friendlist[friendnumber].file_sending[i].status != FILESTATUS_NONE) {
1495 for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) {
1496 if (m->friendlist[friendnumber].file_sending[i].status != FILESTATUS_NONE)
1497 m->friendlist[friendnumber].file_sending[i].status = FILESTATUS_NONE; 1642 m->friendlist[friendnumber].file_sending[i].status = FILESTATUS_NONE;
1643 }
1498 1644
1499 if (m->friendlist[friendnumber].file_receiving[i].status != FILESTATUS_NONE) 1645 if (m->friendlist[friendnumber].file_receiving[i].status != FILESTATUS_NONE) {
1500 m->friendlist[friendnumber].file_receiving[i].status = FILESTATUS_NONE; 1646 m->friendlist[friendnumber].file_receiving[i].status = FILESTATUS_NONE;
1647 }
1501 } 1648 }
1502} 1649}
1503 1650
1504/* return -1 on failure, 0 on success. 1651static struct File_Transfers *get_file_transfer(uint8_t receive_send, uint8_t filenumber,
1505 */ 1652 uint32_t *real_filenumber, Friend *sender)
1506static int handle_filecontrol(Messenger *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber,
1507 uint8_t control_type, uint8_t *data, uint16_t length)
1508{ 1653{
1509 if (receive_send > 1)
1510 return -1;
1511
1512 if (control_type > FILECONTROL_SEEK)
1513 return -1;
1514
1515 uint32_t real_filenumber = filenumber;
1516 struct File_Transfers *ft; 1654 struct File_Transfers *ft;
1517 1655
1518 if (receive_send == 0) { 1656 if (receive_send == 0) {
1519 real_filenumber += 1; 1657 *real_filenumber = (filenumber + 1) << 16;
1520 real_filenumber <<= 16; 1658 ft = &sender->file_receiving[filenumber];
1521 ft = &m->friendlist[friendnumber].file_receiving[filenumber];
1522 } else { 1659 } else {
1523 ft = &m->friendlist[friendnumber].file_sending[filenumber]; 1660 *real_filenumber = filenumber;
1661 ft = &sender->file_sending[filenumber];
1524 } 1662 }
1525 1663
1526 if (ft->status == FILESTATUS_NONE) { 1664 if (ft->status == FILESTATUS_NONE) {
1527 /* File transfer doesn't exist, tell the other to kill it. */ 1665 return nullptr;
1528 send_file_control_packet(m, friendnumber, !receive_send, filenumber, FILECONTROL_KILL, 0, 0); 1666 }
1667
1668 return ft;
1669}
1670
1671/* return -1 on failure, 0 on success.
1672 */
1673static int handle_filecontrol(Messenger *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber,
1674 uint8_t control_type, const uint8_t *data, uint16_t length, void *userdata)
1675{
1676 if (receive_send > 1) {
1677 LOGGER_DEBUG(m->log, "file control (friend %d, file %d): receive_send value is invalid (should be 0 or 1): %d",
1678 friendnumber, filenumber, receive_send);
1529 return -1; 1679 return -1;
1530 } 1680 }
1531 1681
1532 if (control_type == FILECONTROL_ACCEPT) { 1682 uint32_t real_filenumber;
1533 if (receive_send && ft->status == FILESTATUS_NOT_ACCEPTED) { 1683 struct File_Transfers *ft = get_file_transfer(receive_send, filenumber, &real_filenumber, &m->friendlist[friendnumber]);
1534 ft->status = FILESTATUS_TRANSFERRING; 1684
1535 } else { 1685 if (ft == nullptr) {
1536 if (ft->paused & FILE_PAUSE_OTHER) { 1686 LOGGER_DEBUG(m->log, "file control (friend %d, file %d): file transfer does not exist; telling the other to kill it",
1537 ft->paused ^= FILE_PAUSE_OTHER; 1687 friendnumber, filenumber);
1688 send_file_control_packet(m, friendnumber, !receive_send, filenumber, FILECONTROL_KILL, nullptr, 0);
1689 return -1;
1690 }
1691
1692 switch (control_type) {
1693 case FILECONTROL_ACCEPT: {
1694 if (receive_send && ft->status == FILESTATUS_NOT_ACCEPTED) {
1695 ft->status = FILESTATUS_TRANSFERRING;
1538 } else { 1696 } else {
1539 return -1; 1697 if (ft->paused & FILE_PAUSE_OTHER) {
1698 ft->paused ^= FILE_PAUSE_OTHER;
1699 } else {
1700 LOGGER_DEBUG(m->log, "file control (friend %d, file %d): friend told us to resume file transfer that wasn't paused",
1701 friendnumber, filenumber);
1702 return -1;
1703 }
1540 } 1704 }
1541 }
1542 1705
1543 if (m->file_filecontrol) 1706 if (m->file_filecontrol) {
1544 (*m->file_filecontrol)(m, friendnumber, real_filenumber, control_type, m->file_filecontrol_userdata); 1707 m->file_filecontrol(m, friendnumber, real_filenumber, control_type, userdata);
1545 } else if (control_type == FILECONTROL_PAUSE) { 1708 }
1546 if ((ft->paused & FILE_PAUSE_OTHER) || ft->status != FILESTATUS_TRANSFERRING) {
1547 return -1;
1548 }
1549 1709
1550 ft->paused |= FILE_PAUSE_OTHER; 1710 return 0;
1711 }
1551 1712
1552 if (m->file_filecontrol) 1713 case FILECONTROL_PAUSE: {
1553 (*m->file_filecontrol)(m, friendnumber, real_filenumber, control_type, m->file_filecontrol_userdata); 1714 if ((ft->paused & FILE_PAUSE_OTHER) || ft->status != FILESTATUS_TRANSFERRING) {
1554 } else if (control_type == FILECONTROL_KILL) { 1715 LOGGER_DEBUG(m->log, "file control (friend %d, file %d): friend told us to pause file transfer that is already paused",
1716 friendnumber, filenumber);
1717 return -1;
1718 }
1555 1719
1556 if (m->file_filecontrol) 1720 ft->paused |= FILE_PAUSE_OTHER;
1557 (*m->file_filecontrol)(m, friendnumber, real_filenumber, control_type, m->file_filecontrol_userdata);
1558 1721
1559 ft->status = FILESTATUS_NONE; 1722 if (m->file_filecontrol) {
1723 m->file_filecontrol(m, friendnumber, real_filenumber, control_type, userdata);
1724 }
1560 1725
1561 if (receive_send) { 1726 return 0;
1562 --m->friendlist[friendnumber].num_sending_files;
1563 } 1727 }
1564 1728
1565 } else if (control_type == FILECONTROL_SEEK) { 1729 case FILECONTROL_KILL: {
1566 uint64_t position; 1730 if (m->file_filecontrol) {
1731 m->file_filecontrol(m, friendnumber, real_filenumber, control_type, userdata);
1732 }
1567 1733
1568 if (length != sizeof(position)) { 1734 ft->status = FILESTATUS_NONE;
1569 return -1;
1570 }
1571 1735
1572 /* seek can only be sent by the receiver to seek before resuming broken transfers. */ 1736 if (receive_send) {
1573 if (ft->status != FILESTATUS_NOT_ACCEPTED || !receive_send) { 1737 --m->friendlist[friendnumber].num_sending_files;
1574 return -1; 1738 }
1739
1740 return 0;
1575 } 1741 }
1576 1742
1577 memcpy(&position, data, sizeof(position)); 1743 case FILECONTROL_SEEK: {
1578 net_to_host((uint8_t *) &position, sizeof(position)); 1744 uint64_t position;
1579 1745
1580 if (position >= ft->size) { 1746 if (length != sizeof(position)) {
1581 return -1; 1747 LOGGER_DEBUG(m->log, "file control (friend %d, file %d): expected payload of length %d, but got %d",
1748 friendnumber, filenumber, (uint32_t)sizeof(position), length);
1749 return -1;
1750 }
1751
1752 /* seek can only be sent by the receiver to seek before resuming broken transfers. */
1753 if (ft->status != FILESTATUS_NOT_ACCEPTED || !receive_send) {
1754 LOGGER_DEBUG(m->log,
1755 "file control (friend %d, file %d): seek was either sent by a sender or by the receiver after accepting",
1756 friendnumber, filenumber);
1757 return -1;
1758 }
1759
1760 memcpy(&position, data, sizeof(position));
1761 net_to_host((uint8_t *) &position, sizeof(position));
1762
1763 if (position >= ft->size) {
1764 LOGGER_DEBUG(m->log,
1765 "file control (friend %d, file %d): seek position %lld exceeds file size %lld",
1766 friendnumber, filenumber, (unsigned long long)position, (unsigned long long)ft->size);
1767 return -1;
1768 }
1769
1770 ft->transferred = ft->requested = position;
1771 return 0;
1582 } 1772 }
1583 1773
1584 ft->transferred = ft->requested = position; 1774 default: {
1585 } else { 1775 LOGGER_DEBUG(m->log, "file control (friend %d, file %d): invalid file control: %d",
1586 return -1; 1776 friendnumber, filenumber, control_type);
1777 return -1;
1778 }
1587 } 1779 }
1588
1589 return 0;
1590} 1780}
1591 1781
1592/**************************************/ 1782/**************************************/
@@ -1612,137 +1802,157 @@ int m_msi_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data,
1612 return write_cryptpacket_id(m, friendnumber, PACKET_ID_MSI, data, length, 0); 1802 return write_cryptpacket_id(m, friendnumber, PACKET_ID_MSI, data, length, 0);
1613} 1803}
1614 1804
1615static int handle_custom_lossy_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length) 1805static int m_handle_custom_lossy_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length,
1806 void *userdata)
1616{ 1807{
1617 Messenger *m = object; 1808 Messenger *m = (Messenger *)object;
1618 1809
1619 if (friend_not_valid(m, friend_num)) 1810 if (friend_not_valid(m, friend_num)) {
1620 return 1; 1811 return 1;
1812 }
1621 1813
1622 if (packet[0] < (PACKET_ID_LOSSY_RANGE_START + PACKET_LOSSY_AV_RESERVED)) { 1814 if (packet[0] < (PACKET_ID_LOSSY_RANGE_START + PACKET_LOSSY_AV_RESERVED)) {
1623 if (m->friendlist[friend_num].lossy_rtp_packethandlers[packet[0] % PACKET_LOSSY_AV_RESERVED].function) 1815 if (m->friendlist[friend_num].lossy_rtp_packethandlers[packet[0] % PACKET_LOSSY_AV_RESERVED].function) {
1624 return m->friendlist[friend_num].lossy_rtp_packethandlers[packet[0] % PACKET_LOSSY_AV_RESERVED].function( 1816 return m->friendlist[friend_num].lossy_rtp_packethandlers[packet[0] % PACKET_LOSSY_AV_RESERVED].function(
1625 m, friend_num, packet, length, m->friendlist[friend_num].lossy_rtp_packethandlers[packet[0] % 1817 m, friend_num, packet, length, m->friendlist[friend_num].lossy_rtp_packethandlers[packet[0] %
1626 PACKET_LOSSY_AV_RESERVED].object); 1818 PACKET_LOSSY_AV_RESERVED].object);
1819 }
1627 1820
1628 return 1; 1821 return 1;
1629 } 1822 }
1630 1823
1631 if (m->lossy_packethandler) 1824 if (m->lossy_packethandler) {
1632 m->lossy_packethandler(m, friend_num, packet, length, m->lossy_packethandler_userdata); 1825 m->lossy_packethandler(m, friend_num, packet, length, userdata);
1826 }
1633 1827
1634 return 1; 1828 return 1;
1635} 1829}
1636 1830
1637void custom_lossy_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m, 1831void custom_lossy_packet_registerhandler(Messenger *m, void (*lossy_packethandler)(Messenger *m,
1638 uint32_t friendnumber, const uint8_t *data, size_t len, void *object), void *object) 1832 uint32_t friendnumber, const uint8_t *data, size_t len, void *object))
1639{ 1833{
1640 m->lossy_packethandler = packet_handler_callback; 1834 m->lossy_packethandler = lossy_packethandler;
1641 m->lossy_packethandler_userdata = object;
1642} 1835}
1643 1836
1644int m_callback_rtp_packet(Messenger *m, int32_t friendnumber, uint8_t byte, int (*packet_handler_callback)(Messenger *m, 1837int m_callback_rtp_packet(Messenger *m, int32_t friendnumber, uint8_t byte, int (*function)(Messenger *m,
1645 uint32_t friendnumber, const uint8_t *data, uint16_t len, void *object), void *object) 1838 uint32_t friendnumber, const uint8_t *data, uint16_t len, void *object), void *object)
1646{ 1839{
1647 if (friend_not_valid(m, friendnumber)) 1840 if (friend_not_valid(m, friendnumber)) {
1648 return -1; 1841 return -1;
1842 }
1649 1843
1650 if (byte < PACKET_ID_LOSSY_RANGE_START) 1844 if (byte < PACKET_ID_LOSSY_RANGE_START) {
1651 return -1; 1845 return -1;
1846 }
1652 1847
1653 if (byte >= (PACKET_ID_LOSSY_RANGE_START + PACKET_LOSSY_AV_RESERVED)) 1848 if (byte >= (PACKET_ID_LOSSY_RANGE_START + PACKET_LOSSY_AV_RESERVED)) {
1654 return -1; 1849 return -1;
1850 }
1655 1851
1656 m->friendlist[friendnumber].lossy_rtp_packethandlers[byte % PACKET_LOSSY_AV_RESERVED].function = 1852 m->friendlist[friendnumber].lossy_rtp_packethandlers[byte % PACKET_LOSSY_AV_RESERVED].function = function;
1657 packet_handler_callback;
1658 m->friendlist[friendnumber].lossy_rtp_packethandlers[byte % PACKET_LOSSY_AV_RESERVED].object = object; 1853 m->friendlist[friendnumber].lossy_rtp_packethandlers[byte % PACKET_LOSSY_AV_RESERVED].object = object;
1659 return 0; 1854 return 0;
1660} 1855}
1661 1856
1662 1857
1663int send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length) 1858int m_send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length)
1664{ 1859{
1665 if (friend_not_valid(m, friendnumber)) 1860 if (friend_not_valid(m, friendnumber)) {
1666 return -1; 1861 return -1;
1862 }
1667 1863
1668 if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) 1864 if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) {
1669 return -2; 1865 return -2;
1866 }
1670 1867
1671 if (data[0] < PACKET_ID_LOSSY_RANGE_START) 1868 if (data[0] < PACKET_ID_LOSSY_RANGE_START) {
1672 return -3; 1869 return -3;
1870 }
1673 1871
1674 if (data[0] >= (PACKET_ID_LOSSY_RANGE_START + PACKET_ID_LOSSY_RANGE_SIZE)) 1872 if (data[0] >= (PACKET_ID_LOSSY_RANGE_START + PACKET_ID_LOSSY_RANGE_SIZE)) {
1675 return -3; 1873 return -3;
1874 }
1676 1875
1677 if (m->friendlist[friendnumber].status != FRIEND_ONLINE) 1876 if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
1678 return -4; 1877 return -4;
1878 }
1679 1879
1680 if (send_lossy_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, 1880 if (send_lossy_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
1681 m->friendlist[friendnumber].friendcon_id), data, length) == -1) { 1881 m->friendlist[friendnumber].friendcon_id), data, length) == -1) {
1682 return -5; 1882 return -5;
1683 } else {
1684 return 0;
1685 } 1883 }
1884
1885 return 0;
1686} 1886}
1687 1887
1688static int handle_custom_lossless_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length) 1888static int handle_custom_lossless_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length,
1889 void *userdata)
1689{ 1890{
1690 Messenger *m = object; 1891 Messenger *m = (Messenger *)object;
1691 1892
1692 if (friend_not_valid(m, friend_num)) 1893 if (friend_not_valid(m, friend_num)) {
1693 return -1; 1894 return -1;
1895 }
1694 1896
1695 if (packet[0] < PACKET_ID_LOSSLESS_RANGE_START) 1897 if (packet[0] < PACKET_ID_LOSSLESS_RANGE_START) {
1696 return -1; 1898 return -1;
1899 }
1697 1900
1698 if (packet[0] >= (PACKET_ID_LOSSLESS_RANGE_START + PACKET_ID_LOSSLESS_RANGE_SIZE)) 1901 if (packet[0] >= (PACKET_ID_LOSSLESS_RANGE_START + PACKET_ID_LOSSLESS_RANGE_SIZE)) {
1699 return -1; 1902 return -1;
1903 }
1700 1904
1701 if (m->lossless_packethandler) 1905 if (m->lossless_packethandler) {
1702 m->lossless_packethandler(m, friend_num, packet, length, m->lossless_packethandler_userdata); 1906 m->lossless_packethandler(m, friend_num, packet, length, userdata);
1907 }
1703 1908
1704 return 1; 1909 return 1;
1705} 1910}
1706 1911
1707void custom_lossless_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m, 1912void custom_lossless_packet_registerhandler(Messenger *m, void (*lossless_packethandler)(Messenger *m,
1708 uint32_t friendnumber, const uint8_t *data, size_t len, void *object), void *object) 1913 uint32_t friendnumber, const uint8_t *data, size_t len, void *object))
1709{ 1914{
1710 m->lossless_packethandler = packet_handler_callback; 1915 m->lossless_packethandler = lossless_packethandler;
1711 m->lossless_packethandler_userdata = object;
1712} 1916}
1713 1917
1714int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length) 1918int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length)
1715{ 1919{
1716 if (friend_not_valid(m, friendnumber)) 1920 if (friend_not_valid(m, friendnumber)) {
1717 return -1; 1921 return -1;
1922 }
1718 1923
1719 if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) 1924 if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) {
1720 return -2; 1925 return -2;
1926 }
1721 1927
1722 if (data[0] < PACKET_ID_LOSSLESS_RANGE_START) 1928 if (data[0] < PACKET_ID_LOSSLESS_RANGE_START) {
1723 return -3; 1929 return -3;
1930 }
1724 1931
1725 if (data[0] >= (PACKET_ID_LOSSLESS_RANGE_START + PACKET_ID_LOSSLESS_RANGE_SIZE)) 1932 if (data[0] >= (PACKET_ID_LOSSLESS_RANGE_START + PACKET_ID_LOSSLESS_RANGE_SIZE)) {
1726 return -3; 1933 return -3;
1934 }
1727 1935
1728 if (m->friendlist[friendnumber].status != FRIEND_ONLINE) 1936 if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
1729 return -4; 1937 return -4;
1938 }
1730 1939
1731 if (write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, 1940 if (write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
1732 m->friendlist[friendnumber].friendcon_id), data, length, 1) == -1) { 1941 m->friendlist[friendnumber].friendcon_id), data, length, 1) == -1) {
1733 return -5; 1942 return -5;
1734 } else {
1735 return 0;
1736 } 1943 }
1944
1945 return 0;
1737} 1946}
1738 1947
1739/* Function to filter out some friend requests*/ 1948/* Function to filter out some friend requests*/
1740static int friend_already_added(const uint8_t *real_pk, void *data) 1949static int friend_already_added(const uint8_t *real_pk, void *data)
1741{ 1950{
1742 const Messenger *m = data; 1951 const Messenger *m = (const Messenger *)data;
1743 1952
1744 if (getfriend_id(m, real_pk) == -1) 1953 if (getfriend_id(m, real_pk) == -1) {
1745 return 0; 1954 return 0;
1955 }
1746 1956
1747 return -1; 1957 return -1;
1748} 1958}
@@ -1750,56 +1960,84 @@ static int friend_already_added(const uint8_t *real_pk, void *data)
1750/* Run this at startup. */ 1960/* Run this at startup. */
1751Messenger *new_messenger(Messenger_Options *options, unsigned int *error) 1961Messenger *new_messenger(Messenger_Options *options, unsigned int *error)
1752{ 1962{
1753 Messenger *m = calloc(1, sizeof(Messenger)); 1963 if (!options) {
1964 return nullptr;
1965 }
1754 1966
1755 if (error) 1967 if (error) {
1756 *error = MESSENGER_ERROR_OTHER; 1968 *error = MESSENGER_ERROR_OTHER;
1969 }
1970
1971 Messenger *m = (Messenger *)calloc(1, sizeof(Messenger));
1757 1972
1758 if ( ! m ) 1973 if (!m) {
1759 return NULL; 1974 return nullptr;
1975 }
1976
1977 m->fr = friendreq_new();
1978
1979 if (!m->fr) {
1980 free(m);
1981 return nullptr;
1982 }
1983
1984 m->log = logger_new();
1985
1986 if (m->log == nullptr) {
1987 friendreq_kill(m->fr);
1988 free(m);
1989 return nullptr;
1990 }
1991
1992 logger_callback_log(m->log, options->log_callback, m, options->log_user_data);
1760 1993
1761 unsigned int net_err = 0; 1994 unsigned int net_err = 0;
1762 1995
1763 if (options->udp_disabled) { 1996 if (options->udp_disabled) {
1764 /* this is the easiest way to completely disable UDP without changing too much code. */ 1997 m->net = new_networking_no_udp(m->log);
1765 m->net = calloc(1, sizeof(Networking_Core));
1766 } else { 1998 } else {
1767 IP ip; 1999 IP ip;
1768 ip_init(&ip, options->ipv6enabled); 2000 ip_init(&ip, options->ipv6enabled);
1769 m->net = new_networking_ex(ip, options->port_range[0], options->port_range[1], &net_err); 2001 m->net = new_networking_ex(m->log, ip, options->port_range[0], options->port_range[1], &net_err);
1770 } 2002 }
1771 2003
1772 if (m->net == NULL) { 2004 if (m->net == nullptr) {
2005 friendreq_kill(m->fr);
2006 logger_kill(m->log);
1773 free(m); 2007 free(m);
1774 2008
1775 if (error && net_err == 1) { 2009 if (error && net_err == 1) {
1776 *error = MESSENGER_ERROR_PORT; 2010 *error = MESSENGER_ERROR_PORT;
1777 } 2011 }
1778 2012
1779 return NULL; 2013 return nullptr;
1780 } 2014 }
1781 2015
1782 m->dht = new_DHT(m->net); 2016 m->dht = new_DHT(m->log, m->net, options->hole_punching_enabled);
1783 2017
1784 if (m->dht == NULL) { 2018 if (m->dht == nullptr) {
1785 kill_networking(m->net); 2019 kill_networking(m->net);
2020 friendreq_kill(m->fr);
2021 logger_kill(m->log);
1786 free(m); 2022 free(m);
1787 return NULL; 2023 return nullptr;
1788 } 2024 }
1789 2025
1790 m->net_crypto = new_net_crypto(m->dht, &options->proxy_info); 2026 m->net_crypto = new_net_crypto(m->log, m->dht, &options->proxy_info);
1791 2027
1792 if (m->net_crypto == NULL) { 2028 if (m->net_crypto == nullptr) {
1793 kill_networking(m->net); 2029 kill_networking(m->net);
1794 kill_DHT(m->dht); 2030 kill_DHT(m->dht);
2031 friendreq_kill(m->fr);
2032 logger_kill(m->log);
1795 free(m); 2033 free(m);
1796 return NULL; 2034 return nullptr;
1797 } 2035 }
1798 2036
1799 m->onion = new_onion(m->dht); 2037 m->onion = new_onion(m->dht);
1800 m->onion_a = new_onion_announce(m->dht); 2038 m->onion_a = new_onion_announce(m->dht);
1801 m->onion_c = new_onion_client(m->net_crypto); 2039 m->onion_c = new_onion_client(m->net_crypto);
1802 m->fr_c = new_friend_connections(m->onion_c); 2040 m->fr_c = new_friend_connections(m->onion_c, options->local_discovery_enabled);
1803 2041
1804 if (!(m->onion && m->onion_a && m->onion_c)) { 2042 if (!(m->onion && m->onion_a && m->onion_c)) {
1805 kill_friend_connections(m->fr_c); 2043 kill_friend_connections(m->fr_c);
@@ -1809,14 +2047,17 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)
1809 kill_net_crypto(m->net_crypto); 2047 kill_net_crypto(m->net_crypto);
1810 kill_DHT(m->dht); 2048 kill_DHT(m->dht);
1811 kill_networking(m->net); 2049 kill_networking(m->net);
2050 friendreq_kill(m->fr);
2051 logger_kill(m->log);
1812 free(m); 2052 free(m);
1813 return NULL; 2053 return nullptr;
1814 } 2054 }
1815 2055
1816 if (options->tcp_server_port) { 2056 if (options->tcp_server_port) {
1817 m->tcp_server = new_TCP_server(options->ipv6enabled, 1, &options->tcp_server_port, m->dht->self_secret_key, m->onion); 2057 m->tcp_server = new_TCP_server(options->ipv6enabled, 1, &options->tcp_server_port, dht_get_self_secret_key(m->dht),
2058 m->onion);
1818 2059
1819 if (m->tcp_server == NULL) { 2060 if (m->tcp_server == nullptr) {
1820 kill_friend_connections(m->fr_c); 2061 kill_friend_connections(m->fr_c);
1821 kill_onion(m->onion); 2062 kill_onion(m->onion);
1822 kill_onion_announce(m->onion_a); 2063 kill_onion_announce(m->onion_a);
@@ -1824,22 +2065,28 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)
1824 kill_net_crypto(m->net_crypto); 2065 kill_net_crypto(m->net_crypto);
1825 kill_DHT(m->dht); 2066 kill_DHT(m->dht);
1826 kill_networking(m->net); 2067 kill_networking(m->net);
2068 friendreq_kill(m->fr);
2069 logger_kill(m->log);
1827 free(m); 2070 free(m);
1828 2071
1829 if (error) 2072 if (error) {
1830 *error = MESSENGER_ERROR_TCP_SERVER; 2073 *error = MESSENGER_ERROR_TCP_SERVER;
2074 }
1831 2075
1832 return NULL; 2076 return nullptr;
1833 } 2077 }
1834 } 2078 }
1835 2079
1836 m->options = *options; 2080 m->options = *options;
1837 friendreq_init(&(m->fr), m->fr_c); 2081 friendreq_init(m->fr, m->fr_c);
1838 set_nospam(&(m->fr), random_int()); 2082 set_nospam(m->fr, random_u32());
1839 set_filter_function(&(m->fr), &friend_already_added, m); 2083 set_filter_function(m->fr, &friend_already_added, m);
1840 2084
1841 if (error) 2085 m->lastdump = 0;
2086
2087 if (error) {
1842 *error = MESSENGER_ERROR_NONE; 2088 *error = MESSENGER_ERROR_NONE;
2089 }
1843 2090
1844 return m; 2091 return m;
1845} 2092}
@@ -1847,8 +2094,9 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)
1847/* Run this before closing shop. */ 2094/* Run this before closing shop. */
1848void kill_messenger(Messenger *m) 2095void kill_messenger(Messenger *m)
1849{ 2096{
1850 if (!m) 2097 if (!m) {
1851 return; 2098 return;
2099 }
1852 2100
1853 uint32_t i; 2101 uint32_t i;
1854 2102
@@ -1868,7 +2116,9 @@ void kill_messenger(Messenger *m)
1868 clear_receipts(m, i); 2116 clear_receipts(m, i);
1869 } 2117 }
1870 2118
2119 logger_kill(m->log);
1871 free(m->friendlist); 2120 free(m->friendlist);
2121 friendreq_kill(m->fr);
1872 free(m); 2122 free(m);
1873} 2123}
1874 2124
@@ -1877,12 +2127,12 @@ void kill_messenger(Messenger *m)
1877 * i: friendlist index of the timed-out friend 2127 * i: friendlist index of the timed-out friend
1878 * t: time 2128 * t: time
1879 */ 2129 */
1880static void check_friend_request_timed_out(Messenger *m, uint32_t i, uint64_t t) 2130static void check_friend_request_timed_out(Messenger *m, uint32_t i, uint64_t t, void *userdata)
1881{ 2131{
1882 Friend *f = &m->friendlist[i]; 2132 Friend *f = &m->friendlist[i];
1883 2133
1884 if (f->friendrequest_lastsent + f->friendrequest_timeout < t) { 2134 if (f->friendrequest_lastsent + f->friendrequest_timeout < t) {
1885 set_friend_status(m, i, FRIEND_ADDED); 2135 set_friend_status(m, i, FRIEND_ADDED, userdata);
1886 /* Double the default timeout every time if friendrequest is assumed 2136 /* Double the default timeout every time if friendrequest is assumed
1887 * to have been sent unsuccessfully. 2137 * to have been sent unsuccessfully.
1888 */ 2138 */
@@ -1890,34 +2140,35 @@ static void check_friend_request_timed_out(Messenger *m, uint32_t i, uint64_t t)
1890 } 2140 }
1891} 2141}
1892 2142
1893static int handle_status(void *object, int i, uint8_t status) 2143static int m_handle_status(void *object, int i, uint8_t status, void *userdata)
1894{ 2144{
1895 Messenger *m = object; 2145 Messenger *m = (Messenger *)object;
1896 2146
1897 if (status) { /* Went online. */ 2147 if (status) { /* Went online. */
1898 send_online_packet(m, i); 2148 send_online_packet(m, i);
1899 } else { /* Went offline. */ 2149 } else { /* Went offline. */
1900 if (m->friendlist[i].status == FRIEND_ONLINE) { 2150 if (m->friendlist[i].status == FRIEND_ONLINE) {
1901 set_friend_status(m, i, FRIEND_CONFIRMED); 2151 set_friend_status(m, i, FRIEND_CONFIRMED, userdata);
1902 } 2152 }
1903 } 2153 }
1904 2154
1905 return 0; 2155 return 0;
1906} 2156}
1907 2157
1908static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) 2158static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t len, void *userdata)
1909{ 2159{
1910 if (len == 0) 2160 if (len == 0) {
1911 return -1; 2161 return -1;
2162 }
1912 2163
1913 Messenger *m = object; 2164 Messenger *m = (Messenger *)object;
1914 uint8_t packet_id = temp[0]; 2165 uint8_t packet_id = temp[0];
1915 uint8_t *data = temp + 1; 2166 const uint8_t *data = temp + 1;
1916 uint32_t data_length = len - 1; 2167 uint32_t data_length = len - 1;
1917 2168
1918 if (m->friendlist[i].status != FRIEND_ONLINE) { 2169 if (m->friendlist[i].status != FRIEND_ONLINE) {
1919 if (packet_id == PACKET_ID_ONLINE && len == 1) { 2170 if (packet_id == PACKET_ID_ONLINE && len == 1) {
1920 set_friend_status(m, i, FRIEND_ONLINE); 2171 set_friend_status(m, i, FRIEND_ONLINE, userdata);
1921 send_online_packet(m, i); 2172 send_online_packet(m, i);
1922 } else { 2173 } else {
1923 return -1; 2174 return -1;
@@ -1926,25 +2177,28 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
1926 2177
1927 switch (packet_id) { 2178 switch (packet_id) {
1928 case PACKET_ID_OFFLINE: { 2179 case PACKET_ID_OFFLINE: {
1929 if (data_length != 0) 2180 if (data_length != 0) {
1930 break; 2181 break;
2182 }
1931 2183
1932 set_friend_status(m, i, FRIEND_CONFIRMED); 2184 set_friend_status(m, i, FRIEND_CONFIRMED, userdata);
1933 break; 2185 break;
1934 } 2186 }
1935 2187
1936 case PACKET_ID_NICKNAME: { 2188 case PACKET_ID_NICKNAME: {
1937 if (data_length > MAX_NAME_LENGTH) 2189 if (data_length > MAX_NAME_LENGTH) {
1938 break; 2190 break;
2191 }
1939 2192
1940 /* Make sure the NULL terminator is present. */ 2193 /* Make sure the NULL terminator is present. */
1941 uint8_t data_terminated[data_length + 1]; 2194 VLA(uint8_t, data_terminated, data_length + 1);
1942 memcpy(data_terminated, data, data_length); 2195 memcpy(data_terminated, data, data_length);
1943 data_terminated[data_length] = 0; 2196 data_terminated[data_length] = 0;
1944 2197
1945 /* inform of namechange before we overwrite the old name */ 2198 /* inform of namechange before we overwrite the old name */
1946 if (m->friend_namechange) 2199 if (m->friend_namechange) {
1947 m->friend_namechange(m, i, data_terminated, data_length, m->friend_namechange_userdata); 2200 m->friend_namechange(m, i, data_terminated, data_length, userdata);
2201 }
1948 2202
1949 memcpy(m->friendlist[i].name, data_terminated, data_length); 2203 memcpy(m->friendlist[i].name, data_terminated, data_length);
1950 m->friendlist[i].name_length = data_length; 2204 m->friendlist[i].name_length = data_length;
@@ -1953,78 +2207,88 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
1953 } 2207 }
1954 2208
1955 case PACKET_ID_STATUSMESSAGE: { 2209 case PACKET_ID_STATUSMESSAGE: {
1956 if (data_length > MAX_STATUSMESSAGE_LENGTH) 2210 if (data_length > MAX_STATUSMESSAGE_LENGTH) {
1957 break; 2211 break;
2212 }
1958 2213
1959 /* Make sure the NULL terminator is present. */ 2214 /* Make sure the NULL terminator is present. */
1960 uint8_t data_terminated[data_length + 1]; 2215 VLA(uint8_t, data_terminated, data_length + 1);
1961 memcpy(data_terminated, data, data_length); 2216 memcpy(data_terminated, data, data_length);
1962 data_terminated[data_length] = 0; 2217 data_terminated[data_length] = 0;
1963 2218
1964 if (m->friend_statusmessagechange) 2219 if (m->friend_statusmessagechange) {
1965 m->friend_statusmessagechange(m, i, data_terminated, data_length, 2220 m->friend_statusmessagechange(m, i, data_terminated, data_length, userdata);
1966 m->friend_statusmessagechange_userdata); 2221 }
1967 2222
1968 set_friend_statusmessage(m, i, data_terminated, data_length); 2223 set_friend_statusmessage(m, i, data_terminated, data_length);
1969 break; 2224 break;
1970 } 2225 }
1971 2226
1972 case PACKET_ID_USERSTATUS: { 2227 case PACKET_ID_USERSTATUS: {
1973 if (data_length != 1) 2228 if (data_length != 1) {
1974 break; 2229 break;
2230 }
1975 2231
1976 USERSTATUS status = data[0]; 2232 USERSTATUS status = (USERSTATUS)data[0];
1977 2233
1978 if (status >= USERSTATUS_INVALID) 2234 if (status >= USERSTATUS_INVALID) {
1979 break; 2235 break;
2236 }
1980 2237
1981 if (m->friend_userstatuschange) 2238 if (m->friend_userstatuschange) {
1982 m->friend_userstatuschange(m, i, status, m->friend_userstatuschange_userdata); 2239 m->friend_userstatuschange(m, i, status, userdata);
2240 }
1983 2241
1984 set_friend_userstatus(m, i, status); 2242 set_friend_userstatus(m, i, status);
1985 break; 2243 break;
1986 } 2244 }
1987 2245
1988 case PACKET_ID_TYPING: { 2246 case PACKET_ID_TYPING: {
1989 if (data_length != 1) 2247 if (data_length != 1) {
1990 break; 2248 break;
2249 }
1991 2250
1992 _Bool typing = !!data[0]; 2251 bool typing = !!data[0];
1993 2252
1994 set_friend_typing(m, i, typing); 2253 set_friend_typing(m, i, typing);
1995 2254
1996 if (m->friend_typingchange) 2255 if (m->friend_typingchange) {
1997 m->friend_typingchange(m, i, typing, m->friend_typingchange_userdata); 2256 m->friend_typingchange(m, i, typing, userdata);
2257 }
1998 2258
1999 break; 2259 break;
2000 } 2260 }
2001 2261
2002 case PACKET_ID_MESSAGE: 2262 case PACKET_ID_MESSAGE: // fall-through
2003 case PACKET_ID_ACTION: { 2263 case PACKET_ID_ACTION: {
2004 if (data_length == 0) 2264 if (data_length == 0) {
2005 break; 2265 break;
2266 }
2006 2267
2007 const uint8_t *message = data; 2268 const uint8_t *message = data;
2008 uint16_t message_length = data_length; 2269 uint16_t message_length = data_length;
2009 2270
2010 /* Make sure the NULL terminator is present. */ 2271 /* Make sure the NULL terminator is present. */
2011 uint8_t message_terminated[message_length + 1]; 2272 VLA(uint8_t, message_terminated, message_length + 1);
2012 memcpy(message_terminated, message, message_length); 2273 memcpy(message_terminated, message, message_length);
2013 message_terminated[message_length] = 0; 2274 message_terminated[message_length] = 0;
2014 uint8_t type = packet_id - PACKET_ID_MESSAGE; 2275 uint8_t type = packet_id - PACKET_ID_MESSAGE;
2015 2276
2016 if (m->friend_message) 2277 if (m->friend_message) {
2017 (*m->friend_message)(m, i, type, message_terminated, message_length, m->friend_message_userdata); 2278 (*m->friend_message)(m, i, type, message_terminated, message_length, userdata);
2279 }
2018 2280
2019 break; 2281 break;
2020 } 2282 }
2021 2283
2022 case PACKET_ID_INVITE_GROUPCHAT: { 2284 case PACKET_ID_INVITE_CONFERENCE: {
2023 if (data_length == 0) 2285 if (data_length == 0) {
2024 break; 2286 break;
2287 }
2025 2288
2026 if (m->group_invite) 2289 if (m->conference_invite) {
2027 (*m->group_invite)(m, i, data, data_length); 2290 (*m->conference_invite)(m, i, data, data_length, userdata);
2291 }
2028 2292
2029 break; 2293 break;
2030 } 2294 }
@@ -2032,30 +2296,38 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
2032 case PACKET_ID_FILE_SENDREQUEST: { 2296 case PACKET_ID_FILE_SENDREQUEST: {
2033 const unsigned int head_length = 1 + sizeof(uint32_t) + sizeof(uint64_t) + FILE_ID_LENGTH; 2297 const unsigned int head_length = 1 + sizeof(uint32_t) + sizeof(uint64_t) + FILE_ID_LENGTH;
2034 2298
2035 if (data_length < head_length) 2299 if (data_length < head_length) {
2036 break; 2300 break;
2301 }
2037 2302
2038 uint8_t filenumber = data[0]; 2303 uint8_t filenumber = data[0];
2039 2304
2040 if (filenumber >= MAX_CONCURRENT_FILE_PIPES) 2305#if UINT8_MAX >= MAX_CONCURRENT_FILE_PIPES
2306
2307 if (filenumber >= MAX_CONCURRENT_FILE_PIPES) {
2041 break; 2308 break;
2309 }
2310
2311#endif
2042 2312
2043 uint64_t filesize; 2313 uint64_t filesize;
2044 uint32_t file_type; 2314 uint32_t file_type;
2045 uint16_t filename_length = data_length - head_length; 2315 uint16_t filename_length = data_length - head_length;
2046 2316
2047 if (filename_length > MAX_FILENAME_LENGTH) 2317 if (filename_length > MAX_FILENAME_LENGTH) {
2048 break; 2318 break;
2319 }
2049 2320
2050 memcpy(&file_type, data + 1, sizeof(file_type)); 2321 memcpy(&file_type, data + 1, sizeof(file_type));
2051 file_type = ntohl(file_type); 2322 file_type = net_ntohl(file_type);
2052 2323
2053 memcpy(&filesize, data + 1 + sizeof(uint32_t), sizeof(filesize)); 2324 memcpy(&filesize, data + 1 + sizeof(uint32_t), sizeof(filesize));
2054 net_to_host((uint8_t *) &filesize, sizeof(filesize)); 2325 net_to_host((uint8_t *) &filesize, sizeof(filesize));
2055 struct File_Transfers *ft = &m->friendlist[i].file_receiving[filenumber]; 2326 struct File_Transfers *ft = &m->friendlist[i].file_receiving[filenumber];
2056 2327
2057 if (ft->status != FILESTATUS_NONE) 2328 if (ft->status != FILESTATUS_NONE) {
2058 break; 2329 break;
2330 }
2059 2331
2060 ft->status = FILESTATUS_NOT_ACCEPTED; 2332 ft->status = FILESTATUS_NOT_ACCEPTED;
2061 ft->size = filesize; 2333 ft->size = filesize;
@@ -2063,8 +2335,8 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
2063 ft->paused = FILE_PAUSE_NOT; 2335 ft->paused = FILE_PAUSE_NOT;
2064 memcpy(ft->id, data + 1 + sizeof(uint32_t) + sizeof(uint64_t), FILE_ID_LENGTH); 2336 memcpy(ft->id, data + 1 + sizeof(uint32_t) + sizeof(uint64_t), FILE_ID_LENGTH);
2065 2337
2066 uint8_t filename_terminated[filename_length + 1]; 2338 VLA(uint8_t, filename_terminated, filename_length + 1);
2067 uint8_t *filename = NULL; 2339 uint8_t *filename = nullptr;
2068 2340
2069 if (filename_length) { 2341 if (filename_length) {
2070 /* Force NULL terminate file name. */ 2342 /* Force NULL terminate file name. */
@@ -2077,53 +2349,70 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
2077 real_filenumber += 1; 2349 real_filenumber += 1;
2078 real_filenumber <<= 16; 2350 real_filenumber <<= 16;
2079 2351
2080 if (m->file_sendrequest) 2352 if (m->file_sendrequest) {
2081 (*m->file_sendrequest)(m, i, real_filenumber, file_type, filesize, filename, filename_length, 2353 (*m->file_sendrequest)(m, i, real_filenumber, file_type, filesize, filename, filename_length,
2082 m->file_sendrequest_userdata); 2354 userdata);
2355 }
2083 2356
2084 break; 2357 break;
2085 } 2358 }
2086 2359
2087 case PACKET_ID_FILE_CONTROL: { 2360 case PACKET_ID_FILE_CONTROL: {
2088 if (data_length < 3) 2361 if (data_length < 3) {
2089 break; 2362 break;
2363 }
2090 2364
2091 uint8_t send_receive = data[0]; 2365 uint8_t send_receive = data[0];
2092 uint8_t filenumber = data[1]; 2366 uint8_t filenumber = data[1];
2093 uint8_t control_type = data[2]; 2367 uint8_t control_type = data[2];
2094 2368
2095 if (filenumber >= MAX_CONCURRENT_FILE_PIPES) 2369#if UINT8_MAX >= MAX_CONCURRENT_FILE_PIPES
2370
2371 if (filenumber >= MAX_CONCURRENT_FILE_PIPES) {
2096 break; 2372 break;
2373 }
2374
2375#endif
2097 2376
2098 if (handle_filecontrol(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3) == -1) 2377 if (handle_filecontrol(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3, userdata) == -1) {
2378 // TODO(iphydf): Do something different here? Right now, this
2379 // check is pointless.
2099 break; 2380 break;
2381 }
2100 2382
2101 break; 2383 break;
2102 } 2384 }
2103 2385
2104 case PACKET_ID_FILE_DATA: { 2386 case PACKET_ID_FILE_DATA: {
2105 if (data_length < 1) 2387 if (data_length < 1) {
2106 break; 2388 break;
2389 }
2107 2390
2108 uint8_t filenumber = data[0]; 2391 uint8_t filenumber = data[0];
2109 2392
2110 if (filenumber >= MAX_CONCURRENT_FILE_PIPES) 2393#if UINT8_MAX >= MAX_CONCURRENT_FILE_PIPES
2394
2395 if (filenumber >= MAX_CONCURRENT_FILE_PIPES) {
2111 break; 2396 break;
2397 }
2398
2399#endif
2112 2400
2113 struct File_Transfers *ft = &m->friendlist[i].file_receiving[filenumber]; 2401 struct File_Transfers *ft = &m->friendlist[i].file_receiving[filenumber];
2114 2402
2115 if (ft->status != FILESTATUS_TRANSFERRING) 2403 if (ft->status != FILESTATUS_TRANSFERRING) {
2116 break; 2404 break;
2405 }
2117 2406
2118 uint64_t position = ft->transferred; 2407 uint64_t position = ft->transferred;
2119 uint32_t real_filenumber = filenumber; 2408 uint32_t real_filenumber = filenumber;
2120 real_filenumber += 1; 2409 real_filenumber += 1;
2121 real_filenumber <<= 16; 2410 real_filenumber <<= 16;
2122 uint16_t file_data_length = (data_length - 1); 2411 uint16_t file_data_length = (data_length - 1);
2123 uint8_t *file_data; 2412 const uint8_t *file_data;
2124 2413
2125 if (file_data_length == 0) { 2414 if (file_data_length == 0) {
2126 file_data = NULL; 2415 file_data = nullptr;
2127 } else { 2416 } else {
2128 file_data = data + 1; 2417 file_data = data + 1;
2129 } 2418 }
@@ -2133,19 +2422,21 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
2133 file_data_length = ft->size - ft->transferred; 2422 file_data_length = ft->size - ft->transferred;
2134 } 2423 }
2135 2424
2136 if (m->file_filedata) 2425 if (m->file_filedata) {
2137 (*m->file_filedata)(m, i, real_filenumber, position, file_data, file_data_length, m->file_filedata_userdata); 2426 (*m->file_filedata)(m, i, real_filenumber, position, file_data, file_data_length, userdata);
2427 }
2138 2428
2139 ft->transferred += file_data_length; 2429 ft->transferred += file_data_length;
2140 2430
2141 if (file_data_length && (ft->transferred >= ft->size || file_data_length != MAX_FILE_DATA_SIZE)) { 2431 if (file_data_length && (ft->transferred >= ft->size || file_data_length != MAX_FILE_DATA_SIZE)) {
2142 file_data_length = 0; 2432 file_data_length = 0;
2143 file_data = NULL; 2433 file_data = nullptr;
2144 position = ft->transferred; 2434 position = ft->transferred;
2145 2435
2146 /* Full file received. */ 2436 /* Full file received. */
2147 if (m->file_filedata) 2437 if (m->file_filedata) {
2148 (*m->file_filedata)(m, i, real_filenumber, position, file_data, file_data_length, m->file_filedata_userdata); 2438 (*m->file_filedata)(m, i, real_filenumber, position, file_data, file_data_length, userdata);
2439 }
2149 } 2440 }
2150 2441
2151 /* Data is zero, filetransfer is over. */ 2442 /* Data is zero, filetransfer is over. */
@@ -2157,17 +2448,19 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
2157 } 2448 }
2158 2449
2159 case PACKET_ID_MSI: { 2450 case PACKET_ID_MSI: {
2160 if (data_length == 0) 2451 if (data_length == 0) {
2161 break; 2452 break;
2453 }
2162 2454
2163 if (m->msi_packet) 2455 if (m->msi_packet) {
2164 (*m->msi_packet)(m, i, data, data_length, m->msi_packet_userdata); 2456 (*m->msi_packet)(m, i, data, data_length, m->msi_packet_userdata);
2457 }
2165 2458
2166 break; 2459 break;
2167 } 2460 }
2168 2461
2169 default: { 2462 default: {
2170 handle_custom_lossless_packet(object, i, temp, len); 2463 handle_custom_lossless_packet(object, i, temp, len, userdata);
2171 break; 2464 break;
2172 } 2465 }
2173 } 2466 }
@@ -2175,7 +2468,7 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
2175 return 0; 2468 return 0;
2176} 2469}
2177 2470
2178void do_friends(Messenger *m) 2471static void do_friends(Messenger *m, void *userdata)
2179{ 2472{
2180 uint32_t i; 2473 uint32_t i;
2181 uint64_t temp_time = unix_time(); 2474 uint64_t temp_time = unix_time();
@@ -2187,7 +2480,7 @@ void do_friends(Messenger *m)
2187 m->friendlist[i].info_size); 2480 m->friendlist[i].info_size);
2188 2481
2189 if (fr >= 0) { 2482 if (fr >= 0) {
2190 set_friend_status(m, i, FRIEND_REQUESTED); 2483 set_friend_status(m, i, FRIEND_REQUESTED, userdata);
2191 m->friendlist[i].friendrequest_lastsent = temp_time; 2484 m->friendlist[i].friendrequest_lastsent = temp_time;
2192 } 2485 }
2193 } 2486 }
@@ -2198,71 +2491,79 @@ void do_friends(Messenger *m)
2198 /* If we didn't connect to friend after successfully sending him a friend request the request is deemed 2491 /* If we didn't connect to friend after successfully sending him a friend request the request is deemed
2199 * unsuccessful so we set the status back to FRIEND_ADDED and try again. 2492 * unsuccessful so we set the status back to FRIEND_ADDED and try again.
2200 */ 2493 */
2201 check_friend_request_timed_out(m, i, temp_time); 2494 check_friend_request_timed_out(m, i, temp_time, userdata);
2202 } 2495 }
2203 } 2496 }
2204 2497
2205 if (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */ 2498 if (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */
2206 if (m->friendlist[i].name_sent == 0) { 2499 if (m->friendlist[i].name_sent == 0) {
2207 if (m_sendname(m, i, m->name, m->name_length)) 2500 if (m_sendname(m, i, m->name, m->name_length)) {
2208 m->friendlist[i].name_sent = 1; 2501 m->friendlist[i].name_sent = 1;
2502 }
2209 } 2503 }
2210 2504
2211 if (m->friendlist[i].statusmessage_sent == 0) { 2505 if (m->friendlist[i].statusmessage_sent == 0) {
2212 if (send_statusmessage(m, i, m->statusmessage, m->statusmessage_length)) 2506 if (send_statusmessage(m, i, m->statusmessage, m->statusmessage_length)) {
2213 m->friendlist[i].statusmessage_sent = 1; 2507 m->friendlist[i].statusmessage_sent = 1;
2508 }
2214 } 2509 }
2215 2510
2216 if (m->friendlist[i].userstatus_sent == 0) { 2511 if (m->friendlist[i].userstatus_sent == 0) {
2217 if (send_userstatus(m, i, m->userstatus)) 2512 if (send_userstatus(m, i, m->userstatus)) {
2218 m->friendlist[i].userstatus_sent = 1; 2513 m->friendlist[i].userstatus_sent = 1;
2514 }
2219 } 2515 }
2220 2516
2221 if (m->friendlist[i].user_istyping_sent == 0) { 2517 if (m->friendlist[i].user_istyping_sent == 0) {
2222 if (send_user_istyping(m, i, m->friendlist[i].user_istyping)) 2518 if (send_user_istyping(m, i, m->friendlist[i].user_istyping)) {
2223 m->friendlist[i].user_istyping_sent = 1; 2519 m->friendlist[i].user_istyping_sent = 1;
2520 }
2224 } 2521 }
2225 2522
2226 check_friend_tcp_udp(m, i); 2523 check_friend_tcp_udp(m, i, userdata);
2227 do_receipts(m, i); 2524 do_receipts(m, i, userdata);
2228 do_reqchunk_filecb(m, i); 2525 do_reqchunk_filecb(m, i, userdata);
2229 2526
2230 m->friendlist[i].last_seen_time = (uint64_t) time(NULL); 2527 m->friendlist[i].last_seen_time = (uint64_t) time(nullptr);
2231 } 2528 }
2232 } 2529 }
2233} 2530}
2234 2531
2235static void connection_status_cb(Messenger *m) 2532static void connection_status_cb(Messenger *m, void *userdata)
2236{ 2533{
2237 unsigned int conn_status = onion_connection_status(m->onion_c); 2534 unsigned int conn_status = onion_connection_status(m->onion_c);
2238 2535
2239 if (conn_status != m->last_connection_status) { 2536 if (conn_status != m->last_connection_status) {
2240 if (m->core_connection_change) 2537 if (m->core_connection_change) {
2241 (*m->core_connection_change)(m, conn_status, m->core_connection_change_userdata); 2538 (*m->core_connection_change)(m, conn_status, userdata);
2539 }
2242 2540
2243 m->last_connection_status = conn_status; 2541 m->last_connection_status = conn_status;
2244 } 2542 }
2245} 2543}
2246 2544
2247 2545
2248#ifdef TOX_LOGGER
2249#define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60UL 2546#define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60UL
2250static time_t lastdump = 0; 2547
2251static char IDString[crypto_box_PUBLICKEYBYTES * 2 + 1]; 2548#define IDSTRING_LEN (CRYPTO_PUBLIC_KEY_SIZE * 2 + 1)
2252static char *ID2String(const uint8_t *pk) 2549/* id_str should be of length at least IDSTRING_LEN */
2550static char *id_to_string(const uint8_t *pk, char *id_str, size_t length)
2253{ 2551{
2254 uint32_t i; 2552 if (length < IDSTRING_LEN) {
2553 snprintf(id_str, length, "Bad buf length");
2554 return id_str;
2555 }
2255 2556
2256 for (i = 0; i < crypto_box_PUBLICKEYBYTES; i++) 2557 for (uint32_t i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; i++) {
2257 sprintf(&IDString[i * 2], "%02X", pk[i]); 2558 sprintf(&id_str[i * 2], "%02X", pk[i]);
2559 }
2258 2560
2259 IDString[crypto_box_PUBLICKEYBYTES * 2] = 0; 2561 id_str[CRYPTO_PUBLIC_KEY_SIZE * 2] = 0;
2260 return IDString; 2562 return id_str;
2261} 2563}
2262#endif
2263 2564
2264/* Minimum messenger run interval in ms 2565/* Minimum messenger run interval in ms
2265 TODO: A/V */ 2566 TODO(mannol): A/V */
2266#define MIN_RUN_INTERVAL 50 2567#define MIN_RUN_INTERVAL 50
2267 2568
2268/* Return the time in milliseconds before do_messenger() should be called again 2569/* Return the time in milliseconds before do_messenger() should be called again
@@ -2276,13 +2577,13 @@ uint32_t messenger_run_interval(const Messenger *m)
2276 2577
2277 if (crypto_interval > MIN_RUN_INTERVAL) { 2578 if (crypto_interval > MIN_RUN_INTERVAL) {
2278 return MIN_RUN_INTERVAL; 2579 return MIN_RUN_INTERVAL;
2279 } else {
2280 return crypto_interval;
2281 } 2580 }
2581
2582 return crypto_interval;
2282} 2583}
2283 2584
2284/* The main loop that needs to be run at least 20 times per second. */ 2585/* The main loop that needs to be run at least 20 times per second. */
2285void do_messenger(Messenger *m) 2586void do_messenger(Messenger *m, void *userdata)
2286{ 2587{
2287 // Add the TCP relays, but only if this is the first time calling do_messenger 2588 // Add the TCP relays, but only if this is the first time calling do_messenger
2288 if (m->has_added_relays == 0) { 2589 if (m->has_added_relays == 0) {
@@ -2298,16 +2599,17 @@ void do_messenger(Messenger *m)
2298 /* Add self tcp server. */ 2599 /* Add self tcp server. */
2299 IP_Port local_ip_port; 2600 IP_Port local_ip_port;
2300 local_ip_port.port = m->options.tcp_server_port; 2601 local_ip_port.port = m->options.tcp_server_port;
2301 local_ip_port.ip.family = AF_INET; 2602 local_ip_port.ip.family = net_family_ipv4;
2302 local_ip_port.ip.ip4.uint32 = INADDR_LOOPBACK; 2603 local_ip_port.ip.ip.v4 = get_ip4_loopback();
2303 add_tcp_relay(m->net_crypto, local_ip_port, m->tcp_server->public_key); 2604 add_tcp_relay(m->net_crypto, local_ip_port,
2605 tcp_server_public_key(m->tcp_server));
2304 } 2606 }
2305 } 2607 }
2306 2608
2307 unix_time_update(); 2609 unix_time_update();
2308 2610
2309 if (!m->options.udp_disabled) { 2611 if (!m->options.udp_disabled) {
2310 networking_poll(m->net); 2612 networking_poll(m->net, userdata);
2311 do_DHT(m->dht); 2613 do_DHT(m->dht);
2312 } 2614 }
2313 2615
@@ -2315,112 +2617,121 @@ void do_messenger(Messenger *m)
2315 do_TCP_server(m->tcp_server); 2617 do_TCP_server(m->tcp_server);
2316 } 2618 }
2317 2619
2318 do_net_crypto(m->net_crypto); 2620 do_net_crypto(m->net_crypto, userdata);
2319 do_onion_client(m->onion_c); 2621 do_onion_client(m->onion_c);
2320 do_friend_connections(m->fr_c); 2622 do_friend_connections(m->fr_c, userdata);
2321 do_friends(m); 2623 do_friends(m, userdata);
2322 connection_status_cb(m); 2624 connection_status_cb(m, userdata);
2323
2324#ifdef TOX_LOGGER
2325
2326 if (unix_time() > lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) {
2327 2625
2328#ifdef ENABLE_ASSOC_DHT 2626 if (unix_time() > m->lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) {
2329 Assoc_status(m->dht->assoc); 2627 m->lastdump = unix_time();
2330#endif
2331
2332 lastdump = unix_time();
2333 uint32_t client, last_pinged; 2628 uint32_t client, last_pinged;
2334 2629
2335 for (client = 0; client < LCLIENT_LIST; client++) { 2630 for (client = 0; client < LCLIENT_LIST; client++) {
2336 Client_data *cptr = &m->dht->close_clientlist[client]; 2631 const Client_data *cptr = dht_get_close_client(m->dht, client);
2337 IPPTsPng *assoc = NULL; 2632 const IPPTsPng *assoc = nullptr;
2338 uint32_t a; 2633 uint32_t a;
2339 2634
2340 for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6) 2635 for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6) {
2341 if (ip_isset(&assoc->ip_port.ip)) { 2636 if (ip_isset(&assoc->ip_port.ip)) {
2342 last_pinged = lastdump - assoc->last_pinged; 2637 last_pinged = m->lastdump - assoc->last_pinged;
2343 2638
2344 if (last_pinged > 999) 2639 if (last_pinged > 999) {
2345 last_pinged = 999; 2640 last_pinged = 999;
2641 }
2346 2642
2347 LOGGER_TRACE("C[%2u] %s:%u [%3u] %s", 2643 char ip_str[IP_NTOA_LEN];
2348 client, ip_ntoa(&assoc->ip_port.ip), ntohs(assoc->ip_port.port), 2644 char id_str[IDSTRING_LEN];
2349 last_pinged, ID2String(cptr->public_key)); 2645 LOGGER_TRACE(m->log, "C[%2u] %s:%u [%3u] %s",
2646 client, ip_ntoa(&assoc->ip_port.ip, ip_str, sizeof(ip_str)),
2647 net_ntohs(assoc->ip_port.port), last_pinged,
2648 id_to_string(cptr->public_key, id_str, sizeof(id_str)));
2350 } 2649 }
2650 }
2351 } 2651 }
2352 2652
2353 2653
2354 uint32_t friend, dhtfriend; 2654 uint32_t friend_idx, dhtfriend;
2355 2655
2356 /* dht contains additional "friends" (requests) */ 2656 /* dht contains additional "friends" (requests) */
2357 uint32_t num_dhtfriends = m->dht->num_friends; 2657 uint32_t num_dhtfriends = dht_get_num_friends(m->dht);
2358 int32_t m2dht[num_dhtfriends]; 2658 VLA(int32_t, m2dht, num_dhtfriends);
2359 int32_t dht2m[num_dhtfriends]; 2659 VLA(int32_t, dht2m, num_dhtfriends);
2360 2660
2361 for (friend = 0; friend < num_dhtfriends; friend++) { 2661 for (friend_idx = 0; friend_idx < num_dhtfriends; friend_idx++) {
2362 m2dht[friend] = -1; 2662 m2dht[friend_idx] = -1;
2363 dht2m[friend] = -1; 2663 dht2m[friend_idx] = -1;
2364 2664
2365 if (friend >= m->numfriends) 2665 if (friend_idx >= m->numfriends) {
2366 continue; 2666 continue;
2667 }
2367 2668
2368 for (dhtfriend = 0; dhtfriend < m->dht->num_friends; dhtfriend++) 2669 for (dhtfriend = 0; dhtfriend < dht_get_num_friends(m->dht); dhtfriend++) {
2369 if (id_equal(m->friendlist[friend].real_pk, m->dht->friends_list[dhtfriend].public_key)) { 2670 if (id_equal(m->friendlist[friend_idx].real_pk, dht_get_friend_public_key(m->dht, dhtfriend))) {
2370 m2dht[friend] = dhtfriend; 2671 m2dht[friend_idx] = dhtfriend;
2371 break; 2672 break;
2372 } 2673 }
2674 }
2373 } 2675 }
2374 2676
2375 for (friend = 0; friend < num_dhtfriends; friend++) 2677 for (friend_idx = 0; friend_idx < num_dhtfriends; friend_idx++) {
2376 if (m2dht[friend] >= 0) 2678 if (m2dht[friend_idx] >= 0) {
2377 dht2m[m2dht[friend]] = friend; 2679 dht2m[m2dht[friend_idx]] = friend_idx;
2680 }
2681 }
2378 2682
2379 if (m->numfriends != m->dht->num_friends) { 2683 if (m->numfriends != dht_get_num_friends(m->dht)) {
2380 LOGGER_TRACE("Friend num in DHT %u != friend num in msger %u\n", m->dht->num_friends, m->numfriends); 2684 LOGGER_TRACE(m->log, "Friend num in DHT %u != friend num in msger %u\n", dht_get_num_friends(m->dht), m->numfriends);
2381 } 2685 }
2382 2686
2383 Friend *msgfptr; 2687 Friend *msgfptr;
2384 DHT_Friend *dhtfptr; 2688 DHT_Friend *dhtfptr;
2385 2689
2386 for (friend = 0; friend < num_dhtfriends; friend++) { 2690 for (friend_idx = 0; friend_idx < num_dhtfriends; friend_idx++) {
2387 if (dht2m[friend] >= 0) 2691 if (dht2m[friend_idx] >= 0) {
2388 msgfptr = &m->friendlist[dht2m[friend]]; 2692 msgfptr = &m->friendlist[dht2m[friend_idx]];
2389 else 2693 } else {
2390 msgfptr = NULL; 2694 msgfptr = nullptr;
2695 }
2391 2696
2392 dhtfptr = &m->dht->friends_list[friend]; 2697 dhtfptr = dht_get_friend(m->dht, friend_idx);
2393 2698
2394 if (msgfptr) { 2699 if (msgfptr) {
2395 LOGGER_TRACE("F[%2u:%2u] <%s> %s", 2700 char id_str[IDSTRING_LEN];
2396 dht2m[friend], friend, msgfptr->name, 2701 LOGGER_TRACE(m->log, "F[%2u:%2u] <%s> %s",
2397 ID2String(msgfptr->real_pk)); 2702 dht2m[friend_idx], friend_idx, msgfptr->name,
2703 id_to_string(msgfptr->real_pk, id_str, sizeof(id_str)));
2398 } else { 2704 } else {
2399 LOGGER_TRACE("F[--:%2u] %s", friend, ID2String(dhtfptr->public_key)); 2705 char id_str[IDSTRING_LEN];
2706 LOGGER_TRACE(m->log, "F[--:%2u] %s", friend_idx,
2707 id_to_string(dht_friend_public_key(dhtfptr), id_str, sizeof(id_str)));
2400 } 2708 }
2401 2709
2402 for (client = 0; client < MAX_FRIEND_CLIENTS; client++) { 2710 for (client = 0; client < MAX_FRIEND_CLIENTS; client++) {
2403 Client_data *cptr = &dhtfptr->client_list[client]; 2711 const Client_data *cptr = dht_friend_client(dhtfptr, client);
2404 IPPTsPng *assoc = NULL; 2712 const IPPTsPng *const assocs[] = {&cptr->assoc4, &cptr->assoc6};
2405 uint32_t a; 2713
2714 for (size_t a = 0; a < sizeof(assocs) / sizeof(assocs[0]); a++) {
2715 const IPPTsPng *const assoc = assocs[a];
2406 2716
2407 for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6)
2408 if (ip_isset(&assoc->ip_port.ip)) { 2717 if (ip_isset(&assoc->ip_port.ip)) {
2409 last_pinged = lastdump - assoc->last_pinged; 2718 last_pinged = m->lastdump - assoc->last_pinged;
2410 2719
2411 if (last_pinged > 999) 2720 if (last_pinged > 999) {
2412 last_pinged = 999; 2721 last_pinged = 999;
2413 2722 }
2414 LOGGER_TRACE("F[%2u] => C[%2u] %s:%u [%3u] %s", 2723
2415 friend, client, ip_ntoa(&assoc->ip_port.ip), 2724 char ip_str[IP_NTOA_LEN];
2416 ntohs(assoc->ip_port.port), last_pinged, 2725 char id_str[IDSTRING_LEN];
2417 ID2String(cptr->public_key)); 2726 LOGGER_TRACE(m->log, "F[%2u] => C[%2u] %s:%u [%3u] %s",
2727 friend_idx, client, ip_ntoa(&assoc->ip_port.ip, ip_str, sizeof(ip_str)),
2728 net_ntohs(assoc->ip_port.port), last_pinged,
2729 id_to_string(cptr->public_key, id_str, sizeof(id_str)));
2418 } 2730 }
2731 }
2419 } 2732 }
2420 } 2733 }
2421 } 2734 }
2422
2423#endif /* TOX_LOGGER */
2424} 2735}
2425 2736
2426/* new messenger format for load/save, more robust and forward compatible */ 2737/* new messenger format for load/save, more robust and forward compatible */
@@ -2440,9 +2751,10 @@ void do_messenger(Messenger *m)
2440 2751
2441#define SAVED_FRIEND_REQUEST_SIZE 1024 2752#define SAVED_FRIEND_REQUEST_SIZE 1024
2442#define NUM_SAVED_PATH_NODES 8 2753#define NUM_SAVED_PATH_NODES 8
2754
2443struct SAVED_FRIEND { 2755struct SAVED_FRIEND {
2444 uint8_t status; 2756 uint8_t status;
2445 uint8_t real_pk[crypto_box_PUBLICKEYBYTES]; 2757 uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
2446 uint8_t info[SAVED_FRIEND_REQUEST_SIZE]; // the data that is sent during the friend requests we do. 2758 uint8_t info[SAVED_FRIEND_REQUEST_SIZE]; // the data that is sent during the friend requests we do.
2447 uint16_t info_size; // Length of the info. 2759 uint16_t info_size; // Length of the info.
2448 uint8_t name[MAX_NAME_LENGTH]; 2760 uint8_t name[MAX_NAME_LENGTH];
@@ -2454,37 +2766,98 @@ struct SAVED_FRIEND {
2454 uint64_t last_seen_time; 2766 uint64_t last_seen_time;
2455}; 2767};
2456 2768
2769static uint32_t friend_size(void)
2770{
2771 uint32_t data = 0;
2772 const struct SAVED_FRIEND *const temp = nullptr;
2773
2774#define VALUE_MEMBER(NAME) data += sizeof(temp->NAME)
2775#define ARRAY_MEMBER(NAME) data += sizeof(temp->NAME)
2776
2777 // Exactly the same in friend_load, friend_save, and friend_size
2778 VALUE_MEMBER(status);
2779 ARRAY_MEMBER(real_pk);
2780 ARRAY_MEMBER(info);
2781 data++; // padding
2782 VALUE_MEMBER(info_size);
2783 ARRAY_MEMBER(name);
2784 VALUE_MEMBER(name_length);
2785 ARRAY_MEMBER(statusmessage);
2786 data++; // padding
2787 VALUE_MEMBER(statusmessage_length);
2788 VALUE_MEMBER(userstatus);
2789 data += 3; // padding
2790 VALUE_MEMBER(friendrequest_nospam);
2791 VALUE_MEMBER(last_seen_time);
2792
2793#undef VALUE_MEMBER
2794#undef ARRAY_MEMBER
2795
2796 return data;
2797}
2798
2457static uint32_t saved_friendslist_size(const Messenger *m) 2799static uint32_t saved_friendslist_size(const Messenger *m)
2458{ 2800{
2459 return count_friendlist(m) * sizeof(struct SAVED_FRIEND); 2801 return count_friendlist(m) * friend_size();
2802}
2803
2804static uint8_t *friend_save(const struct SAVED_FRIEND *temp, uint8_t *data)
2805{
2806#define VALUE_MEMBER(NAME) \
2807 memcpy(data, &temp->NAME, sizeof(temp->NAME)); \
2808 data += sizeof(temp->NAME)
2809
2810#define ARRAY_MEMBER(NAME) \
2811 memcpy(data, temp->NAME, sizeof(temp->NAME)); \
2812 data += sizeof(temp->NAME)
2813
2814 // Exactly the same in friend_load, friend_save, and friend_size
2815 VALUE_MEMBER(status);
2816 ARRAY_MEMBER(real_pk);
2817 ARRAY_MEMBER(info);
2818 data++; // padding
2819 VALUE_MEMBER(info_size);
2820 ARRAY_MEMBER(name);
2821 VALUE_MEMBER(name_length);
2822 ARRAY_MEMBER(statusmessage);
2823 data++; // padding
2824 VALUE_MEMBER(statusmessage_length);
2825 VALUE_MEMBER(userstatus);
2826 data += 3; // padding
2827 VALUE_MEMBER(friendrequest_nospam);
2828 VALUE_MEMBER(last_seen_time);
2829
2830#undef VALUE_MEMBER
2831#undef ARRAY_MEMBER
2832
2833 return data;
2460} 2834}
2461 2835
2462static uint32_t friends_list_save(const Messenger *m, uint8_t *data) 2836static uint32_t friends_list_save(const Messenger *m, uint8_t *data)
2463{ 2837{
2464 uint32_t i; 2838 uint32_t i;
2465 uint32_t num = 0; 2839 uint32_t num = 0;
2840 uint8_t *cur_data = data;
2466 2841
2467 for (i = 0; i < m->numfriends; i++) { 2842 for (i = 0; i < m->numfriends; i++) {
2468 if (m->friendlist[i].status > 0) { 2843 if (m->friendlist[i].status > 0) {
2469 struct SAVED_FRIEND temp; 2844 struct SAVED_FRIEND temp = { 0 };
2470 memset(&temp, 0, sizeof(struct SAVED_FRIEND));
2471 temp.status = m->friendlist[i].status; 2845 temp.status = m->friendlist[i].status;
2472 memcpy(temp.real_pk, m->friendlist[i].real_pk, crypto_box_PUBLICKEYBYTES); 2846 memcpy(temp.real_pk, m->friendlist[i].real_pk, CRYPTO_PUBLIC_KEY_SIZE);
2473 2847
2474 if (temp.status < 3) { 2848 if (temp.status < 3) {
2475 if (m->friendlist[i].info_size > SAVED_FRIEND_REQUEST_SIZE) { 2849 const size_t friendrequest_length =
2476 memcpy(temp.info, m->friendlist[i].info, SAVED_FRIEND_REQUEST_SIZE); 2850 MIN(m->friendlist[i].info_size,
2477 } else { 2851 MIN(SAVED_FRIEND_REQUEST_SIZE, MAX_FRIEND_REQUEST_DATA_SIZE));
2478 memcpy(temp.info, m->friendlist[i].info, m->friendlist[i].info_size); 2852 memcpy(temp.info, m->friendlist[i].info, friendrequest_length);
2479 }
2480 2853
2481 temp.info_size = htons(m->friendlist[i].info_size); 2854 temp.info_size = net_htons(m->friendlist[i].info_size);
2482 temp.friendrequest_nospam = m->friendlist[i].friendrequest_nospam; 2855 temp.friendrequest_nospam = m->friendlist[i].friendrequest_nospam;
2483 } else { 2856 } else {
2484 memcpy(temp.name, m->friendlist[i].name, m->friendlist[i].name_length); 2857 memcpy(temp.name, m->friendlist[i].name, m->friendlist[i].name_length);
2485 temp.name_length = htons(m->friendlist[i].name_length); 2858 temp.name_length = net_htons(m->friendlist[i].name_length);
2486 memcpy(temp.statusmessage, m->friendlist[i].statusmessage, m->friendlist[i].statusmessage_length); 2859 memcpy(temp.statusmessage, m->friendlist[i].statusmessage, m->friendlist[i].statusmessage_length);
2487 temp.statusmessage_length = htons(m->friendlist[i].statusmessage_length); 2860 temp.statusmessage_length = net_htons(m->friendlist[i].statusmessage_length);
2488 temp.userstatus = m->friendlist[i].userstatus; 2861 temp.userstatus = m->friendlist[i].userstatus;
2489 2862
2490 uint8_t last_seen_time[sizeof(uint64_t)]; 2863 uint8_t last_seen_time[sizeof(uint64_t)];
@@ -2493,48 +2866,93 @@ static uint32_t friends_list_save(const Messenger *m, uint8_t *data)
2493 memcpy(&temp.last_seen_time, last_seen_time, sizeof(uint64_t)); 2866 memcpy(&temp.last_seen_time, last_seen_time, sizeof(uint64_t));
2494 } 2867 }
2495 2868
2496 memcpy(data + num * sizeof(struct SAVED_FRIEND), &temp, sizeof(struct SAVED_FRIEND)); 2869 uint8_t *next_data = friend_save(&temp, cur_data);
2870 assert(next_data - cur_data == friend_size());
2871#ifdef __LP64__
2872 assert(memcmp(cur_data, &temp, friend_size()) == 0);
2873#endif
2874 cur_data = next_data;
2497 num++; 2875 num++;
2498 } 2876 }
2499 } 2877 }
2500 2878
2501 return num * sizeof(struct SAVED_FRIEND); 2879 assert(cur_data - data == num * friend_size());
2880 return cur_data - data;
2881}
2882
2883static const uint8_t *friend_load(struct SAVED_FRIEND *temp, const uint8_t *data)
2884{
2885#define VALUE_MEMBER(NAME) \
2886 memcpy(&temp->NAME, data, sizeof(temp->NAME)); \
2887 data += sizeof(temp->NAME)
2888
2889#define ARRAY_MEMBER(NAME) \
2890 memcpy(temp->NAME, data, sizeof(temp->NAME)); \
2891 data += sizeof(temp->NAME)
2892
2893 // Exactly the same in friend_load, friend_save, and friend_size
2894 VALUE_MEMBER(status);
2895 ARRAY_MEMBER(real_pk);
2896 ARRAY_MEMBER(info);
2897 data++; // padding
2898 VALUE_MEMBER(info_size);
2899 ARRAY_MEMBER(name);
2900 VALUE_MEMBER(name_length);
2901 ARRAY_MEMBER(statusmessage);
2902 data++; // padding
2903 VALUE_MEMBER(statusmessage_length);
2904 VALUE_MEMBER(userstatus);
2905 data += 3; // padding
2906 VALUE_MEMBER(friendrequest_nospam);
2907 VALUE_MEMBER(last_seen_time);
2908
2909#undef VALUE_MEMBER
2910#undef ARRAY_MEMBER
2911
2912 return data;
2502} 2913}
2503 2914
2504static int friends_list_load(Messenger *m, const uint8_t *data, uint32_t length) 2915static int friends_list_load(Messenger *m, const uint8_t *data, uint32_t length)
2505{ 2916{
2506 if (length % sizeof(struct SAVED_FRIEND) != 0) { 2917 if (length % friend_size() != 0) {
2507 return -1; 2918 return -1;
2508 } 2919 }
2509 2920
2510 uint32_t num = length / sizeof(struct SAVED_FRIEND); 2921 uint32_t num = length / friend_size();
2511 uint32_t i; 2922 uint32_t i;
2923 const uint8_t *cur_data = data;
2512 2924
2513 for (i = 0; i < num; ++i) { 2925 for (i = 0; i < num; ++i) {
2514 struct SAVED_FRIEND temp; 2926 struct SAVED_FRIEND temp = { 0 };
2515 memcpy(&temp, data + i * sizeof(struct SAVED_FRIEND), sizeof(struct SAVED_FRIEND)); 2927 const uint8_t *next_data = friend_load(&temp, cur_data);
2928 assert(next_data - cur_data == friend_size());
2929#ifdef __LP64__
2930 assert(memcmp(&temp, cur_data, friend_size()) == 0);
2931#endif
2932 cur_data = next_data;
2516 2933
2517 if (temp.status >= 3) { 2934 if (temp.status >= 3) {
2518 int fnum = m_addfriend_norequest(m, temp.real_pk); 2935 int fnum = m_addfriend_norequest(m, temp.real_pk);
2519 2936
2520 if (fnum < 0) 2937 if (fnum < 0) {
2521 continue; 2938 continue;
2939 }
2522 2940
2523 setfriendname(m, fnum, temp.name, ntohs(temp.name_length)); 2941 setfriendname(m, fnum, temp.name, net_ntohs(temp.name_length));
2524 set_friend_statusmessage(m, fnum, temp.statusmessage, ntohs(temp.statusmessage_length)); 2942 set_friend_statusmessage(m, fnum, temp.statusmessage, net_ntohs(temp.statusmessage_length));
2525 set_friend_userstatus(m, fnum, temp.userstatus); 2943 set_friend_userstatus(m, fnum, temp.userstatus);
2526 uint8_t last_seen_time[sizeof(uint64_t)]; 2944 uint8_t last_seen_time[sizeof(uint64_t)];
2527 memcpy(last_seen_time, &temp.last_seen_time, sizeof(uint64_t)); 2945 memcpy(last_seen_time, &temp.last_seen_time, sizeof(uint64_t));
2528 net_to_host(last_seen_time, sizeof(uint64_t)); 2946 net_to_host(last_seen_time, sizeof(uint64_t));
2529 memcpy(&m->friendlist[fnum].last_seen_time, last_seen_time, sizeof(uint64_t)); 2947 memcpy(&m->friendlist[fnum].last_seen_time, last_seen_time, sizeof(uint64_t));
2530 } else if (temp.status != 0) { 2948 } else if (temp.status != 0) {
2531 /* TODO: This is not a good way to do this. */ 2949 /* TODO(irungentoo): This is not a good way to do this. */
2532 uint8_t address[FRIEND_ADDRESS_SIZE]; 2950 uint8_t address[FRIEND_ADDRESS_SIZE];
2533 id_copy(address, temp.real_pk); 2951 id_copy(address, temp.real_pk);
2534 memcpy(address + crypto_box_PUBLICKEYBYTES, &(temp.friendrequest_nospam), sizeof(uint32_t)); 2952 memcpy(address + CRYPTO_PUBLIC_KEY_SIZE, &temp.friendrequest_nospam, sizeof(uint32_t));
2535 uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); 2953 uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum));
2536 memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), &checksum, sizeof(checksum)); 2954 memcpy(address + CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint32_t), &checksum, sizeof(checksum));
2537 m_addfriend(m, address, temp.info, ntohs(temp.info_size)); 2955 m_addfriend(m, address, temp.info, net_ntohs(temp.info_size));
2538 } 2956 }
2539 } 2957 }
2540 2958
@@ -2546,18 +2964,18 @@ uint32_t messenger_size(const Messenger *m)
2546{ 2964{
2547 uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2; 2965 uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2;
2548 return size32 * 2 // global cookie 2966 return size32 * 2 // global cookie
2549 + sizesubhead + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES 2967 + sizesubhead + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE
2550 + sizesubhead + DHT_size(m->dht) // DHT 2968 + sizesubhead + DHT_size(m->dht) // DHT
2551 + sizesubhead + saved_friendslist_size(m) // Friendlist itself. 2969 + sizesubhead + saved_friendslist_size(m) // Friendlist itself.
2552 + sizesubhead + m->name_length // Own nickname. 2970 + sizesubhead + m->name_length // Own nickname.
2553 + sizesubhead + m->statusmessage_length // status message 2971 + sizesubhead + m->statusmessage_length // status message
2554 + sizesubhead + 1 // status 2972 + sizesubhead + 1 // status
2555 + sizesubhead + NUM_SAVED_TCP_RELAYS * packed_node_size(TCP_INET6) //TCP relays 2973 + sizesubhead + NUM_SAVED_TCP_RELAYS * packed_node_size(net_family_tcp_ipv6) //TCP relays
2556 + sizesubhead + NUM_SAVED_PATH_NODES * packed_node_size(TCP_INET6) //saved path nodes 2974 + sizesubhead + NUM_SAVED_PATH_NODES * packed_node_size(net_family_tcp_ipv6) //saved path nodes
2557 + sizesubhead; 2975 + sizesubhead;
2558} 2976}
2559 2977
2560static uint8_t *z_state_save_subheader(uint8_t *data, uint32_t len, uint16_t type) 2978static uint8_t *messenger_save_subheader(uint8_t *data, uint32_t len, uint16_t type)
2561{ 2979{
2562 host_to_lendian32(data, len); 2980 host_to_lendian32(data, len);
2563 data += sizeof(uint32_t); 2981 data += sizeof(uint32_t);
@@ -2580,91 +2998,90 @@ void messenger_save(const Messenger *m, uint8_t *data)
2580 host_to_lendian32(data, MESSENGER_STATE_COOKIE_GLOBAL); 2998 host_to_lendian32(data, MESSENGER_STATE_COOKIE_GLOBAL);
2581 data += size32; 2999 data += size32;
2582 3000
2583#ifdef DEBUG 3001 assert(sizeof(get_nospam(m->fr)) == sizeof(uint32_t));
2584 assert(sizeof(get_nospam(&(m->fr))) == sizeof(uint32_t)); 3002 len = size32 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE;
2585#endif
2586 len = size32 + crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
2587 type = MESSENGER_STATE_TYPE_NOSPAMKEYS; 3003 type = MESSENGER_STATE_TYPE_NOSPAMKEYS;
2588 data = z_state_save_subheader(data, len, type); 3004 data = messenger_save_subheader(data, len, type);
2589 *(uint32_t *)data = get_nospam(&(m->fr)); 3005 *(uint32_t *)data = get_nospam(m->fr);
2590 save_keys(m->net_crypto, data + size32); 3006 save_keys(m->net_crypto, data + size32);
2591 data += len; 3007 data += len;
2592 3008
2593 len = saved_friendslist_size(m); 3009 len = saved_friendslist_size(m);
2594 type = MESSENGER_STATE_TYPE_FRIENDS; 3010 type = MESSENGER_STATE_TYPE_FRIENDS;
2595 data = z_state_save_subheader(data, len, type); 3011 data = messenger_save_subheader(data, len, type);
2596 friends_list_save(m, data); 3012 friends_list_save(m, data);
2597 data += len; 3013 data += len;
2598 3014
2599 len = m->name_length; 3015 len = m->name_length;
2600 type = MESSENGER_STATE_TYPE_NAME; 3016 type = MESSENGER_STATE_TYPE_NAME;
2601 data = z_state_save_subheader(data, len, type); 3017 data = messenger_save_subheader(data, len, type);
2602 memcpy(data, m->name, len); 3018 memcpy(data, m->name, len);
2603 data += len; 3019 data += len;
2604 3020
2605 len = m->statusmessage_length; 3021 len = m->statusmessage_length;
2606 type = MESSENGER_STATE_TYPE_STATUSMESSAGE; 3022 type = MESSENGER_STATE_TYPE_STATUSMESSAGE;
2607 data = z_state_save_subheader(data, len, type); 3023 data = messenger_save_subheader(data, len, type);
2608 memcpy(data, m->statusmessage, len); 3024 memcpy(data, m->statusmessage, len);
2609 data += len; 3025 data += len;
2610 3026
2611 len = 1; 3027 len = 1;
2612 type = MESSENGER_STATE_TYPE_STATUS; 3028 type = MESSENGER_STATE_TYPE_STATUS;
2613 data = z_state_save_subheader(data, len, type); 3029 data = messenger_save_subheader(data, len, type);
2614 *data = m->userstatus; 3030 *data = m->userstatus;
2615 data += len; 3031 data += len;
2616 3032
2617 len = DHT_size(m->dht); 3033 len = DHT_size(m->dht);
2618 type = MESSENGER_STATE_TYPE_DHT; 3034 type = MESSENGER_STATE_TYPE_DHT;
2619 data = z_state_save_subheader(data, len, type); 3035 data = messenger_save_subheader(data, len, type);
2620 DHT_save(m->dht, data); 3036 DHT_save(m->dht, data);
2621 data += len; 3037 data += len;
2622 3038
2623 Node_format relays[NUM_SAVED_TCP_RELAYS]; 3039 Node_format relays[NUM_SAVED_TCP_RELAYS];
2624 type = MESSENGER_STATE_TYPE_TCP_RELAY; 3040 type = MESSENGER_STATE_TYPE_TCP_RELAY;
2625 uint8_t *temp_data = data; 3041 uint8_t *temp_data = data;
2626 data = z_state_save_subheader(temp_data, 0, type); 3042 data = messenger_save_subheader(temp_data, 0, type);
2627 unsigned int num = copy_connected_tcp_relays(m->net_crypto, relays, NUM_SAVED_TCP_RELAYS); 3043 unsigned int num = copy_connected_tcp_relays(m->net_crypto, relays, NUM_SAVED_TCP_RELAYS);
2628 int l = pack_nodes(data, NUM_SAVED_TCP_RELAYS * packed_node_size(TCP_INET6), relays, num); 3044 int l = pack_nodes(data, NUM_SAVED_TCP_RELAYS * packed_node_size(net_family_tcp_ipv6), relays, num);
2629 3045
2630 if (l > 0) { 3046 if (l > 0) {
2631 len = l; 3047 len = l;
2632 data = z_state_save_subheader(temp_data, len, type); 3048 data = messenger_save_subheader(temp_data, len, type);
2633 data += len; 3049 data += len;
2634 } 3050 }
2635 3051
2636 Node_format nodes[NUM_SAVED_PATH_NODES]; 3052 Node_format nodes[NUM_SAVED_PATH_NODES];
2637 type = MESSENGER_STATE_TYPE_PATH_NODE; 3053 type = MESSENGER_STATE_TYPE_PATH_NODE;
2638 temp_data = data; 3054 temp_data = data;
2639 data = z_state_save_subheader(data, 0, type); 3055 data = messenger_save_subheader(data, 0, type);
2640 memset(nodes, 0, sizeof(nodes)); 3056 memset(nodes, 0, sizeof(nodes));
2641 num = onion_backup_nodes(m->onion_c, nodes, NUM_SAVED_PATH_NODES); 3057 num = onion_backup_nodes(m->onion_c, nodes, NUM_SAVED_PATH_NODES);
2642 l = pack_nodes(data, NUM_SAVED_PATH_NODES * packed_node_size(TCP_INET6), nodes, num); 3058 l = pack_nodes(data, NUM_SAVED_PATH_NODES * packed_node_size(net_family_tcp_ipv6), nodes, num);
2643 3059
2644 if (l > 0) { 3060 if (l > 0) {
2645 len = l; 3061 len = l;
2646 data = z_state_save_subheader(temp_data, len, type); 3062 data = messenger_save_subheader(temp_data, len, type);
2647 data += len; 3063 data += len;
2648 } 3064 }
2649 3065
2650 z_state_save_subheader(data, 0, MESSENGER_STATE_TYPE_END); 3066 messenger_save_subheader(data, 0, MESSENGER_STATE_TYPE_END);
2651} 3067}
2652 3068
2653static int messenger_load_state_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type) 3069static int messenger_load_state_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type)
2654{ 3070{
2655 Messenger *m = outer; 3071 Messenger *m = (Messenger *)outer;
2656 3072
2657 switch (type) { 3073 switch (type) {
2658 case MESSENGER_STATE_TYPE_NOSPAMKEYS: 3074 case MESSENGER_STATE_TYPE_NOSPAMKEYS:
2659 if (length == crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t)) { 3075 if (length == CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE + sizeof(uint32_t)) {
2660 set_nospam(&(m->fr), *(uint32_t *)data); 3076 set_nospam(m->fr, *(const uint32_t *)data);
2661 load_secret_key(m->net_crypto, (&data[sizeof(uint32_t)]) + crypto_box_PUBLICKEYBYTES); 3077 load_secret_key(m->net_crypto, (&data[sizeof(uint32_t)]) + CRYPTO_PUBLIC_KEY_SIZE);
2662 3078
2663 if (public_key_cmp((&data[sizeof(uint32_t)]), m->net_crypto->self_public_key) != 0) { 3079 if (public_key_cmp((&data[sizeof(uint32_t)]), nc_get_self_public_key(m->net_crypto)) != 0) {
2664 return -1; 3080 return -1;
2665 } 3081 }
2666 } else 3082 } else {
2667 return -1; /* critical */ 3083 return -1; /* critical */
3084 }
2668 3085
2669 break; 3086 break;
2670 3087
@@ -2684,7 +3101,7 @@ static int messenger_load_state_callback(void *outer, const uint8_t *data, uint3
2684 break; 3101 break;
2685 3102
2686 case MESSENGER_STATE_TYPE_STATUSMESSAGE: 3103 case MESSENGER_STATE_TYPE_STATUSMESSAGE:
2687 if ((length > 0) && (length < MAX_STATUSMESSAGE_LENGTH)) { 3104 if ((length > 0) && (length <= MAX_STATUSMESSAGE_LENGTH)) {
2688 m_set_statusmessage(m, data, length); 3105 m_set_statusmessage(m, data, length);
2689 } 3106 }
2690 3107
@@ -2702,7 +3119,7 @@ static int messenger_load_state_callback(void *outer, const uint8_t *data, uint3
2702 break; 3119 break;
2703 } 3120 }
2704 3121
2705 unpack_nodes(m->loaded_relays, NUM_SAVED_TCP_RELAYS, 0, data, length, 1); 3122 unpack_nodes(m->loaded_relays, NUM_SAVED_TCP_RELAYS, nullptr, data, length, 1);
2706 m->has_added_relays = 0; 3123 m->has_added_relays = 0;
2707 3124
2708 break; 3125 break;
@@ -2715,7 +3132,7 @@ static int messenger_load_state_callback(void *outer, const uint8_t *data, uint3
2715 break; 3132 break;
2716 } 3133 }
2717 3134
2718 int i, num = unpack_nodes(nodes, NUM_SAVED_PATH_NODES, 0, data, length, 0); 3135 int i, num = unpack_nodes(nodes, NUM_SAVED_PATH_NODES, nullptr, data, length, 0);
2719 3136
2720 for (i = 0; i < num; ++i) { 3137 for (i = 0; i < num; ++i) {
2721 onion_add_bs_path_node(m->onion_c, nodes[i].ip_port, nodes[i].public_key); 3138 onion_add_bs_path_node(m->onion_c, nodes[i].ip_port, nodes[i].public_key);
@@ -2730,16 +3147,12 @@ static int messenger_load_state_callback(void *outer, const uint8_t *data, uint3
2730 } 3147 }
2731 3148
2732 return -2; 3149 return -2;
2733 break;
2734 } 3150 }
2735 3151
2736#ifdef DEBUG
2737
2738 default: 3152 default:
2739 fprintf(stderr, "Load state: contains unrecognized part (len %u, type %u)\n", 3153 LOGGER_ERROR(m->log, "Load state: contains unrecognized part (len %u, type %u)\n",
2740 length, type); 3154 length, type);
2741 break; 3155 break;
2742#endif
2743 } 3156 }
2744 3157
2745 return 0; 3158 return 0;
@@ -2751,17 +3164,19 @@ int messenger_load(Messenger *m, const uint8_t *data, uint32_t length)
2751 uint32_t data32[2]; 3164 uint32_t data32[2];
2752 uint32_t cookie_len = sizeof(data32); 3165 uint32_t cookie_len = sizeof(data32);
2753 3166
2754 if (length < cookie_len) 3167 if (length < cookie_len) {
2755 return -1; 3168 return -1;
3169 }
2756 3170
2757 memcpy(data32, data, sizeof(uint32_t)); 3171 memcpy(data32, data, sizeof(uint32_t));
2758 lendian_to_host32(data32 + 1, data + sizeof(uint32_t)); 3172 lendian_to_host32(data32 + 1, data + sizeof(uint32_t));
2759 3173
2760 if (!data32[0] && (data32[1] == MESSENGER_STATE_COOKIE_GLOBAL)) 3174 if (!data32[0] && (data32[1] == MESSENGER_STATE_COOKIE_GLOBAL)) {
2761 return load_state(messenger_load_state_callback, m, data + cookie_len, 3175 return load_state(messenger_load_state_callback, m->log, m, data + cookie_len,
2762 length - cookie_len, MESSENGER_STATE_COOKIE_TYPE); 3176 length - cookie_len, MESSENGER_STATE_COOKIE_TYPE);
2763 else 3177 }
2764 return -1; 3178
3179 return -1;
2765} 3180}
2766 3181
2767/* Return the number of friends in the instance m. 3182/* Return the number of friends in the instance m.
@@ -2788,8 +3203,9 @@ uint32_t count_friendlist(const Messenger *m)
2788 * of out_list will be truncated to list_size. */ 3203 * of out_list will be truncated to list_size. */
2789uint32_t copy_friendlist(Messenger const *m, uint32_t *out_list, uint32_t list_size) 3204uint32_t copy_friendlist(Messenger const *m, uint32_t *out_list, uint32_t list_size)
2790{ 3205{
2791 if (!out_list) 3206 if (!out_list) {
2792 return 0; 3207 return 0;
3208 }
2793 3209
2794 if (m->numfriends == 0) { 3210 if (m->numfriends == 0) {
2795 return 0; 3211 return 0;
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index 26704dd1..402eb916 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -1,40 +1,48 @@
1/* Messenger.h 1/*
2 * 2 * An implementation of a simple text chat only messenger on the tox network
3 * An implementation of a simple text chat only messenger on the tox network core. 3 * core.
4 * 4 */
5 * NOTE: All the text in the messages must be encoded using UTF-8 5
6 * 6/*
7 * Copyright (C) 2013 Tox project All Rights Reserved. 7 * Copyright © 2016-2017 The TokTok team.
8 * 8 * Copyright © 2013 Tox project.
9 * This file is part of Tox.
10 * 9 *
11 * Tox is free software: you can redistribute it and/or modify 10 * This file is part of Tox, the free peer to peer instant messenger.
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 * 11 *
16 * Tox is distributed in the hope that it will be useful, 12 * Tox is free software: you can redistribute it and/or modify
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * it under the terms of the GNU General Public License as published by
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * the Free Software Foundation, either version 3 of the License, or
19 * GNU General Public License for more details. 15 * (at your option) any later version.
20 * 16 *
21 * You should have received a copy of the GNU General Public License 17 * Tox is distributed in the hope that it will be useful,
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
23 * 21 *
22 * You should have received a copy of the GNU General Public License
23 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
24 */ 24 */
25
26#ifndef MESSENGER_H 25#ifndef MESSENGER_H
27#define MESSENGER_H 26#define MESSENGER_H
28 27
29#include "friend_requests.h"
30#include "friend_connection.h" 28#include "friend_connection.h"
29#include "friend_requests.h"
30#include "logger.h"
31 31
32#define MAX_NAME_LENGTH 128 32#define MAX_NAME_LENGTH 128
33/* TODO: this must depend on other variable. */ 33/* TODO(irungentoo): this must depend on other variable. */
34#define MAX_STATUSMESSAGE_LENGTH 1007 34#define MAX_STATUSMESSAGE_LENGTH 1007
35/* Used for TCP relays in Messenger struct (may need to be % 2 == 0)*/
36#define NUM_SAVED_TCP_RELAYS 8
37/* This cannot be bigger than 256 */
38#define MAX_CONCURRENT_FILE_PIPES 256
39
40#if !defined(__SPLINT__) && MAX_CONCURRENT_FILE_PIPES > UINT8_MAX + 1
41#error "uint8_t cannot represent all file transfer numbers"
42#endif
35 43
36 44
37#define FRIEND_ADDRESS_SIZE (crypto_box_PUBLICKEYBYTES + sizeof(uint32_t) + sizeof(uint16_t)) 45#define FRIEND_ADDRESS_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint32_t) + sizeof(uint16_t))
38 46
39enum { 47enum {
40 MESSAGE_NORMAL, 48 MESSAGE_NORMAL,
@@ -54,11 +62,11 @@ enum {
54#define PACKET_ID_FILE_SENDREQUEST 80 62#define PACKET_ID_FILE_SENDREQUEST 80
55#define PACKET_ID_FILE_CONTROL 81 63#define PACKET_ID_FILE_CONTROL 81
56#define PACKET_ID_FILE_DATA 82 64#define PACKET_ID_FILE_DATA 82
57#define PACKET_ID_INVITE_GROUPCHAT 96 65#define PACKET_ID_INVITE_CONFERENCE 96
58#define PACKET_ID_ONLINE_PACKET 97 66#define PACKET_ID_ONLINE_PACKET 97
59#define PACKET_ID_DIRECT_GROUPCHAT 98 67#define PACKET_ID_DIRECT_CONFERENCE 98
60#define PACKET_ID_MESSAGE_GROUPCHAT 99 68#define PACKET_ID_MESSAGE_CONFERENCE 99
61#define PACKET_ID_LOSSY_GROUPCHAT 199 69#define PACKET_ID_LOSSY_CONFERENCE 199
62 70
63/* All packets starting with a byte in this range can be used for anything. */ 71/* All packets starting with a byte in this range can be used for anything. */
64#define PACKET_ID_LOSSLESS_RANGE_START 160 72#define PACKET_ID_LOSSLESS_RANGE_START 160
@@ -66,11 +74,17 @@ enum {
66#define PACKET_LOSSY_AV_RESERVED 8 /* Number of lossy packet types at start of range reserved for A/V. */ 74#define PACKET_LOSSY_AV_RESERVED 8 /* Number of lossy packet types at start of range reserved for A/V. */
67 75
68typedef struct { 76typedef struct {
69 uint8_t ipv6enabled; 77 bool ipv6enabled;
70 uint8_t udp_disabled; 78 bool udp_disabled;
71 TCP_Proxy_Info proxy_info; 79 TCP_Proxy_Info proxy_info;
72 uint16_t port_range[2]; 80 uint16_t port_range[2];
73 uint16_t tcp_server_port; 81 uint16_t tcp_server_port;
82
83 bool hole_punching_enabled;
84 bool local_discovery_enabled;
85
86 logger_cb *log_callback;
87 void *log_user_data;
74} Messenger_Options; 88} Messenger_Options;
75 89
76 90
@@ -152,9 +166,6 @@ enum {
152 FILE_PAUSE_BOTH 166 FILE_PAUSE_BOTH
153}; 167};
154 168
155/* This cannot be bigger than 256 */
156#define MAX_CONCURRENT_FILE_PIPES 256
157
158enum { 169enum {
159 FILECONTROL_ACCEPT, 170 FILECONTROL_ACCEPT,
160 FILECONTROL_PAUSE, 171 FILECONTROL_PAUSE,
@@ -171,7 +182,7 @@ enum {
171typedef struct Messenger Messenger; 182typedef struct Messenger Messenger;
172 183
173typedef struct { 184typedef struct {
174 uint8_t real_pk[crypto_box_PUBLICKEYBYTES]; 185 uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
175 int friendcon_id; 186 int friendcon_id;
176 187
177 uint64_t friendrequest_lastsent; // Time at which the last friend request was sent. 188 uint64_t friendrequest_lastsent; // Time at which the last friend request was sent.
@@ -195,7 +206,7 @@ typedef struct {
195 uint64_t last_seen_time; 206 uint64_t last_seen_time;
196 uint8_t last_connection_udp_tcp; 207 uint8_t last_connection_udp_tcp;
197 struct File_Transfers file_sending[MAX_CONCURRENT_FILE_PIPES]; 208 struct File_Transfers file_sending[MAX_CONCURRENT_FILE_PIPES];
198 unsigned int num_sending_files; 209 uint32_t num_sending_files;
199 struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES]; 210 struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES];
200 211
201 struct { 212 struct {
@@ -207,8 +218,8 @@ typedef struct {
207 struct Receipts *receipts_end; 218 struct Receipts *receipts_end;
208} Friend; 219} Friend;
209 220
210
211struct Messenger { 221struct Messenger {
222 Logger *log;
212 223
213 Networking_Core *net; 224 Networking_Core *net;
214 Net_Crypto *net_crypto; 225 Net_Crypto *net_crypto;
@@ -221,7 +232,7 @@ struct Messenger {
221 Friend_Connections *fr_c; 232 Friend_Connections *fr_c;
222 233
223 TCP_Server *tcp_server; 234 TCP_Server *tcp_server;
224 Friend_Requests fr; 235 Friend_Requests *fr;
225 uint8_t name[MAX_NAME_LENGTH]; 236 uint8_t name[MAX_NAME_LENGTH];
226 uint16_t name_length; 237 uint16_t name_length;
227 238
@@ -233,51 +244,37 @@ struct Messenger {
233 Friend *friendlist; 244 Friend *friendlist;
234 uint32_t numfriends; 245 uint32_t numfriends;
235 246
236#define NUM_SAVED_TCP_RELAYS 8 247 time_t lastdump;
248
237 uint8_t has_added_relays; // If the first connection has occurred in do_messenger 249 uint8_t has_added_relays; // If the first connection has occurred in do_messenger
238 Node_format loaded_relays[NUM_SAVED_TCP_RELAYS]; // Relays loaded from config 250 Node_format loaded_relays[NUM_SAVED_TCP_RELAYS]; // Relays loaded from config
239 251
240 void (*friend_message)(struct Messenger *m, uint32_t, unsigned int, const uint8_t *, size_t, void *); 252 void (*friend_message)(struct Messenger *m, uint32_t, unsigned int, const uint8_t *, size_t, void *);
241 void *friend_message_userdata;
242 void (*friend_namechange)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *); 253 void (*friend_namechange)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *);
243 void *friend_namechange_userdata;
244 void (*friend_statusmessagechange)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *); 254 void (*friend_statusmessagechange)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *);
245 void *friend_statusmessagechange_userdata;
246 void (*friend_userstatuschange)(struct Messenger *m, uint32_t, unsigned int, void *); 255 void (*friend_userstatuschange)(struct Messenger *m, uint32_t, unsigned int, void *);
247 void *friend_userstatuschange_userdata; 256 void (*friend_typingchange)(struct Messenger *m, uint32_t, bool, void *);
248 void (*friend_typingchange)(struct Messenger *m, uint32_t, _Bool, void *);
249 void *friend_typingchange_userdata;
250 void (*read_receipt)(struct Messenger *m, uint32_t, uint32_t, void *); 257 void (*read_receipt)(struct Messenger *m, uint32_t, uint32_t, void *);
251 void *read_receipt_userdata;
252 void (*friend_connectionstatuschange)(struct Messenger *m, uint32_t, unsigned int, void *); 258 void (*friend_connectionstatuschange)(struct Messenger *m, uint32_t, unsigned int, void *);
253 void *friend_connectionstatuschange_userdata;
254 void (*friend_connectionstatuschange_internal)(struct Messenger *m, uint32_t, uint8_t, void *); 259 void (*friend_connectionstatuschange_internal)(struct Messenger *m, uint32_t, uint8_t, void *);
255 void *friend_connectionstatuschange_internal_userdata; 260 void *friend_connectionstatuschange_internal_userdata;
256 261
257 void *group_chat_object; /* Set by new_groupchats()*/ 262 void *conferences_object; /* Set by new_groupchats()*/
258 void (*group_invite)(struct Messenger *m, uint32_t, const uint8_t *, uint16_t); 263 void (*conference_invite)(struct Messenger *m, uint32_t, const uint8_t *, uint16_t, void *);
259 void (*group_message)(struct Messenger *m, uint32_t, const uint8_t *, uint16_t);
260 264
261 void (*file_sendrequest)(struct Messenger *m, uint32_t, uint32_t, uint32_t, uint64_t, const uint8_t *, size_t, 265 void (*file_sendrequest)(struct Messenger *m, uint32_t, uint32_t, uint32_t, uint64_t, const uint8_t *, size_t,
262 void *); 266 void *);
263 void *file_sendrequest_userdata;
264 void (*file_filecontrol)(struct Messenger *m, uint32_t, uint32_t, unsigned int, void *); 267 void (*file_filecontrol)(struct Messenger *m, uint32_t, uint32_t, unsigned int, void *);
265 void *file_filecontrol_userdata;
266 void (*file_filedata)(struct Messenger *m, uint32_t, uint32_t, uint64_t, const uint8_t *, size_t, void *); 268 void (*file_filedata)(struct Messenger *m, uint32_t, uint32_t, uint64_t, const uint8_t *, size_t, void *);
267 void *file_filedata_userdata;
268 void (*file_reqchunk)(struct Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *); 269 void (*file_reqchunk)(struct Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *);
269 void *file_reqchunk_userdata;
270 270
271 void (*msi_packet)(struct Messenger *m, uint32_t, const uint8_t *, uint16_t, void *); 271 void (*msi_packet)(struct Messenger *m, uint32_t, const uint8_t *, uint16_t, void *);
272 void *msi_packet_userdata; 272 void *msi_packet_userdata;
273 273
274 void (*lossy_packethandler)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *); 274 void (*lossy_packethandler)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *);
275 void *lossy_packethandler_userdata;
276 void (*lossless_packethandler)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *); 275 void (*lossless_packethandler)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *);
277 void *lossless_packethandler_userdata;
278 276
279 void (*core_connection_change)(struct Messenger *m, unsigned int, void *); 277 void (*core_connection_change)(struct Messenger *m, unsigned int, void *);
280 void *core_connection_change_userdata;
281 unsigned int last_connection_status; 278 unsigned int last_connection_status;
282 279
283 Messenger_Options options; 280 Messenger_Options options;
@@ -291,7 +288,9 @@ void getaddress(const Messenger *m, uint8_t *address);
291 288
292/* Add a friend. 289/* Add a friend.
293 * Set the data that will be sent along with friend request. 290 * Set the data that will be sent along with friend request.
294 * address is the address of the friend (returned by getaddress of the friend you wish to add) it must be FRIEND_ADDRESS_SIZE bytes. TODO: add checksum. 291 * address is the address of the friend (returned by getaddress of the friend
292 * you wish to add) it must be FRIEND_ADDRESS_SIZE bytes.
293 * TODO(irungentoo): add checksum.
295 * data is the data and length is the length. 294 * data is the data and length is the length.
296 * 295 *
297 * return the friend number if success. 296 * return the friend number if success.
@@ -322,7 +321,7 @@ int32_t m_addfriend_norequest(Messenger *m, const uint8_t *real_pk);
322int32_t getfriend_id(const Messenger *m, const uint8_t *real_pk); 321int32_t getfriend_id(const Messenger *m, const uint8_t *real_pk);
323 322
324/* Copies the public key associated to that friend id into real_pk buffer. 323/* Copies the public key associated to that friend id into real_pk buffer.
325 * Make sure that real_pk is of size crypto_box_PUBLICKEYBYTES. 324 * Make sure that real_pk is of size CRYPTO_PUBLIC_KEY_SIZE.
326 * 325 *
327 * return 0 if success 326 * return 0 if success
328 * return -1 if failure 327 * return -1 if failure
@@ -470,43 +469,44 @@ int m_set_usertyping(Messenger *m, int32_t friendnumber, uint8_t is_typing);
470 */ 469 */
471int m_get_istyping(const Messenger *m, int32_t friendnumber); 470int m_get_istyping(const Messenger *m, int32_t friendnumber);
472 471
472/* Set the logger callback.
473 */
474void m_callback_log(Messenger *m, logger_cb *function, void *context, void *userdata);
475
473/* Set the function that will be executed when a friend request is received. 476/* Set the function that will be executed when a friend request is received.
474 * Function format is function(uint8_t * public_key, uint8_t * data, size_t length) 477 * Function format is function(uint8_t * public_key, uint8_t * data, size_t length)
475 */ 478 */
476void m_callback_friendrequest(Messenger *m, void (*function)(Messenger *m, const uint8_t *, const uint8_t *, size_t, 479void m_callback_friendrequest(Messenger *m, void (*function)(Messenger *m, const uint8_t *, const uint8_t *, size_t,
477 void *), void *userdata); 480 void *));
478 481
479/* Set the function that will be executed when a message from a friend is received. 482/* Set the function that will be executed when a message from a friend is received.
480 * Function format is: function(uint32_t friendnumber, unsigned int type, uint8_t * message, uint32_t length) 483 * Function format is: function(uint32_t friendnumber, unsigned int type, uint8_t * message, uint32_t length)
481 */ 484 */
482void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, const uint8_t *, 485void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, const uint8_t *,
483 size_t, void *), void *userdata); 486 size_t, void *));
484 487
485/* Set the callback for name changes. 488/* Set the callback for name changes.
486 * Function(uint32_t friendnumber, uint8_t *newname, size_t length) 489 * Function(uint32_t friendnumber, uint8_t *newname, size_t length)
487 * You are not responsible for freeing newname. 490 * You are not responsible for freeing newname.
488 */ 491 */
489void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *), 492void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *));
490 void *userdata);
491 493
492/* Set the callback for status message changes. 494/* Set the callback for status message changes.
493 * Function(uint32_t friendnumber, uint8_t *newstatus, size_t length) 495 * Function(uint32_t friendnumber, uint8_t *newstatus, size_t length)
494 * 496 *
495 * You are not responsible for freeing newstatus 497 * You are not responsible for freeing newstatus
496 */ 498 */
497void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *), 499void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *));
498 void *userdata);
499 500
500/* Set the callback for status type changes. 501/* Set the callback for status type changes.
501 * Function(uint32_t friendnumber, USERSTATUS kind) 502 * Function(uint32_t friendnumber, USERSTATUS kind)
502 */ 503 */
503void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *), 504void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *));
504 void *userdata);
505 505
506/* Set the callback for typing changes. 506/* Set the callback for typing changes.
507 * Function(uint32_t friendnumber, uint8_t is_typing) 507 * Function(uint32_t friendnumber, uint8_t is_typing)
508 */ 508 */
509void m_callback_typingchange(Messenger *m, void(*function)(Messenger *m, uint32_t, _Bool, void *), void *userdata); 509void m_callback_typingchange(Messenger *m, void(*function)(Messenger *m, uint32_t, bool, void *));
510 510
511/* Set the callback for read receipts. 511/* Set the callback for read receipts.
512 * Function(uint32_t friendnumber, uint32_t receipt) 512 * Function(uint32_t friendnumber, uint32_t receipt)
@@ -517,7 +517,7 @@ void m_callback_typingchange(Messenger *m, void(*function)(Messenger *m, uint32_
517 * Since core doesn't track ids for you, receipt may not correspond to any message. 517 * Since core doesn't track ids for you, receipt may not correspond to any message.
518 * In that case, you should discard it. 518 * In that case, you should discard it.
519 */ 519 */
520void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, void *), void *userdata); 520void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, void *));
521 521
522/* Set the callback for connection status changes. 522/* Set the callback for connection status changes.
523 * function(uint32_t friendnumber, uint8_t status) 523 * function(uint32_t friendnumber, uint8_t status)
@@ -530,8 +530,8 @@ void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, uint32
530 * being previously online" part. 530 * being previously online" part.
531 * It's assumed that when adding friends, their connection status is offline. 531 * It's assumed that when adding friends, their connection status is offline.
532 */ 532 */
533void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *), 533void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *));
534 void *userdata); 534
535/* Same as previous but for internal A/V core usage only */ 535/* Same as previous but for internal A/V core usage only */
536void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, void *), 536void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, void *),
537 void *userdata); 537 void *userdata);
@@ -540,22 +540,23 @@ void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Mess
540/* Set the callback for typing changes. 540/* Set the callback for typing changes.
541 * Function(unsigned int connection_status (0 = not connected, 1 = TCP only, 2 = UDP + TCP)) 541 * Function(unsigned int connection_status (0 = not connected, 1 = TCP only, 2 = UDP + TCP))
542 */ 542 */
543void m_callback_core_connection(Messenger *m, void (*function)(Messenger *m, unsigned int, void *), void *userdata); 543void m_callback_core_connection(Messenger *m, void (*function)(Messenger *m, unsigned int, void *));
544 544
545/**********GROUP CHATS************/ 545/**********CONFERENCES************/
546 546
547/* Set the callback for group invites. 547/* Set the callback for conference invites.
548 * 548 *
549 * Function(Messenger *m, uint32_t friendnumber, uint8_t *data, uint16_t length) 549 * Function(Messenger *m, uint32_t friendnumber, uint8_t *data, uint16_t length, void *userdata)
550 */ 550 */
551void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, uint16_t)); 551void m_callback_conference_invite(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, uint16_t,
552 void *));
552 553
553/* Send a group invite packet. 554/* Send a conference invite packet.
554 * 555 *
555 * return 1 on success 556 * return 1 on success
556 * return 0 on failure 557 * return 0 on failure
557 */ 558 */
558int send_group_invite_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length); 559int send_conference_invite_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length);
559 560
560/****************FILE SENDING*****************/ 561/****************FILE SENDING*****************/
561 562
@@ -565,7 +566,7 @@ int send_group_invite_packet(const Messenger *m, int32_t friendnumber, const uin
565 * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint32_t filetype, uint64_t filesize, uint8_t *filename, size_t filename_length, void *userdata) 566 * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint32_t filetype, uint64_t filesize, uint8_t *filename, size_t filename_length, void *userdata)
566 */ 567 */
567void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint32_t, uint64_t, 568void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint32_t, uint64_t,
568 const uint8_t *, size_t, void *), void *userdata); 569 const uint8_t *, size_t, void *));
569 570
570 571
571/* Set the callback for file control requests. 572/* Set the callback for file control requests.
@@ -573,8 +574,7 @@ void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, uin
573 * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, unsigned int control_type, void *userdata) 574 * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, unsigned int control_type, void *userdata)
574 * 575 *
575 */ 576 */
576void callback_file_control(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, unsigned int, void *), 577void callback_file_control(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, unsigned int, void *));
577 void *userdata);
578 578
579/* Set the callback for file data. 579/* Set the callback for file data.
580 * 580 *
@@ -582,15 +582,14 @@ void callback_file_control(Messenger *m, void (*function)(Messenger *m, uint32_t
582 * 582 *
583 */ 583 */
584void callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, const uint8_t *, 584void callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, const uint8_t *,
585 size_t, void *), void *userdata); 585 size_t, void *));
586 586
587/* Set the callback for file request chunk. 587/* Set the callback for file request chunk.
588 * 588 *
589 * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length, void *userdata) 589 * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length, void *userdata)
590 * 590 *
591 */ 591 */
592void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *), 592void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *));
593 void *userdata);
594 593
595 594
596/* Copy the file transfer file id to file_id 595/* Copy the file transfer file id to file_id
@@ -693,7 +692,7 @@ int m_callback_rtp_packet(Messenger *m, int32_t friendnumber, uint8_t byte, int
693 * 692 *
694 */ 693 */
695void custom_lossy_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m, 694void custom_lossy_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m,
696 uint32_t friendnumber, const uint8_t *data, size_t len, void *object), void *object); 695 uint32_t friendnumber, const uint8_t *data, size_t len, void *object));
697 696
698/* High level function to send custom lossy packets. 697/* High level function to send custom lossy packets.
699 * 698 *
@@ -704,14 +703,14 @@ void custom_lossy_packet_registerhandler(Messenger *m, void (*packet_handler_cal
704 * return -5 if packet failed to send because of other error. 703 * return -5 if packet failed to send because of other error.
705 * return 0 on success. 704 * return 0 on success.
706 */ 705 */
707int send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length); 706int m_send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length);
708 707
709 708
710/* Set handlers for custom lossless packets. 709/* Set handlers for custom lossless packets.
711 * 710 *
712 */ 711 */
713void custom_lossless_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m, 712void custom_lossless_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m,
714 uint32_t friendnumber, const uint8_t *data, size_t len, void *object), void *object); 713 uint32_t friendnumber, const uint8_t *data, size_t len, void *object));
715 714
716/* High level function to send custom lossless packets. 715/* High level function to send custom lossless packets.
717 * 716 *
@@ -747,7 +746,7 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error);
747void kill_messenger(Messenger *m); 746void kill_messenger(Messenger *m);
748 747
749/* The main loop that needs to be run at least 20 times per second. */ 748/* The main loop that needs to be run at least 20 times per second. */
750void do_messenger(Messenger *m); 749void do_messenger(Messenger *m, void *userdata);
751 750
752/* Return the time in milliseconds before do_messenger() should be called again 751/* Return the time in milliseconds before do_messenger() should be called again
753 * for optimal performance. 752 * for optimal performance.
diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c
index 752deecf..d1cd4d66 100644
--- a/toxcore/TCP_client.c
+++ b/toxcore/TCP_client.c
@@ -1,70 +1,131 @@
1/* 1/*
2* TCP_client.c -- Implementation of the TCP relay client part of Tox. 2 * Implementation of the TCP relay client part of Tox.
3* 3 */
4* Copyright (C) 2014 Tox project All Rights Reserved.
5*
6* This file is part of Tox.
7*
8* Tox is free software: you can redistribute it and/or modify
9* it under the terms of the GNU General Public License as published by
10* the Free Software Foundation, either version 3 of the License, or
11* (at your option) any later version.
12*
13* Tox is distributed in the hope that it will be useful,
14* but WITHOUT ANY WARRANTY; without even the implied warranty of
15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16* GNU General Public License for more details.
17*
18* You should have received a copy of the GNU General Public License
19* along with Tox. If not, see <http://www.gnu.org/licenses/>.
20*
21*/
22 4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2014 Tox project.
8 *
9 * This file is part of Tox, the free peer to peer instant messenger.
10 *
11 * Tox is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * Tox is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
23 */
23#ifdef HAVE_CONFIG_H 24#ifdef HAVE_CONFIG_H
24#include "config.h" 25#include "config.h"
25#endif 26#endif
26 27
27#include "TCP_client.h" 28#include "TCP_client.h"
28 29
29#if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32) 30#include <stdio.h>
30#include <sys/ioctl.h> 31#include <stdlib.h>
31#endif 32#include <string.h>
32 33
33#include "util.h" 34#include "util.h"
34 35
36struct TCP_Client_Connection {
37 TCP_CLIENT_STATUS status;
38 Socket sock;
39 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* our public key */
40 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* public key of the server */
41 IP_Port ip_port; /* The ip and port of the server */
42 TCP_Proxy_Info proxy_info;
43 uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of received packets. */
44 uint8_t sent_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of sent packets. */
45 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
46 uint16_t next_packet_length;
47
48 uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE];
49
50 uint8_t last_packet[2 + MAX_PACKET_SIZE];
51 uint16_t last_packet_length;
52 uint16_t last_packet_sent;
53
54 TCP_Priority_List *priority_queue_start, *priority_queue_end;
55
56 uint64_t kill_at;
57
58 uint64_t last_pinged;
59 uint64_t ping_id;
60
61 uint64_t ping_response_id;
62 uint64_t ping_request_id;
63
64 struct {
65 uint8_t status; /* 0 if not used, 1 if other is offline, 2 if other is online. */
66 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
67 uint32_t number;
68 } connections[NUM_CLIENT_CONNECTIONS];
69 int (*response_callback)(void *object, uint8_t connection_id, const uint8_t *public_key);
70 void *response_callback_object;
71 int (*status_callback)(void *object, uint32_t number, uint8_t connection_id, uint8_t status);
72 void *status_callback_object;
73 int (*data_callback)(void *object, uint32_t number, uint8_t connection_id, const uint8_t *data, uint16_t length,
74 void *userdata);
75 void *data_callback_object;
76 int (*oob_data_callback)(void *object, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata);
77 void *oob_data_callback_object;
78
79 int (*onion_callback)(void *object, const uint8_t *data, uint16_t length, void *userdata);
80 void *onion_callback_object;
81
82 /* Can be used by user. */
83 void *custom_object;
84 uint32_t custom_uint;
85};
86
87const uint8_t *tcp_con_public_key(const TCP_Client_Connection *con)
88{
89 return con->public_key;
90}
91
92IP_Port tcp_con_ip_port(const TCP_Client_Connection *con)
93{
94 return con->ip_port;
95}
96
97TCP_CLIENT_STATUS tcp_con_status(const TCP_Client_Connection *con)
98{
99 return con->status;
100}
101void *tcp_con_custom_object(const TCP_Client_Connection *con)
102{
103 return con->custom_object;
104}
105uint32_t tcp_con_custom_uint(const TCP_Client_Connection *con)
106{
107 return con->custom_uint;
108}
109void tcp_con_set_custom_object(TCP_Client_Connection *con, void *object)
110{
111 con->custom_object = object;
112}
113void tcp_con_set_custom_uint(TCP_Client_Connection *con, uint32_t value)
114{
115 con->custom_uint = value;
116}
117
35/* return 1 on success 118/* return 1 on success
36 * return 0 on failure 119 * return 0 on failure
37 */ 120 */
38static int connect_sock_to(sock_t sock, IP_Port ip_port, TCP_Proxy_Info *proxy_info) 121static int connect_sock_to(Socket sock, IP_Port ip_port, TCP_Proxy_Info *proxy_info)
39{ 122{
40 if (proxy_info->proxy_type != TCP_PROXY_NONE) { 123 if (proxy_info->proxy_type != TCP_PROXY_NONE) {
41 ip_port = proxy_info->ip_port; 124 ip_port = proxy_info->ip_port;
42 } 125 }
43 126
44 struct sockaddr_storage addr = {0};
45
46 size_t addrsize;
47
48 if (ip_port.ip.family == AF_INET) {
49 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
50
51 addrsize = sizeof(struct sockaddr_in);
52 addr4->sin_family = AF_INET;
53 addr4->sin_addr = ip_port.ip.ip4.in_addr;
54 addr4->sin_port = ip_port.port;
55 } else if (ip_port.ip.family == AF_INET6) {
56 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
57
58 addrsize = sizeof(struct sockaddr_in6);
59 addr6->sin6_family = AF_INET6;
60 addr6->sin6_addr = ip_port.ip.ip6.in6_addr;
61 addr6->sin6_port = ip_port.port;
62 } else {
63 return 0;
64 }
65
66 /* nonblocking socket, connect will never return success */ 127 /* nonblocking socket, connect will never return success */
67 connect(sock, (struct sockaddr *)&addr, addrsize); 128 net_connect(sock, ip_port);
68 return 1; 129 return 1;
69} 130}
70 131
@@ -77,13 +138,13 @@ static int proxy_http_generate_connection_request(TCP_Client_Connection *TCP_con
77 char two[] = " HTTP/1.1\nHost: "; 138 char two[] = " HTTP/1.1\nHost: ";
78 char three[] = "\r\n\r\n"; 139 char three[] = "\r\n\r\n";
79 140
80 char ip[INET6_ADDRSTRLEN]; 141 char ip[TOX_INET6_ADDRSTRLEN];
81 142
82 if (!ip_parse_addr(&TCP_conn->ip_port.ip, ip, sizeof(ip))) { 143 if (!ip_parse_addr(&TCP_conn->ip_port.ip, ip, sizeof(ip))) {
83 return 0; 144 return 0;
84 } 145 }
85 146
86 const uint16_t port = ntohs(TCP_conn->ip_port.port); 147 const uint16_t port = net_ntohs(TCP_conn->ip_port.port);
87 const int written = snprintf((char *)TCP_conn->last_packet, MAX_PACKET_SIZE, "%s%s:%hu%s%s:%hu%s", one, ip, port, two, 148 const int written = snprintf((char *)TCP_conn->last_packet, MAX_PACKET_SIZE, "%s%s:%hu%s%s:%hu%s", one, ip, port, two,
88 ip, port, three); 149 ip, port, three);
89 150
@@ -116,10 +177,10 @@ static int proxy_http_read_connection_response(TCP_Client_Connection *TCP_conn)
116 177
117 if (strstr((char *)data, success)) { 178 if (strstr((char *)data, success)) {
118 // drain all data 179 // drain all data
119 unsigned int data_left = TCP_socket_data_recv_buffer(TCP_conn->sock); 180 unsigned int data_left = net_socket_data_recv_buffer(TCP_conn->sock);
120 181
121 if (data_left) { 182 if (data_left) {
122 uint8_t temp_data[data_left]; 183 VLA(uint8_t, temp_data, data_left);
123 read_TCP_packet(TCP_conn->sock, temp_data, data_left); 184 read_TCP_packet(TCP_conn->sock, temp_data, data_left);
124 } 185 }
125 186
@@ -148,11 +209,13 @@ static int socks5_read_handshake_response(TCP_Client_Connection *TCP_conn)
148 uint8_t data[2]; 209 uint8_t data[2];
149 int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data)); 210 int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data));
150 211
151 if (ret == -1) 212 if (ret == -1) {
152 return 0; 213 return 0;
214 }
153 215
154 if (data[0] == 5 && data[1] == 0) // FIXME magic numbers 216 if (data[0] == 5 && data[1] == 0) { // TODO(irungentoo): magic numbers
155 return 1; 217 return 1;
218 }
156 219
157 return -1; 220 return -1;
158} 221}
@@ -164,15 +227,15 @@ static void proxy_socks5_generate_connection_request(TCP_Client_Connection *TCP_
164 TCP_conn->last_packet[2] = 0; /* reserved, must be 0 */ 227 TCP_conn->last_packet[2] = 0; /* reserved, must be 0 */
165 uint16_t length = 3; 228 uint16_t length = 3;
166 229
167 if (TCP_conn->ip_port.ip.family == AF_INET) { 230 if (net_family_is_ipv4(TCP_conn->ip_port.ip.family)) {
168 TCP_conn->last_packet[3] = 1; /* IPv4 address */ 231 TCP_conn->last_packet[3] = 1; /* IPv4 address */
169 ++length; 232 ++length;
170 memcpy(TCP_conn->last_packet + length, TCP_conn->ip_port.ip.ip4.uint8, sizeof(IP4)); 233 memcpy(TCP_conn->last_packet + length, TCP_conn->ip_port.ip.ip.v4.uint8, sizeof(IP4));
171 length += sizeof(IP4); 234 length += sizeof(IP4);
172 } else { 235 } else {
173 TCP_conn->last_packet[3] = 4; /* IPv6 address */ 236 TCP_conn->last_packet[3] = 4; /* IPv6 address */
174 ++length; 237 ++length;
175 memcpy(TCP_conn->last_packet + length, TCP_conn->ip_port.ip.ip6.uint8, sizeof(IP6)); 238 memcpy(TCP_conn->last_packet + length, TCP_conn->ip_port.ip.ip.v6.uint8, sizeof(IP6));
176 length += sizeof(IP6); 239 length += sizeof(IP6);
177 } 240 }
178 241
@@ -189,25 +252,28 @@ static void proxy_socks5_generate_connection_request(TCP_Client_Connection *TCP_
189 */ 252 */
190static int proxy_socks5_read_connection_response(TCP_Client_Connection *TCP_conn) 253static int proxy_socks5_read_connection_response(TCP_Client_Connection *TCP_conn)
191{ 254{
192 if (TCP_conn->ip_port.ip.family == AF_INET) { 255 if (net_family_is_ipv4(TCP_conn->ip_port.ip.family)) {
193 uint8_t data[4 + sizeof(IP4) + sizeof(uint16_t)]; 256 uint8_t data[4 + sizeof(IP4) + sizeof(uint16_t)];
194 int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data)); 257 int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data));
195 258
196 if (ret == -1) 259 if (ret == -1) {
197 return 0; 260 return 0;
261 }
198 262
199 if (data[0] == 5 && data[1] == 0) 263 if (data[0] == 5 && data[1] == 0) {
200 return 1; 264 return 1;
201 265 }
202 } else { 266 } else {
203 uint8_t data[4 + sizeof(IP6) + sizeof(uint16_t)]; 267 uint8_t data[4 + sizeof(IP6) + sizeof(uint16_t)];
204 int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data)); 268 int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data));
205 269
206 if (ret == -1) 270 if (ret == -1) {
207 return 0; 271 return 0;
272 }
208 273
209 if (data[0] == 5 && data[1] == 0) 274 if (data[0] == 5 && data[1] == 0) {
210 return 1; 275 return 1;
276 }
211 } 277 }
212 278
213 return -1; 279 return -1;
@@ -218,19 +284,20 @@ static int proxy_socks5_read_connection_response(TCP_Client_Connection *TCP_conn
218 */ 284 */
219static int generate_handshake(TCP_Client_Connection *TCP_conn) 285static int generate_handshake(TCP_Client_Connection *TCP_conn)
220{ 286{
221 uint8_t plain[crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES]; 287 uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE];
222 crypto_box_keypair(plain, TCP_conn->temp_secret_key); 288 crypto_new_keypair(plain, TCP_conn->temp_secret_key);
223 random_nonce(TCP_conn->sent_nonce); 289 random_nonce(TCP_conn->sent_nonce);
224 memcpy(plain + crypto_box_PUBLICKEYBYTES, TCP_conn->sent_nonce, crypto_box_NONCEBYTES); 290 memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, TCP_conn->sent_nonce, CRYPTO_NONCE_SIZE);
225 memcpy(TCP_conn->last_packet, TCP_conn->self_public_key, crypto_box_PUBLICKEYBYTES); 291 memcpy(TCP_conn->last_packet, TCP_conn->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
226 new_nonce(TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES); 292 random_nonce(TCP_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE);
227 int len = encrypt_data_symmetric(TCP_conn->shared_key, TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES, plain, 293 int len = encrypt_data_symmetric(TCP_conn->shared_key, TCP_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE, plain,
228 sizeof(plain), TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); 294 sizeof(plain), TCP_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
229 295
230 if (len != sizeof(plain) + crypto_box_MACBYTES) 296 if (len != sizeof(plain) + CRYPTO_MAC_SIZE) {
231 return -1; 297 return -1;
298 }
232 299
233 TCP_conn->last_packet_length = crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + sizeof(plain) + crypto_box_MACBYTES; 300 TCP_conn->last_packet_length = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + sizeof(plain) + CRYPTO_MAC_SIZE;
234 TCP_conn->last_packet_sent = 0; 301 TCP_conn->last_packet_sent = 0;
235 return 0; 302 return 0;
236} 303}
@@ -242,33 +309,35 @@ static int generate_handshake(TCP_Client_Connection *TCP_conn)
242 */ 309 */
243static int handle_handshake(TCP_Client_Connection *TCP_conn, const uint8_t *data) 310static int handle_handshake(TCP_Client_Connection *TCP_conn, const uint8_t *data)
244{ 311{
245 uint8_t plain[crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES]; 312 uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE];
246 int len = decrypt_data_symmetric(TCP_conn->shared_key, data, data + crypto_box_NONCEBYTES, 313 int len = decrypt_data_symmetric(TCP_conn->shared_key, data, data + CRYPTO_NONCE_SIZE,
247 TCP_SERVER_HANDSHAKE_SIZE - crypto_box_NONCEBYTES, plain); 314 TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, plain);
248 315
249 if (len != sizeof(plain)) 316 if (len != sizeof(plain)) {
250 return -1; 317 return -1;
318 }
251 319
252 memcpy(TCP_conn->recv_nonce, plain + crypto_box_PUBLICKEYBYTES, crypto_box_NONCEBYTES); 320 memcpy(TCP_conn->recv_nonce, plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_NONCE_SIZE);
253 encrypt_precompute(plain, TCP_conn->temp_secret_key, TCP_conn->shared_key); 321 encrypt_precompute(plain, TCP_conn->temp_secret_key, TCP_conn->shared_key);
254 sodium_memzero(TCP_conn->temp_secret_key, crypto_box_SECRETKEYBYTES); 322 crypto_memzero(TCP_conn->temp_secret_key, CRYPTO_SECRET_KEY_SIZE);
255 return 0; 323 return 0;
256} 324}
257 325
258/* return 0 if pending data was sent completely 326/* return 0 if pending data was sent completely
259 * return -1 if it wasn't 327 * return -1 if it wasn't
260 */ 328 */
261static int send_pending_data_nonpriority(TCP_Client_Connection *con) 329static int client_send_pending_data_nonpriority(TCP_Client_Connection *con)
262{ 330{
263 if (con->last_packet_length == 0) { 331 if (con->last_packet_length == 0) {
264 return 0; 332 return 0;
265 } 333 }
266 334
267 uint16_t left = con->last_packet_length - con->last_packet_sent; 335 const uint16_t left = con->last_packet_length - con->last_packet_sent;
268 int len = send(con->sock, con->last_packet + con->last_packet_sent, left, MSG_NOSIGNAL); 336 const int len = net_send(con->sock, con->last_packet + con->last_packet_sent, left);
269 337
270 if (len <= 0) 338 if (len <= 0) {
271 return -1; 339 return -1;
340 }
272 341
273 if (len == left) { 342 if (len == left) {
274 con->last_packet_length = 0; 343 con->last_packet_length = 0;
@@ -283,18 +352,18 @@ static int send_pending_data_nonpriority(TCP_Client_Connection *con)
283/* return 0 if pending data was sent completely 352/* return 0 if pending data was sent completely
284 * return -1 if it wasn't 353 * return -1 if it wasn't
285 */ 354 */
286static int send_pending_data(TCP_Client_Connection *con) 355static int client_send_pending_data(TCP_Client_Connection *con)
287{ 356{
288 /* finish sending current non-priority packet */ 357 /* finish sending current non-priority packet */
289 if (send_pending_data_nonpriority(con) == -1) { 358 if (client_send_pending_data_nonpriority(con) == -1) {
290 return -1; 359 return -1;
291 } 360 }
292 361
293 TCP_Priority_List *p = con->priority_queue_start; 362 TCP_Priority_List *p = con->priority_queue_start;
294 363
295 while (p) { 364 while (p) {
296 uint16_t left = p->size - p->sent; 365 const uint16_t left = p->size - p->sent;
297 int len = send(con->sock, p->data + p->sent, left, MSG_NOSIGNAL); 366 const int len = net_send(con->sock, p->data + p->sent, left);
298 367
299 if (len != left) { 368 if (len != left) {
300 if (len > 0) { 369 if (len > 0) {
@@ -312,7 +381,7 @@ static int send_pending_data(TCP_Client_Connection *con)
312 con->priority_queue_start = p; 381 con->priority_queue_start = p;
313 382
314 if (!p) { 383 if (!p) {
315 con->priority_queue_end = NULL; 384 con->priority_queue_end = nullptr;
316 return 0; 385 return 0;
317 } 386 }
318 387
@@ -322,27 +391,27 @@ static int send_pending_data(TCP_Client_Connection *con)
322/* return 0 on failure (only if malloc fails) 391/* return 0 on failure (only if malloc fails)
323 * return 1 on success 392 * return 1 on success
324 */ 393 */
325static _Bool add_priority(TCP_Client_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent) 394static bool client_add_priority(TCP_Client_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent)
326{ 395{
327 TCP_Priority_List *p = con->priority_queue_end, *new; 396 TCP_Priority_List *p = con->priority_queue_end;
328 new = malloc(sizeof(TCP_Priority_List) + size); 397 TCP_Priority_List *new_list = (TCP_Priority_List *)malloc(sizeof(TCP_Priority_List) + size);
329 398
330 if (!new) { 399 if (!new_list) {
331 return 0; 400 return 0;
332 } 401 }
333 402
334 new->next = NULL; 403 new_list->next = nullptr;
335 new->size = size; 404 new_list->size = size;
336 new->sent = sent; 405 new_list->sent = sent;
337 memcpy(new->data, packet, size); 406 memcpy(new_list->data, packet, size);
338 407
339 if (p) { 408 if (p) {
340 p->next = new; 409 p->next = new_list;
341 } else { 410 } else {
342 con->priority_queue_start = new; 411 con->priority_queue_start = new_list;
343 } 412 }
344 413
345 con->priority_queue_end = new; 414 con->priority_queue_end = new_list;
346 return 1; 415 return 1;
347} 416}
348 417
@@ -355,22 +424,22 @@ static void wipe_priority_list(TCP_Client_Connection *con)
355 p = p->next; 424 p = p->next;
356 free(pp); 425 free(pp);
357 } 426 }
358
359} 427}
360 428
361/* return 1 on success. 429/* return 1 on success.
362 * return 0 if could not send packet. 430 * return 0 if could not send packet.
363 * return -1 on failure (connection must be killed). 431 * return -1 on failure (connection must be killed).
364 */ 432 */
365static int write_packet_TCP_secure_connection(TCP_Client_Connection *con, const uint8_t *data, uint16_t length, 433static int write_packet_TCP_client_secure_connection(TCP_Client_Connection *con, const uint8_t *data, uint16_t length,
366 _Bool priority) 434 bool priority)
367{ 435{
368 if (length + crypto_box_MACBYTES > MAX_PACKET_SIZE) 436 if (length + CRYPTO_MAC_SIZE > MAX_PACKET_SIZE) {
369 return -1; 437 return -1;
438 }
370 439
371 _Bool sendpriority = 1; 440 bool sendpriority = 1;
372 441
373 if (send_pending_data(con) == -1) { 442 if (client_send_pending_data(con) == -1) {
374 if (priority) { 443 if (priority) {
375 sendpriority = 0; 444 sendpriority = 0;
376 } else { 445 } else {
@@ -378,17 +447,18 @@ static int write_packet_TCP_secure_connection(TCP_Client_Connection *con, const
378 } 447 }
379 } 448 }
380 449
381 uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES]; 450 VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE);
382 451
383 uint16_t c_length = htons(length + crypto_box_MACBYTES); 452 uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE);
384 memcpy(packet, &c_length, sizeof(uint16_t)); 453 memcpy(packet, &c_length, sizeof(uint16_t));
385 int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); 454 int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));
386 455
387 if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) 456 if ((unsigned int)len != (SIZEOF_VLA(packet) - sizeof(uint16_t))) {
388 return -1; 457 return -1;
458 }
389 459
390 if (priority) { 460 if (priority) {
391 len = sendpriority ? send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL) : 0; 461 len = sendpriority ? net_send(con->sock, packet, SIZEOF_VLA(packet)) : 0;
392 462
393 if (len <= 0) { 463 if (len <= 0) {
394 len = 0; 464 len = 0;
@@ -396,25 +466,27 @@ static int write_packet_TCP_secure_connection(TCP_Client_Connection *con, const
396 466
397 increment_nonce(con->sent_nonce); 467 increment_nonce(con->sent_nonce);
398 468
399 if ((unsigned int)len == sizeof(packet)) { 469 if ((unsigned int)len == SIZEOF_VLA(packet)) {
400 return 1; 470 return 1;
401 } 471 }
402 472
403 return add_priority(con, packet, sizeof(packet), len); 473 return client_add_priority(con, packet, SIZEOF_VLA(packet), len);
404 } 474 }
405 475
406 len = send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL); 476 len = net_send(con->sock, packet, SIZEOF_VLA(packet));
407 477
408 if (len <= 0) 478 if (len <= 0) {
409 return 0; 479 return 0;
480 }
410 481
411 increment_nonce(con->sent_nonce); 482 increment_nonce(con->sent_nonce);
412 483
413 if ((unsigned int)len == sizeof(packet)) 484 if ((unsigned int)len == SIZEOF_VLA(packet)) {
414 return 1; 485 return 1;
486 }
415 487
416 memcpy(con->last_packet, packet, sizeof(packet)); 488 memcpy(con->last_packet, packet, SIZEOF_VLA(packet));
417 con->last_packet_length = sizeof(packet); 489 con->last_packet_length = SIZEOF_VLA(packet);
418 con->last_packet_sent = len; 490 con->last_packet_sent = len;
419 return 1; 491 return 1;
420} 492}
@@ -425,10 +497,10 @@ static int write_packet_TCP_secure_connection(TCP_Client_Connection *con, const
425 */ 497 */
426int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key) 498int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key)
427{ 499{
428 uint8_t packet[1 + crypto_box_PUBLICKEYBYTES]; 500 uint8_t packet[1 + CRYPTO_PUBLIC_KEY_SIZE];
429 packet[0] = TCP_PACKET_ROUTING_REQUEST; 501 packet[0] = TCP_PACKET_ROUTING_REQUEST;
430 memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); 502 memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);
431 return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 1); 503 return write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1);
432} 504}
433 505
434void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id, 506void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id,
@@ -445,8 +517,8 @@ void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(v
445 con->status_callback_object = object; 517 con->status_callback_object = object;
446} 518}
447 519
448static int send_ping_response(TCP_Client_Connection *con); 520static int tcp_send_ping_response(TCP_Client_Connection *con);
449static int send_ping_request(TCP_Client_Connection *con); 521static int tcp_send_ping_request(TCP_Client_Connection *con);
450 522
451/* return 1 on success. 523/* return 1 on success.
452 * return 0 if could not send packet. 524 * return 0 if could not send packet.
@@ -454,19 +526,22 @@ static int send_ping_request(TCP_Client_Connection *con);
454 */ 526 */
455int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length) 527int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length)
456{ 528{
457 if (con_id >= NUM_CLIENT_CONNECTIONS) 529 if (con_id >= NUM_CLIENT_CONNECTIONS) {
458 return -1; 530 return -1;
531 }
459 532
460 if (con->connections[con_id].status != 2) 533 if (con->connections[con_id].status != 2) {
461 return -1; 534 return -1;
535 }
462 536
463 if (send_ping_response(con) == 0 || send_ping_request(con) == 0) 537 if (tcp_send_ping_response(con) == 0 || tcp_send_ping_request(con) == 0) {
464 return 0; 538 return 0;
539 }
465 540
466 uint8_t packet[1 + length]; 541 VLA(uint8_t, packet, 1 + length);
467 packet[0] = con_id + NUM_RESERVED_PORTS; 542 packet[0] = con_id + NUM_RESERVED_PORTS;
468 memcpy(packet + 1, data, length); 543 memcpy(packet + 1, data, length);
469 return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 0); 544 return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0);
470} 545}
471 546
472/* return 1 on success. 547/* return 1 on success.
@@ -475,14 +550,15 @@ int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, u
475 */ 550 */
476int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data, uint16_t length) 551int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data, uint16_t length)
477{ 552{
478 if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) 553 if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) {
479 return -1; 554 return -1;
555 }
480 556
481 uint8_t packet[1 + crypto_box_PUBLICKEYBYTES + length]; 557 VLA(uint8_t, packet, 1 + CRYPTO_PUBLIC_KEY_SIZE + length);
482 packet[0] = TCP_PACKET_OOB_SEND; 558 packet[0] = TCP_PACKET_OOB_SEND;
483 memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); 559 memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);
484 memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, data, length); 560 memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length);
485 return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 0); 561 return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0);
486} 562}
487 563
488 564
@@ -495,25 +571,27 @@ int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const
495 */ 571 */
496int set_tcp_connection_number(TCP_Client_Connection *con, uint8_t con_id, uint32_t number) 572int set_tcp_connection_number(TCP_Client_Connection *con, uint8_t con_id, uint32_t number)
497{ 573{
498 if (con_id >= NUM_CLIENT_CONNECTIONS) 574 if (con_id >= NUM_CLIENT_CONNECTIONS) {
499 return -1; 575 return -1;
576 }
500 577
501 if (con->connections[con_id].status == 0) 578 if (con->connections[con_id].status == 0) {
502 return -1; 579 return -1;
580 }
503 581
504 con->connections[con_id].number = number; 582 con->connections[con_id].number = number;
505 return 0; 583 return 0;
506} 584}
507 585
508void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number, 586void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number,
509 uint8_t connection_id, const uint8_t *data, uint16_t length), void *object) 587 uint8_t connection_id, const uint8_t *data, uint16_t length, void *userdata), void *object)
510{ 588{
511 con->data_callback = data_callback; 589 con->data_callback = data_callback;
512 con->data_callback_object = object; 590 con->data_callback_object = object;
513} 591}
514 592
515void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, const uint8_t *public_key, 593void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, const uint8_t *public_key,
516 const uint8_t *data, uint16_t length), void *object) 594 const uint8_t *data, uint16_t length, void *userdata), void *object)
517{ 595{
518 con->oob_data_callback = oob_data_callback; 596 con->oob_data_callback = oob_data_callback;
519 con->oob_data_callback_object = object; 597 con->oob_data_callback_object = object;
@@ -523,29 +601,30 @@ void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void
523 * return 0 if could not send packet. 601 * return 0 if could not send packet.
524 * return -1 on failure (connection must be killed). 602 * return -1 on failure (connection must be killed).
525 */ 603 */
526static int send_disconnect_notification(TCP_Client_Connection *con, uint8_t id) 604static int client_send_disconnect_notification(TCP_Client_Connection *con, uint8_t id)
527{ 605{
528 uint8_t packet[1 + 1]; 606 uint8_t packet[1 + 1];
529 packet[0] = TCP_PACKET_DISCONNECT_NOTIFICATION; 607 packet[0] = TCP_PACKET_DISCONNECT_NOTIFICATION;
530 packet[1] = id; 608 packet[1] = id;
531 return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 1); 609 return write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1);
532} 610}
533 611
534/* return 1 on success. 612/* return 1 on success.
535 * return 0 if could not send packet. 613 * return 0 if could not send packet.
536 * return -1 on failure (connection must be killed). 614 * return -1 on failure (connection must be killed).
537 */ 615 */
538static int send_ping_request(TCP_Client_Connection *con) 616static int tcp_send_ping_request(TCP_Client_Connection *con)
539{ 617{
540 if (!con->ping_request_id) 618 if (!con->ping_request_id) {
541 return 1; 619 return 1;
620 }
542 621
543 uint8_t packet[1 + sizeof(uint64_t)]; 622 uint8_t packet[1 + sizeof(uint64_t)];
544 packet[0] = TCP_PACKET_PING; 623 packet[0] = TCP_PACKET_PING;
545 memcpy(packet + 1, &con->ping_request_id, sizeof(uint64_t)); 624 memcpy(packet + 1, &con->ping_request_id, sizeof(uint64_t));
546 int ret; 625 int ret;
547 626
548 if ((ret = write_packet_TCP_secure_connection(con, packet, sizeof(packet), 1)) == 1) { 627 if ((ret = write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1)) == 1) {
549 con->ping_request_id = 0; 628 con->ping_request_id = 0;
550 } 629 }
551 630
@@ -556,17 +635,18 @@ static int send_ping_request(TCP_Client_Connection *con)
556 * return 0 if could not send packet. 635 * return 0 if could not send packet.
557 * return -1 on failure (connection must be killed). 636 * return -1 on failure (connection must be killed).
558 */ 637 */
559static int send_ping_response(TCP_Client_Connection *con) 638static int tcp_send_ping_response(TCP_Client_Connection *con)
560{ 639{
561 if (!con->ping_response_id) 640 if (!con->ping_response_id) {
562 return 1; 641 return 1;
642 }
563 643
564 uint8_t packet[1 + sizeof(uint64_t)]; 644 uint8_t packet[1 + sizeof(uint64_t)];
565 packet[0] = TCP_PACKET_PONG; 645 packet[0] = TCP_PACKET_PONG;
566 memcpy(packet + 1, &con->ping_response_id, sizeof(uint64_t)); 646 memcpy(packet + 1, &con->ping_response_id, sizeof(uint64_t));
567 int ret; 647 int ret;
568 648
569 if ((ret = write_packet_TCP_secure_connection(con, packet, sizeof(packet), 1)) == 1) { 649 if ((ret = write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1)) == 1) {
570 con->ping_response_id = 0; 650 con->ping_response_id = 0;
571 } 651 }
572 652
@@ -579,12 +659,13 @@ static int send_ping_response(TCP_Client_Connection *con)
579 */ 659 */
580int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id) 660int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id)
581{ 661{
582 if (con_id >= NUM_CLIENT_CONNECTIONS) 662 if (con_id >= NUM_CLIENT_CONNECTIONS) {
583 return -1; 663 return -1;
664 }
584 665
585 con->connections[con_id].status = 0; 666 con->connections[con_id].status = 0;
586 con->connections[con_id].number = 0; 667 con->connections[con_id].number = 0;
587 return send_disconnect_notification(con, con_id + NUM_RESERVED_PORTS); 668 return client_send_disconnect_notification(con, con_id + NUM_RESERVED_PORTS);
588} 669}
589 670
590/* return 1 on success. 671/* return 1 on success.
@@ -593,14 +674,14 @@ int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id)
593 */ 674 */
594int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t length) 675int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t length)
595{ 676{
596 uint8_t packet[1 + length]; 677 VLA(uint8_t, packet, 1 + length);
597 packet[0] = TCP_PACKET_ONION_REQUEST; 678 packet[0] = TCP_PACKET_ONION_REQUEST;
598 memcpy(packet + 1, data, length); 679 memcpy(packet + 1, data, length);
599 return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 0); 680 return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0);
600} 681}
601 682
602void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, const uint8_t *data, 683void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, const uint8_t *data,
603 uint16_t length), void *object) 684 uint16_t length, void *userdata), void *object)
604{ 685{
605 con->onion_callback = onion_callback; 686 con->onion_callback = onion_callback;
606 con->onion_callback_object = object; 687 con->onion_callback_object = object;
@@ -612,51 +693,52 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public
612 const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info) 693 const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info)
613{ 694{
614 if (networking_at_startup() != 0) { 695 if (networking_at_startup() != 0) {
615 return NULL; 696 return nullptr;
616 } 697 }
617 698
618 if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6) 699 if (!net_family_is_ipv4(ip_port.ip.family) && !net_family_is_ipv6(ip_port.ip.family)) {
619 return NULL; 700 return nullptr;
620 701 }
621 uint8_t family = ip_port.ip.family;
622 702
623 TCP_Proxy_Info default_proxyinfo; 703 TCP_Proxy_Info default_proxyinfo;
624 704
625 if (proxy_info == NULL) { 705 if (proxy_info == nullptr) {
626 default_proxyinfo.proxy_type = TCP_PROXY_NONE; 706 default_proxyinfo.proxy_type = TCP_PROXY_NONE;
627 proxy_info = &default_proxyinfo; 707 proxy_info = &default_proxyinfo;
628 } 708 }
629 709
710 Family family = ip_port.ip.family;
711
630 if (proxy_info->proxy_type != TCP_PROXY_NONE) { 712 if (proxy_info->proxy_type != TCP_PROXY_NONE) {
631 family = proxy_info->ip_port.ip.family; 713 family = proxy_info->ip_port.ip.family;
632 } 714 }
633 715
634 sock_t sock = socket(family, SOCK_STREAM, IPPROTO_TCP); 716 Socket sock = net_socket(family, TOX_SOCK_STREAM, TOX_PROTO_TCP);
635 717
636 if (!sock_valid(sock)) { 718 if (!sock_valid(sock)) {
637 return NULL; 719 return nullptr;
638 } 720 }
639 721
640 if (!set_socket_nosigpipe(sock)) { 722 if (!set_socket_nosigpipe(sock)) {
641 kill_sock(sock); 723 kill_sock(sock);
642 return 0; 724 return nullptr;
643 } 725 }
644 726
645 if (!(set_socket_nonblock(sock) && connect_sock_to(sock, ip_port, proxy_info))) { 727 if (!(set_socket_nonblock(sock) && connect_sock_to(sock, ip_port, proxy_info))) {
646 kill_sock(sock); 728 kill_sock(sock);
647 return NULL; 729 return nullptr;
648 } 730 }
649 731
650 TCP_Client_Connection *temp = calloc(sizeof(TCP_Client_Connection), 1); 732 TCP_Client_Connection *temp = (TCP_Client_Connection *)calloc(sizeof(TCP_Client_Connection), 1);
651 733
652 if (temp == NULL) { 734 if (temp == nullptr) {
653 kill_sock(sock); 735 kill_sock(sock);
654 return NULL; 736 return nullptr;
655 } 737 }
656 738
657 temp->sock = sock; 739 temp->sock = sock;
658 memcpy(temp->public_key, public_key, crypto_box_PUBLICKEYBYTES); 740 memcpy(temp->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
659 memcpy(temp->self_public_key, self_public_key, crypto_box_PUBLICKEYBYTES); 741 memcpy(temp->self_public_key, self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
660 encrypt_precompute(temp->public_key, self_secret_key, temp->shared_key); 742 encrypt_precompute(temp->public_key, self_secret_key, temp->shared_key);
661 temp->ip_port = ip_port; 743 temp->ip_port = ip_port;
662 temp->proxy_info = *proxy_info; 744 temp->proxy_info = *proxy_info;
@@ -678,7 +760,7 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public
678 if (generate_handshake(temp) == -1) { 760 if (generate_handshake(temp) == -1) {
679 kill_sock(sock); 761 kill_sock(sock);
680 free(temp); 762 free(temp);
681 return NULL; 763 return nullptr;
682 } 764 }
683 765
684 break; 766 break;
@@ -692,93 +774,109 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public
692/* return 0 on success 774/* return 0 on success
693 * return -1 on failure 775 * return -1 on failure
694 */ 776 */
695static int handle_TCP_packet(TCP_Client_Connection *conn, const uint8_t *data, uint16_t length) 777static int handle_TCP_client_packet(TCP_Client_Connection *conn, const uint8_t *data, uint16_t length, void *userdata)
696{ 778{
697 if (length <= 1) 779 if (length <= 1) {
698 return -1; 780 return -1;
781 }
699 782
700 switch (data[0]) { 783 switch (data[0]) {
701 case TCP_PACKET_ROUTING_RESPONSE: { 784 case TCP_PACKET_ROUTING_RESPONSE: {
702 if (length != 1 + 1 + crypto_box_PUBLICKEYBYTES) 785 if (length != 1 + 1 + CRYPTO_PUBLIC_KEY_SIZE) {
703 return -1; 786 return -1;
787 }
704 788
705 if (data[1] < NUM_RESERVED_PORTS) 789 if (data[1] < NUM_RESERVED_PORTS) {
706 return 0; 790 return 0;
791 }
707 792
708 uint8_t con_id = data[1] - NUM_RESERVED_PORTS; 793 uint8_t con_id = data[1] - NUM_RESERVED_PORTS;
709 794
710 if (conn->connections[con_id].status != 0) 795 if (conn->connections[con_id].status != 0) {
711 return 0; 796 return 0;
797 }
712 798
713 conn->connections[con_id].status = 1; 799 conn->connections[con_id].status = 1;
714 conn->connections[con_id].number = ~0; 800 conn->connections[con_id].number = ~0;
715 memcpy(conn->connections[con_id].public_key, data + 2, crypto_box_PUBLICKEYBYTES); 801 memcpy(conn->connections[con_id].public_key, data + 2, CRYPTO_PUBLIC_KEY_SIZE);
716 802
717 if (conn->response_callback) 803 if (conn->response_callback) {
718 conn->response_callback(conn->response_callback_object, con_id, conn->connections[con_id].public_key); 804 conn->response_callback(conn->response_callback_object, con_id, conn->connections[con_id].public_key);
805 }
719 806
720 return 0; 807 return 0;
721 } 808 }
722 809
723 case TCP_PACKET_CONNECTION_NOTIFICATION: { 810 case TCP_PACKET_CONNECTION_NOTIFICATION: {
724 if (length != 1 + 1) 811 if (length != 1 + 1) {
725 return -1; 812 return -1;
813 }
726 814
727 if (data[1] < NUM_RESERVED_PORTS) 815 if (data[1] < NUM_RESERVED_PORTS) {
728 return -1; 816 return -1;
817 }
729 818
730 uint8_t con_id = data[1] - NUM_RESERVED_PORTS; 819 uint8_t con_id = data[1] - NUM_RESERVED_PORTS;
731 820
732 if (conn->connections[con_id].status != 1) 821 if (conn->connections[con_id].status != 1) {
733 return 0; 822 return 0;
823 }
734 824
735 conn->connections[con_id].status = 2; 825 conn->connections[con_id].status = 2;
736 826
737 if (conn->status_callback) 827 if (conn->status_callback) {
738 conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id, 828 conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id,
739 conn->connections[con_id].status); 829 conn->connections[con_id].status);
830 }
740 831
741 return 0; 832 return 0;
742 } 833 }
743 834
744 case TCP_PACKET_DISCONNECT_NOTIFICATION: { 835 case TCP_PACKET_DISCONNECT_NOTIFICATION: {
745 if (length != 1 + 1) 836 if (length != 1 + 1) {
746 return -1; 837 return -1;
838 }
747 839
748 if (data[1] < NUM_RESERVED_PORTS) 840 if (data[1] < NUM_RESERVED_PORTS) {
749 return -1; 841 return -1;
842 }
750 843
751 uint8_t con_id = data[1] - NUM_RESERVED_PORTS; 844 uint8_t con_id = data[1] - NUM_RESERVED_PORTS;
752 845
753 if (conn->connections[con_id].status == 0) 846 if (conn->connections[con_id].status == 0) {
754 return 0; 847 return 0;
848 }
755 849
756 if (conn->connections[con_id].status != 2) 850 if (conn->connections[con_id].status != 2) {
757 return 0; 851 return 0;
852 }
758 853
759 conn->connections[con_id].status = 1; 854 conn->connections[con_id].status = 1;
760 855
761 if (conn->status_callback) 856 if (conn->status_callback) {
762 conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id, 857 conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id,
763 conn->connections[con_id].status); 858 conn->connections[con_id].status);
859 }
764 860
765 return 0; 861 return 0;
766 } 862 }
767 863
768 case TCP_PACKET_PING: { 864 case TCP_PACKET_PING: {
769 if (length != 1 + sizeof(uint64_t)) 865 if (length != 1 + sizeof(uint64_t)) {
770 return -1; 866 return -1;
867 }
771 868
772 uint64_t ping_id; 869 uint64_t ping_id;
773 memcpy(&ping_id, data + 1, sizeof(uint64_t)); 870 memcpy(&ping_id, data + 1, sizeof(uint64_t));
774 conn->ping_response_id = ping_id; 871 conn->ping_response_id = ping_id;
775 send_ping_response(conn); 872 tcp_send_ping_response(conn);
776 return 0; 873 return 0;
777 } 874 }
778 875
779 case TCP_PACKET_PONG: { 876 case TCP_PACKET_PONG: {
780 if (length != 1 + sizeof(uint64_t)) 877 if (length != 1 + sizeof(uint64_t)) {
781 return -1; 878 return -1;
879 }
782 880
783 uint64_t ping_id; 881 uint64_t ping_id;
784 memcpy(&ping_id, data + 1, sizeof(uint64_t)); 882 memcpy(&ping_id, data + 1, sizeof(uint64_t));
@@ -789,58 +887,64 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, const uint8_t *data, u
789 } 887 }
790 888
791 return 0; 889 return 0;
792 } else {
793 return -1;
794 } 890 }
891
892 return -1;
795 } 893 }
796 894
797 case TCP_PACKET_OOB_RECV: { 895 case TCP_PACKET_OOB_RECV: {
798 if (length <= 1 + crypto_box_PUBLICKEYBYTES) 896 if (length <= 1 + CRYPTO_PUBLIC_KEY_SIZE) {
799 return -1; 897 return -1;
898 }
800 899
801 if (conn->oob_data_callback) 900 if (conn->oob_data_callback) {
802 conn->oob_data_callback(conn->oob_data_callback_object, data + 1, data + 1 + crypto_box_PUBLICKEYBYTES, 901 conn->oob_data_callback(conn->oob_data_callback_object, data + 1, data + 1 + CRYPTO_PUBLIC_KEY_SIZE,
803 length - (1 + crypto_box_PUBLICKEYBYTES)); 902 length - (1 + CRYPTO_PUBLIC_KEY_SIZE), userdata);
903 }
804 904
805 return 0; 905 return 0;
806 } 906 }
807 907
808 case TCP_PACKET_ONION_RESPONSE: { 908 case TCP_PACKET_ONION_RESPONSE: {
809 conn->onion_callback(conn->onion_callback_object, data + 1, length - 1); 909 conn->onion_callback(conn->onion_callback_object, data + 1, length - 1, userdata);
810 return 0; 910 return 0;
811 } 911 }
812 912
813 default: { 913 default: {
814 if (data[0] < NUM_RESERVED_PORTS) 914 if (data[0] < NUM_RESERVED_PORTS) {
815 return -1; 915 return -1;
916 }
816 917
817 uint8_t con_id = data[0] - NUM_RESERVED_PORTS; 918 uint8_t con_id = data[0] - NUM_RESERVED_PORTS;
818 919
819 if (conn->data_callback) 920 if (conn->data_callback) {
820 conn->data_callback(conn->data_callback_object, conn->connections[con_id].number, con_id, data + 1, length - 1); 921 conn->data_callback(conn->data_callback_object, conn->connections[con_id].number, con_id, data + 1, length - 1,
922 userdata);
923 }
821 } 924 }
822 } 925 }
823 926
824 return 0; 927 return 0;
825} 928}
826 929
827static int do_confirmed_TCP(TCP_Client_Connection *conn) 930static int do_confirmed_TCP(TCP_Client_Connection *conn, void *userdata)
828{ 931{
829 send_pending_data(conn); 932 client_send_pending_data(conn);
830 send_ping_response(conn); 933 tcp_send_ping_response(conn);
831 send_ping_request(conn); 934 tcp_send_ping_request(conn);
832 935
833 uint8_t packet[MAX_PACKET_SIZE]; 936 uint8_t packet[MAX_PACKET_SIZE];
834 int len; 937 int len;
835 938
836 if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) { 939 if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) {
837 uint64_t ping_id = random_64b(); 940 uint64_t ping_id = random_u64();
838 941
839 if (!ping_id) 942 if (!ping_id) {
840 ++ping_id; 943 ++ping_id;
944 }
841 945
842 conn->ping_request_id = conn->ping_id = ping_id; 946 conn->ping_request_id = conn->ping_id = ping_id;
843 send_ping_request(conn); 947 tcp_send_ping_request(conn);
844 conn->last_pinged = unix_time(); 948 conn->last_pinged = unix_time();
845 } 949 }
846 950
@@ -856,7 +960,7 @@ static int do_confirmed_TCP(TCP_Client_Connection *conn)
856 break; 960 break;
857 } 961 }
858 962
859 if (handle_TCP_packet(conn, packet, len) == -1) { 963 if (handle_TCP_client_packet(conn, packet, len, userdata) == -1) {
860 conn->status = TCP_CLIENT_DISCONNECTED; 964 conn->status = TCP_CLIENT_DISCONNECTED;
861 break; 965 break;
862 } 966 }
@@ -867,7 +971,7 @@ static int do_confirmed_TCP(TCP_Client_Connection *conn)
867 971
868/* Run the TCP connection 972/* Run the TCP connection
869 */ 973 */
870void do_TCP_connection(TCP_Client_Connection *TCP_connection) 974void do_TCP_connection(TCP_Client_Connection *TCP_connection, void *userdata)
871{ 975{
872 unix_time_update(); 976 unix_time_update();
873 977
@@ -876,7 +980,7 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection)
876 } 980 }
877 981
878 if (TCP_connection->status == TCP_CLIENT_PROXY_HTTP_CONNECTING) { 982 if (TCP_connection->status == TCP_CLIENT_PROXY_HTTP_CONNECTING) {
879 if (send_pending_data(TCP_connection) == 0) { 983 if (client_send_pending_data(TCP_connection) == 0) {
880 int ret = proxy_http_read_connection_response(TCP_connection); 984 int ret = proxy_http_read_connection_response(TCP_connection);
881 985
882 if (ret == -1) { 986 if (ret == -1) {
@@ -892,7 +996,7 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection)
892 } 996 }
893 997
894 if (TCP_connection->status == TCP_CLIENT_PROXY_SOCKS5_CONNECTING) { 998 if (TCP_connection->status == TCP_CLIENT_PROXY_SOCKS5_CONNECTING) {
895 if (send_pending_data(TCP_connection) == 0) { 999 if (client_send_pending_data(TCP_connection) == 0) {
896 int ret = socks5_read_handshake_response(TCP_connection); 1000 int ret = socks5_read_handshake_response(TCP_connection);
897 1001
898 if (ret == -1) { 1002 if (ret == -1) {
@@ -908,7 +1012,7 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection)
908 } 1012 }
909 1013
910 if (TCP_connection->status == TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED) { 1014 if (TCP_connection->status == TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED) {
911 if (send_pending_data(TCP_connection) == 0) { 1015 if (client_send_pending_data(TCP_connection) == 0) {
912 int ret = proxy_socks5_read_connection_response(TCP_connection); 1016 int ret = proxy_socks5_read_connection_response(TCP_connection);
913 1017
914 if (ret == -1) { 1018 if (ret == -1) {
@@ -924,7 +1028,7 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection)
924 } 1028 }
925 1029
926 if (TCP_connection->status == TCP_CLIENT_CONNECTING) { 1030 if (TCP_connection->status == TCP_CLIENT_CONNECTING) {
927 if (send_pending_data(TCP_connection) == 0) { 1031 if (client_send_pending_data(TCP_connection) == 0) {
928 TCP_connection->status = TCP_CLIENT_UNCONFIRMED; 1032 TCP_connection->status = TCP_CLIENT_UNCONFIRMED;
929 } 1033 }
930 } 1034 }
@@ -945,7 +1049,7 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection)
945 } 1049 }
946 1050
947 if (TCP_connection->status == TCP_CLIENT_CONFIRMED) { 1051 if (TCP_connection->status == TCP_CLIENT_CONFIRMED) {
948 do_confirmed_TCP(TCP_connection); 1052 do_confirmed_TCP(TCP_connection, userdata);
949 } 1053 }
950 1054
951 if (TCP_connection->kill_at <= unix_time()) { 1055 if (TCP_connection->kill_at <= unix_time()) {
@@ -957,11 +1061,12 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection)
957 */ 1061 */
958void kill_TCP_connection(TCP_Client_Connection *TCP_connection) 1062void kill_TCP_connection(TCP_Client_Connection *TCP_connection)
959{ 1063{
960 if (TCP_connection == NULL) 1064 if (TCP_connection == nullptr) {
961 return; 1065 return;
1066 }
962 1067
963 wipe_priority_list(TCP_connection); 1068 wipe_priority_list(TCP_connection);
964 kill_sock(TCP_connection->sock); 1069 kill_sock(TCP_connection->sock);
965 sodium_memzero(TCP_connection, sizeof(TCP_Client_Connection)); 1070 crypto_memzero(TCP_connection, sizeof(TCP_Client_Connection));
966 free(TCP_connection); 1071 free(TCP_connection);
967} 1072}
diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h
index 722430e0..96e04d67 100644
--- a/toxcore/TCP_client.h
+++ b/toxcore/TCP_client.h
@@ -1,31 +1,31 @@
1/* 1/*
2* TCP_client.h -- Implementation of the TCP relay client part of Tox. 2 * Implementation of the TCP relay client part of Tox.
3* 3 */
4* Copyright (C) 2014 Tox project All Rights Reserved.
5*
6* This file is part of Tox.
7*
8* Tox is free software: you can redistribute it and/or modify
9* it under the terms of the GNU General Public License as published by
10* the Free Software Foundation, either version 3 of the License, or
11* (at your option) any later version.
12*
13* Tox is distributed in the hope that it will be useful,
14* but WITHOUT ANY WARRANTY; without even the implied warranty of
15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16* GNU General Public License for more details.
17*
18* You should have received a copy of the GNU General Public License
19* along with Tox. If not, see <http://www.gnu.org/licenses/>.
20*
21*/
22
23 4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2014 Tox project.
8 *
9 * This file is part of Tox, the free peer to peer instant messenger.
10 *
11 * Tox is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * Tox is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
23 */
24#ifndef TCP_CLIENT_H 24#ifndef TCP_CLIENT_H
25#define TCP_CLIENT_H 25#define TCP_CLIENT_H
26 26
27#include "crypto_core.h"
28#include "TCP_server.h" 27#include "TCP_server.h"
28#include "crypto_core.h"
29 29
30#define TCP_CONNECTION_TIMEOUT 10 30#define TCP_CONNECTION_TIMEOUT 10
31 31
@@ -40,7 +40,7 @@ typedef struct {
40 uint8_t proxy_type; // a value from TCP_PROXY_TYPE 40 uint8_t proxy_type; // a value from TCP_PROXY_TYPE
41} TCP_Proxy_Info; 41} TCP_Proxy_Info;
42 42
43enum { 43typedef enum {
44 TCP_CLIENT_NO_STATUS, 44 TCP_CLIENT_NO_STATUS,
45 TCP_CLIENT_PROXY_HTTP_CONNECTING, 45 TCP_CLIENT_PROXY_HTTP_CONNECTING,
46 TCP_CLIENT_PROXY_SOCKS5_CONNECTING, 46 TCP_CLIENT_PROXY_SOCKS5_CONNECTING,
@@ -49,56 +49,17 @@ enum {
49 TCP_CLIENT_UNCONFIRMED, 49 TCP_CLIENT_UNCONFIRMED,
50 TCP_CLIENT_CONFIRMED, 50 TCP_CLIENT_CONFIRMED,
51 TCP_CLIENT_DISCONNECTED, 51 TCP_CLIENT_DISCONNECTED,
52}; 52} TCP_CLIENT_STATUS;
53typedef struct { 53typedef struct TCP_Client_Connection TCP_Client_Connection;
54 uint8_t status; 54
55 sock_t sock; 55const uint8_t *tcp_con_public_key(const TCP_Client_Connection *con);
56 uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; /* our public key */ 56IP_Port tcp_con_ip_port(const TCP_Client_Connection *con);
57 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* public key of the server */ 57TCP_CLIENT_STATUS tcp_con_status(const TCP_Client_Connection *con);
58 IP_Port ip_port; /* The ip and port of the server */ 58
59 TCP_Proxy_Info proxy_info; 59void *tcp_con_custom_object(const TCP_Client_Connection *con);
60 uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */ 60uint32_t tcp_con_custom_uint(const TCP_Client_Connection *con);
61 uint8_t sent_nonce[crypto_box_NONCEBYTES]; /* Nonce of sent packets. */ 61void tcp_con_set_custom_object(TCP_Client_Connection *con, void *object);
62 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 62void tcp_con_set_custom_uint(TCP_Client_Connection *con, uint32_t uint);
63 uint16_t next_packet_length;
64
65 uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES];
66
67 uint8_t last_packet[2 + MAX_PACKET_SIZE];
68 uint16_t last_packet_length;
69 uint16_t last_packet_sent;
70
71 TCP_Priority_List *priority_queue_start, *priority_queue_end;
72
73 uint64_t kill_at;
74
75 uint64_t last_pinged;
76 uint64_t ping_id;
77
78 uint64_t ping_response_id;
79 uint64_t ping_request_id;
80
81 struct {
82 uint8_t status; /* 0 if not used, 1 if other is offline, 2 if other is online. */
83 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
84 uint32_t number;
85 } connections[NUM_CLIENT_CONNECTIONS];
86 int (*response_callback)(void *object, uint8_t connection_id, const uint8_t *public_key);
87 void *response_callback_object;
88 int (*status_callback)(void *object, uint32_t number, uint8_t connection_id, uint8_t status);
89 void *status_callback_object;
90 int (*data_callback)(void *object, uint32_t number, uint8_t connection_id, const uint8_t *data, uint16_t length);
91 void *data_callback_object;
92 int (*oob_data_callback)(void *object, const uint8_t *public_key, const uint8_t *data, uint16_t length);
93 void *oob_data_callback_object;
94
95 int (*onion_callback)(void *object, const uint8_t *data, uint16_t length);
96 void *onion_callback_object;
97
98 /* Can be used by user. */
99 void *custom_object;
100 uint32_t custom_uint;
101} TCP_Client_Connection;
102 63
103/* Create new TCP connection to ip_port/public_key 64/* Create new TCP connection to ip_port/public_key
104 */ 65 */
@@ -107,7 +68,7 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public
107 68
108/* Run the TCP connection 69/* Run the TCP connection
109 */ 70 */
110void do_TCP_connection(TCP_Client_Connection *TCP_connection); 71void do_TCP_connection(TCP_Client_Connection *TCP_connection, void *userdata);
111 72
112/* Kill the TCP connection 73/* Kill the TCP connection
113 */ 74 */
@@ -119,7 +80,7 @@ void kill_TCP_connection(TCP_Client_Connection *TCP_connection);
119 */ 80 */
120int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t length); 81int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t length);
121void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, const uint8_t *data, 82void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, const uint8_t *data,
122 uint16_t length), void *object); 83 uint16_t length, void *userdata), void *object);
123 84
124/* return 1 on success. 85/* return 1 on success.
125 * return 0 if could not send packet. 86 * return 0 if could not send packet.
@@ -152,7 +113,7 @@ int set_tcp_connection_number(TCP_Client_Connection *con, uint8_t con_id, uint32
152 */ 113 */
153int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length); 114int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length);
154void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number, 115void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number,
155 uint8_t connection_id, const uint8_t *data, uint16_t length), void *object); 116 uint8_t connection_id, const uint8_t *data, uint16_t length, void *userdata), void *object);
156 117
157/* return 1 on success. 118/* return 1 on success.
158 * return 0 if could not send packet. 119 * return 0 if could not send packet.
@@ -160,7 +121,7 @@ void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void
160 */ 121 */
161int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data, uint16_t length); 122int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data, uint16_t length);
162void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, const uint8_t *public_key, 123void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, const uint8_t *public_key,
163 const uint8_t *data, uint16_t length), void *object); 124 const uint8_t *data, uint16_t length, void *userdata), void *object);
164 125
165 126
166#endif 127#endif
diff --git a/toxcore/TCP_connection.c b/toxcore/TCP_connection.c
index 027779dd..06cb6e34 100644
--- a/toxcore/TCP_connection.c
+++ b/toxcore/TCP_connection.c
@@ -1,54 +1,119 @@
1/* TCP_connection.c 1/*
2 *
3 * Handles TCP relay connections between two Tox clients. 2 * Handles TCP relay connections between two Tox clients.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2015 Tox project.
4 * 8 *
5 * Copyright (C) 2015 Tox project All Rights Reserved. 9 * This file is part of Tox, the free peer to peer instant messenger.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23
24#ifdef HAVE_CONFIG_H 24#ifdef HAVE_CONFIG_H
25#include "config.h" 25#include "config.h"
26#endif 26#endif
27 27
28#include "TCP_connection.h" 28#include "TCP_connection.h"
29
30#include <assert.h>
31#include <stdlib.h>
32#include <string.h>
33
29#include "util.h" 34#include "util.h"
30 35
36
37struct TCP_Connections {
38 DHT *dht;
39
40 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
41 uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
42
43 TCP_Connection_to *connections;
44 uint32_t connections_length; /* Length of connections array. */
45
46 TCP_con *tcp_connections;
47 uint32_t tcp_connections_length; /* Length of tcp_connections array. */
48
49 int (*tcp_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
50 void *tcp_data_callback_object;
51
52 int (*tcp_oob_callback)(void *object, const uint8_t *public_key, unsigned int tcp_connections_number,
53 const uint8_t *data, uint16_t length, void *userdata);
54 void *tcp_oob_callback_object;
55
56 int (*tcp_onion_callback)(void *object, const uint8_t *data, uint16_t length, void *userdata);
57 void *tcp_onion_callback_object;
58
59 TCP_Proxy_Info proxy_info;
60
61 bool onion_status;
62 uint16_t onion_num_conns;
63};
64
65
66const uint8_t *tcp_connections_public_key(const TCP_Connections *tcp_c)
67{
68 return tcp_c->self_public_key;
69}
70
71
31/* Set the size of the array to num. 72/* Set the size of the array to num.
32 * 73 *
33 * return -1 if realloc fails. 74 * return -1 if realloc fails.
34 * return 0 if it succeeds. 75 * return 0 if it succeeds.
35 */ 76 */
36#define realloc_tox_array(array, element_size, num, temp_pointer) (num ? (temp_pointer = realloc(array, ((num) * (element_size))), temp_pointer ? (array = temp_pointer, 0) : (-1) ) : (free(array), array = NULL, 0)) 77#define MAKE_REALLOC(T) \
78static int realloc_##T(T **array, size_t num) \
79{ \
80 if (!num) { \
81 free(*array); \
82 *array = nullptr; \
83 return 0; \
84 } \
85 \
86 T *temp_pointer = (T *)realloc(*array, num * sizeof(T)); \
87 \
88 if (!temp_pointer) { \
89 return -1; \
90 } \
91 \
92 *array = temp_pointer; \
93 \
94 return 0; \
95}
96
97MAKE_REALLOC(TCP_Connection_to)
98MAKE_REALLOC(TCP_con)
37 99
38 100
39/* return 1 if the connections_number is not valid. 101/* return 1 if the connections_number is not valid.
40 * return 0 if the connections_number is valid. 102 * return 0 if the connections_number is valid.
41 */ 103 */
42static _Bool connections_number_not_valid(const TCP_Connections *tcp_c, int connections_number) 104static bool connections_number_not_valid(const TCP_Connections *tcp_c, int connections_number)
43{ 105{
44 if ((unsigned int)connections_number >= tcp_c->connections_length) 106 if ((unsigned int)connections_number >= tcp_c->connections_length) {
45 return 1; 107 return 1;
108 }
46 109
47 if (tcp_c->connections == NULL) 110 if (tcp_c->connections == nullptr) {
48 return 1; 111 return 1;
112 }
49 113
50 if (tcp_c->connections[connections_number].status == TCP_CONN_NONE) 114 if (tcp_c->connections[connections_number].status == TCP_CONN_NONE) {
51 return 1; 115 return 1;
116 }
52 117
53 return 0; 118 return 0;
54} 119}
@@ -56,16 +121,19 @@ static _Bool connections_number_not_valid(const TCP_Connections *tcp_c, int conn
56/* return 1 if the tcp_connections_number is not valid. 121/* return 1 if the tcp_connections_number is not valid.
57 * return 0 if the tcp_connections_number is valid. 122 * return 0 if the tcp_connections_number is valid.
58 */ 123 */
59static _Bool tcp_connections_number_not_valid(const TCP_Connections *tcp_c, int tcp_connections_number) 124static bool tcp_connections_number_not_valid(const TCP_Connections *tcp_c, int tcp_connections_number)
60{ 125{
61 if ((unsigned int)tcp_connections_number >= tcp_c->tcp_connections_length) 126 if ((unsigned int)tcp_connections_number >= tcp_c->tcp_connections_length) {
62 return 1; 127 return 1;
128 }
63 129
64 if (tcp_c->tcp_connections == NULL) 130 if (tcp_c->tcp_connections == nullptr) {
65 return 1; 131 return 1;
132 }
66 133
67 if (tcp_c->tcp_connections[tcp_connections_number].status == TCP_CONN_NONE) 134 if (tcp_c->tcp_connections[tcp_connections_number].status == TCP_CONN_NONE) {
68 return 1; 135 return 1;
136 }
69 137
70 return 0; 138 return 0;
71} 139}
@@ -80,19 +148,17 @@ static int create_connection(TCP_Connections *tcp_c)
80 uint32_t i; 148 uint32_t i;
81 149
82 for (i = 0; i < tcp_c->connections_length; ++i) { 150 for (i = 0; i < tcp_c->connections_length; ++i) {
83 if (tcp_c->connections[i].status == TCP_CONN_NONE) 151 if (tcp_c->connections[i].status == TCP_CONN_NONE) {
84 return i; 152 return i;
153 }
85 } 154 }
86 155
87 int id = -1; 156 int id = -1;
88 157
89 TCP_Connection_to *temp_pointer; 158 if (realloc_TCP_Connection_to(&tcp_c->connections, tcp_c->connections_length + 1) == 0) {
90
91 if (realloc_tox_array(tcp_c->connections, sizeof(TCP_Connection_to), tcp_c->connections_length + 1,
92 temp_pointer) == 0) {
93 id = tcp_c->connections_length; 159 id = tcp_c->connections_length;
94 ++tcp_c->connections_length; 160 ++tcp_c->connections_length;
95 memset(&(tcp_c->connections[id]), 0, sizeof(TCP_Connection_to)); 161 memset(&tcp_c->connections[id], 0, sizeof(TCP_Connection_to));
96 } 162 }
97 163
98 return id; 164 return id;
@@ -108,18 +174,17 @@ static int create_tcp_connection(TCP_Connections *tcp_c)
108 uint32_t i; 174 uint32_t i;
109 175
110 for (i = 0; i < tcp_c->tcp_connections_length; ++i) { 176 for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
111 if (tcp_c->tcp_connections[i].status == TCP_CONN_NONE) 177 if (tcp_c->tcp_connections[i].status == TCP_CONN_NONE) {
112 return i; 178 return i;
179 }
113 } 180 }
114 181
115 int id = -1; 182 int id = -1;
116 183
117 TCP_con *temp_pointer; 184 if (realloc_TCP_con(&tcp_c->tcp_connections, tcp_c->tcp_connections_length + 1) == 0) {
118
119 if (realloc_tox_array(tcp_c->tcp_connections, sizeof(TCP_con), tcp_c->tcp_connections_length + 1, temp_pointer) == 0) {
120 id = tcp_c->tcp_connections_length; 185 id = tcp_c->tcp_connections_length;
121 ++tcp_c->tcp_connections_length; 186 ++tcp_c->tcp_connections_length;
122 memset(&(tcp_c->tcp_connections[id]), 0, sizeof(TCP_con)); 187 memset(&tcp_c->tcp_connections[id], 0, sizeof(TCP_con));
123 } 188 }
124 189
125 return id; 190 return id;
@@ -132,21 +197,22 @@ static int create_tcp_connection(TCP_Connections *tcp_c)
132 */ 197 */
133static int wipe_connection(TCP_Connections *tcp_c, int connections_number) 198static int wipe_connection(TCP_Connections *tcp_c, int connections_number)
134{ 199{
135 if (connections_number_not_valid(tcp_c, connections_number)) 200 if (connections_number_not_valid(tcp_c, connections_number)) {
136 return -1; 201 return -1;
202 }
137 203
138 uint32_t i; 204 uint32_t i;
139 memset(&(tcp_c->connections[connections_number]), 0 , sizeof(TCP_Connection_to)); 205 memset(&tcp_c->connections[connections_number], 0, sizeof(TCP_Connection_to));
140 206
141 for (i = tcp_c->connections_length; i != 0; --i) { 207 for (i = tcp_c->connections_length; i != 0; --i) {
142 if (tcp_c->connections[i - 1].status != TCP_CONN_NONE) 208 if (tcp_c->connections[i - 1].status != TCP_CONN_NONE) {
143 break; 209 break;
210 }
144 } 211 }
145 212
146 if (tcp_c->connections_length != i) { 213 if (tcp_c->connections_length != i) {
147 tcp_c->connections_length = i; 214 tcp_c->connections_length = i;
148 TCP_Connection_to *temp_pointer; 215 realloc_TCP_Connection_to(&tcp_c->connections, tcp_c->connections_length);
149 realloc_tox_array(tcp_c->connections, sizeof(TCP_Connection_to), tcp_c->connections_length, temp_pointer);
150 } 216 }
151 217
152 return 0; 218 return 0;
@@ -159,21 +225,22 @@ static int wipe_connection(TCP_Connections *tcp_c, int connections_number)
159 */ 225 */
160static int wipe_tcp_connection(TCP_Connections *tcp_c, int tcp_connections_number) 226static int wipe_tcp_connection(TCP_Connections *tcp_c, int tcp_connections_number)
161{ 227{
162 if (tcp_connections_number_not_valid(tcp_c, tcp_connections_number)) 228 if (tcp_connections_number_not_valid(tcp_c, tcp_connections_number)) {
163 return -1; 229 return -1;
230 }
164 231
165 uint32_t i; 232 uint32_t i;
166 memset(&(tcp_c->tcp_connections[tcp_connections_number]), 0 , sizeof(TCP_con)); 233 memset(&tcp_c->tcp_connections[tcp_connections_number], 0, sizeof(TCP_con));
167 234
168 for (i = tcp_c->tcp_connections_length; i != 0; --i) { 235 for (i = tcp_c->tcp_connections_length; i != 0; --i) {
169 if (tcp_c->tcp_connections[i - 1].status != TCP_CONN_NONE) 236 if (tcp_c->tcp_connections[i - 1].status != TCP_CONN_NONE) {
170 break; 237 break;
238 }
171 } 239 }
172 240
173 if (tcp_c->tcp_connections_length != i) { 241 if (tcp_c->tcp_connections_length != i) {
174 tcp_c->tcp_connections_length = i; 242 tcp_c->tcp_connections_length = i;
175 TCP_con *temp_pointer; 243 realloc_TCP_con(&tcp_c->tcp_connections, tcp_c->tcp_connections_length);
176 realloc_tox_array(tcp_c->tcp_connections, sizeof(TCP_con), tcp_c->tcp_connections_length, temp_pointer);
177 } 244 }
178 245
179 return 0; 246 return 0;
@@ -181,16 +248,18 @@ static int wipe_tcp_connection(TCP_Connections *tcp_c, int tcp_connections_numbe
181 248
182static TCP_Connection_to *get_connection(const TCP_Connections *tcp_c, int connections_number) 249static TCP_Connection_to *get_connection(const TCP_Connections *tcp_c, int connections_number)
183{ 250{
184 if (connections_number_not_valid(tcp_c, connections_number)) 251 if (connections_number_not_valid(tcp_c, connections_number)) {
185 return 0; 252 return nullptr;
253 }
186 254
187 return &tcp_c->connections[connections_number]; 255 return &tcp_c->connections[connections_number];
188} 256}
189 257
190static TCP_con *get_tcp_connection(const TCP_Connections *tcp_c, int tcp_connections_number) 258static TCP_con *get_tcp_connection(const TCP_Connections *tcp_c, int tcp_connections_number)
191{ 259{
192 if (tcp_connections_number_not_valid(tcp_c, tcp_connections_number)) 260 if (tcp_connections_number_not_valid(tcp_c, tcp_connections_number)) {
193 return 0; 261 return nullptr;
262 }
194 263
195 return &tcp_c->tcp_connections[tcp_connections_number]; 264 return &tcp_c->tcp_connections[tcp_connections_number];
196} 265}
@@ -208,12 +277,12 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c
208 return -1; 277 return -1;
209 } 278 }
210 279
211 //TODO: detect and kill bad relays. 280 // TODO(irungentoo): detect and kill bad relays.
212 //TODO: thread safety? 281 // TODO(irungentoo): thread safety?
213 unsigned int i; 282 unsigned int i;
214 int ret = -1; 283 int ret = -1;
215 284
216 _Bool limit_reached = 0; 285 bool limit_reached = 0;
217 286
218 for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { 287 for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
219 uint32_t tcp_con_num = con_to->connections[i].tcp_connection; 288 uint32_t tcp_con_num = con_to->connections[i].tcp_connection;
@@ -242,7 +311,9 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c
242 311
243 if (ret == 1) { 312 if (ret == 1) {
244 return 0; 313 return 0;
245 } else if (!limit_reached) { 314 }
315
316 if (!limit_reached) {
246 ret = 0; 317 ret = 0;
247 318
248 /* Send oob packets to all relays tied to the connection. */ 319 /* Send oob packets to all relays tied to the connection. */
@@ -266,18 +337,18 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c
266 337
267 if (ret >= 1) { 338 if (ret >= 1) {
268 return 0; 339 return 0;
269 } else {
270 return -1;
271 } 340 }
272 } else { 341
273 return -1; 342 return -1;
274 } 343 }
344
345 return -1;
275} 346}
276 347
277/* Return a random TCP connection number for use in send_tcp_onion_request. 348/* Return a random TCP connection number for use in send_tcp_onion_request.
278 * 349 *
279 * TODO: This number is just the index of an array that the elements can 350 * TODO(irungentoo): This number is just the index of an array that the elements
280 * change without warning. 351 * can change without warning.
281 * 352 *
282 * return TCP connection number on success. 353 * return TCP connection number on success.
283 * return -1 on failure. 354 * return -1 on failure.
@@ -312,8 +383,9 @@ int tcp_send_onion_request(TCP_Connections *tcp_c, unsigned int tcp_connections_
312 if (tcp_c->tcp_connections[tcp_connections_number].status == TCP_CONN_CONNECTED) { 383 if (tcp_c->tcp_connections[tcp_connections_number].status == TCP_CONN_CONNECTED) {
313 int ret = send_onion_request(tcp_c->tcp_connections[tcp_connections_number].connection, data, length); 384 int ret = send_onion_request(tcp_c->tcp_connections[tcp_connections_number].connection, data, length);
314 385
315 if (ret == 1) 386 if (ret == 1) {
316 return 0; 387 return 0;
388 }
317 } 389 }
318 390
319 return -1; 391 return -1;
@@ -329,16 +401,19 @@ int tcp_send_oob_packet(TCP_Connections *tcp_c, unsigned int tcp_connections_num
329{ 401{
330 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); 402 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
331 403
332 if (!tcp_con) 404 if (!tcp_con) {
333 return -1; 405 return -1;
406 }
334 407
335 if (tcp_con->status != TCP_CONN_CONNECTED) 408 if (tcp_con->status != TCP_CONN_CONNECTED) {
336 return -1; 409 return -1;
410 }
337 411
338 int ret = send_oob_packet(tcp_con->connection, public_key, packet, length); 412 int ret = send_oob_packet(tcp_con->connection, public_key, packet, length);
339 413
340 if (ret == 1) 414 if (ret == 1) {
341 return 0; 415 return 0;
416 }
342 417
343 return -1; 418 return -1;
344} 419}
@@ -346,7 +421,7 @@ int tcp_send_oob_packet(TCP_Connections *tcp_c, unsigned int tcp_connections_num
346/* Set the callback for TCP data packets. 421/* Set the callback for TCP data packets.
347 */ 422 */
348void set_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_data_callback)(void *object, int id, 423void set_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_data_callback)(void *object, int id,
349 const uint8_t *data, uint16_t length), void *object) 424 const uint8_t *data, uint16_t length, void *userdata), void *object)
350{ 425{
351 tcp_c->tcp_data_callback = tcp_data_callback; 426 tcp_c->tcp_data_callback = tcp_data_callback;
352 tcp_c->tcp_data_callback_object = object; 427 tcp_c->tcp_data_callback_object = object;
@@ -355,7 +430,8 @@ void set_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_data_c
355/* Set the callback for TCP onion packets. 430/* Set the callback for TCP onion packets.
356 */ 431 */
357void set_oob_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_oob_callback)(void *object, 432void set_oob_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_oob_callback)(void *object,
358 const uint8_t *public_key, unsigned int tcp_connections_number, const uint8_t *data, uint16_t length), void *object) 433 const uint8_t *public_key, unsigned int tcp_connections_number, const uint8_t *data, uint16_t length, void *userdata),
434 void *object)
359{ 435{
360 tcp_c->tcp_oob_callback = tcp_oob_callback; 436 tcp_c->tcp_oob_callback = tcp_oob_callback;
361 tcp_c->tcp_oob_callback_object = object; 437 tcp_c->tcp_oob_callback_object = object;
@@ -364,7 +440,7 @@ void set_oob_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_oo
364/* Set the callback for TCP oob data packets. 440/* Set the callback for TCP oob data packets.
365 */ 441 */
366void set_onion_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_onion_callback)(void *object, 442void set_onion_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_onion_callback)(void *object,
367 const uint8_t *data, uint16_t length), void *object) 443 const uint8_t *data, uint16_t length, void *userdata), void *object)
368{ 444{
369 tcp_c->tcp_onion_callback = tcp_onion_callback; 445 tcp_c->tcp_onion_callback = tcp_onion_callback;
370 tcp_c->tcp_onion_callback_object = object; 446 tcp_c->tcp_onion_callback_object = object;
@@ -411,7 +487,7 @@ static int find_tcp_connection_relay(TCP_Connections *tcp_c, const uint8_t *rela
411 return i; 487 return i;
412 } 488 }
413 } else { 489 } else {
414 if (public_key_cmp(tcp_con->connection->public_key, relay_pk) == 0) { 490 if (public_key_cmp(tcp_con_public_key(tcp_con->connection), relay_pk) == 0) {
415 return i; 491 return i;
416 } 492 }
417 } 493 }
@@ -432,18 +508,20 @@ static int find_tcp_connection_relay(TCP_Connections *tcp_c, const uint8_t *rela
432 */ 508 */
433int new_tcp_connection_to(TCP_Connections *tcp_c, const uint8_t *public_key, int id) 509int new_tcp_connection_to(TCP_Connections *tcp_c, const uint8_t *public_key, int id)
434{ 510{
435 if (find_tcp_connection_to(tcp_c, public_key) != -1) 511 if (find_tcp_connection_to(tcp_c, public_key) != -1) {
436 return -1; 512 return -1;
513 }
437 514
438 int connections_number = create_connection(tcp_c); 515 int connections_number = create_connection(tcp_c);
439 516
440 if (connections_number == -1) 517 if (connections_number == -1) {
441 return -1; 518 return -1;
519 }
442 520
443 TCP_Connection_to *con_to = &tcp_c->connections[connections_number]; 521 TCP_Connection_to *con_to = &tcp_c->connections[connections_number];
444 522
445 con_to->status = TCP_CONN_VALID; 523 con_to->status = TCP_CONN_VALID;
446 memcpy(con_to->public_key, public_key, crypto_box_PUBLICKEYBYTES); 524 memcpy(con_to->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
447 con_to->id = id; 525 con_to->id = id;
448 526
449 return connections_number; 527 return connections_number;
@@ -456,8 +534,9 @@ int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number)
456{ 534{
457 TCP_Connection_to *con_to = get_connection(tcp_c, connections_number); 535 TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
458 536
459 if (!con_to) 537 if (!con_to) {
460 return -1; 538 return -1;
539 }
461 540
462 unsigned int i; 541 unsigned int i;
463 542
@@ -466,8 +545,9 @@ int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number)
466 unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1; 545 unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;
467 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); 546 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
468 547
469 if (!tcp_con) 548 if (!tcp_con) {
470 continue; 549 continue;
550 }
471 551
472 if (tcp_con->status == TCP_CONN_CONNECTED) { 552 if (tcp_con->status == TCP_CONN_CONNECTED) {
473 send_disconnect_request(tcp_con->connection, con_to->connections[i].connection_id); 553 send_disconnect_request(tcp_con->connection, con_to->connections[i].connection_id);
@@ -496,17 +576,19 @@ int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number)
496 * return 0 on success. 576 * return 0 on success.
497 * return -1 on failure. 577 * return -1 on failure.
498 */ 578 */
499int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number, _Bool status) 579int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number, bool status)
500{ 580{
501 TCP_Connection_to *con_to = get_connection(tcp_c, connections_number); 581 TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
502 582
503 if (!con_to) 583 if (!con_to) {
504 return -1; 584 return -1;
585 }
505 586
506 if (status) { 587 if (status) {
507 /* Conection is unsleeping. */ 588 /* Connection is unsleeping. */
508 if (con_to->status != TCP_CONN_SLEEPING) 589 if (con_to->status != TCP_CONN_SLEEPING) {
509 return -1; 590 return -1;
591 }
510 592
511 unsigned int i; 593 unsigned int i;
512 594
@@ -515,8 +597,9 @@ int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number,
515 unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1; 597 unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;
516 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); 598 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
517 599
518 if (!tcp_con) 600 if (!tcp_con) {
519 continue; 601 continue;
602 }
520 603
521 if (tcp_con->status == TCP_CONN_SLEEPING) { 604 if (tcp_con->status == TCP_CONN_SLEEPING) {
522 tcp_con->unsleep = 1; 605 tcp_con->unsleep = 1;
@@ -526,33 +609,35 @@ int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number,
526 609
527 con_to->status = TCP_CONN_VALID; 610 con_to->status = TCP_CONN_VALID;
528 return 0; 611 return 0;
529 } else { 612 }
530 /* Conection is going to sleep. */
531 if (con_to->status != TCP_CONN_VALID)
532 return -1;
533 613
534 unsigned int i; 614 /* Connection is going to sleep. */
615 if (con_to->status != TCP_CONN_VALID) {
616 return -1;
617 }
535 618
536 for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { 619 unsigned int i;
537 if (con_to->connections[i].tcp_connection) {
538 unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;
539 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
540 620
541 if (!tcp_con) 621 for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
542 continue; 622 if (con_to->connections[i].tcp_connection) {
623 unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;
624 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
543 625
544 if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) { 626 if (!tcp_con) {
545 ++tcp_con->sleep_count; 627 continue;
546 }
547 } 628 }
548 }
549 629
550 con_to->status = TCP_CONN_SLEEPING; 630 if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) {
551 return 0; 631 ++tcp_con->sleep_count;
632 }
633 }
552 } 634 }
635
636 con_to->status = TCP_CONN_SLEEPING;
637 return 0;
553} 638}
554 639
555static _Bool tcp_connection_in_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number) 640static bool tcp_connection_in_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number)
556{ 641{
557 unsigned int i; 642 unsigned int i;
558 643
@@ -572,8 +657,9 @@ static int add_tcp_connection_to_conn(TCP_Connection_to *con_to, unsigned int tc
572{ 657{
573 unsigned int i; 658 unsigned int i;
574 659
575 if (tcp_connection_in_conn(con_to, tcp_connections_number)) 660 if (tcp_connection_in_conn(con_to, tcp_connections_number)) {
576 return -1; 661 return -1;
662 }
577 663
578 for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { 664 for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
579 if (con_to->connections[i].tcp_connection == 0) { 665 if (con_to->connections[i].tcp_connection == 0) {
@@ -657,8 +743,9 @@ static int kill_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections
657{ 743{
658 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); 744 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
659 745
660 if (!tcp_con) 746 if (!tcp_con) {
661 return -1; 747 return -1;
748 }
662 749
663 unsigned int i; 750 unsigned int i;
664 751
@@ -683,15 +770,17 @@ static int reconnect_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connec
683{ 770{
684 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); 771 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
685 772
686 if (!tcp_con) 773 if (!tcp_con) {
687 return -1; 774 return -1;
775 }
688 776
689 if (tcp_con->status == TCP_CONN_SLEEPING) 777 if (tcp_con->status == TCP_CONN_SLEEPING) {
690 return -1; 778 return -1;
779 }
691 780
692 IP_Port ip_port = tcp_con->connection->ip_port; 781 IP_Port ip_port = tcp_con_ip_port(tcp_con->connection);
693 uint8_t relay_pk[crypto_box_PUBLICKEYBYTES]; 782 uint8_t relay_pk[CRYPTO_PUBLIC_KEY_SIZE];
694 memcpy(relay_pk, tcp_con->connection->public_key, crypto_box_PUBLICKEYBYTES); 783 memcpy(relay_pk, tcp_con_public_key(tcp_con->connection), CRYPTO_PUBLIC_KEY_SIZE);
695 kill_TCP_connection(tcp_con->connection); 784 kill_TCP_connection(tcp_con->connection);
696 tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, 785 tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key,
697 &tcp_c->proxy_info); 786 &tcp_c->proxy_info);
@@ -729,20 +818,23 @@ static int sleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connection
729{ 818{
730 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); 819 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
731 820
732 if (!tcp_con) 821 if (!tcp_con) {
733 return -1; 822 return -1;
823 }
734 824
735 if (tcp_con->status != TCP_CONN_CONNECTED) 825 if (tcp_con->status != TCP_CONN_CONNECTED) {
736 return -1; 826 return -1;
827 }
737 828
738 if (tcp_con->lock_count != tcp_con->sleep_count) 829 if (tcp_con->lock_count != tcp_con->sleep_count) {
739 return -1; 830 return -1;
831 }
740 832
741 tcp_con->ip_port = tcp_con->connection->ip_port; 833 tcp_con->ip_port = tcp_con_ip_port(tcp_con->connection);
742 memcpy(tcp_con->relay_pk, tcp_con->connection->public_key, crypto_box_PUBLICKEYBYTES); 834 memcpy(tcp_con->relay_pk, tcp_con_public_key(tcp_con->connection), CRYPTO_PUBLIC_KEY_SIZE);
743 835
744 kill_TCP_connection(tcp_con->connection); 836 kill_TCP_connection(tcp_con->connection);
745 tcp_con->connection = NULL; 837 tcp_con->connection = nullptr;
746 838
747 unsigned int i; 839 unsigned int i;
748 840
@@ -772,11 +864,13 @@ static int unsleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connecti
772{ 864{
773 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); 865 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
774 866
775 if (!tcp_con) 867 if (!tcp_con) {
776 return -1; 868 return -1;
869 }
777 870
778 if (tcp_con->status != TCP_CONN_SLEEPING) 871 if (tcp_con->status != TCP_CONN_SLEEPING) {
779 return -1; 872 return -1;
873 }
780 874
781 tcp_con->connection = new_TCP_connection(tcp_con->ip_port, tcp_con->relay_pk, tcp_c->self_public_key, 875 tcp_con->connection = new_TCP_connection(tcp_con->ip_port, tcp_con->relay_pk, tcp_c->self_public_key,
782 tcp_c->self_secret_key, &tcp_c->proxy_info); 876 tcp_c->self_secret_key, &tcp_c->proxy_info);
@@ -803,41 +897,48 @@ static int send_tcp_relay_routing_request(TCP_Connections *tcp_c, int tcp_connec
803{ 897{
804 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); 898 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
805 899
806 if (!tcp_con) 900 if (!tcp_con) {
807 return -1; 901 return -1;
902 }
808 903
809 if (tcp_con->status == TCP_CONN_SLEEPING) 904 if (tcp_con->status == TCP_CONN_SLEEPING) {
810 return -1; 905 return -1;
906 }
811 907
812 if (send_routing_request(tcp_con->connection, public_key) != 1) 908 if (send_routing_request(tcp_con->connection, public_key) != 1) {
813 return -1; 909 return -1;
910 }
814 911
815 return 0; 912 return 0;
816} 913}
817 914
818static int tcp_response_callback(void *object, uint8_t connection_id, const uint8_t *public_key) 915static int tcp_response_callback(void *object, uint8_t connection_id, const uint8_t *public_key)
819{ 916{
820 TCP_Client_Connection *TCP_client_con = object; 917 TCP_Client_Connection *TCP_client_con = (TCP_Client_Connection *)object;
821 TCP_Connections *tcp_c = TCP_client_con->custom_object; 918 TCP_Connections *tcp_c = (TCP_Connections *)tcp_con_custom_object(TCP_client_con);
822 919
823 unsigned int tcp_connections_number = TCP_client_con->custom_uint; 920 unsigned int tcp_connections_number = tcp_con_custom_uint(TCP_client_con);
824 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); 921 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
825 922
826 if (!tcp_con) 923 if (!tcp_con) {
827 return -1; 924 return -1;
925 }
828 926
829 int connections_number = find_tcp_connection_to(tcp_c, public_key); 927 int connections_number = find_tcp_connection_to(tcp_c, public_key);
830 928
831 if (connections_number == -1) 929 if (connections_number == -1) {
832 return -1; 930 return -1;
931 }
833 932
834 TCP_Connection_to *con_to = get_connection(tcp_c, connections_number); 933 TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
835 934
836 if (con_to == NULL) 935 if (con_to == nullptr) {
837 return -1; 936 return -1;
937 }
838 938
839 if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_REGISTERED, connection_id) == -1) 939 if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_REGISTERED, connection_id) == -1) {
840 return -1; 940 return -1;
941 }
841 942
842 set_tcp_connection_number(tcp_con->connection, connection_id, connections_number); 943 set_tcp_connection_number(tcp_con->connection, connection_id, connections_number);
843 944
@@ -846,19 +947,21 @@ static int tcp_response_callback(void *object, uint8_t connection_id, const uint
846 947
847static int tcp_status_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t status) 948static int tcp_status_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t status)
848{ 949{
849 TCP_Client_Connection *TCP_client_con = object; 950 TCP_Client_Connection *TCP_client_con = (TCP_Client_Connection *)object;
850 TCP_Connections *tcp_c = TCP_client_con->custom_object; 951 TCP_Connections *tcp_c = (TCP_Connections *)tcp_con_custom_object(TCP_client_con);
851 952
852 unsigned int tcp_connections_number = TCP_client_con->custom_uint; 953 unsigned int tcp_connections_number = tcp_con_custom_uint(TCP_client_con);
853 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); 954 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
854 TCP_Connection_to *con_to = get_connection(tcp_c, number); 955 TCP_Connection_to *con_to = get_connection(tcp_c, number);
855 956
856 if (!con_to || !tcp_con) 957 if (!con_to || !tcp_con) {
857 return -1; 958 return -1;
959 }
858 960
859 if (status == 1) { 961 if (status == 1) {
860 if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_REGISTERED, connection_id) == -1) 962 if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_REGISTERED, connection_id) == -1) {
861 return -1; 963 return -1;
964 }
862 965
863 --tcp_con->lock_count; 966 --tcp_con->lock_count;
864 967
@@ -866,8 +969,9 @@ static int tcp_status_callback(void *object, uint32_t number, uint8_t connection
866 --tcp_con->sleep_count; 969 --tcp_con->sleep_count;
867 } 970 }
868 } else if (status == 2) { 971 } else if (status == 2) {
869 if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_ONLINE, connection_id) == -1) 972 if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_ONLINE, connection_id) == -1) {
870 return -1; 973 return -1;
974 }
871 975
872 ++tcp_con->lock_count; 976 ++tcp_con->lock_count;
873 977
@@ -879,67 +983,76 @@ static int tcp_status_callback(void *object, uint32_t number, uint8_t connection
879 return 0; 983 return 0;
880} 984}
881 985
882static int tcp_data_callback(void *object, uint32_t number, uint8_t connection_id, const uint8_t *data, uint16_t length) 986static int tcp_conn_data_callback(void *object, uint32_t number, uint8_t connection_id, const uint8_t *data,
987 uint16_t length, void *userdata)
883{ 988{
884 989 if (length == 0) {
885 if (length == 0)
886 return -1; 990 return -1;
991 }
887 992
888 TCP_Client_Connection *TCP_client_con = object; 993 TCP_Client_Connection *TCP_client_con = (TCP_Client_Connection *)object;
889 TCP_Connections *tcp_c = TCP_client_con->custom_object; 994 TCP_Connections *tcp_c = (TCP_Connections *)tcp_con_custom_object(TCP_client_con);
890 995
891 unsigned int tcp_connections_number = TCP_client_con->custom_uint; 996 unsigned int tcp_connections_number = tcp_con_custom_uint(TCP_client_con);
892 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); 997 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
893 998
894 if (!tcp_con) 999 if (!tcp_con) {
895 return -1; 1000 return -1;
1001 }
896 1002
897 TCP_Connection_to *con_to = get_connection(tcp_c, number); 1003 TCP_Connection_to *con_to = get_connection(tcp_c, number);
898 1004
899 if (!con_to) 1005 if (!con_to) {
900 return -1; 1006 return -1;
1007 }
901 1008
902 if (tcp_c->tcp_data_callback) 1009 if (tcp_c->tcp_data_callback) {
903 tcp_c->tcp_data_callback(tcp_c->tcp_data_callback_object, con_to->id, data, length); 1010 tcp_c->tcp_data_callback(tcp_c->tcp_data_callback_object, con_to->id, data, length, userdata);
1011 }
904 1012
905 return 0; 1013 return 0;
906} 1014}
907 1015
908static int tcp_oob_callback(void *object, const uint8_t *public_key, const uint8_t *data, uint16_t length) 1016static int tcp_conn_oob_callback(void *object, const uint8_t *public_key, const uint8_t *data, uint16_t length,
1017 void *userdata)
909{ 1018{
910 if (length == 0) 1019 if (length == 0) {
911 return -1; 1020 return -1;
1021 }
912 1022
913 TCP_Client_Connection *TCP_client_con = object; 1023 TCP_Client_Connection *TCP_client_con = (TCP_Client_Connection *)object;
914 TCP_Connections *tcp_c = TCP_client_con->custom_object; 1024 TCP_Connections *tcp_c = (TCP_Connections *)tcp_con_custom_object(TCP_client_con);
915 1025
916 unsigned int tcp_connections_number = TCP_client_con->custom_uint; 1026 unsigned int tcp_connections_number = tcp_con_custom_uint(TCP_client_con);
917 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); 1027 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
918 1028
919 if (!tcp_con) 1029 if (!tcp_con) {
920 return -1; 1030 return -1;
1031 }
921 1032
922 /* TODO: optimize */ 1033 /* TODO(irungentoo): optimize */
923 int connections_number = find_tcp_connection_to(tcp_c, public_key); 1034 int connections_number = find_tcp_connection_to(tcp_c, public_key);
924 1035
925 TCP_Connection_to *con_to = get_connection(tcp_c, connections_number); 1036 TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
926 1037
927 if (con_to && tcp_connection_in_conn(con_to, tcp_connections_number)) { 1038 if (con_to && tcp_connection_in_conn(con_to, tcp_connections_number)) {
928 return tcp_data_callback(object, connections_number, 0, data, length); 1039 return tcp_conn_data_callback(object, connections_number, 0, data, length, userdata);
929 } else { 1040 }
930 if (tcp_c->tcp_oob_callback) 1041
931 tcp_c->tcp_oob_callback(tcp_c->tcp_oob_callback_object, public_key, tcp_connections_number, data, length); 1042 if (tcp_c->tcp_oob_callback) {
1043 tcp_c->tcp_oob_callback(tcp_c->tcp_oob_callback_object, public_key, tcp_connections_number, data, length, userdata);
932 } 1044 }
933 1045
934 return 0; 1046 return 0;
935} 1047}
936 1048
937static int tcp_onion_callback(void *object, const uint8_t *data, uint16_t length) 1049static int tcp_onion_callback(void *object, const uint8_t *data, uint16_t length, void *userdata)
938{ 1050{
939 TCP_Connections *tcp_c = object; 1051 TCP_Connections *tcp_c = (TCP_Connections *)object;
940 1052
941 if (tcp_c->tcp_onion_callback) 1053 if (tcp_c->tcp_onion_callback) {
942 tcp_c->tcp_onion_callback(tcp_c->tcp_onion_callback_object, data, length); 1054 tcp_c->tcp_onion_callback(tcp_c->tcp_onion_callback_object, data, length, userdata);
1055 }
943 1056
944 return 0; 1057 return 0;
945} 1058}
@@ -953,18 +1066,19 @@ static int tcp_relay_set_callbacks(TCP_Connections *tcp_c, int tcp_connections_n
953{ 1066{
954 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); 1067 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
955 1068
956 if (!tcp_con) 1069 if (!tcp_con) {
957 return -1; 1070 return -1;
1071 }
958 1072
959 TCP_Client_Connection *con = tcp_con->connection; 1073 TCP_Client_Connection *con = tcp_con->connection;
960 1074
961 con->custom_object = tcp_c; 1075 tcp_con_set_custom_object(con, tcp_c);
962 con->custom_uint = tcp_connections_number; 1076 tcp_con_set_custom_uint(con, tcp_connections_number);
963 onion_response_handler(con, &tcp_onion_callback, tcp_c); 1077 onion_response_handler(con, &tcp_onion_callback, tcp_c);
964 routing_response_handler(con, &tcp_response_callback, con); 1078 routing_response_handler(con, &tcp_response_callback, con);
965 routing_status_handler(con, &tcp_status_callback, con); 1079 routing_status_handler(con, &tcp_status_callback, con);
966 routing_data_handler(con, &tcp_data_callback, con); 1080 routing_data_handler(con, &tcp_conn_data_callback, con);
967 oob_data_handler(con, &tcp_oob_callback, con); 1081 oob_data_handler(con, &tcp_conn_oob_callback, con);
968 1082
969 return 0; 1083 return 0;
970} 1084}
@@ -973,8 +1087,9 @@ static int tcp_relay_on_online(TCP_Connections *tcp_c, int tcp_connections_numbe
973{ 1087{
974 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); 1088 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
975 1089
976 if (!tcp_con) 1090 if (!tcp_con) {
977 return -1; 1091 return -1;
1092 }
978 1093
979 unsigned int i, sent = 0; 1094 unsigned int i, sent = 0;
980 1095
@@ -1010,28 +1125,30 @@ static int tcp_relay_on_online(TCP_Connections *tcp_c, int tcp_connections_numbe
1010 1125
1011static int add_tcp_relay_instance(TCP_Connections *tcp_c, IP_Port ip_port, const uint8_t *relay_pk) 1126static int add_tcp_relay_instance(TCP_Connections *tcp_c, IP_Port ip_port, const uint8_t *relay_pk)
1012{ 1127{
1013 if (ip_port.ip.family == TCP_INET) { 1128 if (net_family_is_tcp_ipv4(ip_port.ip.family)) {
1014 ip_port.ip.family = AF_INET; 1129 ip_port.ip.family = net_family_ipv4;
1015 } else if (ip_port.ip.family == TCP_INET6) { 1130 } else if (net_family_is_tcp_ipv6(ip_port.ip.family)) {
1016 ip_port.ip.family = AF_INET6; 1131 ip_port.ip.family = net_family_ipv6;
1017 } 1132 }
1018 1133
1019 if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6) 1134 if (!net_family_is_ipv4(ip_port.ip.family) && !net_family_is_ipv6(ip_port.ip.family)) {
1020 return -1; 1135 return -1;
1136 }
1021 1137
1022 int tcp_connections_number = create_tcp_connection(tcp_c); 1138 int tcp_connections_number = create_tcp_connection(tcp_c);
1023 1139
1024 if (tcp_connections_number == -1) 1140 if (tcp_connections_number == -1) {
1025 return -1; 1141 return -1;
1142 }
1026 1143
1027 TCP_con *tcp_con = &tcp_c->tcp_connections[tcp_connections_number]; 1144 TCP_con *tcp_con = &tcp_c->tcp_connections[tcp_connections_number];
1028 1145
1029
1030 tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, 1146 tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key,
1031 &tcp_c->proxy_info); 1147 &tcp_c->proxy_info);
1032 1148
1033 if (!tcp_con->connection) 1149 if (!tcp_con->connection) {
1034 return -1; 1150 return -1;
1151 }
1035 1152
1036 tcp_con->status = TCP_CONN_VALID; 1153 tcp_con->status = TCP_CONN_VALID;
1037 1154
@@ -1047,11 +1164,13 @@ int add_tcp_relay_global(TCP_Connections *tcp_c, IP_Port ip_port, const uint8_t
1047{ 1164{
1048 int tcp_connections_number = find_tcp_connection_relay(tcp_c, relay_pk); 1165 int tcp_connections_number = find_tcp_connection_relay(tcp_c, relay_pk);
1049 1166
1050 if (tcp_connections_number != -1) 1167 if (tcp_connections_number != -1) {
1051 return -1; 1168 return -1;
1169 }
1052 1170
1053 if (add_tcp_relay_instance(tcp_c, ip_port, relay_pk) == -1) 1171 if (add_tcp_relay_instance(tcp_c, ip_port, relay_pk) == -1) {
1054 return -1; 1172 return -1;
1173 }
1055 1174
1056 return 0; 1175 return 0;
1057} 1176}
@@ -1065,20 +1184,23 @@ int add_tcp_number_relay_connection(TCP_Connections *tcp_c, int connections_numb
1065{ 1184{
1066 TCP_Connection_to *con_to = get_connection(tcp_c, connections_number); 1185 TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
1067 1186
1068 if (!con_to) 1187 if (!con_to) {
1069 return -1; 1188 return -1;
1189 }
1070 1190
1071 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); 1191 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
1072 1192
1073 if (!tcp_con) 1193 if (!tcp_con) {
1074 return -1; 1194 return -1;
1195 }
1075 1196
1076 if (con_to->status != TCP_CONN_SLEEPING && tcp_con->status == TCP_CONN_SLEEPING) { 1197 if (con_to->status != TCP_CONN_SLEEPING && tcp_con->status == TCP_CONN_SLEEPING) {
1077 tcp_con->unsleep = 1; 1198 tcp_con->unsleep = 1;
1078 } 1199 }
1079 1200
1080 if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) 1201 if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) {
1081 return -1; 1202 return -1;
1203 }
1082 1204
1083 if (tcp_con->status == TCP_CONN_CONNECTED) { 1205 if (tcp_con->status == TCP_CONN_CONNECTED) {
1084 if (send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key) == 0) { 1206 if (send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key) == 0) {
@@ -1100,31 +1222,33 @@ int add_tcp_relay_connection(TCP_Connections *tcp_c, int connections_number, IP_
1100{ 1222{
1101 TCP_Connection_to *con_to = get_connection(tcp_c, connections_number); 1223 TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
1102 1224
1103 if (!con_to) 1225 if (!con_to) {
1104 return -1; 1226 return -1;
1227 }
1105 1228
1106 int tcp_connections_number = find_tcp_connection_relay(tcp_c, relay_pk); 1229 int tcp_connections_number = find_tcp_connection_relay(tcp_c, relay_pk);
1107 1230
1108 if (tcp_connections_number != -1) { 1231 if (tcp_connections_number != -1) {
1109 return add_tcp_number_relay_connection(tcp_c, connections_number, tcp_connections_number); 1232 return add_tcp_number_relay_connection(tcp_c, connections_number, tcp_connections_number);
1110 } else { 1233 }
1111 if (online_tcp_connection_from_conn(con_to) >= RECOMMENDED_FRIEND_TCP_CONNECTIONS) {
1112 return -1;
1113 }
1114 1234
1115 int tcp_connections_number = add_tcp_relay_instance(tcp_c, ip_port, relay_pk); 1235 if (online_tcp_connection_from_conn(con_to) >= RECOMMENDED_FRIEND_TCP_CONNECTIONS) {
1236 return -1;
1237 }
1116 1238
1117 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); 1239 tcp_connections_number = add_tcp_relay_instance(tcp_c, ip_port, relay_pk);
1118 1240
1119 if (!tcp_con) 1241 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
1120 return -1;
1121 1242
1122 if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) { 1243 if (!tcp_con) {
1123 return -1; 1244 return -1;
1124 } 1245 }
1125 1246
1126 return 0; 1247 if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) {
1248 return -1;
1127 } 1249 }
1250
1251 return 0;
1128} 1252}
1129 1253
1130/* return number of online tcp relays tied to the connection on success. 1254/* return number of online tcp relays tied to the connection on success.
@@ -1134,8 +1258,9 @@ unsigned int tcp_connection_to_online_tcp_relays(TCP_Connections *tcp_c, int con
1134{ 1258{
1135 TCP_Connection_to *con_to = get_connection(tcp_c, connections_number); 1259 TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
1136 1260
1137 if (!con_to) 1261 if (!con_to) {
1138 return 0; 1262 return 0;
1263 }
1139 1264
1140 return online_tcp_connection_from_conn(con_to); 1265 return online_tcp_connection_from_conn(con_to);
1141} 1266}
@@ -1158,13 +1283,15 @@ unsigned int tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_
1158 } 1283 }
1159 1284
1160 if (tcp_con->status == TCP_CONN_CONNECTED) { 1285 if (tcp_con->status == TCP_CONN_CONNECTED) {
1161 memcpy(tcp_relays[copied].public_key, tcp_con->connection->public_key, crypto_box_PUBLICKEYBYTES); 1286 memcpy(tcp_relays[copied].public_key, tcp_con_public_key(tcp_con->connection), CRYPTO_PUBLIC_KEY_SIZE);
1162 tcp_relays[copied].ip_port = tcp_con->connection->ip_port; 1287 tcp_relays[copied].ip_port = tcp_con_ip_port(tcp_con->connection);
1288
1289 Family *const family = &tcp_relays[copied].ip_port.ip.family;
1163 1290
1164 if (tcp_relays[copied].ip_port.ip.family == AF_INET) { 1291 if (net_family_is_ipv4(*family)) {
1165 tcp_relays[copied].ip_port.ip.family = TCP_INET; 1292 *family = net_family_tcp_ipv4;
1166 } else if (tcp_relays[copied].ip_port.ip.family == AF_INET6) { 1293 } else if (net_family_is_ipv6(*family)) {
1167 tcp_relays[copied].ip_port.ip.family = TCP_INET6; 1294 *family = net_family_tcp_ipv6;
1168 } 1295 }
1169 1296
1170 ++copied; 1297 ++copied;
@@ -1181,10 +1308,11 @@ unsigned int tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_
1181 * return 0 on success. 1308 * return 0 on success.
1182 * return -1 on failure. 1309 * return -1 on failure.
1183 */ 1310 */
1184int set_tcp_onion_status(TCP_Connections *tcp_c, _Bool status) 1311int set_tcp_onion_status(TCP_Connections *tcp_c, bool status)
1185{ 1312{
1186 if (tcp_c->onion_status == status) 1313 if (tcp_c->onion_status == status) {
1187 return -1; 1314 return -1;
1315 }
1188 1316
1189 if (status) { 1317 if (status) {
1190 unsigned int i; 1318 unsigned int i;
@@ -1199,8 +1327,9 @@ int set_tcp_onion_status(TCP_Connections *tcp_c, _Bool status)
1199 } 1327 }
1200 } 1328 }
1201 1329
1202 if (tcp_c->onion_num_conns >= NUM_ONION_TCP_CONNECTIONS) 1330 if (tcp_c->onion_num_conns >= NUM_ONION_TCP_CONNECTIONS) {
1203 break; 1331 break;
1332 }
1204 } 1333 }
1205 1334
1206 if (tcp_c->onion_num_conns < NUM_ONION_TCP_CONNECTIONS) { 1335 if (tcp_c->onion_num_conns < NUM_ONION_TCP_CONNECTIONS) {
@@ -1215,8 +1344,9 @@ int set_tcp_onion_status(TCP_Connections *tcp_c, _Bool status)
1215 } 1344 }
1216 } 1345 }
1217 1346
1218 if (!wakeup) 1347 if (!wakeup) {
1219 break; 1348 break;
1349 }
1220 } 1350 }
1221 } 1351 }
1222 1352
@@ -1250,22 +1380,24 @@ int set_tcp_onion_status(TCP_Connections *tcp_c, _Bool status)
1250 */ 1380 */
1251TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *proxy_info) 1381TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *proxy_info)
1252{ 1382{
1253 if (secret_key == NULL) 1383 if (secret_key == nullptr) {
1254 return NULL; 1384 return nullptr;
1385 }
1255 1386
1256 TCP_Connections *temp = calloc(1, sizeof(TCP_Connections)); 1387 TCP_Connections *temp = (TCP_Connections *)calloc(1, sizeof(TCP_Connections));
1257 1388
1258 if (temp == NULL) 1389 if (temp == nullptr) {
1259 return NULL; 1390 return nullptr;
1391 }
1260 1392
1261 memcpy(temp->self_secret_key, secret_key, crypto_box_SECRETKEYBYTES); 1393 memcpy(temp->self_secret_key, secret_key, CRYPTO_SECRET_KEY_SIZE);
1262 crypto_scalarmult_curve25519_base(temp->self_public_key, temp->self_secret_key); 1394 crypto_derive_public_key(temp->self_public_key, temp->self_secret_key);
1263 temp->proxy_info = *proxy_info; 1395 temp->proxy_info = *proxy_info;
1264 1396
1265 return temp; 1397 return temp;
1266} 1398}
1267 1399
1268static void do_tcp_conns(TCP_Connections *tcp_c) 1400static void do_tcp_conns(TCP_Connections *tcp_c, void *userdata)
1269{ 1401{
1270 unsigned int i; 1402 unsigned int i;
1271 1403
@@ -1274,12 +1406,15 @@ static void do_tcp_conns(TCP_Connections *tcp_c)
1274 1406
1275 if (tcp_con) { 1407 if (tcp_con) {
1276 if (tcp_con->status != TCP_CONN_SLEEPING) { 1408 if (tcp_con->status != TCP_CONN_SLEEPING) {
1277 do_TCP_connection(tcp_con->connection); 1409 do_TCP_connection(tcp_con->connection, userdata);
1278 1410
1279 /* callbacks can change TCP connection address. */ 1411 /* callbacks can change TCP connection address. */
1280 tcp_con = get_tcp_connection(tcp_c, i); 1412 tcp_con = get_tcp_connection(tcp_c, i);
1281 1413
1282 if (tcp_con->connection->status == TCP_CLIENT_DISCONNECTED) { 1414 // Make sure the TCP connection wasn't dropped in any of the callbacks.
1415 assert(tcp_con != nullptr);
1416
1417 if (tcp_con_status(tcp_con->connection) == TCP_CLIENT_DISCONNECTED) {
1283 if (tcp_con->status == TCP_CONN_CONNECTED) { 1418 if (tcp_con->status == TCP_CONN_CONNECTED) {
1284 reconnect_tcp_relay_connection(tcp_c, i); 1419 reconnect_tcp_relay_connection(tcp_c, i);
1285 } else { 1420 } else {
@@ -1289,7 +1424,7 @@ static void do_tcp_conns(TCP_Connections *tcp_c)
1289 continue; 1424 continue;
1290 } 1425 }
1291 1426
1292 if (tcp_con->status == TCP_CONN_VALID && tcp_con->connection->status == TCP_CLIENT_CONFIRMED) { 1427 if (tcp_con->status == TCP_CONN_VALID && tcp_con_status(tcp_con->connection) == TCP_CLIENT_CONFIRMED) {
1293 tcp_relay_on_online(tcp_c, i); 1428 tcp_relay_on_online(tcp_c, i);
1294 } 1429 }
1295 1430
@@ -1309,10 +1444,14 @@ static void do_tcp_conns(TCP_Connections *tcp_c)
1309 1444
1310static void kill_nonused_tcp(TCP_Connections *tcp_c) 1445static void kill_nonused_tcp(TCP_Connections *tcp_c)
1311{ 1446{
1312 if (tcp_c->tcp_connections_length == 0) 1447 if (tcp_c->tcp_connections_length == 0) {
1313 return; 1448 return;
1449 }
1314 1450
1315 unsigned int i, num_online = 0, num_kill = 0, to_kill[tcp_c->tcp_connections_length]; 1451 unsigned int i;
1452 unsigned int num_online = 0;
1453 unsigned int num_kill = 0;
1454 VLA(unsigned int, to_kill, tcp_c->tcp_connections_length);
1316 1455
1317 for (i = 0; i < tcp_c->tcp_connections_length; ++i) { 1456 for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
1318 TCP_con *tcp_con = get_tcp_connection(tcp_c, i); 1457 TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
@@ -1331,11 +1470,12 @@ static void kill_nonused_tcp(TCP_Connections *tcp_c)
1331 1470
1332 if (num_online <= RECOMMENDED_FRIEND_TCP_CONNECTIONS) { 1471 if (num_online <= RECOMMENDED_FRIEND_TCP_CONNECTIONS) {
1333 return; 1472 return;
1334 } else { 1473 }
1335 unsigned int n = num_online - RECOMMENDED_FRIEND_TCP_CONNECTIONS; 1474
1475 unsigned int n = num_online - RECOMMENDED_FRIEND_TCP_CONNECTIONS;
1336 1476
1337 if (n < num_kill) 1477 if (n < num_kill) {
1338 num_kill = n; 1478 num_kill = n;
1339 } 1479 }
1340 1480
1341 for (i = 0; i < num_kill; ++i) { 1481 for (i = 0; i < num_kill; ++i) {
@@ -1343,9 +1483,9 @@ static void kill_nonused_tcp(TCP_Connections *tcp_c)
1343 } 1483 }
1344} 1484}
1345 1485
1346void do_tcp_connections(TCP_Connections *tcp_c) 1486void do_tcp_connections(TCP_Connections *tcp_c, void *userdata)
1347{ 1487{
1348 do_tcp_conns(tcp_c); 1488 do_tcp_conns(tcp_c, userdata);
1349 kill_nonused_tcp(tcp_c); 1489 kill_nonused_tcp(tcp_c);
1350} 1490}
1351 1491
@@ -1361,5 +1501,3 @@ void kill_tcp_connections(TCP_Connections *tcp_c)
1361 free(tcp_c->connections); 1501 free(tcp_c->connections);
1362 free(tcp_c); 1502 free(tcp_c);
1363} 1503}
1364
1365
diff --git a/toxcore/TCP_connection.h b/toxcore/TCP_connection.h
index 7bc34f86..a45129a7 100644
--- a/toxcore/TCP_connection.h
+++ b/toxcore/TCP_connection.h
@@ -1,26 +1,26 @@
1/* TCP_connection.h 1/*
2 *
3 * Handles TCP relay connections between two Tox clients. 2 * Handles TCP relay connections between two Tox clients.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2015 Tox project.
4 * 8 *
5 * Copyright (C) 2015 Tox project All Rights Reserved. 9 * This file is part of Tox, the free peer to peer instant messenger.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23
24#ifndef TCP_CONNECTION_H 24#ifndef TCP_CONNECTION_H
25#define TCP_CONNECTION_H 25#define TCP_CONNECTION_H
26 26
@@ -41,7 +41,7 @@
41 41
42#define MAX_FRIEND_TCP_CONNECTIONS 6 42#define MAX_FRIEND_TCP_CONNECTIONS 6
43 43
44/* Time until connection to friend gets killed (if it doesn't get locked withing that time) */ 44/* Time until connection to friend gets killed (if it doesn't get locked within that time) */
45#define TCP_CONNECTION_ANNOUNCE_TIMEOUT (TCP_CONNECTION_TIMEOUT) 45#define TCP_CONNECTION_ANNOUNCE_TIMEOUT (TCP_CONNECTION_TIMEOUT)
46 46
47/* The amount of recommended connections for each friend 47/* The amount of recommended connections for each friend
@@ -53,7 +53,7 @@
53 53
54typedef struct { 54typedef struct {
55 uint8_t status; 55 uint8_t status;
56 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The dht public key of the peer */ 56 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The dht public key of the peer */
57 57
58 struct { 58 struct {
59 uint32_t tcp_connection; 59 uint32_t tcp_connection;
@@ -70,41 +70,17 @@ typedef struct {
70 uint64_t connected_time; 70 uint64_t connected_time;
71 uint32_t lock_count; 71 uint32_t lock_count;
72 uint32_t sleep_count; 72 uint32_t sleep_count;
73 _Bool onion; 73 bool onion;
74 74
75 /* Only used when connection is sleeping. */ 75 /* Only used when connection is sleeping. */
76 IP_Port ip_port; 76 IP_Port ip_port;
77 uint8_t relay_pk[crypto_box_PUBLICKEYBYTES]; 77 uint8_t relay_pk[CRYPTO_PUBLIC_KEY_SIZE];
78 _Bool unsleep; /* set to 1 to unsleep connection. */ 78 bool unsleep; /* set to 1 to unsleep connection. */
79} TCP_con; 79} TCP_con;
80 80
81typedef struct { 81typedef struct TCP_Connections TCP_Connections;
82 DHT *dht;
83
84 uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
85 uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
86
87 TCP_Connection_to *connections;
88 uint32_t connections_length; /* Length of connections array. */
89
90 TCP_con *tcp_connections;
91 uint32_t tcp_connections_length; /* Length of tcp_connections array. */
92
93 int (*tcp_data_callback)(void *object, int id, const uint8_t *data, uint16_t length);
94 void *tcp_data_callback_object;
95
96 int (*tcp_oob_callback)(void *object, const uint8_t *public_key, unsigned int tcp_connections_number,
97 const uint8_t *data, uint16_t length);
98 void *tcp_oob_callback_object;
99
100 int (*tcp_onion_callback)(void *object, const uint8_t *data, uint16_t length);
101 void *tcp_onion_callback_object;
102
103 TCP_Proxy_Info proxy_info;
104 82
105 _Bool onion_status; 83const uint8_t *tcp_connections_public_key(const TCP_Connections *tcp_c);
106 uint16_t onion_num_conns;
107} TCP_Connections;
108 84
109/* Send a packet to the TCP connection. 85/* Send a packet to the TCP connection.
110 * 86 *
@@ -115,8 +91,8 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c
115 91
116/* Return a random TCP connection number for use in send_tcp_onion_request. 92/* Return a random TCP connection number for use in send_tcp_onion_request.
117 * 93 *
118 * TODO: This number is just the index of an array that the elements can 94 * TODO(irungentoo): This number is just the index of an array that the elements
119 * change without warning. 95 * can change without warning.
120 * 96 *
121 * return TCP connection number on success. 97 * return TCP connection number on success.
122 * return -1 on failure. 98 * return -1 on failure.
@@ -138,7 +114,7 @@ int tcp_send_onion_request(TCP_Connections *tcp_c, unsigned int tcp_connections_
138 * return 0 on success. 114 * return 0 on success.
139 * return -1 on failure. 115 * return -1 on failure.
140 */ 116 */
141int set_tcp_onion_status(TCP_Connections *tcp_c, _Bool status); 117int set_tcp_onion_status(TCP_Connections *tcp_c, bool status);
142 118
143/* Send an oob packet via the TCP relay corresponding to tcp_connections_number. 119/* Send an oob packet via the TCP relay corresponding to tcp_connections_number.
144 * 120 *
@@ -151,17 +127,18 @@ int tcp_send_oob_packet(TCP_Connections *tcp_c, unsigned int tcp_connections_num
151/* Set the callback for TCP data packets. 127/* Set the callback for TCP data packets.
152 */ 128 */
153void set_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_data_callback)(void *object, int id, 129void set_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_data_callback)(void *object, int id,
154 const uint8_t *data, uint16_t length), void *object); 130 const uint8_t *data, uint16_t length, void *userdata), void *object);
155 131
156/* Set the callback for TCP onion packets. 132/* Set the callback for TCP onion packets.
157 */ 133 */
158void set_onion_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_onion_callback)(void *object, 134void set_onion_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_onion_callback)(void *object,
159 const uint8_t *data, uint16_t length), void *object); 135 const uint8_t *data, uint16_t length, void *userdata), void *object);
160 136
161/* Set the callback for TCP oob data packets. 137/* Set the callback for TCP oob data packets.
162 */ 138 */
163void set_oob_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_oob_callback)(void *object, 139void set_oob_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_oob_callback)(void *object,
164 const uint8_t *public_key, unsigned int tcp_connections_number, const uint8_t *data, uint16_t length), void *object); 140 const uint8_t *public_key, unsigned int tcp_connections_number, const uint8_t *data, uint16_t length, void *userdata),
141 void *object);
165 142
166/* Create a new TCP connection to public_key. 143/* Create a new TCP connection to public_key.
167 * 144 *
@@ -189,7 +166,7 @@ int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number);
189 * return 0 on success. 166 * return 0 on success.
190 * return -1 on failure. 167 * return -1 on failure.
191 */ 168 */
192int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number, _Bool status); 169int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number, bool status);
193 170
194/* return number of online tcp relays tied to the connection on success. 171/* return number of online tcp relays tied to the connection on success.
195 * return 0 on failure. 172 * return 0 on failure.
@@ -239,7 +216,7 @@ unsigned int tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_
239 */ 216 */
240TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *proxy_info); 217TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *proxy_info);
241 218
242void do_tcp_connections(TCP_Connections *tcp_c); 219void do_tcp_connections(TCP_Connections *tcp_c, void *userdata);
243void kill_tcp_connections(TCP_Connections *tcp_c); 220void kill_tcp_connections(TCP_Connections *tcp_c);
244 221
245#endif 222#endif
diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c
index d4944aed..65dc81c3 100644
--- a/toxcore/TCP_server.c
+++ b/toxcore/TCP_server.c
@@ -1,64 +1,117 @@
1/* 1/*
2* TCP_server.c -- Implementation of the TCP relay server part of Tox. 2 * Implementation of the TCP relay server part of Tox.
3* 3 */
4* Copyright (C) 2014 Tox project All Rights Reserved.
5*
6* This file is part of Tox.
7*
8* Tox is free software: you can redistribute it and/or modify
9* it under the terms of the GNU General Public License as published by
10* the Free Software Foundation, either version 3 of the License, or
11* (at your option) any later version.
12*
13* Tox is distributed in the hope that it will be useful,
14* but WITHOUT ANY WARRANTY; without even the implied warranty of
15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16* GNU General Public License for more details.
17*
18* You should have received a copy of the GNU General Public License
19* along with Tox. If not, see <http://www.gnu.org/licenses/>.
20*
21*/
22 4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2014 Tox project.
8 *
9 * This file is part of Tox, the free peer to peer instant messenger.
10 *
11 * Tox is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * Tox is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
23 */
23#ifdef HAVE_CONFIG_H 24#ifdef HAVE_CONFIG_H
24#include "config.h" 25#include "config.h"
25#endif 26#endif
26 27
27#include "TCP_server.h" 28#include "TCP_server.h"
28 29
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
29#if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32) 33#if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32)
30#include <sys/ioctl.h> 34#include <sys/ioctl.h>
31#endif 35#endif
32 36
37#ifdef TCP_SERVER_USE_EPOLL
38#include <sys/epoll.h>
39#include <unistd.h>
40#endif
41
33#include "util.h" 42#include "util.h"
34 43
35/* return 1 on success 44typedef struct TCP_Secure_Connection {
36 * return 0 on failure 45 Socket sock;
37 */ 46 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
38static int bind_to_port(sock_t sock, int family, uint16_t port) 47 uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of received packets. */
39{ 48 uint8_t sent_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of sent packets. */
40 struct sockaddr_storage addr = {0}; 49 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
41 size_t addrsize; 50 uint16_t next_packet_length;
51 struct {
52 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
53 uint32_t index;
54 uint8_t status; /* 0 if not used, 1 if other is offline, 2 if other is online. */
55 uint8_t other_id;
56 } connections[NUM_CLIENT_CONNECTIONS];
57 uint8_t last_packet[2 + MAX_PACKET_SIZE];
58 uint8_t status;
59 uint16_t last_packet_length;
60 uint16_t last_packet_sent;
42 61
43 if (family == AF_INET) { 62 TCP_Priority_List *priority_queue_start, *priority_queue_end;
44 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
45 63
46 addrsize = sizeof(struct sockaddr_in); 64 uint64_t identifier;
47 addr4->sin_family = AF_INET; 65
48 addr4->sin_port = htons(port); 66 uint64_t last_pinged;
49 } else if (family == AF_INET6) { 67 uint64_t ping_id;
50 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; 68} TCP_Secure_Connection;
51 69
52 addrsize = sizeof(struct sockaddr_in6);
53 addr6->sin6_family = AF_INET6;
54 addr6->sin6_port = htons(port);
55 } else {
56 return 0;
57 }
58 70
59 return (bind(sock, (struct sockaddr *)&addr, addrsize) == 0); 71struct TCP_Server {
72 Onion *onion;
73
74#ifdef TCP_SERVER_USE_EPOLL
75 int efd;
76 uint64_t last_run_pinged;
77#endif
78 Socket *socks_listening;
79 unsigned int num_listening_socks;
80
81 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
82 uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE];
83 TCP_Secure_Connection incoming_connection_queue[MAX_INCOMING_CONNECTIONS];
84 uint16_t incoming_connection_queue_index;
85 TCP_Secure_Connection unconfirmed_connection_queue[MAX_INCOMING_CONNECTIONS];
86 uint16_t unconfirmed_connection_queue_index;
87
88 TCP_Secure_Connection *accepted_connection_array;
89 uint32_t size_accepted_connections;
90 uint32_t num_accepted_connections;
91
92 uint64_t counter;
93
94 BS_LIST accepted_key_list;
95};
96
97const uint8_t *tcp_server_public_key(const TCP_Server *tcp_server)
98{
99 return tcp_server->public_key;
100}
101
102size_t tcp_server_listen_count(const TCP_Server *tcp_server)
103{
104 return tcp_server->num_listening_socks;
60} 105}
61 106
107/* This is needed to compile on Android below API 21
108 */
109#ifdef TCP_SERVER_USE_EPOLL
110#ifndef EPOLLRDHUP
111#define EPOLLRDHUP 0x2000
112#endif
113#endif
114
62/* Set the size of the connection list to numfriends. 115/* Set the size of the connection list to numfriends.
63 * 116 *
64 * return -1 if realloc fails. 117 * return -1 if realloc fails.
@@ -68,7 +121,7 @@ static int realloc_connection(TCP_Server *TCP_server, uint32_t num)
68{ 121{
69 if (num == 0) { 122 if (num == 0) {
70 free(TCP_server->accepted_connection_array); 123 free(TCP_server->accepted_connection_array);
71 TCP_server->accepted_connection_array = NULL; 124 TCP_server->accepted_connection_array = nullptr;
72 TCP_server->size_accepted_connections = 0; 125 TCP_server->size_accepted_connections = 0;
73 return 0; 126 return 0;
74 } 127 }
@@ -77,11 +130,13 @@ static int realloc_connection(TCP_Server *TCP_server, uint32_t num)
77 return 0; 130 return 0;
78 } 131 }
79 132
80 TCP_Secure_Connection *new_connections = realloc(TCP_server->accepted_connection_array, 133 TCP_Secure_Connection *new_connections = (TCP_Secure_Connection *)realloc(
81 num * sizeof(TCP_Secure_Connection)); 134 TCP_server->accepted_connection_array,
135 num * sizeof(TCP_Secure_Connection));
82 136
83 if (new_connections == NULL) 137 if (new_connections == nullptr) {
84 return -1; 138 return -1;
139 }
85 140
86 if (num > TCP_server->size_accepted_connections) { 141 if (num > TCP_server->size_accepted_connections) {
87 uint32_t old_size = TCP_server->size_accepted_connections; 142 uint32_t old_size = TCP_server->size_accepted_connections;
@@ -120,8 +175,9 @@ static int add_accepted(TCP_Server *TCP_server, const TCP_Secure_Connection *con
120 } 175 }
121 176
122 if (TCP_server->size_accepted_connections == TCP_server->num_accepted_connections) { 177 if (TCP_server->size_accepted_connections == TCP_server->num_accepted_connections) {
123 if (realloc_connection(TCP_server, TCP_server->size_accepted_connections + 4) == -1) 178 if (realloc_connection(TCP_server, TCP_server->size_accepted_connections + 4) == -1) {
124 return -1; 179 return -1;
180 }
125 181
126 index = TCP_server->num_accepted_connections; 182 index = TCP_server->num_accepted_connections;
127 } else { 183 } else {
@@ -140,8 +196,9 @@ static int add_accepted(TCP_Server *TCP_server, const TCP_Secure_Connection *con
140 return -1; 196 return -1;
141 } 197 }
142 198
143 if (!bs_list_add(&TCP_server->accepted_key_list, con->public_key, index)) 199 if (!bs_list_add(&TCP_server->accepted_key_list, con->public_key, index)) {
144 return -1; 200 return -1;
201 }
145 202
146 memcpy(&TCP_server->accepted_connection_array[index], con, sizeof(TCP_Secure_Connection)); 203 memcpy(&TCP_server->accepted_connection_array[index], con, sizeof(TCP_Secure_Connection));
147 TCP_server->accepted_connection_array[index].status = TCP_STATUS_CONFIRMED; 204 TCP_server->accepted_connection_array[index].status = TCP_STATUS_CONFIRMED;
@@ -160,40 +217,28 @@ static int add_accepted(TCP_Server *TCP_server, const TCP_Secure_Connection *con
160 */ 217 */
161static int del_accepted(TCP_Server *TCP_server, int index) 218static int del_accepted(TCP_Server *TCP_server, int index)
162{ 219{
163 if ((uint32_t)index >= TCP_server->size_accepted_connections) 220 if ((uint32_t)index >= TCP_server->size_accepted_connections) {
164 return -1; 221 return -1;
222 }
165 223
166 if (TCP_server->accepted_connection_array[index].status == TCP_STATUS_NO_STATUS) 224 if (TCP_server->accepted_connection_array[index].status == TCP_STATUS_NO_STATUS) {
167 return -1; 225 return -1;
226 }
168 227
169 if (!bs_list_remove(&TCP_server->accepted_key_list, TCP_server->accepted_connection_array[index].public_key, index)) 228 if (!bs_list_remove(&TCP_server->accepted_key_list, TCP_server->accepted_connection_array[index].public_key, index)) {
170 return -1; 229 return -1;
230 }
171 231
172 sodium_memzero(&TCP_server->accepted_connection_array[index], sizeof(TCP_Secure_Connection)); 232 crypto_memzero(&TCP_server->accepted_connection_array[index], sizeof(TCP_Secure_Connection));
173 --TCP_server->num_accepted_connections; 233 --TCP_server->num_accepted_connections;
174 234
175 if (TCP_server->num_accepted_connections == 0) 235 if (TCP_server->num_accepted_connections == 0) {
176 realloc_connection(TCP_server, 0); 236 realloc_connection(TCP_server, 0);
237 }
177 238
178 return 0; 239 return 0;
179} 240}
180 241
181/* return the amount of data in the tcp recv buffer.
182 * return 0 on failure.
183 */
184unsigned int TCP_socket_data_recv_buffer(sock_t sock)
185{
186#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
187 unsigned long count = 0;
188 ioctlsocket(sock, FIONREAD, &count);
189#else
190 int count = 0;
191 ioctl(sock, FIONREAD, &count);
192#endif
193
194 return count;
195}
196
197/* Read the next two bytes in TCP stream then convert them to 242/* Read the next two bytes in TCP stream then convert them to
198 * length (host byte order). 243 * length (host byte order).
199 * 244 *
@@ -201,20 +246,20 @@ unsigned int TCP_socket_data_recv_buffer(sock_t sock)
201 * return 0 if nothing has been read from socket. 246 * return 0 if nothing has been read from socket.
202 * return ~0 on failure. 247 * return ~0 on failure.
203 */ 248 */
204uint16_t read_TCP_length(sock_t sock) 249uint16_t read_TCP_length(Socket sock)
205{ 250{
206 unsigned int count = TCP_socket_data_recv_buffer(sock); 251 const unsigned int count = net_socket_data_recv_buffer(sock);
207 252
208 if (count >= sizeof(uint16_t)) { 253 if (count >= sizeof(uint16_t)) {
209 uint16_t length; 254 uint16_t length;
210 int len = recv(sock, (uint8_t *)&length, sizeof(uint16_t), MSG_NOSIGNAL); 255 const int len = net_recv(sock, &length, sizeof(uint16_t));
211 256
212 if (len != sizeof(uint16_t)) { 257 if (len != sizeof(uint16_t)) {
213 fprintf(stderr, "FAIL recv packet\n"); 258 fprintf(stderr, "FAIL recv packet\n");
214 return 0; 259 return 0;
215 } 260 }
216 261
217 length = ntohs(length); 262 length = net_ntohs(length);
218 263
219 if (length > MAX_PACKET_SIZE) { 264 if (length > MAX_PACKET_SIZE) {
220 return ~0; 265 return ~0;
@@ -231,12 +276,12 @@ uint16_t read_TCP_length(sock_t sock)
231 * return length on success 276 * return length on success
232 * return -1 on failure/no data in buffer. 277 * return -1 on failure/no data in buffer.
233 */ 278 */
234int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length) 279int read_TCP_packet(Socket sock, uint8_t *data, uint16_t length)
235{ 280{
236 unsigned int count = TCP_socket_data_recv_buffer(sock); 281 unsigned int count = net_socket_data_recv_buffer(sock);
237 282
238 if (count >= length) { 283 if (count >= length) {
239 int len = recv(sock, data, length, MSG_NOSIGNAL); 284 const int len = net_recv(sock, data, length);
240 285
241 if (len != length) { 286 if (len != length) {
242 fprintf(stderr, "FAIL recv packet\n"); 287 fprintf(stderr, "FAIL recv packet\n");
@@ -253,36 +298,41 @@ int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length)
253 * return 0 if could not read any packet. 298 * return 0 if could not read any packet.
254 * return -1 on failure (connection must be killed). 299 * return -1 on failure (connection must be killed).
255 */ 300 */
256int read_packet_TCP_secure_connection(sock_t sock, uint16_t *next_packet_length, const uint8_t *shared_key, 301int read_packet_TCP_secure_connection(Socket sock, uint16_t *next_packet_length, const uint8_t *shared_key,
257 uint8_t *recv_nonce, uint8_t *data, uint16_t max_len) 302 uint8_t *recv_nonce, uint8_t *data, uint16_t max_len)
258{ 303{
259 if (*next_packet_length == 0) { 304 if (*next_packet_length == 0) {
260 uint16_t len = read_TCP_length(sock); 305 uint16_t len = read_TCP_length(sock);
261 306
262 if (len == (uint16_t)~0) 307 if (len == (uint16_t)~0) {
263 return -1; 308 return -1;
309 }
264 310
265 if (len == 0) 311 if (len == 0) {
266 return 0; 312 return 0;
313 }
267 314
268 *next_packet_length = len; 315 *next_packet_length = len;
269 } 316 }
270 317
271 if (max_len + crypto_box_MACBYTES < *next_packet_length) 318 if (max_len + CRYPTO_MAC_SIZE < *next_packet_length) {
272 return -1; 319 return -1;
320 }
273 321
274 uint8_t data_encrypted[*next_packet_length]; 322 VLA(uint8_t, data_encrypted, *next_packet_length);
275 int len_packet = read_TCP_packet(sock, data_encrypted, *next_packet_length); 323 int len_packet = read_TCP_packet(sock, data_encrypted, *next_packet_length);
276 324
277 if (len_packet != *next_packet_length) 325 if (len_packet != *next_packet_length) {
278 return 0; 326 return 0;
327 }
279 328
280 *next_packet_length = 0; 329 *next_packet_length = 0;
281 330
282 int len = decrypt_data_symmetric(shared_key, recv_nonce, data_encrypted, len_packet, data); 331 int len = decrypt_data_symmetric(shared_key, recv_nonce, data_encrypted, len_packet, data);
283 332
284 if (len + crypto_box_MACBYTES != len_packet) 333 if (len + CRYPTO_MAC_SIZE != len_packet) {
285 return -1; 334 return -1;
335 }
286 336
287 increment_nonce(recv_nonce); 337 increment_nonce(recv_nonce);
288 338
@@ -298,11 +348,12 @@ static int send_pending_data_nonpriority(TCP_Secure_Connection *con)
298 return 0; 348 return 0;
299 } 349 }
300 350
301 uint16_t left = con->last_packet_length - con->last_packet_sent; 351 const uint16_t left = con->last_packet_length - con->last_packet_sent;
302 int len = send(con->sock, con->last_packet + con->last_packet_sent, left, MSG_NOSIGNAL); 352 const int len = net_send(con->sock, con->last_packet + con->last_packet_sent, left);
303 353
304 if (len <= 0) 354 if (len <= 0) {
305 return -1; 355 return -1;
356 }
306 357
307 if (len == left) { 358 if (len == left) {
308 con->last_packet_length = 0; 359 con->last_packet_length = 0;
@@ -312,7 +363,6 @@ static int send_pending_data_nonpriority(TCP_Secure_Connection *con)
312 363
313 con->last_packet_sent += len; 364 con->last_packet_sent += len;
314 return -1; 365 return -1;
315
316} 366}
317 367
318/* return 0 if pending data was sent completely 368/* return 0 if pending data was sent completely
@@ -328,8 +378,8 @@ static int send_pending_data(TCP_Secure_Connection *con)
328 TCP_Priority_List *p = con->priority_queue_start; 378 TCP_Priority_List *p = con->priority_queue_start;
329 379
330 while (p) { 380 while (p) {
331 uint16_t left = p->size - p->sent; 381 const uint16_t left = p->size - p->sent;
332 int len = send(con->sock, p->data + p->sent, left, MSG_NOSIGNAL); 382 const int len = net_send(con->sock, p->data + p->sent, left);
333 383
334 if (len != left) { 384 if (len != left) {
335 if (len > 0) { 385 if (len > 0) {
@@ -347,7 +397,7 @@ static int send_pending_data(TCP_Secure_Connection *con)
347 con->priority_queue_start = p; 397 con->priority_queue_start = p;
348 398
349 if (!p) { 399 if (!p) {
350 con->priority_queue_end = NULL; 400 con->priority_queue_end = nullptr;
351 return 0; 401 return 0;
352 } 402 }
353 403
@@ -357,27 +407,27 @@ static int send_pending_data(TCP_Secure_Connection *con)
357/* return 0 on failure (only if malloc fails) 407/* return 0 on failure (only if malloc fails)
358 * return 1 on success 408 * return 1 on success
359 */ 409 */
360static _Bool add_priority(TCP_Secure_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent) 410static bool add_priority(TCP_Secure_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent)
361{ 411{
362 TCP_Priority_List *p = con->priority_queue_end, *new; 412 TCP_Priority_List *p = con->priority_queue_end;
363 new = malloc(sizeof(TCP_Priority_List) + size); 413 TCP_Priority_List *new_list = (TCP_Priority_List *)malloc(sizeof(TCP_Priority_List) + size);
364 414
365 if (!new) { 415 if (!new_list) {
366 return 0; 416 return 0;
367 } 417 }
368 418
369 new->next = NULL; 419 new_list->next = nullptr;
370 new->size = size; 420 new_list->size = size;
371 new->sent = sent; 421 new_list->sent = sent;
372 memcpy(new->data, packet, size); 422 memcpy(new_list->data, packet, size);
373 423
374 if (p) { 424 if (p) {
375 p->next = new; 425 p->next = new_list;
376 } else { 426 } else {
377 con->priority_queue_start = new; 427 con->priority_queue_start = new_list;
378 } 428 }
379 429
380 con->priority_queue_end = new; 430 con->priority_queue_end = new_list;
381 return 1; 431 return 1;
382} 432}
383 433
@@ -386,12 +436,13 @@ static _Bool add_priority(TCP_Secure_Connection *con, const uint8_t *packet, uin
386 * return -1 on failure (connection must be killed). 436 * return -1 on failure (connection must be killed).
387 */ 437 */
388static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length, 438static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length,
389 _Bool priority) 439 bool priority)
390{ 440{
391 if (length + crypto_box_MACBYTES > MAX_PACKET_SIZE) 441 if (length + CRYPTO_MAC_SIZE > MAX_PACKET_SIZE) {
392 return -1; 442 return -1;
443 }
393 444
394 _Bool sendpriority = 1; 445 bool sendpriority = 1;
395 446
396 if (send_pending_data(con) == -1) { 447 if (send_pending_data(con) == -1) {
397 if (priority) { 448 if (priority) {
@@ -401,17 +452,18 @@ static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const
401 } 452 }
402 } 453 }
403 454
404 uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES]; 455 VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE);
405 456
406 uint16_t c_length = htons(length + crypto_box_MACBYTES); 457 const uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE);
407 memcpy(packet, &c_length, sizeof(uint16_t)); 458 memcpy(packet, &c_length, sizeof(uint16_t));
408 int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); 459 int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));
409 460
410 if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) 461 if ((unsigned int)len != (SIZEOF_VLA(packet) - sizeof(uint16_t))) {
411 return -1; 462 return -1;
463 }
412 464
413 if (priority) { 465 if (priority) {
414 len = sendpriority ? send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL) : 0; 466 len = sendpriority ? net_send(con->sock, packet, SIZEOF_VLA(packet)) : 0;
415 467
416 if (len <= 0) { 468 if (len <= 0) {
417 len = 0; 469 len = 0;
@@ -419,35 +471,37 @@ static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const
419 471
420 increment_nonce(con->sent_nonce); 472 increment_nonce(con->sent_nonce);
421 473
422 if ((unsigned int)len == sizeof(packet)) { 474 if ((unsigned int)len == SIZEOF_VLA(packet)) {
423 return 1; 475 return 1;
424 } 476 }
425 477
426 return add_priority(con, packet, sizeof(packet), len); 478 return add_priority(con, packet, SIZEOF_VLA(packet), len);
427 } 479 }
428 480
429 len = send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL); 481 len = net_send(con->sock, packet, SIZEOF_VLA(packet));
430 482
431 if (len <= 0) 483 if (len <= 0) {
432 return 0; 484 return 0;
485 }
433 486
434 increment_nonce(con->sent_nonce); 487 increment_nonce(con->sent_nonce);
435 488
436 if ((unsigned int)len == sizeof(packet)) 489 if ((unsigned int)len == SIZEOF_VLA(packet)) {
437 return 1; 490 return 1;
491 }
438 492
439 memcpy(con->last_packet, packet, sizeof(packet)); 493 memcpy(con->last_packet, packet, SIZEOF_VLA(packet));
440 con->last_packet_length = sizeof(packet); 494 con->last_packet_length = SIZEOF_VLA(packet);
441 con->last_packet_sent = len; 495 con->last_packet_sent = len;
442 return 1; 496 return 1;
443} 497}
444 498
445/* Kill a TCP_Secure_Connection 499/* Kill a TCP_Secure_Connection
446 */ 500 */
447static void kill_TCP_connection(TCP_Secure_Connection *con) 501static void kill_TCP_secure_connection(TCP_Secure_Connection *con)
448{ 502{
449 kill_sock(con->sock); 503 kill_sock(con->sock);
450 sodium_memzero(con, sizeof(TCP_Secure_Connection)); 504 crypto_memzero(con, sizeof(TCP_Secure_Connection));
451} 505}
452 506
453static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number); 507static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number);
@@ -459,8 +513,9 @@ static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *co
459 */ 513 */
460static int kill_accepted(TCP_Server *TCP_server, int index) 514static int kill_accepted(TCP_Server *TCP_server, int index)
461{ 515{
462 if ((uint32_t)index >= TCP_server->size_accepted_connections) 516 if ((uint32_t)index >= TCP_server->size_accepted_connections) {
463 return -1; 517 return -1;
518 }
464 519
465 uint32_t i; 520 uint32_t i;
466 521
@@ -468,10 +523,11 @@ static int kill_accepted(TCP_Server *TCP_server, int index)
468 rm_connection_index(TCP_server, &TCP_server->accepted_connection_array[index], i); 523 rm_connection_index(TCP_server, &TCP_server->accepted_connection_array[index], i);
469 } 524 }
470 525
471 sock_t sock = TCP_server->accepted_connection_array[index].sock; 526 Socket sock = TCP_server->accepted_connection_array[index].sock;
472 527
473 if (del_accepted(TCP_server, index) != 0) 528 if (del_accepted(TCP_server, index) != 0) {
474 return -1; 529 return -1;
530 }
475 531
476 kill_sock(sock); 532 kill_sock(sock);
477 return 0; 533 return 0;
@@ -483,40 +539,45 @@ static int kill_accepted(TCP_Server *TCP_server, int index)
483static int handle_TCP_handshake(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length, 539static int handle_TCP_handshake(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length,
484 const uint8_t *self_secret_key) 540 const uint8_t *self_secret_key)
485{ 541{
486 if (length != TCP_CLIENT_HANDSHAKE_SIZE) 542 if (length != TCP_CLIENT_HANDSHAKE_SIZE) {
487 return -1; 543 return -1;
544 }
488 545
489 if (con->status != TCP_STATUS_CONNECTED) 546 if (con->status != TCP_STATUS_CONNECTED) {
490 return -1; 547 return -1;
548 }
491 549
492 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 550 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
493 encrypt_precompute(data, self_secret_key, shared_key); 551 encrypt_precompute(data, self_secret_key, shared_key);
494 uint8_t plain[TCP_HANDSHAKE_PLAIN_SIZE]; 552 uint8_t plain[TCP_HANDSHAKE_PLAIN_SIZE];
495 int len = decrypt_data_symmetric(shared_key, data + crypto_box_PUBLICKEYBYTES, 553 int len = decrypt_data_symmetric(shared_key, data + CRYPTO_PUBLIC_KEY_SIZE,
496 data + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES, plain); 554 data + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE, plain);
497 555
498 if (len != TCP_HANDSHAKE_PLAIN_SIZE) 556 if (len != TCP_HANDSHAKE_PLAIN_SIZE) {
499 return -1; 557 return -1;
558 }
500 559
501 memcpy(con->public_key, data, crypto_box_PUBLICKEYBYTES); 560 memcpy(con->public_key, data, CRYPTO_PUBLIC_KEY_SIZE);
502 uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES]; 561 uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE];
503 uint8_t resp_plain[TCP_HANDSHAKE_PLAIN_SIZE]; 562 uint8_t resp_plain[TCP_HANDSHAKE_PLAIN_SIZE];
504 crypto_box_keypair(resp_plain, temp_secret_key); 563 crypto_new_keypair(resp_plain, temp_secret_key);
505 random_nonce(con->sent_nonce); 564 random_nonce(con->sent_nonce);
506 memcpy(resp_plain + crypto_box_PUBLICKEYBYTES, con->sent_nonce, crypto_box_NONCEBYTES); 565 memcpy(resp_plain + CRYPTO_PUBLIC_KEY_SIZE, con->sent_nonce, CRYPTO_NONCE_SIZE);
507 memcpy(con->recv_nonce, plain + crypto_box_PUBLICKEYBYTES, crypto_box_NONCEBYTES); 566 memcpy(con->recv_nonce, plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_NONCE_SIZE);
508 567
509 uint8_t response[TCP_SERVER_HANDSHAKE_SIZE]; 568 uint8_t response[TCP_SERVER_HANDSHAKE_SIZE];
510 new_nonce(response); 569 random_nonce(response);
511 570
512 len = encrypt_data_symmetric(shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE, 571 len = encrypt_data_symmetric(shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE,
513 response + crypto_box_NONCEBYTES); 572 response + CRYPTO_NONCE_SIZE);
514 573
515 if (len != TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES) 574 if (len != TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE) {
516 return -1; 575 return -1;
576 }
517 577
518 if (TCP_SERVER_HANDSHAKE_SIZE != send(con->sock, response, TCP_SERVER_HANDSHAKE_SIZE, MSG_NOSIGNAL)) 578 if (TCP_SERVER_HANDSHAKE_SIZE != net_send(con->sock, response, TCP_SERVER_HANDSHAKE_SIZE)) {
519 return -1; 579 return -1;
580 }
520 581
521 encrypt_precompute(plain, temp_secret_key, con->shared_key); 582 encrypt_precompute(plain, temp_secret_key, con->shared_key);
522 con->status = TCP_STATUS_UNCONFIRMED; 583 con->status = TCP_STATUS_UNCONFIRMED;
@@ -545,10 +606,10 @@ static int read_connection_handshake(TCP_Secure_Connection *con, const uint8_t *
545 */ 606 */
546static int send_routing_response(TCP_Secure_Connection *con, uint8_t rpid, const uint8_t *public_key) 607static int send_routing_response(TCP_Secure_Connection *con, uint8_t rpid, const uint8_t *public_key)
547{ 608{
548 uint8_t data[1 + 1 + crypto_box_PUBLICKEYBYTES]; 609 uint8_t data[1 + 1 + CRYPTO_PUBLIC_KEY_SIZE];
549 data[0] = TCP_PACKET_ROUTING_RESPONSE; 610 data[0] = TCP_PACKET_ROUTING_RESPONSE;
550 data[1] = rpid; 611 data[1] = rpid;
551 memcpy(data + 2, public_key, crypto_box_PUBLICKEYBYTES); 612 memcpy(data + 2, public_key, CRYPTO_PUBLIC_KEY_SIZE);
552 613
553 return write_packet_TCP_secure_connection(con, data, sizeof(data), 1); 614 return write_packet_TCP_secure_connection(con, data, sizeof(data), 1);
554} 615}
@@ -559,7 +620,7 @@ static int send_routing_response(TCP_Secure_Connection *con, uint8_t rpid, const
559 */ 620 */
560static int send_connect_notification(TCP_Secure_Connection *con, uint8_t id) 621static int send_connect_notification(TCP_Secure_Connection *con, uint8_t id)
561{ 622{
562 uint8_t data[2] = {TCP_PACKET_CONNECTION_NOTIFICATION, id + NUM_RESERVED_PORTS}; 623 uint8_t data[2] = {TCP_PACKET_CONNECTION_NOTIFICATION, (uint8_t)(id + NUM_RESERVED_PORTS)};
563 return write_packet_TCP_secure_connection(con, data, sizeof(data), 1); 624 return write_packet_TCP_secure_connection(con, data, sizeof(data), 1);
564} 625}
565 626
@@ -569,7 +630,7 @@ static int send_connect_notification(TCP_Secure_Connection *con, uint8_t id)
569 */ 630 */
570static int send_disconnect_notification(TCP_Secure_Connection *con, uint8_t id) 631static int send_disconnect_notification(TCP_Secure_Connection *con, uint8_t id)
571{ 632{
572 uint8_t data[2] = {TCP_PACKET_DISCONNECT_NOTIFICATION, id + NUM_RESERVED_PORTS}; 633 uint8_t data[2] = {TCP_PACKET_DISCONNECT_NOTIFICATION, (uint8_t)(id + NUM_RESERVED_PORTS)};
573 return write_packet_TCP_secure_connection(con, data, sizeof(data), 1); 634 return write_packet_TCP_secure_connection(con, data, sizeof(data), 1);
574} 635}
575 636
@@ -584,8 +645,9 @@ static int handle_TCP_routing_req(TCP_Server *TCP_server, uint32_t con_id, const
584 645
585 /* If person tries to cennect to himself we deny the request*/ 646 /* If person tries to cennect to himself we deny the request*/
586 if (public_key_cmp(con->public_key, public_key) == 0) { 647 if (public_key_cmp(con->public_key, public_key) == 0) {
587 if (send_routing_response(con, 0, public_key) == -1) 648 if (send_routing_response(con, 0, public_key) == -1) {
588 return -1; 649 return -1;
650 }
589 651
590 return 0; 652 return 0;
591 } 653 }
@@ -595,9 +657,9 @@ static int handle_TCP_routing_req(TCP_Server *TCP_server, uint32_t con_id, const
595 if (public_key_cmp(public_key, con->connections[i].public_key) == 0) { 657 if (public_key_cmp(public_key, con->connections[i].public_key) == 0) {
596 if (send_routing_response(con, i + NUM_RESERVED_PORTS, public_key) == -1) { 658 if (send_routing_response(con, i + NUM_RESERVED_PORTS, public_key) == -1) {
597 return -1; 659 return -1;
598 } else {
599 return 0;
600 } 660 }
661
662 return 0;
601 } 663 }
602 } else if (index == (uint32_t)~0) { 664 } else if (index == (uint32_t)~0) {
603 index = i; 665 index = i;
@@ -605,22 +667,25 @@ static int handle_TCP_routing_req(TCP_Server *TCP_server, uint32_t con_id, const
605 } 667 }
606 668
607 if (index == (uint32_t)~0) { 669 if (index == (uint32_t)~0) {
608 if (send_routing_response(con, 0, public_key) == -1) 670 if (send_routing_response(con, 0, public_key) == -1) {
609 return -1; 671 return -1;
672 }
610 673
611 return 0; 674 return 0;
612 } 675 }
613 676
614 int ret = send_routing_response(con, index + NUM_RESERVED_PORTS, public_key); 677 int ret = send_routing_response(con, index + NUM_RESERVED_PORTS, public_key);
615 678
616 if (ret == 0) 679 if (ret == 0) {
617 return 0; 680 return 0;
681 }
618 682
619 if (ret == -1) 683 if (ret == -1) {
620 return -1; 684 return -1;
685 }
621 686
622 con->connections[index].status = 1; 687 con->connections[index].status = 1;
623 memcpy(con->connections[index].public_key, public_key, crypto_box_PUBLICKEYBYTES); 688 memcpy(con->connections[index].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
624 int other_index = get_TCP_connection_index(TCP_server, public_key); 689 int other_index = get_TCP_connection_index(TCP_server, public_key);
625 690
626 if (other_index != -1) { 691 if (other_index != -1) {
@@ -642,7 +707,7 @@ static int handle_TCP_routing_req(TCP_Server *TCP_server, uint32_t con_id, const
642 other_conn->connections[other_id].status = 2; 707 other_conn->connections[other_id].status = 2;
643 other_conn->connections[other_id].index = con_id; 708 other_conn->connections[other_id].index = con_id;
644 other_conn->connections[other_id].other_id = index; 709 other_conn->connections[other_id].other_id = index;
645 //TODO: return values? 710 // TODO(irungentoo): return values?
646 send_connect_notification(con, index); 711 send_connect_notification(con, index);
647 send_connect_notification(other_conn, other_id); 712 send_connect_notification(other_conn, other_id);
648 } 713 }
@@ -657,20 +722,21 @@ static int handle_TCP_routing_req(TCP_Server *TCP_server, uint32_t con_id, const
657static int handle_TCP_oob_send(TCP_Server *TCP_server, uint32_t con_id, const uint8_t *public_key, const uint8_t *data, 722static int handle_TCP_oob_send(TCP_Server *TCP_server, uint32_t con_id, const uint8_t *public_key, const uint8_t *data,
658 uint16_t length) 723 uint16_t length)
659{ 724{
660 if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) 725 if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) {
661 return -1; 726 return -1;
727 }
662 728
663 TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[con_id]; 729 TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[con_id];
664 730
665 int other_index = get_TCP_connection_index(TCP_server, public_key); 731 int other_index = get_TCP_connection_index(TCP_server, public_key);
666 732
667 if (other_index != -1) { 733 if (other_index != -1) {
668 uint8_t resp_packet[1 + crypto_box_PUBLICKEYBYTES + length]; 734 VLA(uint8_t, resp_packet, 1 + CRYPTO_PUBLIC_KEY_SIZE + length);
669 resp_packet[0] = TCP_PACKET_OOB_RECV; 735 resp_packet[0] = TCP_PACKET_OOB_RECV;
670 memcpy(resp_packet + 1, con->public_key, crypto_box_PUBLICKEYBYTES); 736 memcpy(resp_packet + 1, con->public_key, CRYPTO_PUBLIC_KEY_SIZE);
671 memcpy(resp_packet + 1 + crypto_box_PUBLICKEYBYTES, data, length); 737 memcpy(resp_packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length);
672 write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[other_index], resp_packet, 738 write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[other_index], resp_packet,
673 sizeof(resp_packet), 0); 739 SIZEOF_VLA(resp_packet), 0);
674 } 740 }
675 741
676 return 0; 742 return 0;
@@ -683,8 +749,9 @@ static int handle_TCP_oob_send(TCP_Server *TCP_server, uint32_t con_id, const ui
683 */ 749 */
684static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number) 750static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number)
685{ 751{
686 if (con_number >= NUM_CLIENT_CONNECTIONS) 752 if (con_number >= NUM_CLIENT_CONNECTIONS) {
687 return -1; 753 return -1;
754 }
688 755
689 if (con->connections[con_number].status) { 756 if (con->connections[con_number].status) {
690 uint32_t index = con->connections[con_number].index; 757 uint32_t index = con->connections[con_number].index;
@@ -692,13 +759,14 @@ static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *co
692 759
693 if (con->connections[con_number].status == 2) { 760 if (con->connections[con_number].status == 2) {
694 761
695 if (index >= TCP_server->size_accepted_connections) 762 if (index >= TCP_server->size_accepted_connections) {
696 return -1; 763 return -1;
764 }
697 765
698 TCP_server->accepted_connection_array[index].connections[other_id].other_id = 0; 766 TCP_server->accepted_connection_array[index].connections[other_id].other_id = 0;
699 TCP_server->accepted_connection_array[index].connections[other_id].index = 0; 767 TCP_server->accepted_connection_array[index].connections[other_id].index = 0;
700 TCP_server->accepted_connection_array[index].connections[other_id].status = 1; 768 TCP_server->accepted_connection_array[index].connections[other_id].status = 1;
701 //TODO: return values? 769 // TODO(irungentoo): return values?
702 send_disconnect_notification(&TCP_server->accepted_connection_array[index], other_id); 770 send_disconnect_notification(&TCP_server->accepted_connection_array[index], other_id);
703 } 771 }
704 772
@@ -706,30 +774,33 @@ static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *co
706 con->connections[con_number].other_id = 0; 774 con->connections[con_number].other_id = 0;
707 con->connections[con_number].status = 0; 775 con->connections[con_number].status = 0;
708 return 0; 776 return 0;
709 } else {
710 return -1;
711 } 777 }
778
779 return -1;
712} 780}
713 781
714static int handle_onion_recv_1(void *object, IP_Port dest, const uint8_t *data, uint16_t length) 782static int handle_onion_recv_1(void *object, IP_Port dest, const uint8_t *data, uint16_t length)
715{ 783{
716 TCP_Server *TCP_server = object; 784 TCP_Server *TCP_server = (TCP_Server *)object;
717 uint32_t index = dest.ip.ip6.uint32[0]; 785 uint32_t index = dest.ip.ip.v6.uint32[0];
718 786
719 if (index >= TCP_server->size_accepted_connections) 787 if (index >= TCP_server->size_accepted_connections) {
720 return 1; 788 return 1;
789 }
721 790
722 TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[index]; 791 TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[index];
723 792
724 if (con->identifier != dest.ip.ip6.uint64[1]) 793 if (con->identifier != dest.ip.ip.v6.uint64[1]) {
725 return 1; 794 return 1;
795 }
726 796
727 uint8_t packet[1 + length]; 797 VLA(uint8_t, packet, 1 + length);
728 memcpy(packet + 1, data, length); 798 memcpy(packet + 1, data, length);
729 packet[0] = TCP_PACKET_ONION_RESPONSE; 799 packet[0] = TCP_PACKET_ONION_RESPONSE;
730 800
731 if (write_packet_TCP_secure_connection(con, packet, sizeof(packet), 0) != 1) 801 if (write_packet_TCP_secure_connection(con, packet, SIZEOF_VLA(packet), 0) != 1) {
732 return 1; 802 return 1;
803 }
733 804
734 return 0; 805 return 0;
735} 806}
@@ -739,36 +810,41 @@ static int handle_onion_recv_1(void *object, IP_Port dest, const uint8_t *data,
739 */ 810 */
740static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, const uint8_t *data, uint16_t length) 811static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, const uint8_t *data, uint16_t length)
741{ 812{
742 if (length == 0) 813 if (length == 0) {
743 return -1; 814 return -1;
815 }
744 816
745 TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[con_id]; 817 TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[con_id];
746 818
747 switch (data[0]) { 819 switch (data[0]) {
748 case TCP_PACKET_ROUTING_REQUEST: { 820 case TCP_PACKET_ROUTING_REQUEST: {
749 if (length != 1 + crypto_box_PUBLICKEYBYTES) 821 if (length != 1 + CRYPTO_PUBLIC_KEY_SIZE) {
750 return -1; 822 return -1;
823 }
751 824
752 return handle_TCP_routing_req(TCP_server, con_id, data + 1); 825 return handle_TCP_routing_req(TCP_server, con_id, data + 1);
753 } 826 }
754 827
755 case TCP_PACKET_CONNECTION_NOTIFICATION: { 828 case TCP_PACKET_CONNECTION_NOTIFICATION: {
756 if (length != 2) 829 if (length != 2) {
757 return -1; 830 return -1;
831 }
758 832
759 break; 833 break;
760 } 834 }
761 835
762 case TCP_PACKET_DISCONNECT_NOTIFICATION: { 836 case TCP_PACKET_DISCONNECT_NOTIFICATION: {
763 if (length != 2) 837 if (length != 2) {
764 return -1; 838 return -1;
839 }
765 840
766 return rm_connection_index(TCP_server, con, data[1] - NUM_RESERVED_PORTS); 841 return rm_connection_index(TCP_server, con, data[1] - NUM_RESERVED_PORTS);
767 } 842 }
768 843
769 case TCP_PACKET_PING: { 844 case TCP_PACKET_PING: {
770 if (length != 1 + sizeof(uint64_t)) 845 if (length != 1 + sizeof(uint64_t)) {
771 return -1; 846 return -1;
847 }
772 848
773 uint8_t response[1 + sizeof(uint64_t)]; 849 uint8_t response[1 + sizeof(uint64_t)];
774 response[0] = TCP_PACKET_PONG; 850 response[0] = TCP_PACKET_PONG;
@@ -778,8 +854,9 @@ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, const uint
778 } 854 }
779 855
780 case TCP_PACKET_PONG: { 856 case TCP_PACKET_PONG: {
781 if (length != 1 + sizeof(uint64_t)) 857 if (length != 1 + sizeof(uint64_t)) {
782 return -1; 858 return -1;
859 }
783 860
784 uint64_t ping_id; 861 uint64_t ping_id;
785 memcpy(&ping_id, data + 1, sizeof(uint64_t)); 862 memcpy(&ping_id, data + 1, sizeof(uint64_t));
@@ -790,31 +867,33 @@ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, const uint
790 } 867 }
791 868
792 return 0; 869 return 0;
793 } else {
794 return -1;
795 } 870 }
871
872 return -1;
796 } 873 }
797 874
798 case TCP_PACKET_OOB_SEND: { 875 case TCP_PACKET_OOB_SEND: {
799 if (length <= 1 + crypto_box_PUBLICKEYBYTES) 876 if (length <= 1 + CRYPTO_PUBLIC_KEY_SIZE) {
800 return -1; 877 return -1;
878 }
801 879
802 return handle_TCP_oob_send(TCP_server, con_id, data + 1, data + 1 + crypto_box_PUBLICKEYBYTES, 880 return handle_TCP_oob_send(TCP_server, con_id, data + 1, data + 1 + CRYPTO_PUBLIC_KEY_SIZE,
803 length - (1 + crypto_box_PUBLICKEYBYTES)); 881 length - (1 + CRYPTO_PUBLIC_KEY_SIZE));
804 } 882 }
805 883
806 case TCP_PACKET_ONION_REQUEST: { 884 case TCP_PACKET_ONION_REQUEST: {
807 if (TCP_server->onion) { 885 if (TCP_server->onion) {
808 if (length <= 1 + crypto_box_NONCEBYTES + ONION_SEND_BASE * 2) 886 if (length <= 1 + CRYPTO_NONCE_SIZE + ONION_SEND_BASE * 2) {
809 return -1; 887 return -1;
888 }
810 889
811 IP_Port source; 890 IP_Port source;
812 source.port = 0; // dummy initialise 891 source.port = 0; // dummy initialise
813 source.ip.family = TCP_ONION_FAMILY; 892 source.ip.family = net_family_tcp_onion;
814 source.ip.ip6.uint32[0] = con_id; 893 source.ip.ip.v6.uint32[0] = con_id;
815 source.ip.ip6.uint32[1] = 0; 894 source.ip.ip.v6.uint32[1] = 0;
816 source.ip.ip6.uint64[1] = con->identifier; 895 source.ip.ip.v6.uint64[1] = con->identifier;
817 onion_send_1(TCP_server->onion, data + 1 + crypto_box_NONCEBYTES, length - (1 + crypto_box_NONCEBYTES), source, 896 onion_send_1(TCP_server->onion, data + 1 + CRYPTO_NONCE_SIZE, length - (1 + CRYPTO_NONCE_SIZE), source,
818 data + 1); 897 data + 1);
819 } 898 }
820 899
@@ -826,29 +905,34 @@ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, const uint
826 } 905 }
827 906
828 default: { 907 default: {
829 if (data[0] < NUM_RESERVED_PORTS) 908 if (data[0] < NUM_RESERVED_PORTS) {
830 return -1; 909 return -1;
910 }
831 911
832 uint8_t c_id = data[0] - NUM_RESERVED_PORTS; 912 uint8_t c_id = data[0] - NUM_RESERVED_PORTS;
833 913
834 if (c_id >= NUM_CLIENT_CONNECTIONS) 914 if (c_id >= NUM_CLIENT_CONNECTIONS) {
835 return -1; 915 return -1;
916 }
836 917
837 if (con->connections[c_id].status == 0) 918 if (con->connections[c_id].status == 0) {
838 return -1; 919 return -1;
920 }
839 921
840 if (con->connections[c_id].status != 2) 922 if (con->connections[c_id].status != 2) {
841 return 0; 923 return 0;
924 }
842 925
843 uint32_t index = con->connections[c_id].index; 926 uint32_t index = con->connections[c_id].index;
844 uint8_t other_c_id = con->connections[c_id].other_id + NUM_RESERVED_PORTS; 927 uint8_t other_c_id = con->connections[c_id].other_id + NUM_RESERVED_PORTS;
845 uint8_t new_data[length]; 928 VLA(uint8_t, new_data, length);
846 memcpy(new_data, data, length); 929 memcpy(new_data, data, length);
847 new_data[0] = other_c_id; 930 new_data[0] = other_c_id;
848 int ret = write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[index], new_data, length, 0); 931 int ret = write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[index], new_data, length, 0);
849 932
850 if (ret == -1) 933 if (ret == -1) {
851 return -1; 934 return -1;
935 }
852 936
853 return 0; 937 return 0;
854 } 938 }
@@ -864,11 +948,11 @@ static int confirm_TCP_connection(TCP_Server *TCP_server, TCP_Secure_Connection
864 int index = add_accepted(TCP_server, con); 948 int index = add_accepted(TCP_server, con);
865 949
866 if (index == -1) { 950 if (index == -1) {
867 kill_TCP_connection(con); 951 kill_TCP_secure_connection(con);
868 return -1; 952 return -1;
869 } 953 }
870 954
871 sodium_memzero(con, sizeof(TCP_Secure_Connection)); 955 crypto_memzero(con, sizeof(TCP_Secure_Connection));
872 956
873 if (handle_TCP_packet(TCP_server, index, data, length) == -1) { 957 if (handle_TCP_packet(TCP_server, index, data, length) == -1) {
874 kill_accepted(TCP_server, index); 958 kill_accepted(TCP_server, index);
@@ -881,10 +965,11 @@ static int confirm_TCP_connection(TCP_Server *TCP_server, TCP_Secure_Connection
881/* return index on success 965/* return index on success
882 * return -1 on failure 966 * return -1 on failure
883 */ 967 */
884static int accept_connection(TCP_Server *TCP_server, sock_t sock) 968static int accept_connection(TCP_Server *TCP_server, Socket sock)
885{ 969{
886 if (!sock_valid(sock)) 970 if (!sock_valid(sock)) {
887 return -1; 971 return -1;
972 }
888 973
889 if (!set_socket_nonblock(sock)) { 974 if (!set_socket_nonblock(sock)) {
890 kill_sock(sock); 975 kill_sock(sock);
@@ -896,32 +981,33 @@ static int accept_connection(TCP_Server *TCP_server, sock_t sock)
896 return -1; 981 return -1;
897 } 982 }
898 983
899 uint16_t index = TCP_server->incomming_connection_queue_index % MAX_INCOMMING_CONNECTIONS; 984 uint16_t index = TCP_server->incoming_connection_queue_index % MAX_INCOMING_CONNECTIONS;
900 985
901 TCP_Secure_Connection *conn = &TCP_server->incomming_connection_queue[index]; 986 TCP_Secure_Connection *conn = &TCP_server->incoming_connection_queue[index];
902 987
903 if (conn->status != TCP_STATUS_NO_STATUS) 988 if (conn->status != TCP_STATUS_NO_STATUS) {
904 kill_TCP_connection(conn); 989 kill_TCP_secure_connection(conn);
990 }
905 991
906 conn->status = TCP_STATUS_CONNECTED; 992 conn->status = TCP_STATUS_CONNECTED;
907 conn->sock = sock; 993 conn->sock = sock;
908 conn->next_packet_length = 0; 994 conn->next_packet_length = 0;
909 995
910 ++TCP_server->incomming_connection_queue_index; 996 ++TCP_server->incoming_connection_queue_index;
911 return index; 997 return index;
912} 998}
913 999
914static sock_t new_listening_TCP_socket(int family, uint16_t port) 1000static Socket new_listening_TCP_socket(Family family, uint16_t port)
915{ 1001{
916 sock_t sock = socket(family, SOCK_STREAM, IPPROTO_TCP); 1002 Socket sock = net_socket(family, TOX_SOCK_STREAM, TOX_PROTO_TCP);
917 1003
918 if (!sock_valid(sock)) { 1004 if (!sock_valid(sock)) {
919 return ~0; 1005 return net_invalid_socket;
920 } 1006 }
921 1007
922 int ok = set_socket_nonblock(sock); 1008 int ok = set_socket_nonblock(sock);
923 1009
924 if (ok && family == AF_INET6) { 1010 if (ok && net_family_is_ipv6(family)) {
925 ok = set_socket_dualstack(sock); 1011 ok = set_socket_dualstack(sock);
926 } 1012 }
927 1013
@@ -929,11 +1015,11 @@ static sock_t new_listening_TCP_socket(int family, uint16_t port)
929 ok = set_socket_reuseaddr(sock); 1015 ok = set_socket_reuseaddr(sock);
930 } 1016 }
931 1017
932 ok = ok && bind_to_port(sock, family, port) && (listen(sock, TCP_MAX_BACKLOG) == 0); 1018 ok = ok && bind_to_port(sock, family, port) && (net_listen(sock, TCP_MAX_BACKLOG) == 0);
933 1019
934 if (!ok) { 1020 if (!ok) {
935 kill_sock(sock); 1021 kill_sock(sock);
936 return ~0; 1022 return net_invalid_socket;
937 } 1023 }
938 1024
939 return sock; 1025 return sock;
@@ -942,23 +1028,25 @@ static sock_t new_listening_TCP_socket(int family, uint16_t port)
942TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, const uint16_t *ports, const uint8_t *secret_key, 1028TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, const uint16_t *ports, const uint8_t *secret_key,
943 Onion *onion) 1029 Onion *onion)
944{ 1030{
945 if (num_sockets == 0 || ports == NULL) 1031 if (num_sockets == 0 || ports == nullptr) {
946 return NULL; 1032 return nullptr;
1033 }
947 1034
948 if (networking_at_startup() != 0) { 1035 if (networking_at_startup() != 0) {
949 return NULL; 1036 return nullptr;
950 } 1037 }
951 1038
952 TCP_Server *temp = calloc(1, sizeof(TCP_Server)); 1039 TCP_Server *temp = (TCP_Server *)calloc(1, sizeof(TCP_Server));
953 1040
954 if (temp == NULL) 1041 if (temp == nullptr) {
955 return NULL; 1042 return nullptr;
1043 }
956 1044
957 temp->socks_listening = calloc(num_sockets, sizeof(sock_t)); 1045 temp->socks_listening = (Socket *)calloc(num_sockets, sizeof(Socket));
958 1046
959 if (temp->socks_listening == NULL) { 1047 if (temp->socks_listening == nullptr) {
960 free(temp); 1048 free(temp);
961 return NULL; 1049 return nullptr;
962 } 1050 }
963 1051
964#ifdef TCP_SERVER_USE_EPOLL 1052#ifdef TCP_SERVER_USE_EPOLL
@@ -967,18 +1055,12 @@ TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, const uin
967 if (temp->efd == -1) { 1055 if (temp->efd == -1) {
968 free(temp->socks_listening); 1056 free(temp->socks_listening);
969 free(temp); 1057 free(temp);
970 return NULL; 1058 return nullptr;
971 } 1059 }
972 1060
973#endif 1061#endif
974 1062
975 uint8_t family; 1063 const Family family = ipv6_enabled ? net_family_ipv6 : net_family_ipv4;
976
977 if (ipv6_enabled) {
978 family = AF_INET6;
979 } else {
980 family = AF_INET;
981 }
982 1064
983 uint32_t i; 1065 uint32_t i;
984#ifdef TCP_SERVER_USE_EPOLL 1066#ifdef TCP_SERVER_USE_EPOLL
@@ -986,14 +1068,14 @@ TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, const uin
986#endif 1068#endif
987 1069
988 for (i = 0; i < num_sockets; ++i) { 1070 for (i = 0; i < num_sockets; ++i) {
989 sock_t sock = new_listening_TCP_socket(family, ports[i]); 1071 Socket sock = new_listening_TCP_socket(family, ports[i]);
990 1072
991 if (sock_valid(sock)) { 1073 if (sock_valid(sock)) {
992#ifdef TCP_SERVER_USE_EPOLL 1074#ifdef TCP_SERVER_USE_EPOLL
993 ev.events = EPOLLIN | EPOLLET; 1075 ev.events = EPOLLIN | EPOLLET;
994 ev.data.u64 = sock | ((uint64_t)TCP_SOCKET_LISTENING << 32); 1076 ev.data.u64 = sock.socket | ((uint64_t)TCP_SOCKET_LISTENING << 32);
995 1077
996 if (epoll_ctl(temp->efd, EPOLL_CTL_ADD, sock, &ev) == -1) { 1078 if (epoll_ctl(temp->efd, EPOLL_CTL_ADD, sock.socket, &ev) == -1) {
997 continue; 1079 continue;
998 } 1080 }
999 1081
@@ -1007,7 +1089,7 @@ TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, const uin
1007 if (temp->num_listening_socks == 0) { 1089 if (temp->num_listening_socks == 0) {
1008 free(temp->socks_listening); 1090 free(temp->socks_listening);
1009 free(temp); 1091 free(temp);
1010 return NULL; 1092 return nullptr;
1011 } 1093 }
1012 1094
1013 if (onion) { 1095 if (onion) {
@@ -1015,48 +1097,50 @@ TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, const uin
1015 set_callback_handle_recv_1(onion, &handle_onion_recv_1, temp); 1097 set_callback_handle_recv_1(onion, &handle_onion_recv_1, temp);
1016 } 1098 }
1017 1099
1018 memcpy(temp->secret_key, secret_key, crypto_box_SECRETKEYBYTES); 1100 memcpy(temp->secret_key, secret_key, CRYPTO_SECRET_KEY_SIZE);
1019 crypto_scalarmult_curve25519_base(temp->public_key, temp->secret_key); 1101 crypto_derive_public_key(temp->public_key, temp->secret_key);
1020 1102
1021 bs_list_init(&temp->accepted_key_list, crypto_box_PUBLICKEYBYTES, 8); 1103 bs_list_init(&temp->accepted_key_list, CRYPTO_PUBLIC_KEY_SIZE, 8);
1022 1104
1023 return temp; 1105 return temp;
1024} 1106}
1025 1107
1108#ifndef TCP_SERVER_USE_EPOLL
1026static void do_TCP_accept_new(TCP_Server *TCP_server) 1109static void do_TCP_accept_new(TCP_Server *TCP_server)
1027{ 1110{
1028 uint32_t i; 1111 uint32_t i;
1029 1112
1030 for (i = 0; i < TCP_server->num_listening_socks; ++i) { 1113 for (i = 0; i < TCP_server->num_listening_socks; ++i) {
1031 struct sockaddr_storage addr; 1114 Socket sock;
1032 unsigned int addrlen = sizeof(addr);
1033 sock_t sock;
1034 1115
1035 do { 1116 do {
1036 sock = accept(TCP_server->socks_listening[i], (struct sockaddr *)&addr, &addrlen); 1117 sock = net_accept(TCP_server->socks_listening[i]);
1037 } while (accept_connection(TCP_server, sock) != -1); 1118 } while (accept_connection(TCP_server, sock) != -1);
1038 } 1119 }
1039} 1120}
1121#endif
1040 1122
1041static int do_incoming(TCP_Server *TCP_server, uint32_t i) 1123static int do_incoming(TCP_Server *TCP_server, uint32_t i)
1042{ 1124{
1043 if (TCP_server->incomming_connection_queue[i].status != TCP_STATUS_CONNECTED) 1125 if (TCP_server->incoming_connection_queue[i].status != TCP_STATUS_CONNECTED) {
1044 return -1; 1126 return -1;
1127 }
1045 1128
1046 int ret = read_connection_handshake(&TCP_server->incomming_connection_queue[i], TCP_server->secret_key); 1129 int ret = read_connection_handshake(&TCP_server->incoming_connection_queue[i], TCP_server->secret_key);
1047 1130
1048 if (ret == -1) { 1131 if (ret == -1) {
1049 kill_TCP_connection(&TCP_server->incomming_connection_queue[i]); 1132 kill_TCP_secure_connection(&TCP_server->incoming_connection_queue[i]);
1050 } else if (ret == 1) { 1133 } else if (ret == 1) {
1051 int index_new = TCP_server->unconfirmed_connection_queue_index % MAX_INCOMMING_CONNECTIONS; 1134 int index_new = TCP_server->unconfirmed_connection_queue_index % MAX_INCOMING_CONNECTIONS;
1052 TCP_Secure_Connection *conn_old = &TCP_server->incomming_connection_queue[i]; 1135 TCP_Secure_Connection *conn_old = &TCP_server->incoming_connection_queue[i];
1053 TCP_Secure_Connection *conn_new = &TCP_server->unconfirmed_connection_queue[index_new]; 1136 TCP_Secure_Connection *conn_new = &TCP_server->unconfirmed_connection_queue[index_new];
1054 1137
1055 if (conn_new->status != TCP_STATUS_NO_STATUS) 1138 if (conn_new->status != TCP_STATUS_NO_STATUS) {
1056 kill_TCP_connection(conn_new); 1139 kill_TCP_secure_connection(conn_new);
1140 }
1057 1141
1058 memcpy(conn_new, conn_old, sizeof(TCP_Secure_Connection)); 1142 memcpy(conn_new, conn_old, sizeof(TCP_Secure_Connection));
1059 sodium_memzero(conn_old, sizeof(TCP_Secure_Connection)); 1143 crypto_memzero(conn_old, sizeof(TCP_Secure_Connection));
1060 ++TCP_server->unconfirmed_connection_queue_index; 1144 ++TCP_server->unconfirmed_connection_queue_index;
1061 1145
1062 return index_new; 1146 return index_new;
@@ -1069,8 +1153,9 @@ static int do_unconfirmed(TCP_Server *TCP_server, uint32_t i)
1069{ 1153{
1070 TCP_Secure_Connection *conn = &TCP_server->unconfirmed_connection_queue[i]; 1154 TCP_Secure_Connection *conn = &TCP_server->unconfirmed_connection_queue[i];
1071 1155
1072 if (conn->status != TCP_STATUS_UNCONFIRMED) 1156 if (conn->status != TCP_STATUS_UNCONFIRMED) {
1073 return -1; 1157 return -1;
1158 }
1074 1159
1075 uint8_t packet[MAX_PACKET_SIZE]; 1160 uint8_t packet[MAX_PACKET_SIZE];
1076 int len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key, conn->recv_nonce, 1161 int len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key, conn->recv_nonce,
@@ -1078,12 +1163,14 @@ static int do_unconfirmed(TCP_Server *TCP_server, uint32_t i)
1078 1163
1079 if (len == 0) { 1164 if (len == 0) {
1080 return -1; 1165 return -1;
1081 } else if (len == -1) { 1166 }
1082 kill_TCP_connection(conn); 1167
1168 if (len == -1) {
1169 kill_TCP_secure_connection(conn);
1083 return -1; 1170 return -1;
1084 } else {
1085 return confirm_TCP_connection(TCP_server, conn, packet, len);
1086 } 1171 }
1172
1173 return confirm_TCP_connection(TCP_server, conn, packet, len);
1087} 1174}
1088 1175
1089static void do_confirmed_recv(TCP_Server *TCP_server, uint32_t i) 1176static void do_confirmed_recv(TCP_Server *TCP_server, uint32_t i)
@@ -1107,11 +1194,12 @@ static void do_confirmed_recv(TCP_Server *TCP_server, uint32_t i)
1107 } 1194 }
1108} 1195}
1109 1196
1110static void do_TCP_incomming(TCP_Server *TCP_server) 1197#ifndef TCP_SERVER_USE_EPOLL
1198static void do_TCP_incoming(TCP_Server *TCP_server)
1111{ 1199{
1112 uint32_t i; 1200 uint32_t i;
1113 1201
1114 for (i = 0; i < MAX_INCOMMING_CONNECTIONS; ++i) { 1202 for (i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) {
1115 do_incoming(TCP_server, i); 1203 do_incoming(TCP_server, i);
1116 } 1204 }
1117} 1205}
@@ -1120,17 +1208,19 @@ static void do_TCP_unconfirmed(TCP_Server *TCP_server)
1120{ 1208{
1121 uint32_t i; 1209 uint32_t i;
1122 1210
1123 for (i = 0; i < MAX_INCOMMING_CONNECTIONS; ++i) { 1211 for (i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) {
1124 do_unconfirmed(TCP_server, i); 1212 do_unconfirmed(TCP_server, i);
1125 } 1213 }
1126} 1214}
1215#endif
1127 1216
1128static void do_TCP_confirmed(TCP_Server *TCP_server) 1217static void do_TCP_confirmed(TCP_Server *TCP_server)
1129{ 1218{
1130#ifdef TCP_SERVER_USE_EPOLL 1219#ifdef TCP_SERVER_USE_EPOLL
1131 1220
1132 if (TCP_server->last_run_pinged == unix_time()) 1221 if (TCP_server->last_run_pinged == unix_time()) {
1133 return; 1222 return;
1223 }
1134 1224
1135 TCP_server->last_run_pinged = unix_time(); 1225 TCP_server->last_run_pinged = unix_time();
1136#endif 1226#endif
@@ -1139,16 +1229,18 @@ static void do_TCP_confirmed(TCP_Server *TCP_server)
1139 for (i = 0; i < TCP_server->size_accepted_connections; ++i) { 1229 for (i = 0; i < TCP_server->size_accepted_connections; ++i) {
1140 TCP_Secure_Connection *conn = &TCP_server->accepted_connection_array[i]; 1230 TCP_Secure_Connection *conn = &TCP_server->accepted_connection_array[i];
1141 1231
1142 if (conn->status != TCP_STATUS_CONFIRMED) 1232 if (conn->status != TCP_STATUS_CONFIRMED) {
1143 continue; 1233 continue;
1234 }
1144 1235
1145 if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) { 1236 if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) {
1146 uint8_t ping[1 + sizeof(uint64_t)]; 1237 uint8_t ping[1 + sizeof(uint64_t)];
1147 ping[0] = TCP_PACKET_PING; 1238 ping[0] = TCP_PACKET_PING;
1148 uint64_t ping_id = random_64b(); 1239 uint64_t ping_id = random_u64();
1149 1240
1150 if (!ping_id) 1241 if (!ping_id) {
1151 ++ping_id; 1242 ++ping_id;
1243 }
1152 1244
1153 memcpy(ping + 1, &ping_id, sizeof(uint64_t)); 1245 memcpy(ping + 1, &ping_id, sizeof(uint64_t));
1154 int ret = write_packet_TCP_secure_connection(conn, ping, sizeof(ping), 1); 1246 int ret = write_packet_TCP_secure_connection(conn, ping, sizeof(ping), 1);
@@ -1190,8 +1282,9 @@ static void do_TCP_epoll(TCP_Server *TCP_server)
1190 int n; 1282 int n;
1191 1283
1192 for (n = 0; n < nfds; ++n) { 1284 for (n = 0; n < nfds; ++n) {
1193 sock_t sock = events[n].data.u64 & 0xFFFFFFFF; 1285 const Socket sock = {(int)(events[n].data.u64 & 0xFFFFFFFF)};
1194 int status = (events[n].data.u64 >> 32) & 0xFF, index = (events[n].data.u64 >> 40); 1286 const int status = (events[n].data.u64 >> 32) & 0xFF;
1287 const int index = events[n].data.u64 >> 40;
1195 1288
1196 if ((events[n].events & EPOLLERR) || (events[n].events & EPOLLHUP) || (events[n].events & EPOLLRDHUP)) { 1289 if ((events[n].events & EPOLLERR) || (events[n].events & EPOLLHUP) || (events[n].events & EPOLLRDHUP)) {
1197 switch (status) { 1290 switch (status) {
@@ -1201,12 +1294,12 @@ static void do_TCP_epoll(TCP_Server *TCP_server)
1201 } 1294 }
1202 1295
1203 case TCP_SOCKET_INCOMING: { 1296 case TCP_SOCKET_INCOMING: {
1204 kill_TCP_connection(&TCP_server->incomming_connection_queue[index]); 1297 kill_TCP_secure_connection(&TCP_server->incoming_connection_queue[index]);
1205 break; 1298 break;
1206 } 1299 }
1207 1300
1208 case TCP_SOCKET_UNCONFIRMED: { 1301 case TCP_SOCKET_UNCONFIRMED: {
1209 kill_TCP_connection(&TCP_server->unconfirmed_connection_queue[index]); 1302 kill_TCP_secure_connection(&TCP_server->unconfirmed_connection_queue[index]);
1210 break; 1303 break;
1211 } 1304 }
1212 1305
@@ -1227,11 +1320,8 @@ static void do_TCP_epoll(TCP_Server *TCP_server)
1227 switch (status) { 1320 switch (status) {
1228 case TCP_SOCKET_LISTENING: { 1321 case TCP_SOCKET_LISTENING: {
1229 //socket is from socks_listening, accept connection 1322 //socket is from socks_listening, accept connection
1230 struct sockaddr_storage addr;
1231 unsigned int addrlen = sizeof(addr);
1232
1233 while (1) { 1323 while (1) {
1234 sock_t sock_new = accept(sock, (struct sockaddr *)&addr, &addrlen); 1324 Socket sock_new = net_accept(sock);
1235 1325
1236 if (!sock_valid(sock_new)) { 1326 if (!sock_valid(sock_new)) {
1237 break; 1327 break;
@@ -1245,11 +1335,11 @@ static void do_TCP_epoll(TCP_Server *TCP_server)
1245 1335
1246 struct epoll_event ev = { 1336 struct epoll_event ev = {
1247 .events = EPOLLIN | EPOLLET | EPOLLRDHUP, 1337 .events = EPOLLIN | EPOLLET | EPOLLRDHUP,
1248 .data.u64 = sock_new | ((uint64_t)TCP_SOCKET_INCOMING << 32) | ((uint64_t)index_new << 40) 1338 .data.u64 = sock_new.socket | ((uint64_t)TCP_SOCKET_INCOMING << 32) | ((uint64_t)index_new << 40)
1249 }; 1339 };
1250 1340
1251 if (epoll_ctl(TCP_server->efd, EPOLL_CTL_ADD, sock_new, &ev) == -1) { 1341 if (epoll_ctl(TCP_server->efd, EPOLL_CTL_ADD, sock_new.socket, &ev) == -1) {
1252 kill_TCP_connection(&TCP_server->incomming_connection_queue[index_new]); 1342 kill_TCP_secure_connection(&TCP_server->incoming_connection_queue[index_new]);
1253 continue; 1343 continue;
1254 } 1344 }
1255 } 1345 }
@@ -1262,10 +1352,10 @@ static void do_TCP_epoll(TCP_Server *TCP_server)
1262 1352
1263 if ((index_new = do_incoming(TCP_server, index)) != -1) { 1353 if ((index_new = do_incoming(TCP_server, index)) != -1) {
1264 events[n].events = EPOLLIN | EPOLLET | EPOLLRDHUP; 1354 events[n].events = EPOLLIN | EPOLLET | EPOLLRDHUP;
1265 events[n].data.u64 = sock | ((uint64_t)TCP_SOCKET_UNCONFIRMED << 32) | ((uint64_t)index_new << 40); 1355 events[n].data.u64 = sock.socket | ((uint64_t)TCP_SOCKET_UNCONFIRMED << 32) | ((uint64_t)index_new << 40);
1266 1356
1267 if (epoll_ctl(TCP_server->efd, EPOLL_CTL_MOD, sock, &events[n]) == -1) { 1357 if (epoll_ctl(TCP_server->efd, EPOLL_CTL_MOD, sock.socket, &events[n]) == -1) {
1268 kill_TCP_connection(&TCP_server->unconfirmed_connection_queue[index_new]); 1358 kill_TCP_secure_connection(&TCP_server->unconfirmed_connection_queue[index_new]);
1269 break; 1359 break;
1270 } 1360 }
1271 } 1361 }
@@ -1278,9 +1368,9 @@ static void do_TCP_epoll(TCP_Server *TCP_server)
1278 1368
1279 if ((index_new = do_unconfirmed(TCP_server, index)) != -1) { 1369 if ((index_new = do_unconfirmed(TCP_server, index)) != -1) {
1280 events[n].events = EPOLLIN | EPOLLET | EPOLLRDHUP; 1370 events[n].events = EPOLLIN | EPOLLET | EPOLLRDHUP;
1281 events[n].data.u64 = sock | ((uint64_t)TCP_SOCKET_CONFIRMED << 32) | ((uint64_t)index_new << 40); 1371 events[n].data.u64 = sock.socket | ((uint64_t)TCP_SOCKET_CONFIRMED << 32) | ((uint64_t)index_new << 40);
1282 1372
1283 if (epoll_ctl(TCP_server->efd, EPOLL_CTL_MOD, sock, &events[n]) == -1) { 1373 if (epoll_ctl(TCP_server->efd, EPOLL_CTL_MOD, sock.socket, &events[n]) == -1) {
1284 //remove from confirmed connections 1374 //remove from confirmed connections
1285 kill_accepted(TCP_server, index_new); 1375 kill_accepted(TCP_server, index_new);
1286 break; 1376 break;
@@ -1311,7 +1401,7 @@ void do_TCP_server(TCP_Server *TCP_server)
1311 1401
1312#else 1402#else
1313 do_TCP_accept_new(TCP_server); 1403 do_TCP_accept_new(TCP_server);
1314 do_TCP_incomming(TCP_server); 1404 do_TCP_incoming(TCP_server);
1315 do_TCP_unconfirmed(TCP_server); 1405 do_TCP_unconfirmed(TCP_server);
1316#endif 1406#endif
1317 1407
@@ -1327,7 +1417,7 @@ void kill_TCP_server(TCP_Server *TCP_server)
1327 } 1417 }
1328 1418
1329 if (TCP_server->onion) { 1419 if (TCP_server->onion) {
1330 set_callback_handle_recv_1(TCP_server->onion, NULL, NULL); 1420 set_callback_handle_recv_1(TCP_server->onion, nullptr, nullptr);
1331 } 1421 }
1332 1422
1333 bs_list_free(&TCP_server->accepted_key_list); 1423 bs_list_free(&TCP_server->accepted_key_list);
diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h
index 3f6b18ae..c8cbeda0 100644
--- a/toxcore/TCP_server.h
+++ b/toxcore/TCP_server.h
@@ -1,49 +1,46 @@
1/* 1/*
2* TCP_server.h -- Implementation of the TCP relay server part of Tox. 2 * Implementation of the TCP relay server part of Tox.
3* 3 */
4* Copyright (C) 2014 Tox project All Rights Reserved.
5*
6* This file is part of Tox.
7*
8* Tox is free software: you can redistribute it and/or modify
9* it under the terms of the GNU General Public License as published by
10* the Free Software Foundation, either version 3 of the License, or
11* (at your option) any later version.
12*
13* Tox is distributed in the hope that it will be useful,
14* but WITHOUT ANY WARRANTY; without even the implied warranty of
15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16* GNU General Public License for more details.
17*
18* You should have received a copy of the GNU General Public License
19* along with Tox. If not, see <http://www.gnu.org/licenses/>.
20*
21*/
22 4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2014 Tox project.
8 *
9 * This file is part of Tox, the free peer to peer instant messenger.
10 *
11 * Tox is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * Tox is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
23 */
23#ifndef TCP_SERVER_H 24#ifndef TCP_SERVER_H
24#define TCP_SERVER_H 25#define TCP_SERVER_H
25 26
26#include "crypto_core.h" 27#include "crypto_core.h"
27#include "onion.h"
28#include "list.h" 28#include "list.h"
29#include "onion.h"
29 30
30#ifdef TCP_SERVER_USE_EPOLL 31#ifdef TCP_SERVER_USE_EPOLL
31#include "sys/epoll.h" 32#include <sys/epoll.h>
32#endif 33#endif
33 34
34#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MACH__) 35#define MAX_INCOMING_CONNECTIONS 256
35#define MSG_NOSIGNAL 0
36#endif
37
38#define MAX_INCOMMING_CONNECTIONS 256
39 36
40#define TCP_MAX_BACKLOG MAX_INCOMMING_CONNECTIONS 37#define TCP_MAX_BACKLOG MAX_INCOMING_CONNECTIONS
41 38
42#define MAX_PACKET_SIZE 2048 39#define MAX_PACKET_SIZE 2048
43 40
44#define TCP_HANDSHAKE_PLAIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES) 41#define TCP_HANDSHAKE_PLAIN_SIZE (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE)
45#define TCP_SERVER_HANDSHAKE_SIZE (crypto_box_NONCEBYTES + TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES) 42#define TCP_SERVER_HANDSHAKE_SIZE (CRYPTO_NONCE_SIZE + TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE)
46#define TCP_CLIENT_HANDSHAKE_SIZE (crypto_box_PUBLICKEYBYTES + TCP_SERVER_HANDSHAKE_SIZE) 43#define TCP_CLIENT_HANDSHAKE_SIZE (CRYPTO_PUBLIC_KEY_SIZE + TCP_SERVER_HANDSHAKE_SIZE)
47#define TCP_MAX_OOB_DATA_LENGTH 1024 44#define TCP_MAX_OOB_DATA_LENGTH 1024
48 45
49#define NUM_RESERVED_PORTS 16 46#define NUM_RESERVED_PORTS 16
@@ -88,58 +85,10 @@ struct TCP_Priority_List {
88 uint8_t data[]; 85 uint8_t data[];
89}; 86};
90 87
91typedef struct TCP_Secure_Connection { 88typedef struct TCP_Server TCP_Server;
92 uint8_t status;
93 sock_t sock;
94 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
95 uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */
96 uint8_t sent_nonce[crypto_box_NONCEBYTES]; /* Nonce of sent packets. */
97 uint8_t shared_key[crypto_box_BEFORENMBYTES];
98 uint16_t next_packet_length;
99 struct {
100 uint8_t status; /* 0 if not used, 1 if other is offline, 2 if other is online. */
101 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
102 uint32_t index;
103 uint8_t other_id;
104 } connections[NUM_CLIENT_CONNECTIONS];
105 uint8_t last_packet[2 + MAX_PACKET_SIZE];
106 uint16_t last_packet_length;
107 uint16_t last_packet_sent;
108
109 TCP_Priority_List *priority_queue_start, *priority_queue_end;
110 89
111 uint64_t identifier; 90const uint8_t *tcp_server_public_key(const TCP_Server *tcp_server);
112 91size_t tcp_server_listen_count(const TCP_Server *tcp_server);
113 uint64_t last_pinged;
114 uint64_t ping_id;
115} TCP_Secure_Connection;
116
117
118typedef struct {
119 Onion *onion;
120
121#ifdef TCP_SERVER_USE_EPOLL
122 int efd;
123 uint64_t last_run_pinged;
124#endif
125 sock_t *socks_listening;
126 unsigned int num_listening_socks;
127
128 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
129 uint8_t secret_key[crypto_box_SECRETKEYBYTES];
130 TCP_Secure_Connection incomming_connection_queue[MAX_INCOMMING_CONNECTIONS];
131 uint16_t incomming_connection_queue_index;
132 TCP_Secure_Connection unconfirmed_connection_queue[MAX_INCOMMING_CONNECTIONS];
133 uint16_t unconfirmed_connection_queue_index;
134
135 TCP_Secure_Connection *accepted_connection_array;
136 uint32_t size_accepted_connections;
137 uint32_t num_accepted_connections;
138
139 uint64_t counter;
140
141 BS_LIST accepted_key_list;
142} TCP_Server;
143 92
144/* Create new TCP server instance. 93/* Create new TCP server instance.
145 */ 94 */
@@ -154,11 +103,6 @@ void do_TCP_server(TCP_Server *TCP_server);
154 */ 103 */
155void kill_TCP_server(TCP_Server *TCP_server); 104void kill_TCP_server(TCP_Server *TCP_server);
156 105
157/* return the amount of data in the tcp recv buffer.
158 * return 0 on failure.
159 */
160unsigned int TCP_socket_data_recv_buffer(sock_t sock);
161
162/* Read the next two bytes in TCP stream then convert them to 106/* Read the next two bytes in TCP stream then convert them to
163 * length (host byte order). 107 * length (host byte order).
164 * 108 *
@@ -166,20 +110,20 @@ unsigned int TCP_socket_data_recv_buffer(sock_t sock);
166 * return 0 if nothing has been read from socket. 110 * return 0 if nothing has been read from socket.
167 * return ~0 on failure. 111 * return ~0 on failure.
168 */ 112 */
169uint16_t read_TCP_length(sock_t sock); 113uint16_t read_TCP_length(Socket sock);
170 114
171/* Read length bytes from socket. 115/* Read length bytes from socket.
172 * 116 *
173 * return length on success 117 * return length on success
174 * return -1 on failure/no data in buffer. 118 * return -1 on failure/no data in buffer.
175 */ 119 */
176int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length); 120int read_TCP_packet(Socket sock, uint8_t *data, uint16_t length);
177 121
178/* return length of received packet on success. 122/* return length of received packet on success.
179 * return 0 if could not read any packet. 123 * return 0 if could not read any packet.
180 * return -1 on failure (connection must be killed). 124 * return -1 on failure (connection must be killed).
181 */ 125 */
182int read_packet_TCP_secure_connection(sock_t sock, uint16_t *next_packet_length, const uint8_t *shared_key, 126int read_packet_TCP_secure_connection(Socket sock, uint16_t *next_packet_length, const uint8_t *shared_key,
183 uint8_t *recv_nonce, uint8_t *data, uint16_t max_len); 127 uint8_t *recv_nonce, uint8_t *data, uint16_t max_len);
184 128
185 129
diff --git a/toxcore/assoc.c b/toxcore/assoc.c
deleted file mode 100644
index 932adc76..00000000
--- a/toxcore/assoc.c
+++ /dev/null
@@ -1,1031 +0,0 @@
1
2#ifdef HAVE_CONFIG_H
3#include "config.h"
4#endif
5
6#include "logger.h"
7#include "DHT.h"
8#include "assoc.h"
9#include "ping.h"
10
11#include "LAN_discovery.h"
12
13#include <assert.h>
14#include "util.h"
15
16/*
17 * BASIC OVERVIEW:
18 *
19 * Hash: The client_id is hashed with a local hash function.
20 * Hashes are used in multiple places for searching.
21 * Bucket: The first n bits of the client_id are used to
22 * select a bucket. This speeds up sorting, but the more
23 * important reason is to enforce a spread in the space of
24 * client_ids available.
25 *
26 *
27 * Candidates:
28 *
29 * Candidates are kept in buckets of hash tables. The hash
30 * function is calculated from the client_id. Up to
31 * HASH_COLLIDE_COUNT alternative positions are tried if
32 * the initial position is already used by a different entry.
33 * The collision function is multiplicative, not additive.
34 *
35 * A new candidate can bump an existing candidate, if it is
36 * more "desirable": Seen beats Heard.
37 */
38
39/* candidates: alternative places for the same hash value */
40#define HASH_COLLIDE_COUNT 5
41
42/* bucket size shall be co-prime to this */
43#define HASH_COLLIDE_PRIME 101
44
45/* candidates: bump entries: timeout values for seen/heard to be considered of value */
46#define CANDIDATES_SEEN_TIMEOUT 1800
47#define CANDIDATES_HEARD_TIMEOUT 600
48
49/* distance/index: index size & access mask */
50#define DISTANCE_INDEX_INDEX_BITS (64 - DISTANCE_INDEX_DISTANCE_BITS)
51#define DISTANCE_INDEX_INDEX_MASK ((1 << DISTANCE_INDEX_INDEX_BITS) - 1)
52
53/* types to stay consistent */
54typedef uint16_t bucket_t;
55typedef uint32_t hash_t;
56typedef uint16_t usecnt_t;
57
58/* abbreviations ... */
59typedef Assoc_distance_relative_callback dist_rel_cb;
60typedef Assoc_distance_absolute_callback dist_abs_cb;
61
62/*
63 * Client_data wrapped with additional data
64 */
65typedef struct Client_entry {
66 hash_t hash;
67
68 /* shortcuts & rumors: timers and data */
69 uint64_t getnodes;
70 uint64_t used_at;
71
72 uint64_t seen_at;
73 uint64_t heard_at;
74
75 uint16_t seen_family;
76 uint16_t heard_family;
77
78 IP_Port assoc_heard4;
79 IP_Port assoc_heard6;
80
81 Client_data client;
82} Client_entry;
83
84typedef struct candidates_bucket {
85 Client_entry *list; /* hashed list */
86} candidates_bucket;
87
88struct Assoc {
89 hash_t self_hash; /* hash of self_client_id */
90 uint8_t self_client_id[crypto_box_PUBLICKEYBYTES]; /* don't store entries for this */
91
92 /* association centralization: clients not in use */
93 size_t candidates_bucket_bits;
94 size_t candidates_bucket_count;
95 size_t candidates_bucket_size;
96 candidates_bucket *candidates;
97 uint64_t getnodes;
98};
99
100/*****************************************************************************/
101/* HELPER FUNCTIONS */
102/*****************************************************************************/
103
104/* the complete distance would be crypto_box_PUBLICKEYBYTES long...
105 * returns DISTANCE_INDEX_DISTANCE_BITS valid bits */
106static uint64_t id_distance(const Assoc *assoc, void *callback_data, const uint8_t *id_ref, const uint8_t *id_test)
107{
108 /* with BIG_ENDIAN, this would be a one-liner... */
109 uint64_t retval = 0;
110
111 uint8_t pos = 0, bits = DISTANCE_INDEX_DISTANCE_BITS;
112
113 while (bits > 8) {
114 uint8_t distance = abs((int8_t)id_ref[pos] ^ (int8_t)id_test[pos]);
115 retval = (retval << 8) | distance;
116 bits -= 8;
117 pos++;
118 }
119
120 return (retval << bits) | ((id_ref[pos] ^ id_test[pos]) >> (8 - bits));
121}
122
123/* qsort() callback for a sorting by id_distance() values */
124static int dist_index_comp(const void *a, const void *b)
125{
126 const uint64_t *_a = a;
127 const uint64_t *_b = b;
128
129 if (*_a < *_b)
130 return -1;
131
132 if (*_a > *_b)
133 return 1;
134
135 return 0;
136}
137
138/* get actual entry to a distance_index */
139static Client_entry *dist_index_entry(Assoc *assoc, uint64_t dist_ind)
140{
141 if ((dist_ind & DISTANCE_INDEX_INDEX_MASK) == DISTANCE_INDEX_INDEX_MASK)
142 return NULL;
143
144 size_t total = assoc->candidates_bucket_count * assoc->candidates_bucket_size;
145 uint32_t index = dist_ind & DISTANCE_INDEX_INDEX_MASK;
146
147 if (index < total) {
148 bucket_t b_id = index / assoc->candidates_bucket_size;
149 candidates_bucket *cnd_bckt = &assoc->candidates[b_id];
150 size_t b_ix = index % assoc->candidates_bucket_size;
151 Client_entry *entry = &cnd_bckt->list[b_ix];
152
153 if (entry->hash)
154 return entry;
155 }
156
157 return NULL;
158}
159
160/* get actual entry's public_key to a distance_index */
161static uint8_t *dist_index_id(Assoc *assoc, uint64_t dist_ind)
162{
163 Client_entry *entry = dist_index_entry(assoc, dist_ind);
164
165 if (entry)
166 return entry->client.public_key;
167
168 return NULL;
169}
170
171/* sorts first .. last, i.e. last is included */
172static void dist_index_bubble(Assoc *assoc, uint64_t *dist_list, size_t first, size_t last, uint8_t *id,
173 void *custom_data, Assoc_distance_relative_callback dist_rel_func)
174{
175 size_t i, k;
176
177 for (i = first; i <= last; i++) {
178 uint8_t *id1 = dist_index_id(assoc, dist_list[i]);
179
180 for (k = i + 1; k <= last; k++) {
181 uint8_t *id2 = dist_index_id(assoc, dist_list[k]);
182
183 if (id1 && id2)
184 if (dist_rel_func(assoc, custom_data, id, id1, id2) == 2) {
185 uint64_t swap = dist_list[i];
186 dist_list[i] = dist_list[k];
187 dist_list[k] = swap;
188 }
189 }
190 }
191}
192
193/* TODO: Check that there isn't a function like this elsewhere hidden.
194 * E.g. the one which creates a handshake_id isn't usable for this, it must
195 * always map the same ID to the same hash.
196 *
197 * Result is NOT MAPPED to CANDIDATES_TO_KEEP range, i.e. map before using
198 * it for list access. */
199static hash_t id_hash(const Assoc *assoc, const uint8_t *id)
200{
201 uint32_t i, res = 0x19a64e82;
202
203 for (i = 0; i < crypto_box_PUBLICKEYBYTES; i++)
204 res = ((res << 1) ^ id[i]) + (res >> 31);
205
206 /* can't have zero as hash, a) marks an unused spot,
207 * b) collision function is multiplicative */
208 if (!(res % assoc->candidates_bucket_size))
209 res++;
210
211 return res;
212}
213
214/* up to HASH_COLLIDE_COUNT calls to different spots,
215 * result IS mapped to CANDIDATES_TO_KEEP range */
216static hash_t hash_collide(const Assoc *assoc, hash_t hash)
217{
218 uint64_t hash64 = hash % assoc->candidates_bucket_size;
219 hash64 = (hash64 * HASH_COLLIDE_PRIME) % assoc->candidates_bucket_size;
220
221 hash_t retval = hash64;
222
223 /* this should never happen when CANDIDATES_TO_KEEP is prime and hash not a multiple
224 * (id_hash() checks for a multiple and returns a different hash in that case)
225 *
226 * ( 1 .. (prime - 1) is a group over multiplication and every number has its inverse
227 * in the group, so no multiplication should ever end on zero as long neither
228 * of the two factors was zero-equivalent )
229 *
230 * BUT: because the usage of the word "never" invokes Murphy's law, catch it */
231 if (!retval) {
232#ifdef DEBUG
233 fprintf(stderr, "assoc::hash_collide: hash %u, bucket size %u => %u!", hash, (uint)assoc->candidates_bucket_size,
234 retval);
235 assert(retval != 0);
236#endif
237 retval = 1;
238 }
239
240 return retval;
241}
242
243/* returns the "seen" assoc related to the ipp */
244static IPPTsPng *entry_assoc(Client_entry *cl_entry, const IP_Port *ipp)
245{
246 if (!cl_entry)
247 return NULL;
248
249 if (ipp->ip.family == AF_INET)
250 return &cl_entry->client.assoc4;
251
252 if (ipp->ip.family == AF_INET6)
253 return &cl_entry->client.assoc6;
254
255 return NULL;
256}
257
258/* returns the "heard" assoc related to the ipp */
259static IP_Port *entry_heard_get(Client_entry *entry, const IP_Port *ipp)
260{
261 if (ipp->ip.family == AF_INET)
262 return &entry->assoc_heard4;
263 else if (ipp->ip.family == AF_INET6)
264 return &entry->assoc_heard6;
265 else
266 return NULL;
267}
268
269/* store a "heard" entry
270 * overwrites empty entry, does NOT overwrite non-LAN ip with
271 * LAN ip
272 *
273 * returns 1 if the entry did change */
274static int entry_heard_store(Client_entry *entry, const IPPTs *ippts)
275{
276 if (!entry || !ippts)
277 return 0;
278
279 if (!ipport_isset(&ippts->ip_port))
280 return 0;
281
282 IP_Port *heard;
283 const IP_Port *ipp = &ippts->ip_port;
284
285 if (ipp->ip.family == AF_INET)
286 heard = &entry->assoc_heard4;
287 else if (ipp->ip.family == AF_INET6)
288 heard = &entry->assoc_heard6;
289 else
290 return 0;
291
292 if (ipport_equal(ipp, heard))
293 return 0;
294
295 if (!ipport_isset(heard)) {
296 *heard = *ipp;
297 entry->heard_at = ippts->timestamp;
298 entry->heard_family = ipp->ip.family;
299 return 1;
300 }
301
302 /* don't destroy a good address with a crappy one
303 * (unless we're very timed out) */
304 uint8_t LAN_ipp = LAN_ip(ipp->ip) == 0;
305 uint8_t LAN_entry = LAN_ip(heard->ip) == 0;
306
307 if (LAN_ipp && !LAN_entry && !is_timeout(entry->heard_at, CANDIDATES_HEARD_TIMEOUT))
308 return 0;
309
310 *heard = *ipp;
311 entry->heard_at = ippts->timestamp;
312 entry->heard_family = ipp->ip.family;
313
314 return 1;
315}
316
317/* maps Assoc callback signature to id_closest() */
318static int assoc_id_closest(const Assoc *assoc, void *callback_data, const uint8_t *client_id,
319 const uint8_t *client_id1, const uint8_t *client_id2)
320{
321 return id_closest(client_id, client_id1, client_id2);
322}
323
324static bucket_t id_bucket(const uint8_t *id, uint8_t bits)
325{
326 /* return the first "bits" bits of id */
327 bucket_t retval = 0;
328
329 uint8_t pos = 0;
330
331 while (bits > 8) {
332 retval = (retval << 8) | id[pos++];
333 bits -= 8;
334 }
335
336 return (retval << bits) | (id[pos] >> (8 - bits));
337}
338
339/*****************************************************************************/
340/* CANDIDATES FUNCTIONS */
341/*****************************************************************************/
342
343
344static bucket_t candidates_id_bucket(const Assoc *assoc, const uint8_t *id)
345{
346 return id_bucket(id, assoc->candidates_bucket_bits);
347}
348
349static uint8_t candidates_search(const Assoc *assoc, const uint8_t *id, hash_t hash, Client_entry **entryptr)
350{
351 bucket_t bucket = candidates_id_bucket(assoc, id);
352 candidates_bucket *cnd_bckt = &assoc->candidates[bucket];
353 size_t coll, pos = hash % assoc->candidates_bucket_size;
354
355 for (coll = 0; coll < HASH_COLLIDE_COUNT; pos = hash_collide(assoc, pos) , coll++) {
356 Client_entry *entry = &cnd_bckt->list[pos];
357
358 if (entry->hash == hash)
359 if (id_equal(entry->client.public_key, id)) {
360 *entryptr = entry;
361 return 1;
362 }
363 }
364
365 *entryptr = NULL;
366 return 0;
367}
368
369static void candidates_update_assoc(const Assoc *assoc, Client_entry *entry, uint8_t used, const IPPTs *ippts_send,
370 const IP_Port *ipp_recv)
371{
372 if (!assoc || !entry || !ippts_send)
373 return;
374
375 IPPTsPng *ipptsp = entry_assoc(entry, &ippts_send->ip_port);
376
377 if (!ipptsp)
378 return;
379
380 if (used)
381 entry->used_at = unix_time();
382
383 /* do NOT do anything related to wanted, that's handled outside,
384 * just update the assoc (in the most sensible way)
385 */
386 if (ipp_recv) {
387 ipptsp->ip_port = ippts_send->ip_port;
388 ipptsp->timestamp = ippts_send->timestamp;
389 ipptsp->ret_ip_port = *ipp_recv;
390 ipptsp->ret_timestamp = unix_time();
391
392 entry->seen_at = unix_time();
393 entry->seen_family = ippts_send->ip_port.ip.family;
394
395 return;
396 }
397
398 entry_heard_store(entry, ippts_send);
399}
400
401static uint8_t candidates_create_internal(const Assoc *assoc, hash_t const hash, const uint8_t *id, uint8_t seen,
402 uint8_t used, bucket_t *bucketptr, size_t *posptr)
403{
404 if (!assoc || !id || !bucketptr || !posptr)
405 return 0;
406
407 bucket_t bucket = candidates_id_bucket(assoc, id);
408 candidates_bucket *cnd_bckt = &assoc->candidates[bucket];
409
410 size_t coll, pos = hash % assoc->candidates_bucket_size, check;
411 size_t pos_check[6];
412
413 memset(pos_check, 0, sizeof(pos_check));
414
415 for (coll = 0; coll < HASH_COLLIDE_COUNT; pos = hash_collide(assoc, pos) , coll++) {
416 Client_entry *entry = &cnd_bckt->list[pos];
417
418 /* unset */
419 if (!entry->hash) {
420 *bucketptr = bucket;
421 *posptr = pos;
422
423 return 1;
424 }
425
426 /* 0. bad
427 * 1. seen bad, heard good
428 * 2. seen good
429 * 3. used */
430 // enumerated lists are superior to magic numbers
431 if (!is_timeout(entry->used_at, BAD_NODE_TIMEOUT))
432 check = USED;
433 else if (!is_timeout(entry->seen_at, CANDIDATES_SEEN_TIMEOUT))
434 check = SEENG;
435 else if (!is_timeout(entry->heard_at, CANDIDATES_HEARD_TIMEOUT))
436 check = SEENB_HEARDG;
437 else
438 check = BAD;
439
440 if (!pos_check[check])
441 pos_check[check] = pos + 1;
442 }
443
444 /* used > seen > heard > bad */
445 size_t i, pos_max = used ? USED : (seen ? SEENG : SEENB_HEARDG);
446
447 for (i = 0; i < pos_max; i++)
448 if (pos_check[i]) {
449 *bucketptr = bucket;
450 *posptr = pos_check[i] - 1;
451
452 return 1;
453 }
454
455 return 0;
456}
457
458static uint8_t candidates_create_new(const Assoc *assoc, hash_t hash, const uint8_t *id, uint8_t used,
459 const IPPTs *ippts_send, const IP_Port *ipp_recv)
460{
461 if (!assoc || !id || !ippts_send)
462 return 0;
463
464 bucket_t bucket;
465 size_t pos;
466
467 if (!candidates_create_internal(assoc, hash, id, ipp_recv != NULL, used, &bucket, &pos))
468 return 0;
469
470 candidates_bucket *cnd_bckt = &assoc->candidates[bucket];
471 Client_entry *entry = &cnd_bckt->list[pos];
472 memset(entry, 0, sizeof(*entry));
473 IPPTsPng *ipptsp = entry_assoc(entry, &ippts_send->ip_port);
474
475 if (!ipptsp)
476 return 0;
477
478 entry->hash = hash;
479 id_copy(entry->client.public_key, id);
480
481 if (used)
482 entry->used_at = unix_time();
483
484 if (ipp_recv && !ipport_isset(ipp_recv))
485 ipp_recv = NULL;
486
487 if (ipp_recv) {
488 entry->seen_at = ippts_send->timestamp;
489 entry->seen_family = ippts_send->ip_port.ip.family;
490
491 ipptsp->ip_port = ippts_send->ip_port;
492 ipptsp->timestamp = ippts_send->timestamp;
493 ipptsp->ret_ip_port = *ipp_recv;
494 ipptsp->ret_timestamp = unix_time();
495 } else {
496 IP_Port *heard = entry_heard_get(entry, &ippts_send->ip_port);
497
498 if (heard) {
499 entry->heard_at = ippts_send->timestamp;
500 entry->heard_family = ippts_send->ip_port.ip.family;
501
502 *heard = ippts_send->ip_port;
503 }
504 }
505
506 return 1;
507}
508
509/*****************************************************************************/
510
511static void client_id_self_update(Assoc *assoc)
512{
513 if (assoc->self_hash)
514 return;
515
516 size_t i, sum = 0;
517
518 for (i = 0; i < crypto_box_PUBLICKEYBYTES; i++)
519 sum |= assoc->self_client_id[i];
520
521 if (!sum)
522 return;
523
524 assoc->self_hash = id_hash(assoc, assoc->self_client_id);
525
526 LOGGER_DEBUG("id is now set, purging cache of self-references");
527
528 /* if we already added some (or loaded some) entries,
529 * look and remove if we find a match
530 */
531 bucket_t b_id = candidates_id_bucket(assoc, assoc->self_client_id);
532 candidates_bucket *cnd_bckt = &assoc->candidates[b_id];
533 size_t pos = assoc->self_hash % assoc->candidates_bucket_size;
534
535 for (i = 0; i < HASH_COLLIDE_COUNT; pos = hash_collide(assoc, pos), i++) {
536 Client_entry *entry = &cnd_bckt->list[pos];
537
538 if (entry->hash == assoc->self_hash)
539 if (id_equal(entry->client.public_key, assoc->self_client_id))
540 entry->hash = 0;
541 }
542}
543
544/*****************************************************************************/
545/* TRIGGER FUNCTIONS */
546/*****************************************************************************/
547
548/* Central entry point for new associations: add a new candidate to the cache
549 * seen should be 0 (zero), if the candidate was announced by someone else,
550 * seen should be 1 (one), if there is confirmed connectivity (a definite response)
551 */
552uint8_t Assoc_add_entry(Assoc *assoc, const uint8_t *id, const IPPTs *ippts_send, const IP_Port *ipp_recv, uint8_t used)
553{
554 if (!assoc || !id || !ippts_send)
555 return 0;
556
557 if (!assoc->self_hash) {
558 client_id_self_update(assoc);
559
560 if (!assoc->self_hash)
561 return 0;
562 }
563
564 if (!ipport_isset(&ippts_send->ip_port))
565 return 0;
566
567 if (ipp_recv && !ipport_isset(ipp_recv))
568 ipp_recv = NULL;
569
570 hash_t hash = id_hash(assoc, id);
571
572 if (hash == assoc->self_hash)
573 if (id_equal(id, assoc->self_client_id))
574 return 0;
575
576 /* if it's new:
577 * callback, if there's desire, add to clients, else to candidates
578 *
579 * if it's "old":
580 * if it's client: refresh
581 * if it's candidate:
582 * if !ipp_recv, refresh
583 * if ipp_recv: callback, if there's desire, move to candidates
584 */
585 Client_entry *cnd_entry;
586
587 if (!candidates_search(assoc, id, hash, &cnd_entry)) {
588 if (candidates_create_new(assoc, hash, id, used, ippts_send, ipp_recv))
589 return 1;
590 else
591 return 0;
592 } else {
593 candidates_update_assoc(assoc, cnd_entry, used, ippts_send, ipp_recv);
594 return 2;
595 }
596}
597
598/*****************************************************************************/
599/* MAIN USE */
600/*****************************************************************************/
601
602uint8_t Assoc_get_close_entries(Assoc *assoc, Assoc_close_entries *state)
603{
604 if (!assoc || !state || !state->wanted_id || !state->result)
605 return 0;
606
607 if (!assoc->self_hash) {
608 client_id_self_update(assoc);
609
610 if (!assoc->self_hash)
611 return 0;
612 }
613
614 if (!state->distance_relative_func)
615 state->distance_relative_func = assoc_id_closest;
616
617 if (!state->distance_absolute_func)
618 state->distance_absolute_func = id_distance;
619
620 size_t dist_list_len = assoc->candidates_bucket_count * assoc->candidates_bucket_size;
621 uint64_t dist_list[dist_list_len];
622 memset(dist_list, ~0, dist_list_len * sizeof(dist_list[0]));
623 bucket_t b;
624 size_t i;
625
626 for (b = 0; b < assoc->candidates_bucket_count; b++) {
627 candidates_bucket *cnd_bckt = &assoc->candidates[b];
628
629 for (i = 0; i < assoc->candidates_bucket_size; i++) {
630 Client_entry *entry = &cnd_bckt->list[i];
631
632 if (entry->hash) {
633 if (state->flags & ProtoIPv4) {
634 if (!ipport_isset(&entry->client.assoc4.ip_port))
635 continue;
636
637 if (!(state->flags & LANOk))
638 if (!LAN_ip(entry->client.assoc4.ip_port.ip))
639 continue;
640 }
641
642 if (state->flags & ProtoIPv6) {
643 if (!ipport_isset(&entry->client.assoc6.ip_port))
644 continue;
645
646 if (!(state->flags & LANOk))
647 if (!LAN_ip(entry->client.assoc6.ip_port.ip))
648 continue;
649 }
650
651 uint64_t dist = state->distance_absolute_func(assoc, state->custom_data, state->wanted_id, entry->client.public_key);
652 uint32_t index = b * assoc->candidates_bucket_size + i;
653 dist_list[index] = (dist << DISTANCE_INDEX_INDEX_BITS) | index;
654 }
655 }
656 }
657
658 qsort(dist_list, dist_list_len, sizeof(dist_list[0]), dist_index_comp);
659
660 /* ok, ok, it's not *perfectly* sorted, because we used an absolute distance
661 * go over the result and see if we need to "smoothen things out"
662 * because those should be only very few and short streaks, the worst regularly
663 * used sorting function aka bubble sort is used */
664 uint64_t dist_prev = ~0;
665 size_t ind_prev = ~0, ind_curr;
666 size_t len = 1;
667
668 for (ind_curr = 0; ind_curr < dist_list_len; ind_curr++) {
669 /* sorted increasingly, so an invalid entry marks the end */
670 if ((dist_list[ind_curr] & DISTANCE_INDEX_INDEX_MASK) == DISTANCE_INDEX_INDEX_MASK)
671 break;
672
673 uint64_t dist_curr = dist_list[ind_curr] >> DISTANCE_INDEX_INDEX_BITS;
674
675 if (dist_prev == dist_curr)
676 len++;
677 else {
678 if (len > 1)
679 dist_index_bubble(assoc, dist_list, ind_prev, ind_curr - 1, state->wanted_id, state->custom_data,
680 state->distance_relative_func);
681
682 dist_prev = dist_curr;
683 ind_prev = ind_curr;
684 len = 1;
685 }
686 }
687
688 if (len > 1)
689 dist_index_bubble(assoc, dist_list, ind_prev, ind_curr - 1, state->wanted_id, state->custom_data,
690 state->distance_relative_func);
691
692 /* ok, now dist_list is a strictly ascending sorted list of nodes
693 * a) extract CLOSE_QUOTA_USED clients, not timed out
694 * b) extract (1 - QUOTA) (better!) clients & candidates, not timed out
695 * c) save candidates which would be better, if contact can be established */
696 size_t client_quota_good = 0, pos = 0;
697 size_t client_quota_max = state->count_good;
698
699 ssize_t taken_last = - 1;
700
701 for (i = 0; (i < dist_list_len) && (pos < state->count); i++) {
702 /* sorted increasingly, so an invalid entry marks the end */
703 if ((dist_list[i] & DISTANCE_INDEX_INDEX_MASK) == DISTANCE_INDEX_INDEX_MASK)
704 break;
705
706 Client_entry *entry = dist_index_entry(assoc, dist_list[i]);
707
708 if (entry && entry->hash) {
709 if (client_quota_good >= client_quota_max) {
710 state->result[pos++] = &entry->client;
711 taken_last = i;
712 } else {
713 if (state->flags & (ProtoIPv4 | ProtoIPv6)) {
714 if ((state->flags & ProtoIPv4) && is_timeout(entry->client.assoc4.timestamp, BAD_NODE_TIMEOUT))
715 continue;
716
717 if ((state->flags & ProtoIPv6) && is_timeout(entry->client.assoc6.timestamp, BAD_NODE_TIMEOUT))
718 continue;
719 } else if (is_timeout(entry->seen_at, BAD_NODE_TIMEOUT))
720 continue;
721
722 state->result[pos++] = &entry->client;
723 client_quota_good++;
724 taken_last = i;
725 }
726 }
727 }
728
729 /* if we had not enough valid entries the list might still not be filled.
730 *
731 * start again from last taken client, but leave out any requirement
732 */
733 if (pos < state->count) {
734 for (i = taken_last + 1; (i < dist_list_len) && (pos < state->count); i++) {
735 /* sorted increasingly, so an invalid entry marks the end */
736 if ((dist_list[i] & DISTANCE_INDEX_INDEX_MASK) == DISTANCE_INDEX_INDEX_MASK)
737 break;
738
739 Client_entry *entry = dist_index_entry(assoc, dist_list[i]);
740
741 if (entry && entry->hash)
742 state->result[pos++] = &entry->client;
743 }
744 }
745
746 return pos;
747}
748
749/*****************************************************************************/
750/* GLOBAL STRUCTURE FUNCTIONS */
751/*****************************************************************************/
752
753static uint8_t odd_min9_is_prime(size_t value)
754{
755 size_t i = 3;
756
757 while (i * i <= value) {
758 if (!(value % i))
759 return 0;
760
761 i += 2;
762 }
763
764 return 1;
765}
766
767static size_t prime_upto_min9(size_t limit)
768{
769 /* even => odd */
770 limit = limit - (1 - (limit % 2));
771
772 while (!odd_min9_is_prime(limit))
773 limit -= 2;
774
775 return limit;
776}
777
778/* create */
779Assoc *new_Assoc(size_t bits, size_t entries, const uint8_t *public_id)
780{
781 if (!public_id)
782 return NULL;
783
784 Assoc *assoc = calloc(1, sizeof(*assoc));
785
786 if (!assoc)
787 return NULL;
788
789 /*
790 * bits must be in [ 2 .. 15 ]
791 * entries must be a prime
792 */
793 if (bits < 2)
794 bits = 2;
795 else if (bits > 15)
796 bits = 15;
797
798 assoc->candidates_bucket_bits = bits;
799 assoc->candidates_bucket_count = 1U << bits;
800
801 if (entries < 25) {
802 if (entries <= 6)
803 entries = 5;
804 else {
805 entries = entries - (1 - (entries % 2)); /* even => odd */
806
807 /* 7..23: all odds but 9&15 are prime */
808 if (!(entries % 3)) /* 9, 15 */
809 entries -= 2; /* 7, 13 */
810 }
811 } else if (entries > ((1 << 17) - 1)) /* 130k+ */
812 entries = (1 << 17) - 1;
813 else {
814 /* 9+: test and find a prime less or equal */
815 size_t entries_test = prime_upto_min9(entries);
816
817 if (entries_test == HASH_COLLIDE_PRIME) /* disallowed */
818 entries_test = prime_upto_min9(entries_test - 1);
819
820 if (entries_test != entries) {
821
822 LOGGER_DEBUG("trimmed %i to %i.\n", (int)entries, (int)entries_test);
823 entries = (size_t)entries_test;
824 }
825 }
826
827 assoc->candidates_bucket_size = entries;
828
829 /* allocation: preferably few blobs */
830 size_t bckt, cix;
831 Client_entry *clients = malloc(sizeof(*clients) * assoc->candidates_bucket_count * assoc->candidates_bucket_size);
832
833 if (!clients) {
834 free(assoc);
835 return NULL;
836 }
837
838 candidates_bucket *lists = malloc(sizeof(*lists) * assoc->candidates_bucket_count);
839
840 if (!lists) {
841 free(assoc);
842 free(clients);
843 return NULL;
844 }
845
846 for (bckt = 0; bckt < assoc->candidates_bucket_count; bckt++) {
847 candidates_bucket *list = &lists[bckt];
848
849 list->list = &clients[bckt * assoc->candidates_bucket_size];
850
851 for (cix = 0; cix < assoc->candidates_bucket_size; cix++)
852 list->list[cix].hash = 0;
853 }
854
855 assoc->candidates = lists;
856 assoc->getnodes = unix_time();
857
858 id_copy(assoc->self_client_id, public_id);
859 client_id_self_update(assoc);
860
861 return assoc;
862}
863
864Assoc *new_Assoc_default(const uint8_t *public_id)
865{
866 /* original 8, 251 averages to ~32k entries... probably the whole DHT :D
867 * 320 entries is fine, hopefully */
868 return new_Assoc(6, 15, public_id);
869}
870
871/* own client_id, assocs for this have to be ignored */
872void Assoc_self_client_id_changed(Assoc *assoc, const uint8_t *id)
873{
874 if (assoc && id) {
875 assoc->self_hash = 0;
876 id_copy(assoc->self_client_id, id);
877 client_id_self_update(assoc);
878 }
879}
880
881#ifdef TOX_LOGGER
882static char *idpart2str(uint8_t *id, size_t len);
883#endif /* TOX_LOGGER */
884
885/* refresh buckets */
886void do_Assoc(Assoc *assoc, DHT *dht)
887{
888 if (is_timeout(assoc->getnodes, ASSOC_BUCKET_REFRESH)) {
889 assoc->getnodes = unix_time();
890
891 size_t candidate = (rand() % assoc->candidates_bucket_count) + assoc->candidates_bucket_count;
892
893 /* in that bucket or the buckets closest to it:
894 * find the best heard candidate
895 * find the best seen candidate
896 * send getnode() requests to both */
897 uint8_t *target_id = NULL;
898 Client_entry *heard = NULL, *seen = NULL;
899 size_t i, k, m;
900
901 for (i = 1; i < assoc->candidates_bucket_count; i++) {
902 if (i % 2)
903 k = - (i >> 1);
904 else
905 k = i >> 1;
906
907 size_t bckt = (candidate + k) % assoc->candidates_bucket_count;
908
909 for (m = 0; m < assoc->candidates_bucket_size; m++)
910 if (assoc->candidates[bckt].list[m].hash) {
911 Client_entry *entry = &assoc->candidates[bckt].list[m];
912
913 if (!is_timeout(entry->getnodes, CANDIDATES_SEEN_TIMEOUT))
914 continue;
915
916 if (!target_id)
917 target_id = entry->client.public_key;
918
919 if (entry->seen_at) {
920 if (!seen)
921 if (!is_timeout(entry->seen_at, CANDIDATES_SEEN_TIMEOUT))
922 seen = entry;
923 }
924
925 if (entry->heard_at) {
926 if (!heard)
927 if (!is_timeout(entry->heard_at, CANDIDATES_HEARD_TIMEOUT))
928 heard = entry;
929 }
930
931 if (seen && heard)
932 break;
933 }
934
935 if (seen && heard)
936 break;
937 }
938
939 if (seen) {
940 IPPTsPng *ippts = seen->seen_family == AF_INET ? &seen->client.assoc4 : &seen->client.assoc6;
941
942 LOGGER_DEBUG("[%u] => S[%s...] %s:%u", (uint32_t)(candidate % assoc->candidates_bucket_count),
943 idpart2str(seen->client.public_key, 8), ip_ntoa(&ippts->ip_port.ip), htons(ippts->ip_port.port));
944
945 DHT_getnodes(dht, &ippts->ip_port, seen->client.public_key, target_id);
946 seen->getnodes = unix_time();
947 }
948
949 if (heard && (heard != seen)) {
950 IP_Port *ipp = heard->heard_family == AF_INET ? &heard->assoc_heard4 : &heard->assoc_heard6;
951
952 LOGGER_DEBUG("[%u] => H[%s...] %s:%u", (uint32_t)(candidate % assoc->candidates_bucket_count),
953 idpart2str(heard->client.public_key, 8), ip_ntoa(&ipp->ip), htons(ipp->port));
954
955 DHT_getnodes(dht, ipp, heard->client.public_key, target_id);
956 heard->getnodes = unix_time();
957 }
958
959 LOGGER_SCOPE (
960
961 if ( !heard && !seen )
962 LOGGER_DEBUG("[%u] => no nodes to talk to??", (uint32_t)(candidate % assoc->candidates_bucket_count));
963 );
964 }
965}
966
967/* destroy */
968void kill_Assoc(Assoc *assoc)
969{
970 if (assoc) {
971 free(assoc->candidates->list);
972 free(assoc->candidates);
973 free(assoc);
974 }
975}
976
977#ifdef TOX_LOGGER
978
979static char buffer[crypto_box_PUBLICKEYBYTES * 2 + 1];
980static char *idpart2str(uint8_t *id, size_t len)
981{
982 if (len > crypto_box_PUBLICKEYBYTES)
983 len = crypto_box_PUBLICKEYBYTES;
984
985 size_t i;
986
987 for (i = 0; i < len; i++)
988 sprintf(buffer + i * 2, "%02hhx", id[i]);
989
990 buffer[len * 2] = 0;
991 return buffer;
992}
993
994void Assoc_status(const Assoc *assoc)
995{
996 if (!assoc) {
997 LOGGER_TRACE("Assoc status: no assoc");
998 return;
999 }
1000
1001 LOGGER_TRACE("[b:p] hash => [id...] used, seen, heard");
1002
1003 size_t bid, cid, total = 0;
1004
1005 for (bid = 0; bid < assoc->candidates_bucket_count; bid++) {
1006 candidates_bucket *bucket = &assoc->candidates[bid];
1007
1008 for (cid = 0; cid < assoc->candidates_bucket_size; cid++) {
1009 Client_entry *entry = &bucket->list[cid];
1010
1011 if (entry->hash) {
1012 total++;
1013
1014 LOGGER_TRACE("[%3i:%3i] %08x => [%s...] %i, %i(%c), %i(%c)\n",
1015 (int)bid, (int)cid, entry->hash, idpart2str(entry->client.public_key, 8),
1016 entry->used_at ? (int)(unix_time() - entry->used_at) : 0,
1017 entry->seen_at ? (int)(unix_time() - entry->seen_at) : 0,
1018 entry->seen_at ? (entry->seen_family == AF_INET ? '4' : (entry->seen_family == AF_INET6 ? '6' : '?')) : '?',
1019 entry->heard_at ? (int)(unix_time() - entry->heard_at) : 0,
1020 entry->heard_at ? (entry->heard_family == AF_INET ? '4' : (entry->heard_family == AF_INET6 ? '6' : '?')) : '?');
1021 }
1022 }
1023 }
1024
1025 if (total) {
1026 LOGGER_TRACE("Total: %i entries, table usage %i%%.\n", (int)total,
1027 (int)(total * 100 / (assoc->candidates_bucket_count * assoc->candidates_bucket_size)));
1028 }
1029}
1030
1031#endif /* TOX_LOGGER */
diff --git a/toxcore/assoc.h b/toxcore/assoc.h
deleted file mode 100644
index 65a2745d..00000000
--- a/toxcore/assoc.h
+++ /dev/null
@@ -1,104 +0,0 @@
1
2#ifndef __ASSOC_H__
3#define __ASSOC_H__
4
5/* used by rendezvous */
6#define ASSOC_AVAILABLE
7
8/* For the legalese parts, see tox.h. */
9
10/* enumerated lists are superior to magic numbers */
11enum NODE_STATUS { BAD, SEENB_HEARDG, SEENG, USED };
12
13/*
14 * Module to store currently unused ID <=> IP associations
15 * for a potential future use
16 */
17
18typedef struct Assoc Assoc;
19
20/*****************************************************************************/
21
22/* custom distance handler, if it's not ID-distance based
23 * return values exactly like id_closest() */
24typedef int (*Assoc_distance_relative_callback)(const Assoc *assoc, void *callback_data, const uint8_t *client_id,
25 const uint8_t *client_id1, const uint8_t *client_id2);
26
27#define DISTANCE_INDEX_DISTANCE_BITS 44
28
29/* absolute distance: can be same for different client_id_check values
30 * return value should have DISTANCE_INDEX_DISTANCE_BITS valid bits */
31typedef uint64_t (*Assoc_distance_absolute_callback)(const Assoc *assoc, void *callback_data,
32 const uint8_t *client_id_ref, const uint8_t *client_id_check);
33
34/*****************************************************************************/
35
36/* Central entry point for new associations: add a new candidate to the cache
37 * returns 1 if entry is stored, 2 if existing entry was updated, 0 else */
38uint8_t Assoc_add_entry(Assoc *assoc, const uint8_t *id, const IPPTs *ippts_send, const IP_Port *ipp_recv,
39 uint8_t used);
40
41/*****************************************************************************/
42
43typedef enum AssocCloseEntriesFlags {
44 ProtoIPv4 = 1,
45 ProtoIPv6 = 2,
46 LANOk = 4,
47} AssocCloseEntriesFlags;
48
49typedef struct Assoc_close_entries {
50 void *custom_data; /* given to distance functions */
51 uint8_t *wanted_id; /* the target client_id */
52 uint8_t flags; /* additional flags */
53
54 Assoc_distance_relative_callback distance_relative_func;
55 Assoc_distance_absolute_callback distance_absolute_func;
56
57 uint8_t count_good; /* that many should be "good" w.r.t. timeout */
58 uint8_t count; /* allocated number of close_indices */
59 Client_data **result;
60} Assoc_close_entries;
61
62/* find up to close_count nodes to put into close_nodes_used of ID_Nodes
63 * the distance functions can be NULL, then standard distance functions will be used
64 * the caller is responsible for allocating close_indices of sufficient size
65 *
66 * returns 0 on error
67 * returns the number of found nodes and the list of indices usable by Assoc_client()
68 * the caller is assumed to be registered from Assoc_register_callback()
69 * if they aren't, they should copy the Client_data and call Assoc_client_drop()
70 */
71uint8_t Assoc_get_close_entries(Assoc *assoc, Assoc_close_entries *close_entries);
72
73/*****************************************************************************/
74
75/* create: default sizes (6, 5 => 320 entries) */
76Assoc *new_Assoc_default(const uint8_t *public_id);
77
78/* create: customized sizes
79 * total is (2^bits) * entries
80 * bits should be between 2 and 15 (else it's trimmed)
81 * entries will be reduced to the closest prime smaller or equal
82 *
83 * preferably bits should be large and entries small to ensure spread
84 * in the search space (e. g. 5, 5 is preferable to 2, 41) */
85Assoc *new_Assoc(size_t bits, size_t entries, const uint8_t *public_id);
86
87/* public_id changed (loaded), update which entry isn't stored */
88void Assoc_self_client_id_changed(Assoc *assoc, const uint8_t *public_id);
89
90/* every 45s send out a getnodes() for a "random" bucket */
91#define ASSOC_BUCKET_REFRESH 45
92
93/* refresh bucket's data from time to time
94 * this must be called only from DHT */
95void do_Assoc(Assoc *assoc, DHT *dht);
96
97/* destroy */
98void kill_Assoc(Assoc *assoc);
99
100#ifdef TOX_LOGGER
101void Assoc_status(const Assoc *assoc);
102#endif /* TOX_LOGGER */
103
104#endif /* !__ASSOC_H__ */
diff --git a/toxcore/ccompat.h b/toxcore/ccompat.h
new file mode 100644
index 00000000..f4aa1d89
--- /dev/null
+++ b/toxcore/ccompat.h
@@ -0,0 +1,51 @@
1/*
2 * C language compatibility macros for varying compiler support.
3 */
4#ifndef CCOMPAT_H
5#define CCOMPAT_H
6
7// Variable length arrays.
8// VLA(type, name, size) allocates a variable length array with automatic
9// storage duration. VLA_SIZE(name) evaluates to the runtime size of that array
10// in bytes.
11//
12// If C99 VLAs are not available, an emulation using alloca (stack allocation
13// "function") is used. Note the semantic difference: alloca'd memory does not
14// get freed at the end of the declaration's scope. Do not use VLA() in loops or
15// you may run out of stack space.
16#if !defined(_MSC_VER) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
17// C99 VLAs.
18#define VLA(type, name, size) type name[size]
19#define SIZEOF_VLA sizeof
20#else
21
22// Emulation using alloca.
23#ifdef _WIN32
24#include <malloc.h>
25#elif defined(__linux__)
26#include <alloca.h>
27#else
28#include <stdlib.h>
29#if !defined(alloca) && defined(__GNUC__)
30#define alloca __builtin_alloca
31#endif
32#endif
33
34#define VLA(type, name, size) \
35 const size_t name##_size = (size) * sizeof(type); \
36 type *const name = (type *)alloca(name##_size)
37#define SIZEOF_VLA(name) name##_size
38
39#endif
40
41#ifndef __cplusplus
42#define nullptr NULL
43#endif
44
45#ifdef __GNUC__
46#define GNU_PRINTF(f, a) __attribute__((__format__(__printf__, f, a)))
47#else
48#define GNU_PRINTF(f, a)
49#endif
50
51#endif /* CCOMPAT_H */
diff --git a/toxcore/crypto_core.api.h b/toxcore/crypto_core.api.h
new file mode 100644
index 00000000..4b40860d
--- /dev/null
+++ b/toxcore/crypto_core.api.h
@@ -0,0 +1,268 @@
1%{
2/*
3 * Functions for the core crypto.
4 */
5
6/*
7 * Copyright © 2016-2017 The TokTok team.
8 * Copyright © 2013 Tox project.
9 *
10 * This file is part of Tox, the free peer to peer instant messenger.
11 *
12 * Tox is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * Tox is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
24 */
25#ifndef CRYPTO_CORE_H
26#define CRYPTO_CORE_H
27
28#include <stdbool.h>
29#include <stddef.h>
30#include <stdint.h>
31
32#ifdef __cplusplus
33extern "C" {
34#endif
35%}
36
37/**
38 * The number of bytes in a Tox public key.
39 */
40const CRYPTO_PUBLIC_KEY_SIZE = 32;
41
42/**
43 * The number of bytes in a Tox secret key.
44 */
45const CRYPTO_SECRET_KEY_SIZE = 32;
46
47/**
48 * The number of bytes in a shared key computed from public and secret keys.
49 */
50const CRYPTO_SHARED_KEY_SIZE = 32;
51
52/**
53 * The number of bytes in a symmetric key.
54 */
55const CRYPTO_SYMMETRIC_KEY_SIZE = CRYPTO_SHARED_KEY_SIZE;
56
57/**
58 * The number of bytes needed for the MAC (message authentication code) in an
59 * encrypted message.
60 */
61const CRYPTO_MAC_SIZE = 16;
62
63/**
64 * The number of bytes in a nonce used for encryption/decryption.
65 */
66const CRYPTO_NONCE_SIZE = 24;
67
68/**
69 * The number of bytes in a SHA256 hash.
70 */
71const CRYPTO_SHA256_SIZE = 32;
72
73/**
74 * The number of bytes in a SHA512 hash.
75 */
76const CRYPTO_SHA512_SIZE = 64;
77
78/**
79 * A `memcmp`-like function whose running time does not depend on the input
80 * bytes, only on the input length. Useful to compare sensitive data where
81 * timing attacks could reveal that data.
82 *
83 * This means for instance that comparing "aaaa" and "aaaa" takes 4 time, and
84 * "aaaa" and "baaa" also takes 4 time. With a regular `memcmp`, the latter may
85 * take 1 time, because it immediately knows that the two strings are not equal.
86 */
87static int32_t crypto_memcmp(const void *p1, const void *p2, size_t length);
88
89/**
90 * A `bzero`-like function which won't be optimised away by the compiler. Some
91 * compilers will inline `bzero` or `memset` if they can prove that there will
92 * be no reads to the written data. Use this function if you want to be sure the
93 * memory is indeed zeroed.
94 */
95static void crypto_memzero(void *data, size_t length);
96
97/**
98 * Compute a SHA256 hash (32 bytes).
99 */
100static void crypto_sha256(uint8_t[CRYPTO_SHA256_SIZE] hash, const uint8_t[length] data);
101
102/**
103 * Compute a SHA512 hash (64 bytes).
104 */
105static void crypto_sha512(uint8_t[CRYPTO_SHA512_SIZE] hash, const uint8_t[length] data);
106
107/**
108 * Compare 2 public keys of length CRYPTO_PUBLIC_KEY_SIZE, not vulnerable to
109 * timing attacks.
110 *
111 * @return 0 if both mem locations of length are equal, -1 if they are not.
112 */
113static int32_t public_key_cmp(
114 const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] pk1,
115 const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] pk2);
116
117namespace random {
118
119/**
120 * Return a random 8 bit integer.
121 */
122static uint8_t u08();
123
124/**
125 * Return a random 16 bit integer.
126 */
127static uint16_t u16();
128
129/**
130 * Return a random 32 bit integer.
131 */
132static uint32_t u32();
133
134/**
135 * Return a random 64 bit integer.
136 */
137static uint64_t u64();
138
139/**
140 * Fill the given nonce with random bytes.
141 */
142static void nonce(uint8_t[CRYPTO_NONCE_SIZE] nonce);
143
144/**
145 * Fill an array of bytes with random values.
146 */
147static void bytes(uint8_t[length] bytes);
148
149}
150
151/**
152 * Check if a Tox public key CRYPTO_PUBLIC_KEY_SIZE is valid or not. This
153 * should only be used for input validation.
154 *
155 * @return false if it isn't, true if it is.
156 */
157static bool public_key_valid(const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key);
158
159/**
160 * Generate a new random keypair. Every call to this function is likely to
161 * generate a different keypair.
162 */
163static int32_t crypto_new_keypair(
164 uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
165 uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key);
166
167/**
168 * Derive the public key from a given secret key.
169 */
170static void crypto_derive_public_key(
171 uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
172 const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key);
173
174/**
175 * Encrypt plain text of the given length to encrypted of length +
176 * $CRYPTO_MAC_SIZE using the public key ($CRYPTO_PUBLIC_KEY_SIZE bytes) of the
177 * receiver and the secret key of the sender and a $CRYPTO_NONCE_SIZE byte
178 * nonce.
179 *
180 * @return -1 if there was a problem, length of encrypted data if everything
181 * was fine.
182 */
183static int32_t encrypt_data(
184 const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
185 const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key,
186 const uint8_t[CRYPTO_NONCE_SIZE] nonce,
187 const uint8_t[length] plain,
188 uint8_t *encrypted);
189
190
191/**
192 * Decrypt encrypted text of the given length to plain text of the given length
193 * - $CRYPTO_MAC_SIZE using the public key ($CRYPTO_PUBLIC_KEY_SIZE bytes) of
194 * the sender, the secret key of the receiver and a $CRYPTO_NONCE_SIZE byte
195 * nonce.
196 *
197 * @return -1 if there was a problem (decryption failed), length of plain text
198 * data if everything was fine.
199 */
200static int32_t decrypt_data(
201 const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
202 const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key,
203 const uint8_t[CRYPTO_NONCE_SIZE] nonce,
204 const uint8_t[length] encrypted,
205 uint8_t *plain);
206
207/**
208 * Fast encrypt/decrypt operations. Use if this is not a one-time communication.
209 * $encrypt_precompute does the shared-key generation once so it does not have
210 * to be preformed on every encrypt/decrypt.
211 */
212static int32_t encrypt_precompute(
213 const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
214 const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key,
215 uint8_t[CRYPTO_SHARED_KEY_SIZE] shared_key);
216
217/**
218 * Encrypts plain of length length to encrypted of length + $CRYPTO_MAC_SIZE
219 * using a shared key $CRYPTO_SYMMETRIC_KEY_SIZE big and a $CRYPTO_NONCE_SIZE
220 * byte nonce.
221 *
222 * @return -1 if there was a problem, length of encrypted data if everything
223 * was fine.
224 */
225static int32_t encrypt_data_symmetric(
226 const uint8_t[CRYPTO_SHARED_KEY_SIZE] shared_key,
227 const uint8_t[CRYPTO_NONCE_SIZE] nonce,
228 const uint8_t[length] plain,
229 uint8_t *encrypted);
230
231/**
232 * Decrypts encrypted of length length to plain of length length -
233 * $CRYPTO_MAC_SIZE using a shared key CRYPTO_SHARED_KEY_SIZE big and a
234 * $CRYPTO_NONCE_SIZE byte nonce.
235 *
236 * @return -1 if there was a problem (decryption failed), length of plain data
237 * if everything was fine.
238 */
239static int32_t decrypt_data_symmetric(
240 const uint8_t[CRYPTO_SHARED_KEY_SIZE] shared_key,
241 const uint8_t[CRYPTO_NONCE_SIZE] nonce,
242 const uint8_t[length] encrypted,
243 uint8_t *plain);
244
245/**
246 * Increment the given nonce by 1 in big endian (rightmost byte incremented
247 * first).
248 */
249static void increment_nonce(uint8_t[CRYPTO_NONCE_SIZE] nonce);
250
251/**
252 * Increment the given nonce by a given number. The number should be in host
253 * byte order.
254 */
255static void increment_nonce_number(uint8_t[CRYPTO_NONCE_SIZE] nonce, uint32_t host_order_num);
256
257/**
258 * Fill a key CRYPTO_SYMMETRIC_KEY_SIZE big with random bytes.
259 */
260static void new_symmetric_key(uint8_t[CRYPTO_SYMMETRIC_KEY_SIZE] key);
261
262%{
263#ifdef __cplusplus
264} // extern "C"
265#endif
266
267#endif /* CRYPTO_CORE_H */
268%}
diff --git a/toxcore/crypto_core.c b/toxcore/crypto_core.c
index a733c38e..b2f0e5f0 100644
--- a/toxcore/crypto_core.c
+++ b/toxcore/crypto_core.c
@@ -1,72 +1,124 @@
1/* net_crypto.c 1/*
2 *
3 * Functions for the core crypto. 2 * Functions for the core crypto.
4 * 3 *
5 * NOTE: This code has to be perfect. We don't mess around with encryption. 4 * NOTE: This code has to be perfect. We don't mess around with encryption.
5 */
6
7/*
8 * Copyright © 2016-2017 The TokTok team.
9 * Copyright © 2013 Tox project.
6 * 10 *
7 * Copyright (C) 2013 Tox project All Rights Reserved. 11 * This file is part of Tox, the free peer to peer instant messenger.
8 *
9 * This file is part of Tox.
10 *
11 * Tox is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 * 12 *
16 * Tox is distributed in the hope that it will be useful, 13 * Tox is free software: you can redistribute it and/or modify
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * it under the terms of the GNU General Public License as published by
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * the Free Software Foundation, either version 3 of the License, or
19 * GNU General Public License for more details. 16 * (at your option) any later version.
20 * 17 *
21 * You should have received a copy of the GNU General Public License 18 * Tox is distributed in the hope that it will be useful,
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * 22 *
23 * You should have received a copy of the GNU General Public License
24 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
24 */ 25 */
25
26#ifdef HAVE_CONFIG_H 26#ifdef HAVE_CONFIG_H
27#include "config.h" 27#include "config.h"
28#endif 28#endif
29 29
30#include "ccompat.h"
30#include "crypto_core.h" 31#include "crypto_core.h"
31 32
32#if crypto_box_PUBLICKEYBYTES != 32 33#include <string.h>
33#error crypto_box_PUBLICKEYBYTES is required to be 32 bytes for public_key_cmp to work, 34
35#ifndef VANILLA_NACL
36/* We use libsodium by default. */
37#include <sodium.h>
38#else
39#include <crypto_box.h>
40#include <crypto_hash_sha256.h>
41#include <crypto_hash_sha512.h>
42#include <crypto_scalarmult_curve25519.h>
43#include <crypto_verify_16.h>
44#include <crypto_verify_32.h>
45#include <randombytes.h>
46#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
47#endif
48
49#if CRYPTO_PUBLIC_KEY_SIZE != crypto_box_PUBLICKEYBYTES
50#error CRYPTO_PUBLIC_KEY_SIZE should be equal to crypto_box_PUBLICKEYBYTES
51#endif
52
53#if CRYPTO_SECRET_KEY_SIZE != crypto_box_SECRETKEYBYTES
54#error CRYPTO_SECRET_KEY_SIZE should be equal to crypto_box_SECRETKEYBYTES
55#endif
56
57#if CRYPTO_SHARED_KEY_SIZE != crypto_box_BEFORENMBYTES
58#error CRYPTO_SHARED_KEY_SIZE should be equal to crypto_box_BEFORENMBYTES
59#endif
60
61#if CRYPTO_SYMMETRIC_KEY_SIZE != crypto_box_BEFORENMBYTES
62#error CRYPTO_SYMMETRIC_KEY_SIZE should be equal to crypto_box_BEFORENMBYTES
63#endif
64
65#if CRYPTO_MAC_SIZE != crypto_box_MACBYTES
66#error CRYPTO_MAC_SIZE should be equal to crypto_box_MACBYTES
67#endif
68
69#if CRYPTO_NONCE_SIZE != crypto_box_NONCEBYTES
70#error CRYPTO_NONCE_SIZE should be equal to crypto_box_NONCEBYTES
34#endif 71#endif
35 72
36/* compare 2 public keys of length crypto_box_PUBLICKEYBYTES, not vulnerable to timing attacks. 73#if CRYPTO_SHA256_SIZE != crypto_hash_sha256_BYTES
37 returns 0 if both mem locations of length are equal, 74#error CRYPTO_SHA256_SIZE should be equal to crypto_hash_sha256_BYTES
38 return -1 if they are not. */ 75#endif
39int public_key_cmp(const uint8_t *pk1, const uint8_t *pk2) 76
77#if CRYPTO_SHA512_SIZE != crypto_hash_sha512_BYTES
78#error CRYPTO_SHA512_SIZE should be equal to crypto_hash_sha512_BYTES
79#endif
80
81int32_t public_key_cmp(const uint8_t *pk1, const uint8_t *pk2)
40{ 82{
83#if CRYPTO_PUBLIC_KEY_SIZE != 32
84#error CRYPTO_PUBLIC_KEY_SIZE is required to be 32 bytes for public_key_cmp to work,
85#endif
41 return crypto_verify_32(pk1, pk2); 86 return crypto_verify_32(pk1, pk2);
42} 87}
43 88
44/* return a random number. 89uint8_t random_u08(void)
45 */ 90{
46uint32_t random_int(void) 91 uint8_t randnum;
92 randombytes(&randnum, 1);
93 return randnum;
94}
95
96uint16_t random_u16(void)
97{
98 uint16_t randnum;
99 randombytes((uint8_t *)&randnum, sizeof(randnum));
100 return randnum;
101}
102
103uint32_t random_u32(void)
47{ 104{
48 uint32_t randnum; 105 uint32_t randnum;
49 randombytes((uint8_t *)&randnum , sizeof(randnum)); 106 randombytes((uint8_t *)&randnum, sizeof(randnum));
50 return randnum; 107 return randnum;
51} 108}
52 109
53uint64_t random_64b(void) 110uint64_t random_u64(void)
54{ 111{
55 uint64_t randnum; 112 uint64_t randnum;
56 randombytes((uint8_t *)&randnum, sizeof(randnum)); 113 randombytes((uint8_t *)&randnum, sizeof(randnum));
57 return randnum; 114 return randnum;
58} 115}
59 116
60/* Check if a Tox public key crypto_box_PUBLICKEYBYTES is valid or not. 117bool public_key_valid(const uint8_t *public_key)
61 * This should only be used for input validation.
62 *
63 * return 0 if it isn't.
64 * return 1 if it is.
65 */
66int public_key_valid(const uint8_t *public_key)
67{ 118{
68 if (public_key[31] >= 128) /* Last bit of key is always zero. */ 119 if (public_key[31] >= 128) { /* Last bit of key is always zero. */
69 return 0; 120 return 0;
121 }
70 122
71 return 1; 123 return 1;
72} 124}
@@ -74,75 +126,81 @@ int public_key_valid(const uint8_t *public_key)
74/* Precomputes the shared key from their public_key and our secret_key. 126/* Precomputes the shared key from their public_key and our secret_key.
75 * This way we can avoid an expensive elliptic curve scalar multiply for each 127 * This way we can avoid an expensive elliptic curve scalar multiply for each
76 * encrypt/decrypt operation. 128 * encrypt/decrypt operation.
77 * enc_key has to be crypto_box_BEFORENMBYTES bytes long. 129 * shared_key has to be crypto_box_BEFORENMBYTES bytes long.
78 */ 130 */
79void encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key, uint8_t *enc_key) 131int32_t encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key, uint8_t *shared_key)
80{ 132{
81 crypto_box_beforenm(enc_key, public_key, secret_key); 133 return crypto_box_beforenm(shared_key, public_key, secret_key);
82} 134}
83 135
84int encrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *plain, uint32_t length, 136int32_t encrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *plain, size_t length,
85 uint8_t *encrypted) 137 uint8_t *encrypted)
86{ 138{
87 if (length == 0 || !secret_key || !nonce || !plain || !encrypted) 139 if (length == 0 || !secret_key || !nonce || !plain || !encrypted) {
88 return -1; 140 return -1;
141 }
89 142
90 uint8_t temp_plain[length + crypto_box_ZEROBYTES]; 143 VLA(uint8_t, temp_plain, length + crypto_box_ZEROBYTES);
91 uint8_t temp_encrypted[length + crypto_box_MACBYTES + crypto_box_BOXZEROBYTES]; 144 VLA(uint8_t, temp_encrypted, length + crypto_box_MACBYTES + crypto_box_BOXZEROBYTES);
92 145
93 memset(temp_plain, 0, crypto_box_ZEROBYTES); 146 memset(temp_plain, 0, crypto_box_ZEROBYTES);
94 memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); // Pad the message with 32 0 bytes. 147 memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); // Pad the message with 32 0 bytes.
95 148
96 if (crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, secret_key) != 0) 149 if (crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, secret_key) != 0) {
97 return -1; 150 return -1;
151 }
98 152
99 /* Unpad the encrypted message. */ 153 /* Unpad the encrypted message. */
100 memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES); 154 memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES);
101 return length + crypto_box_MACBYTES; 155 return length + crypto_box_MACBYTES;
102} 156}
103 157
104int decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *encrypted, uint32_t length, 158int32_t decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *encrypted, size_t length,
105 uint8_t *plain) 159 uint8_t *plain)
106{ 160{
107 if (length <= crypto_box_BOXZEROBYTES || !secret_key || !nonce || !encrypted || !plain) 161 if (length <= crypto_box_BOXZEROBYTES || !secret_key || !nonce || !encrypted || !plain) {
108 return -1; 162 return -1;
163 }
109 164
110 uint8_t temp_plain[length + crypto_box_ZEROBYTES]; 165 VLA(uint8_t, temp_plain, length + crypto_box_ZEROBYTES);
111 uint8_t temp_encrypted[length + crypto_box_BOXZEROBYTES]; 166 VLA(uint8_t, temp_encrypted, length + crypto_box_BOXZEROBYTES);
112 167
113 memset(temp_encrypted, 0, crypto_box_BOXZEROBYTES); 168 memset(temp_encrypted, 0, crypto_box_BOXZEROBYTES);
114 memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); // Pad the message with 16 0 bytes. 169 memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); // Pad the message with 16 0 bytes.
115 170
116 if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce, secret_key) != 0) 171 if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce, secret_key) != 0) {
117 return -1; 172 return -1;
173 }
118 174
119 memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES); 175 memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES);
120 return length - crypto_box_MACBYTES; 176 return length - crypto_box_MACBYTES;
121} 177}
122 178
123int encrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce, 179int32_t encrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
124 const uint8_t *plain, uint32_t length, uint8_t *encrypted) 180 const uint8_t *plain, size_t length, uint8_t *encrypted)
125{ 181{
126 if (!public_key || !secret_key) 182 if (!public_key || !secret_key) {
127 return -1; 183 return -1;
184 }
128 185
129 uint8_t k[crypto_box_BEFORENMBYTES]; 186 uint8_t k[crypto_box_BEFORENMBYTES];
130 encrypt_precompute(public_key, secret_key, k); 187 encrypt_precompute(public_key, secret_key, k);
131 int ret = encrypt_data_symmetric(k, nonce, plain, length, encrypted); 188 int ret = encrypt_data_symmetric(k, nonce, plain, length, encrypted);
132 sodium_memzero(k, sizeof k); 189 crypto_memzero(k, sizeof k);
133 return ret; 190 return ret;
134} 191}
135 192
136int decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce, 193int32_t decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
137 const uint8_t *encrypted, uint32_t length, uint8_t *plain) 194 const uint8_t *encrypted, size_t length, uint8_t *plain)
138{ 195{
139 if (!public_key || !secret_key) 196 if (!public_key || !secret_key) {
140 return -1; 197 return -1;
198 }
141 199
142 uint8_t k[crypto_box_BEFORENMBYTES]; 200 uint8_t k[crypto_box_BEFORENMBYTES];
143 encrypt_precompute(public_key, secret_key, k); 201 encrypt_precompute(public_key, secret_key, k);
144 int ret = decrypt_data_symmetric(k, nonce, encrypted, length, plain); 202 int ret = decrypt_data_symmetric(k, nonce, encrypted, length, plain);
145 sodium_memzero(k, sizeof k); 203 crypto_memzero(k, sizeof k);
146 return ret; 204 return ret;
147} 205}
148 206
@@ -150,7 +208,7 @@ int decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uin
150/* Increment the given nonce by 1. */ 208/* Increment the given nonce by 1. */
151void increment_nonce(uint8_t *nonce) 209void increment_nonce(uint8_t *nonce)
152{ 210{
153 /* FIXME use increment_nonce_number(nonce, 1) or sodium_increment (change to little endian) 211 /* TODO(irungentoo): use increment_nonce_number(nonce, 1) or sodium_increment (change to little endian)
154 * NOTE don't use breaks inside this loop 212 * NOTE don't use breaks inside this loop
155 * In particular, make sure, as far as possible, 213 * In particular, make sure, as far as possible,
156 * that loop bounds and their potential underflow or overflow 214 * that loop bounds and their potential underflow or overflow
@@ -165,6 +223,20 @@ void increment_nonce(uint8_t *nonce)
165 carry >>= 8; 223 carry >>= 8;
166 } 224 }
167} 225}
226
227static uint32_t host_to_network(uint32_t x)
228{
229#if !defined(BYTE_ORDER) || BYTE_ORDER == LITTLE_ENDIAN
230 return
231 ((x >> 24) & 0x000000FF) | // move byte 3 to byte 0
232 ((x >> 8) & 0x0000FF00) | // move byte 2 to byte 1
233 ((x << 8) & 0x00FF0000) | // move byte 1 to byte 2
234 ((x << 24) & 0xFF000000); // move byte 0 to byte 3
235#else
236 return x;
237#endif
238}
239
168/* increment the given nonce by num */ 240/* increment the given nonce by num */
169void increment_nonce_number(uint8_t *nonce, uint32_t host_order_num) 241void increment_nonce_number(uint8_t *nonce, uint32_t host_order_num)
170{ 242{
@@ -173,7 +245,7 @@ void increment_nonce_number(uint8_t *nonce, uint32_t host_order_num)
173 * that loop bounds and their potential underflow or overflow 245 * that loop bounds and their potential underflow or overflow
174 * are independent of user-controlled input (you may have heard of the Heartbleed bug). 246 * are independent of user-controlled input (you may have heard of the Heartbleed bug).
175 */ 247 */
176 const uint32_t big_endian_num = htonl(host_order_num); 248 const uint32_t big_endian_num = host_to_network(host_order_num);
177 const uint8_t *const num_vec = (const uint8_t *) &big_endian_num; 249 const uint8_t *const num_vec = (const uint8_t *) &big_endian_num;
178 uint8_t num_as_nonce[crypto_box_NONCEBYTES] = {0}; 250 uint8_t num_as_nonce[crypto_box_NONCEBYTES] = {0};
179 num_as_nonce[crypto_box_NONCEBYTES - 4] = num_vec[0]; 251 num_as_nonce[crypto_box_NONCEBYTES - 4] = num_vec[0];
@@ -197,87 +269,33 @@ void random_nonce(uint8_t *nonce)
197 randombytes(nonce, crypto_box_NONCEBYTES); 269 randombytes(nonce, crypto_box_NONCEBYTES);
198} 270}
199 271
200/* Fill a key crypto_box_KEYBYTES big with random bytes */ 272/* Fill a key CRYPTO_SYMMETRIC_KEY_SIZE big with random bytes */
201void new_symmetric_key(uint8_t *key) 273void new_symmetric_key(uint8_t *key)
202{ 274{
203 randombytes(key, crypto_box_KEYBYTES); 275 randombytes(key, CRYPTO_SYMMETRIC_KEY_SIZE);
204} 276}
205 277
206/* Gives a nonce guaranteed to be different from previous ones.*/ 278int32_t crypto_new_keypair(uint8_t *public_key, uint8_t *secret_key)
207void new_nonce(uint8_t *nonce)
208{ 279{
209 random_nonce(nonce); 280 return crypto_box_keypair(public_key, secret_key);
210} 281}
211 282
212/* Create a request to peer. 283void crypto_derive_public_key(uint8_t *public_key, const uint8_t *secret_key)
213 * send_public_key and send_secret_key are the pub/secret keys of the sender.
214 * recv_public_key is public key of receiver.
215 * packet must be an array of MAX_CRYPTO_REQUEST_SIZE big.
216 * Data represents the data we send with the request with length being the length of the data.
217 * request_id is the id of the request (32 = friend request, 254 = ping request).
218 *
219 * return -1 on failure.
220 * return the length of the created packet on success.
221 */
222int create_request(const uint8_t *send_public_key, const uint8_t *send_secret_key, uint8_t *packet,
223 const uint8_t *recv_public_key, const uint8_t *data, uint32_t length, uint8_t request_id)
224{ 284{
225 if (!send_public_key || !packet || !recv_public_key || !data) 285 crypto_scalarmult_curve25519_base(public_key, secret_key);
226 return -1;
227
228 if (MAX_CRYPTO_REQUEST_SIZE < length + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 +
229 crypto_box_MACBYTES)
230 return -1;
231
232 uint8_t *nonce = packet + 1 + crypto_box_PUBLICKEYBYTES * 2;
233 new_nonce(nonce);
234 uint8_t temp[MAX_CRYPTO_REQUEST_SIZE]; // FIXME sodium_memzero before exit function
235 memcpy(temp + 1, data, length);
236 temp[0] = request_id;
237 int len = encrypt_data(recv_public_key, send_secret_key, nonce, temp, length + 1,
238 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + packet);
239
240 if (len == -1)
241 return -1;
242
243 packet[0] = NET_PACKET_CRYPTO;
244 memcpy(packet + 1, recv_public_key, crypto_box_PUBLICKEYBYTES);
245 memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, send_public_key, crypto_box_PUBLICKEYBYTES);
246
247 return len + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES;
248} 286}
249 287
250/* Puts the senders public key in the request in public_key, the data from the request 288void crypto_sha256(uint8_t *hash, const uint8_t *data, size_t length)
251 * in data if a friend or ping request was sent to us and returns the length of the data.
252 * packet is the request packet and length is its length.
253 *
254 * return -1 if not valid request.
255 */
256int handle_request(const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
257 uint8_t *request_id, const uint8_t *packet, uint16_t length)
258{ 289{
259 if (!self_public_key || !public_key || !data || !request_id || !packet) 290 crypto_hash_sha256(hash, data, length);
260 return -1; 291}
261
262 if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + crypto_box_MACBYTES ||
263 length > MAX_CRYPTO_REQUEST_SIZE)
264 return -1;
265
266 if (public_key_cmp(packet + 1, self_public_key) != 0)
267 return -1;
268
269 memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES);
270 const uint8_t *nonce = packet + 1 + crypto_box_PUBLICKEYBYTES * 2;
271 uint8_t temp[MAX_CRYPTO_REQUEST_SIZE]; // FIXME sodium_memzero before exit function
272 int len1 = decrypt_data(public_key, self_secret_key, nonce,
273 packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES,
274 length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), temp);
275 292
276 if (len1 == -1 || len1 == 0) 293void crypto_sha512(uint8_t *hash, const uint8_t *data, size_t length)
277 return -1; 294{
295 crypto_hash_sha512(hash, data, length);
296}
278 297
279 request_id[0] = temp[0]; 298void random_bytes(uint8_t *data, size_t length)
280 --len1; 299{
281 memcpy(data, temp + 1, len1); 300 randombytes(data, length);
282 return len1;
283} 301}
diff --git a/toxcore/crypto_core.h b/toxcore/crypto_core.h
index ab509f09..18c1339e 100644
--- a/toxcore/crypto_core.h
+++ b/toxcore/crypto_core.h
@@ -1,153 +1,252 @@
1/* crypto_core.h 1/*
2 *
3 * Functions for the core crypto. 2 * Functions for the core crypto.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2013 Tox project.
4 * 8 *
5 * Copyright (C) 2013 Tox project All Rights Reserved. 9 * This file is part of Tox, the free peer to peer instant messenger.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23#ifndef CORE_CRYPTO_H 24#ifndef CRYPTO_CORE_H
24#define CORE_CRYPTO_H 25#define CRYPTO_CORE_H
25 26
26#include "network.h" 27#include <stdbool.h>
27 28#include <stddef.h>
28#ifndef VANILLA_NACL 29#include <stdint.h>
29/* We use libsodium by default. */ 30
30#include <sodium.h> 31#ifdef __cplusplus
31#else 32extern "C" {
32#include <crypto_box.h>
33#include <randombytes.h>
34#include <crypto_hash_sha256.h>
35#include <crypto_hash_sha512.h>
36#include <crypto_verify_16.h>
37#include <crypto_verify_32.h>
38#include <crypto_scalarmult_curve25519.h>
39#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
40/* I know */
41#define sodium_memcmp(a, b, c) memcmp(a, b, c)
42#define sodium_memzero(a, c) memset(a, 0, c)
43#endif 33#endif
44 34
45#define crypto_box_KEYBYTES (crypto_box_BEFORENMBYTES) 35/**
36 * The number of bytes in a Tox public key.
37 */
38#define CRYPTO_PUBLIC_KEY_SIZE 32
46 39
47/* compare 2 public keys of length crypto_box_PUBLICKEYBYTES, not vulnerable to timing attacks. 40uint32_t crypto_public_key_size(void);
48 returns 0 if both mem locations of length are equal,
49 return -1 if they are not. */
50int public_key_cmp(const uint8_t *pk1, const uint8_t *pk2);
51 41
52/* return a random number. 42/**
53 * 43 * The number of bytes in a Tox secret key.
54 * random_int for a 32bin int.
55 * random_64b for a 64bit int.
56 */ 44 */
57uint32_t random_int(void); 45#define CRYPTO_SECRET_KEY_SIZE 32
58uint64_t random_64b(void);
59 46
60/* Check if a Tox public key crypto_box_PUBLICKEYBYTES is valid or not. 47uint32_t crypto_secret_key_size(void);
61 * This should only be used for input validation. 48
62 * 49/**
63 * return 0 if it isn't. 50 * The number of bytes in a shared key computed from public and secret keys.
64 * return 1 if it is.
65 */ 51 */
66int public_key_valid(const uint8_t *public_key); 52#define CRYPTO_SHARED_KEY_SIZE 32
67 53
68/* Encrypts plain of length length to encrypted of length + 16 using the 54uint32_t crypto_shared_key_size(void);
69 * public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce. 55
70 * 56/**
71 * return -1 if there was a problem. 57 * The number of bytes in a symmetric key.
72 * return length of encrypted data if everything was fine.
73 */ 58 */
74int encrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce, 59#define CRYPTO_SYMMETRIC_KEY_SIZE CRYPTO_SHARED_KEY_SIZE
75 const uint8_t *plain, uint32_t length, uint8_t *encrypted);
76 60
61uint32_t crypto_symmetric_key_size(void);
77 62
78/* Decrypts encrypted of length length to plain of length length - 16 using the 63/**
79 * public key(32 bytes) of the sender, the secret key of the receiver and a 24 byte nonce. 64 * The number of bytes needed for the MAC (message authentication code) in an
80 * 65 * encrypted message.
81 * return -1 if there was a problem (decryption failed).
82 * return length of plain data if everything was fine.
83 */ 66 */
84int decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce, 67#define CRYPTO_MAC_SIZE 16
85 const uint8_t *encrypted, uint32_t length, uint8_t *plain);
86 68
87/* Fast encrypt/decrypt operations. Use if this is not a one-time communication. 69uint32_t crypto_mac_size(void);
88 encrypt_precompute does the shared-key generation once so it does not have 70
89 to be preformed on every encrypt/decrypt. */ 71/**
90void encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key, uint8_t *enc_key); 72 * The number of bytes in a nonce used for encryption/decryption.
73 */
74#define CRYPTO_NONCE_SIZE 24
91 75
92/* Encrypts plain of length length to encrypted of length + 16 using a 76uint32_t crypto_nonce_size(void);
93 * secret key crypto_box_KEYBYTES big and a 24 byte nonce. 77
78/**
79 * The number of bytes in a SHA256 hash.
80 */
81#define CRYPTO_SHA256_SIZE 32
82
83uint32_t crypto_sha256_size(void);
84
85/**
86 * The number of bytes in a SHA512 hash.
87 */
88#define CRYPTO_SHA512_SIZE 64
89
90uint32_t crypto_sha512_size(void);
91
92/**
93 * A `memcmp`-like function whose running time does not depend on the input
94 * bytes, only on the input length. Useful to compare sensitive data where
95 * timing attacks could reveal that data.
94 * 96 *
95 * return -1 if there was a problem. 97 * This means for instance that comparing "aaaa" and "aaaa" takes 4 time, and
96 * return length of encrypted data if everything was fine. 98 * "aaaa" and "baaa" also takes 4 time. With a regular `memcmp`, the latter may
99 * take 1 time, because it immediately knows that the two strings are not equal.
97 */ 100 */
98int encrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *plain, uint32_t length, 101int32_t crypto_memcmp(const void *p1, const void *p2, size_t length);
99 uint8_t *encrypted);
100 102
101/* Decrypts encrypted of length length to plain of length length - 16 using a 103/**
102 * secret key crypto_box_KEYBYTES big and a 24 byte nonce. 104 * A `bzero`-like function which won't be optimised away by the compiler. Some
105 * compilers will inline `bzero` or `memset` if they can prove that there will
106 * be no reads to the written data. Use this function if you want to be sure the
107 * memory is indeed zeroed.
108 */
109void crypto_memzero(void *data, size_t length);
110
111/**
112 * Compute a SHA256 hash (32 bytes).
113 */
114void crypto_sha256(uint8_t *hash, const uint8_t *data, size_t length);
115
116/**
117 * Compute a SHA512 hash (64 bytes).
118 */
119void crypto_sha512(uint8_t *hash, const uint8_t *data, size_t length);
120
121/**
122 * Compare 2 public keys of length CRYPTO_PUBLIC_KEY_SIZE, not vulnerable to
123 * timing attacks.
103 * 124 *
104 * return -1 if there was a problem (decryption failed). 125 * @return 0 if both mem locations of length are equal, -1 if they are not.
105 * return length of plain data if everything was fine.
106 */ 126 */
107int decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *encrypted, uint32_t length, 127int32_t public_key_cmp(const uint8_t *pk1, const uint8_t *pk2);
108 uint8_t *plain);
109 128
110/* Increment the given nonce by 1. */ 129/**
111void increment_nonce(uint8_t *nonce); 130 * Return a random 8 bit integer.
131 */
132uint8_t random_u08(void);
112 133
113/* increment the given nonce by num */ 134/**
114void increment_nonce_number(uint8_t *nonce, uint32_t host_order_num); 135 * Return a random 16 bit integer.
136 */
137uint16_t random_u16(void);
138
139/**
140 * Return a random 32 bit integer.
141 */
142uint32_t random_u32(void);
115 143
116/* Fill the given nonce with random bytes. */ 144/**
145 * Return a random 64 bit integer.
146 */
147uint64_t random_u64(void);
148
149/**
150 * Fill the given nonce with random bytes.
151 */
117void random_nonce(uint8_t *nonce); 152void random_nonce(uint8_t *nonce);
118 153
119/* Fill a key crypto_box_KEYBYTES big with random bytes */ 154/**
120void new_symmetric_key(uint8_t *key); 155 * Fill an array of bytes with random values.
156 */
157void random_bytes(uint8_t *bytes, size_t length);
121 158
122/*Gives a nonce guaranteed to be different from previous ones.*/ 159/**
123void new_nonce(uint8_t *nonce); 160 * Check if a Tox public key CRYPTO_PUBLIC_KEY_SIZE is valid or not. This
161 * should only be used for input validation.
162 *
163 * @return false if it isn't, true if it is.
164 */
165bool public_key_valid(const uint8_t *public_key);
124 166
125#define MAX_CRYPTO_REQUEST_SIZE 1024 167/**
168 * Generate a new random keypair. Every call to this function is likely to
169 * generate a different keypair.
170 */
171int32_t crypto_new_keypair(uint8_t *public_key, uint8_t *secret_key);
126 172
127#define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */ 173/**
128#define CRYPTO_PACKET_HARDENING 48 /* Hardening crypto packet ID. */ 174 * Derive the public key from a given secret key.
129#define CRYPTO_PACKET_DHTPK 156 175 */
130#define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID. */ 176void crypto_derive_public_key(uint8_t *public_key, const uint8_t *secret_key);
131 177
132/* Create a request to peer. 178/**
133 * send_public_key and send_secret_key are the pub/secret keys of the sender. 179 * Encrypt plain text of the given length to encrypted of length +
134 * recv_public_key is public key of receiver. 180 * CRYPTO_MAC_SIZE using the public key (CRYPTO_PUBLIC_KEY_SIZE bytes) of the
135 * packet must be an array of MAX_CRYPTO_REQUEST_SIZE big. 181 * receiver and the secret key of the sender and a CRYPTO_NONCE_SIZE byte
136 * Data represents the data we send with the request with length being the length of the data. 182 * nonce.
137 * request_id is the id of the request (32 = friend request, 254 = ping request). 183 *
184 * @return -1 if there was a problem, length of encrypted data if everything
185 * was fine.
186 */
187int32_t encrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *plain,
188 size_t length, uint8_t *encrypted);
189
190/**
191 * Decrypt encrypted text of the given length to plain text of the given length
192 * - CRYPTO_MAC_SIZE using the public key (CRYPTO_PUBLIC_KEY_SIZE bytes) of
193 * the sender, the secret key of the receiver and a CRYPTO_NONCE_SIZE byte
194 * nonce.
138 * 195 *
139 * return -1 on failure. 196 * @return -1 if there was a problem (decryption failed), length of plain text
140 * return the length of the created packet on success. 197 * data if everything was fine.
141 */ 198 */
142int create_request(const uint8_t *send_public_key, const uint8_t *send_secret_key, uint8_t *packet, 199int32_t decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
143 const uint8_t *recv_public_key, const uint8_t *data, uint32_t length, uint8_t request_id); 200 const uint8_t *encrypted, size_t length, uint8_t *plain);
144 201
145/* puts the senders public key in the request in public_key, the data from the request 202/**
146 in data if a friend or ping request was sent to us and returns the length of the data. 203 * Fast encrypt/decrypt operations. Use if this is not a one-time communication.
147 packet is the request packet and length is its length 204 * encrypt_precompute does the shared-key generation once so it does not have
148 return -1 if not valid request. */ 205 * to be preformed on every encrypt/decrypt.
149int handle_request(const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data, 206 */
150 uint8_t *request_id, const uint8_t *packet, uint16_t length); 207int32_t encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key, uint8_t *shared_key);
151 208
209/**
210 * Encrypts plain of length length to encrypted of length + CRYPTO_MAC_SIZE
211 * using a shared key CRYPTO_SYMMETRIC_KEY_SIZE big and a CRYPTO_NONCE_SIZE
212 * byte nonce.
213 *
214 * @return -1 if there was a problem, length of encrypted data if everything
215 * was fine.
216 */
217int32_t encrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce, const uint8_t *plain, size_t length,
218 uint8_t *encrypted);
219
220/**
221 * Decrypts encrypted of length length to plain of length length -
222 * CRYPTO_MAC_SIZE using a shared key CRYPTO_SHARED_KEY_SIZE big and a
223 * CRYPTO_NONCE_SIZE byte nonce.
224 *
225 * @return -1 if there was a problem (decryption failed), length of plain data
226 * if everything was fine.
227 */
228int32_t decrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce, const uint8_t *encrypted, size_t length,
229 uint8_t *plain);
230
231/**
232 * Increment the given nonce by 1 in big endian (rightmost byte incremented
233 * first).
234 */
235void increment_nonce(uint8_t *nonce);
152 236
237/**
238 * Increment the given nonce by a given number. The number should be in host
239 * byte order.
240 */
241void increment_nonce_number(uint8_t *nonce, uint32_t host_order_num);
242
243/**
244 * Fill a key CRYPTO_SYMMETRIC_KEY_SIZE big with random bytes.
245 */
246void new_symmetric_key(uint8_t *key);
247
248#ifdef __cplusplus
249} // extern "C"
153#endif 250#endif
251
252#endif /* CRYPTO_CORE_H */
diff --git a/toxcore/crypto_core_mem.c b/toxcore/crypto_core_mem.c
new file mode 100644
index 00000000..b8f4223e
--- /dev/null
+++ b/toxcore/crypto_core_mem.c
@@ -0,0 +1,87 @@
1/*
2 * ISC License
3 *
4 * Copyright (c) 2013-2016
5 * Frank Denis <j at pureftpd dot org>
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19#ifdef HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#include "crypto_core.h"
24
25#ifndef VANILLA_NACL
26/* We use libsodium by default. */
27#include <sodium.h>
28#else
29#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
30#include <windows.h>
31#include <wincrypt.h>
32#endif
33#endif
34
35
36void crypto_memzero(void *data, size_t length)
37{
38#ifndef VANILLA_NACL
39 sodium_memzero(data, length);
40#else
41#ifdef _WIN32
42 SecureZeroMemory(data, length);
43#elif defined(HAVE_MEMSET_S)
44
45 if (length > 0U) {
46 errno_t code = memset_s(data, (rsize_t) length, 0, (rsize_t) length);
47
48 if (code != 0) {
49 abort(); /* LCOV_EXCL_LINE */
50 }
51 }
52
53#elif defined(HAVE_EXPLICIT_BZERO)
54 explicit_bzero(data, length);
55#else
56 volatile unsigned char *volatile pnt =
57 (volatile unsigned char *volatile) data;
58 size_t i = (size_t) 0U;
59
60 while (i < length) {
61 pnt[i++] = 0U;
62 }
63
64#endif
65#endif
66}
67
68int32_t crypto_memcmp(const void *p1, const void *p2, size_t length)
69{
70#ifndef VANILLA_NACL
71 return sodium_memcmp(p1, p2, length);
72#else
73 const volatile unsigned char *volatile b1 =
74 (const volatile unsigned char *volatile) p1;
75 const volatile unsigned char *volatile b2 =
76 (const volatile unsigned char *volatile) p2;
77
78 size_t i;
79 unsigned char d = (unsigned char) 0U;
80
81 for (i = 0U; i < length; i++) {
82 d |= b1[i] ^ b2[i];
83 }
84
85 return (1 & ((d - 1) >> 8)) - 1;
86#endif
87}
diff --git a/toxcore/crypto_core_test.cpp b/toxcore/crypto_core_test.cpp
new file mode 100644
index 00000000..8f91dce8
--- /dev/null
+++ b/toxcore/crypto_core_test.cpp
@@ -0,0 +1,96 @@
1#include "crypto_core.h"
2
3#include <algorithm>
4
5#include <gtest/gtest.h>
6
7namespace
8{
9
10enum {
11 /**
12 * The size of the arrays to compare. This was chosen to take around 2000
13 * CPU clocks on x86_64.
14 */
15 CRYPTO_TEST_MEMCMP_SIZE = 1024 * 1024, // 1 MiB
16 /**
17 * The number of times we run memcmp in the test.
18 *
19 * We compute the median time taken to reduce error margins.
20 */
21 CRYPTO_TEST_MEMCMP_ITERATIONS = 500,
22 /**
23 * The margin of error (in clocks) we allow for this test.
24 *
25 * Should be within 0.5% of ~2000 CPU clocks. In reality, the code is much
26 * more precise and is usually within 1 CPU clock.
27 */
28 CRYPTO_TEST_MEMCMP_EPS = 10,
29};
30
31clock_t memcmp_time(void *a, void *b, size_t len)
32{
33 clock_t start = clock();
34 crypto_memcmp(a, b, len);
35 return clock() - start;
36}
37
38/**
39 * This function performs the actual timing. It interleaves comparison of
40 * equal and non-equal arrays to reduce the influence of external effects
41 * such as the machine being a little more busy 1 second later.
42 */
43void memcmp_median(void *src, void *same, void *not_same, size_t len,
44 clock_t *same_median, clock_t *not_same_median)
45{
46 clock_t same_results[CRYPTO_TEST_MEMCMP_ITERATIONS];
47 clock_t not_same_results[CRYPTO_TEST_MEMCMP_ITERATIONS];
48
49 for (size_t i = 0; i < CRYPTO_TEST_MEMCMP_ITERATIONS; i++) {
50 same_results[i] = memcmp_time(src, same, len);
51 not_same_results[i] = memcmp_time(src, not_same, len);
52 }
53
54 std::sort(same_results, same_results + CRYPTO_TEST_MEMCMP_ITERATIONS);
55 *same_median = same_results[CRYPTO_TEST_MEMCMP_ITERATIONS / 2];
56 std::sort(not_same_results, not_same_results + CRYPTO_TEST_MEMCMP_ITERATIONS);
57 *not_same_median = not_same_results[CRYPTO_TEST_MEMCMP_ITERATIONS / 2];
58}
59
60/**
61 * This test checks whether crypto_memcmp takes the same time for equal and
62 * non-equal chunks of memory.
63 */
64TEST(CryptoCore, MemcmpTimingIsDataIndependent)
65{
66 // A random piece of memory.
67 uint8_t *src = new uint8_t[CRYPTO_TEST_MEMCMP_SIZE];
68 random_bytes(src, CRYPTO_TEST_MEMCMP_SIZE);
69
70 // A separate piece of memory containing the same data.
71 uint8_t *same = new uint8_t[CRYPTO_TEST_MEMCMP_SIZE];
72 memcpy(same, src, CRYPTO_TEST_MEMCMP_SIZE);
73
74 // Another piece of memory containing different data.
75 uint8_t *not_same = new uint8_t[CRYPTO_TEST_MEMCMP_SIZE];
76 random_bytes(not_same, CRYPTO_TEST_MEMCMP_SIZE);
77
78 clock_t same_median;
79 clock_t not_same_median;
80 memcmp_median(src, same, not_same, CRYPTO_TEST_MEMCMP_SIZE, &same_median, &not_same_median);
81
82 delete[] not_same;
83 delete[] same;
84 delete[] src;
85
86 clock_t const delta = same_median > not_same_median
87 ? same_median - not_same_median
88 : not_same_median - same_median;
89
90 EXPECT_LT(delta, CRYPTO_TEST_MEMCMP_EPS)
91 << "Delta time is too long (" << delta << " >= " << CRYPTO_TEST_MEMCMP_EPS << ")\n"
92 << "Time of the same data comparation: " << same_median << " clocks\n"
93 << "Time of the different data comparation: " << not_same_median << " clocks";
94}
95
96} // namespace
diff --git a/toxcore/friend_connection.c b/toxcore/friend_connection.c
index e7c8432b..fd5e3078 100644
--- a/toxcore/friend_connection.c
+++ b/toxcore/friend_connection.c
@@ -1,71 +1,129 @@
1/* friend_connection.c 1/*
2 *
3 * Connection to friends. 2 * Connection to friends.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2014 Tox project.
4 * 8 *
5 * Copyright (C) 2014 Tox project All Rights Reserved. 9 * This file is part of Tox, the free peer to peer instant messenger.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23
24#ifdef HAVE_CONFIG_H 24#ifdef HAVE_CONFIG_H
25#include "config.h" 25#include "config.h"
26#endif 26#endif
27 27
28#include "friend_connection.h" 28#include "friend_connection.h"
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33
29#include "util.h" 34#include "util.h"
30 35
31/* return 1 if the friendcon_id is not valid. 36#define PORTS_PER_DISCOVERY 10
32 * return 0 if the friendcon_id is valid.
33 */
34static uint8_t friendconn_id_not_valid(const Friend_Connections *fr_c, int friendcon_id)
35{
36 if ((unsigned int)friendcon_id >= fr_c->num_cons)
37 return 1;
38 37
39 if (fr_c->conns == NULL) 38typedef struct {
40 return 1; 39 uint8_t status;
41 40
42 if (fr_c->conns[friendcon_id].status == FRIENDCONN_STATUS_NONE) 41 uint8_t real_public_key[CRYPTO_PUBLIC_KEY_SIZE];
43 return 1; 42 uint8_t dht_temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
43 uint16_t dht_lock;
44 IP_Port dht_ip_port;
45 uint64_t dht_pk_lastrecv, dht_ip_port_lastrecv;
44 46
45 return 0; 47 int onion_friendnum;
48 int crypt_connection_id;
49
50 uint64_t ping_lastrecv, ping_lastsent;
51 uint64_t share_relays_lastsent;
52
53 struct {
54 int (*status_callback)(void *object, int id, uint8_t status, void *userdata);
55 int (*data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
56 int (*lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
57
58 void *callback_object;
59 int callback_id;
60 } callbacks[MAX_FRIEND_CONNECTION_CALLBACKS];
61
62 uint16_t lock_count;
63
64 Node_format tcp_relays[FRIEND_MAX_STORED_TCP_RELAYS];
65 uint16_t tcp_relay_counter;
66
67 bool hosting_tcp_relay;
68} Friend_Conn;
69
70
71struct Friend_Connections {
72 Net_Crypto *net_crypto;
73 DHT *dht;
74 Onion_Client *onion_c;
75
76 Friend_Conn *conns;
77 uint32_t num_cons;
78
79 int (*fr_request_callback)(void *object, const uint8_t *source_pubkey, const uint8_t *data, uint16_t len,
80 void *userdata);
81 void *fr_request_object;
82
83 uint64_t last_LANdiscovery;
84 uint16_t next_LANport;
85
86 bool local_discovery_enabled;
87};
88
89Net_Crypto *friendconn_net_crypto(const Friend_Connections *fr_c)
90{
91 return fr_c->net_crypto;
92}
93
94
95/* return true if the friendcon_id is valid.
96 * return false if the friendcon_id is not valid.
97 */
98static bool friendconn_id_valid(const Friend_Connections *fr_c, int friendcon_id)
99{
100 return (unsigned int)friendcon_id < fr_c->num_cons &&
101 fr_c->conns != nullptr &&
102 fr_c->conns[friendcon_id].status != FRIENDCONN_STATUS_NONE;
46} 103}
47 104
48 105
49/* Set the size of the friend connections list to num. 106/* Set the size of the friend connections list to num.
50 * 107 *
51 * return -1 if realloc fails. 108 * return false if realloc fails.
52 * return 0 if it succeeds. 109 * return true if it succeeds.
53 */ 110 */
54static int realloc_friendconns(Friend_Connections *fr_c, uint32_t num) 111static bool realloc_friendconns(Friend_Connections *fr_c, uint32_t num)
55{ 112{
56 if (num == 0) { 113 if (num == 0) {
57 free(fr_c->conns); 114 free(fr_c->conns);
58 fr_c->conns = NULL; 115 fr_c->conns = nullptr;
59 return 0; 116 return true;
60 } 117 }
61 118
62 Friend_Conn *newgroup_cons = realloc(fr_c->conns, num * sizeof(Friend_Conn)); 119 Friend_Conn *newgroup_cons = (Friend_Conn *)realloc(fr_c->conns, num * sizeof(Friend_Conn));
63 120
64 if (newgroup_cons == NULL) 121 if (newgroup_cons == nullptr) {
65 return -1; 122 return false;
123 }
66 124
67 fr_c->conns = newgroup_cons; 125 fr_c->conns = newgroup_cons;
68 return 0; 126 return true;
69} 127}
70 128
71/* Create a new empty friend connection. 129/* Create a new empty friend connection.
@@ -75,21 +133,20 @@ static int realloc_friendconns(Friend_Connections *fr_c, uint32_t num)
75 */ 133 */
76static int create_friend_conn(Friend_Connections *fr_c) 134static int create_friend_conn(Friend_Connections *fr_c)
77{ 135{
78 uint32_t i; 136 for (uint32_t i = 0; i < fr_c->num_cons; ++i) {
79 137 if (fr_c->conns[i].status == FRIENDCONN_STATUS_NONE) {
80 for (i = 0; i < fr_c->num_cons; ++i) {
81 if (fr_c->conns[i].status == FRIENDCONN_STATUS_NONE)
82 return i; 138 return i;
139 }
83 } 140 }
84 141
85 int id = -1; 142 if (!realloc_friendconns(fr_c, fr_c->num_cons + 1)) {
86 143 return -1;
87 if (realloc_friendconns(fr_c, fr_c->num_cons + 1) == 0) {
88 id = fr_c->num_cons;
89 ++fr_c->num_cons;
90 memset(&(fr_c->conns[id]), 0, sizeof(Friend_Conn));
91 } 144 }
92 145
146 const int id = fr_c->num_cons;
147 ++fr_c->num_cons;
148 memset(&fr_c->conns[id], 0, sizeof(Friend_Conn));
149
93 return id; 150 return id;
94} 151}
95 152
@@ -100,15 +157,18 @@ static int create_friend_conn(Friend_Connections *fr_c)
100 */ 157 */
101static int wipe_friend_conn(Friend_Connections *fr_c, int friendcon_id) 158static int wipe_friend_conn(Friend_Connections *fr_c, int friendcon_id)
102{ 159{
103 if (friendconn_id_not_valid(fr_c, friendcon_id)) 160 if (!friendconn_id_valid(fr_c, friendcon_id)) {
104 return -1; 161 return -1;
162 }
163
164 memset(&fr_c->conns[friendcon_id], 0, sizeof(Friend_Conn));
105 165
106 uint32_t i; 166 uint32_t i;
107 memset(&(fr_c->conns[friendcon_id]), 0 , sizeof(Friend_Conn));
108 167
109 for (i = fr_c->num_cons; i != 0; --i) { 168 for (i = fr_c->num_cons; i != 0; --i) {
110 if (fr_c->conns[i - 1].status != FRIENDCONN_STATUS_NONE) 169 if (fr_c->conns[i - 1].status != FRIENDCONN_STATUS_NONE) {
111 break; 170 break;
171 }
112 } 172 }
113 173
114 if (fr_c->num_cons != i) { 174 if (fr_c->num_cons != i) {
@@ -121,8 +181,9 @@ static int wipe_friend_conn(Friend_Connections *fr_c, int friendcon_id)
121 181
122static Friend_Conn *get_conn(const Friend_Connections *fr_c, int friendcon_id) 182static Friend_Conn *get_conn(const Friend_Connections *fr_c, int friendcon_id)
123{ 183{
124 if (friendconn_id_not_valid(fr_c, friendcon_id)) 184 if (!friendconn_id_valid(fr_c, friendcon_id)) {
125 return 0; 185 return nullptr;
186 }
126 187
127 return &fr_c->conns[friendcon_id]; 188 return &fr_c->conns[friendcon_id];
128} 189}
@@ -132,14 +193,13 @@ static Friend_Conn *get_conn(const Friend_Connections *fr_c, int friendcon_id)
132 */ 193 */
133int getfriend_conn_id_pk(Friend_Connections *fr_c, const uint8_t *real_pk) 194int getfriend_conn_id_pk(Friend_Connections *fr_c, const uint8_t *real_pk)
134{ 195{
135 uint32_t i; 196 for (uint32_t i = 0; i < fr_c->num_cons; ++i) {
136
137 for (i = 0; i < fr_c->num_cons; ++i) {
138 Friend_Conn *friend_con = get_conn(fr_c, i); 197 Friend_Conn *friend_con = get_conn(fr_c, i);
139 198
140 if (friend_con) { 199 if (friend_con) {
141 if (public_key_cmp(friend_con->real_public_key, real_pk) == 0) 200 if (public_key_cmp(friend_con->real_public_key, real_pk) == 0) {
142 return i; 201 return i;
202 }
143 } 203 }
144 } 204 }
145 205
@@ -153,33 +213,32 @@ int getfriend_conn_id_pk(Friend_Connections *fr_c, const uint8_t *real_pk)
153 */ 213 */
154int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, IP_Port ip_port, const uint8_t *public_key) 214int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, IP_Port ip_port, const uint8_t *public_key)
155{ 215{
156 Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); 216 Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id);
157 217
158 if (!friend_con) 218 if (!friend_con) {
159 return -1; 219 return -1;
220 }
160 221
161 /* Local ip and same pk means that they are hosting a TCP relay. */ 222 /* Local ip and same pk means that they are hosting a TCP relay. */
162 if (Local_ip(ip_port.ip) && public_key_cmp(friend_con->dht_temp_pk, public_key) == 0) { 223 if (ip_is_local(ip_port.ip) && public_key_cmp(friend_con->dht_temp_pk, public_key) == 0) {
163 if (friend_con->dht_ip_port.ip.family != 0) { 224 if (!net_family_is_unspec(friend_con->dht_ip_port.ip.family)) {
164 ip_port.ip = friend_con->dht_ip_port.ip; 225 ip_port.ip = friend_con->dht_ip_port.ip;
165 } else { 226 } else {
166 friend_con->hosting_tcp_relay = 0; 227 friend_con->hosting_tcp_relay = 0;
167 } 228 }
168 } 229 }
169 230
170 unsigned int i; 231 const uint16_t index = friend_con->tcp_relay_counter % FRIEND_MAX_STORED_TCP_RELAYS;
171
172 uint16_t index = friend_con->tcp_relay_counter % FRIEND_MAX_STORED_TCP_RELAYS;
173 232
174 for (i = 0; i < FRIEND_MAX_STORED_TCP_RELAYS; ++i) { 233 for (unsigned i = 0; i < FRIEND_MAX_STORED_TCP_RELAYS; ++i) {
175 if (friend_con->tcp_relays[i].ip_port.ip.family != 0 234 if (!net_family_is_unspec(friend_con->tcp_relays[i].ip_port.ip.family)
176 && public_key_cmp(friend_con->tcp_relays[i].public_key, public_key) == 0) { 235 && public_key_cmp(friend_con->tcp_relays[i].public_key, public_key) == 0) {
177 memset(&friend_con->tcp_relays[i], 0, sizeof(Node_format)); 236 memset(&friend_con->tcp_relays[i], 0, sizeof(Node_format));
178 } 237 }
179 } 238 }
180 239
181 friend_con->tcp_relays[index].ip_port = ip_port; 240 friend_con->tcp_relays[index].ip_port = ip_port;
182 memcpy(friend_con->tcp_relays[index].public_key, public_key, crypto_box_PUBLICKEYBYTES); 241 memcpy(friend_con->tcp_relays[index].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
183 ++friend_con->tcp_relay_counter; 242 ++friend_con->tcp_relay_counter;
184 243
185 return add_tcp_relay_peer(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, public_key); 244 return add_tcp_relay_peer(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, public_key);
@@ -188,17 +247,16 @@ int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, IP_Port ip_
188/* Connect to number saved relays for friend. */ 247/* Connect to number saved relays for friend. */
189static void connect_to_saved_tcp_relays(Friend_Connections *fr_c, int friendcon_id, unsigned int number) 248static void connect_to_saved_tcp_relays(Friend_Connections *fr_c, int friendcon_id, unsigned int number)
190{ 249{
191 Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); 250 const Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id);
192 251
193 if (!friend_con) 252 if (!friend_con) {
194 return; 253 return;
254 }
195 255
196 unsigned int i; 256 for (unsigned i = 0; (i < FRIEND_MAX_STORED_TCP_RELAYS) && (number != 0); ++i) {
197 257 const uint16_t index = (friend_con->tcp_relay_counter - (i + 1)) % FRIEND_MAX_STORED_TCP_RELAYS;
198 for (i = 0; (i < FRIEND_MAX_STORED_TCP_RELAYS) && (number != 0); ++i) {
199 uint16_t index = (friend_con->tcp_relay_counter - (i + 1)) % FRIEND_MAX_STORED_TCP_RELAYS;
200 258
201 if (friend_con->tcp_relays[index].ip_port.ip.family) { 259 if (!net_family_is_unspec(friend_con->tcp_relays[index].ip_port.ip.family)) {
202 if (add_tcp_relay_peer(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->tcp_relays[index].ip_port, 260 if (add_tcp_relay_peer(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->tcp_relays[index].ip_port,
203 friend_con->tcp_relays[index].public_key) == 0) { 261 friend_con->tcp_relays[index].public_key) == 0) {
204 --number; 262 --number;
@@ -209,29 +267,28 @@ static void connect_to_saved_tcp_relays(Friend_Connections *fr_c, int friendcon_
209 267
210static unsigned int send_relays(Friend_Connections *fr_c, int friendcon_id) 268static unsigned int send_relays(Friend_Connections *fr_c, int friendcon_id)
211{ 269{
212 Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); 270 Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id);
213 271
214 if (!friend_con) 272 if (!friend_con) {
215 return 0; 273 return 0;
274 }
216 275
217 Node_format nodes[MAX_SHARED_RELAYS]; 276 Node_format nodes[MAX_SHARED_RELAYS];
218 uint8_t data[1024]; 277 uint8_t data[1024];
219 int n, length;
220
221 n = copy_connected_tcp_relays(fr_c->net_crypto, nodes, MAX_SHARED_RELAYS);
222 278
223 int i; 279 const int n = copy_connected_tcp_relays(fr_c->net_crypto, nodes, MAX_SHARED_RELAYS);
224 280
225 for (i = 0; i < n; ++i) { 281 for (int i = 0; i < n; ++i) {
226 /* Associated the relays being sent with this connection. 282 /* Associated the relays being sent with this connection.
227 On receiving the peer will do the same which will establish the connection. */ 283 On receiving the peer will do the same which will establish the connection. */
228 friend_add_tcp_relay(fr_c, friendcon_id, nodes[i].ip_port, nodes[i].public_key); 284 friend_add_tcp_relay(fr_c, friendcon_id, nodes[i].ip_port, nodes[i].public_key);
229 } 285 }
230 286
231 length = pack_nodes(data + 1, sizeof(data) - 1, nodes, n); 287 int length = pack_nodes(data + 1, sizeof(data) - 1, nodes, n);
232 288
233 if (length <= 0) 289 if (length <= 0) {
234 return 0; 290 return 0;
291 }
235 292
236 data[0] = PACKET_ID_SHARE_RELAYS; 293 data[0] = PACKET_ID_SHARE_RELAYS;
237 ++length; 294 ++length;
@@ -247,28 +304,30 @@ static unsigned int send_relays(Friend_Connections *fr_c, int friendcon_id)
247/* callback for recv TCP relay nodes. */ 304/* callback for recv TCP relay nodes. */
248static int tcp_relay_node_callback(void *object, uint32_t number, IP_Port ip_port, const uint8_t *public_key) 305static int tcp_relay_node_callback(void *object, uint32_t number, IP_Port ip_port, const uint8_t *public_key)
249{ 306{
250 Friend_Connections *fr_c = object; 307 Friend_Connections *fr_c = (Friend_Connections *)object;
251 Friend_Conn *friend_con = get_conn(fr_c, number); 308 const Friend_Conn *friend_con = get_conn(fr_c, number);
252 309
253 if (!friend_con) 310 if (!friend_con) {
254 return -1; 311 return -1;
312 }
255 313
256 if (friend_con->crypt_connection_id != -1) { 314 if (friend_con->crypt_connection_id != -1) {
257 return friend_add_tcp_relay(fr_c, number, ip_port, public_key); 315 return friend_add_tcp_relay(fr_c, number, ip_port, public_key);
258 } else {
259 return add_tcp_relay(fr_c->net_crypto, ip_port, public_key);
260 } 316 }
317
318 return add_tcp_relay(fr_c->net_crypto, ip_port, public_key);
261} 319}
262 320
263static int friend_new_connection(Friend_Connections *fr_c, int friendcon_id); 321static int friend_new_connection(Friend_Connections *fr_c, int friendcon_id);
264/* Callback for DHT ip_port changes. */ 322/* Callback for DHT ip_port changes. */
265static void dht_ip_callback(void *object, int32_t number, IP_Port ip_port) 323static void dht_ip_callback(void *object, int32_t number, IP_Port ip_port)
266{ 324{
267 Friend_Connections *fr_c = object; 325 Friend_Connections *const fr_c = (Friend_Connections *)object;
268 Friend_Conn *friend_con = get_conn(fr_c, number); 326 Friend_Conn *const friend_con = get_conn(fr_c, number);
269 327
270 if (!friend_con) 328 if (!friend_con) {
271 return; 329 return;
330 }
272 331
273 if (friend_con->crypt_connection_id == -1) { 332 if (friend_con->crypt_connection_id == -1) {
274 friend_new_connection(fr_c, number); 333 friend_new_connection(fr_c, number);
@@ -286,10 +345,11 @@ static void dht_ip_callback(void *object, int32_t number, IP_Port ip_port)
286 345
287static void change_dht_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_public_key) 346static void change_dht_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_public_key)
288{ 347{
289 Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); 348 Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id);
290 349
291 if (!friend_con) 350 if (!friend_con) {
292 return; 351 return;
352 }
293 353
294 friend_con->dht_pk_lastrecv = unix_time(); 354 friend_con->dht_pk_lastrecv = unix_time();
295 355
@@ -303,18 +363,19 @@ static void change_dht_pk(Friend_Connections *fr_c, int friendcon_id, const uint
303 } 363 }
304 364
305 DHT_addfriend(fr_c->dht, dht_public_key, dht_ip_callback, fr_c, friendcon_id, &friend_con->dht_lock); 365 DHT_addfriend(fr_c->dht, dht_public_key, dht_ip_callback, fr_c, friendcon_id, &friend_con->dht_lock);
306 memcpy(friend_con->dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES); 366 memcpy(friend_con->dht_temp_pk, dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);
307} 367}
308 368
309static int handle_status(void *object, int number, uint8_t status) 369static int handle_status(void *object, int number, uint8_t status, void *userdata)
310{ 370{
311 Friend_Connections *fr_c = object; 371 Friend_Connections *const fr_c = (Friend_Connections *)object;
312 Friend_Conn *friend_con = get_conn(fr_c, number); 372 Friend_Conn *const friend_con = get_conn(fr_c, number);
313 373
314 if (!friend_con) 374 if (!friend_con) {
315 return -1; 375 return -1;
376 }
316 377
317 _Bool call_cb = 0; 378 bool call_cb = 0;
318 379
319 if (status) { /* Went online. */ 380 if (status) { /* Went online. */
320 call_cb = 1; 381 call_cb = 1;
@@ -338,9 +399,11 @@ static int handle_status(void *object, int number, uint8_t status)
338 unsigned int i; 399 unsigned int i;
339 400
340 for (i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) { 401 for (i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) {
341 if (friend_con->callbacks[i].status_callback) 402 if (friend_con->callbacks[i].status_callback) {
342 friend_con->callbacks[i].status_callback(friend_con->callbacks[i].status_callback_object, 403 friend_con->callbacks[i].status_callback(
343 friend_con->callbacks[i].status_callback_id, status); 404 friend_con->callbacks[i].callback_object,
405 friend_con->callbacks[i].callback_id, status, userdata);
406 }
344 } 407 }
345 } 408 }
346 409
@@ -348,16 +411,18 @@ static int handle_status(void *object, int number, uint8_t status)
348} 411}
349 412
350/* Callback for dht public key changes. */ 413/* Callback for dht public key changes. */
351static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_public_key) 414static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_public_key, void *userdata)
352{ 415{
353 Friend_Connections *fr_c = object; 416 Friend_Connections *const fr_c = (Friend_Connections *)object;
354 Friend_Conn *friend_con = get_conn(fr_c, number); 417 Friend_Conn *const friend_con = get_conn(fr_c, number);
355 418
356 if (!friend_con) 419 if (!friend_con) {
357 return; 420 return;
421 }
358 422
359 if (public_key_cmp(friend_con->dht_temp_pk, dht_public_key) == 0) 423 if (public_key_cmp(friend_con->dht_temp_pk, dht_public_key) == 0) {
360 return; 424 return;
425 }
361 426
362 change_dht_pk(fr_c, number, dht_public_key); 427 change_dht_pk(fr_c, number, dht_public_key);
363 428
@@ -365,86 +430,96 @@ static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_pub
365 if (friend_con->crypt_connection_id != -1) { 430 if (friend_con->crypt_connection_id != -1) {
366 crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id); 431 crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);
367 friend_con->crypt_connection_id = -1; 432 friend_con->crypt_connection_id = -1;
368 handle_status(object, number, 0); /* Going offline. */ 433 handle_status(object, number, 0, userdata); /* Going offline. */
369 } 434 }
370 435
371 friend_new_connection(fr_c, number); 436 friend_new_connection(fr_c, number);
372 onion_set_friend_DHT_pubkey(fr_c->onion_c, friend_con->onion_friendnum, dht_public_key); 437 onion_set_friend_DHT_pubkey(fr_c->onion_c, friend_con->onion_friendnum, dht_public_key);
373} 438}
374 439
375static int handle_packet(void *object, int number, uint8_t *data, uint16_t length) 440static int handle_packet(void *object, int number, const uint8_t *data, uint16_t length, void *userdata)
376{ 441{
377 if (length == 0) 442 if (length == 0) {
378 return -1; 443 return -1;
444 }
379 445
380 Friend_Connections *fr_c = object; 446 Friend_Connections *const fr_c = (Friend_Connections *)object;
381 Friend_Conn *friend_con = get_conn(fr_c, number); 447 Friend_Conn *friend_con = get_conn(fr_c, number);
382 448
383 if (!friend_con) 449 if (!friend_con) {
384 return -1; 450 return -1;
451 }
385 452
386 if (data[0] == PACKET_ID_FRIEND_REQUESTS) { 453 if (data[0] == PACKET_ID_FRIEND_REQUESTS) {
387 if (fr_c->fr_request_callback) 454 if (fr_c->fr_request_callback) {
388 fr_c->fr_request_callback(fr_c->fr_request_object, friend_con->real_public_key, data, length); 455 fr_c->fr_request_callback(fr_c->fr_request_object, friend_con->real_public_key, data, length, userdata);
456 }
389 457
390 return 0; 458 return 0;
391 } else if (data[0] == PACKET_ID_ALIVE) { 459 }
460
461 if (data[0] == PACKET_ID_ALIVE) {
392 friend_con->ping_lastrecv = unix_time(); 462 friend_con->ping_lastrecv = unix_time();
393 return 0; 463 return 0;
394 } else if (data[0] == PACKET_ID_SHARE_RELAYS) { 464 }
465
466 if (data[0] == PACKET_ID_SHARE_RELAYS) {
395 Node_format nodes[MAX_SHARED_RELAYS]; 467 Node_format nodes[MAX_SHARED_RELAYS];
396 int n; 468 const int n = unpack_nodes(nodes, MAX_SHARED_RELAYS, nullptr, data + 1, length - 1, 1);
397 469
398 if ((n = unpack_nodes(nodes, MAX_SHARED_RELAYS, NULL, data + 1, length - 1, 1)) == -1) 470 if (n == -1) {
399 return -1; 471 return -1;
472 }
400 473
401 int j; 474 for (int j = 0; j < n; j++) {
402
403 for (j = 0; j < n; j++) {
404 friend_add_tcp_relay(fr_c, number, nodes[j].ip_port, nodes[j].public_key); 475 friend_add_tcp_relay(fr_c, number, nodes[j].ip_port, nodes[j].public_key);
405 } 476 }
406 477
407 return 0; 478 return 0;
408 } 479 }
409 480
410 unsigned int i; 481 for (unsigned i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) {
411 482 if (friend_con->callbacks[i].data_callback) {
412 for (i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) { 483 friend_con->callbacks[i].data_callback(
413 if (friend_con->callbacks[i].data_callback) 484 friend_con->callbacks[i].callback_object,
414 friend_con->callbacks[i].data_callback(friend_con->callbacks[i].data_callback_object, 485 friend_con->callbacks[i].callback_id, data, length, userdata);
415 friend_con->callbacks[i].data_callback_id, data, length); 486 }
416 487
417 friend_con = get_conn(fr_c, number); 488 friend_con = get_conn(fr_c, number);
418 489
419 if (!friend_con) 490 if (!friend_con) {
420 return -1; 491 return -1;
492 }
421 } 493 }
422 494
423 return 0; 495 return 0;
424} 496}
425 497
426static int handle_lossy_packet(void *object, int number, const uint8_t *data, uint16_t length) 498static int handle_lossy_packet(void *object, int number, const uint8_t *data, uint16_t length, void *userdata)
427{ 499{
428 if (length == 0) 500 if (length == 0) {
429 return -1; 501 return -1;
502 }
430 503
431 Friend_Connections *fr_c = object; 504 Friend_Connections *const fr_c = (Friend_Connections *)object;
432 Friend_Conn *friend_con = get_conn(fr_c, number); 505 const Friend_Conn *friend_con = get_conn(fr_c, number);
433 506
434 if (!friend_con) 507 if (!friend_con) {
435 return -1; 508 return -1;
509 }
436 510
437 unsigned int i; 511 for (unsigned i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) {
438 512 if (friend_con->callbacks[i].lossy_data_callback) {
439 for (i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) { 513 friend_con->callbacks[i].lossy_data_callback(
440 if (friend_con->callbacks[i].lossy_data_callback) 514 friend_con->callbacks[i].callback_object,
441 friend_con->callbacks[i].lossy_data_callback(friend_con->callbacks[i].lossy_data_callback_object, 515 friend_con->callbacks[i].callback_id, data, length, userdata);
442 friend_con->callbacks[i].lossy_data_callback_id, data, length); 516 }
443 517
444 friend_con = get_conn(fr_c, number); 518 friend_con = get_conn(fr_c, number);
445 519
446 if (!friend_con) 520 if (!friend_con) {
447 return -1; 521 return -1;
522 }
448 } 523 }
449 524
450 return 0; 525 return 0;
@@ -452,50 +527,51 @@ static int handle_lossy_packet(void *object, int number, const uint8_t *data, ui
452 527
453static int handle_new_connections(void *object, New_Connection *n_c) 528static int handle_new_connections(void *object, New_Connection *n_c)
454{ 529{
455 Friend_Connections *fr_c = object; 530 Friend_Connections *const fr_c = (Friend_Connections *)object;
456 int friendcon_id = getfriend_conn_id_pk(fr_c, n_c->public_key); 531 const int friendcon_id = getfriend_conn_id_pk(fr_c, n_c->public_key);
457 Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); 532 Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id);
458 533
459 if (friend_con) { 534 if (!friend_con) {
460 535 return -1;
461 if (friend_con->crypt_connection_id != -1) 536 }
462 return -1;
463 537
464 int id = accept_crypto_connection(fr_c->net_crypto, n_c); 538 if (friend_con->crypt_connection_id != -1) {
539 return -1;
540 }
465 541
466 if (id == -1) { 542 const int id = accept_crypto_connection(fr_c->net_crypto, n_c);
467 return -1;
468 }
469 543
470 connection_status_handler(fr_c->net_crypto, id, &handle_status, fr_c, friendcon_id); 544 if (id == -1) {
471 connection_data_handler(fr_c->net_crypto, id, &handle_packet, fr_c, friendcon_id); 545 return -1;
472 connection_lossy_data_handler(fr_c->net_crypto, id, &handle_lossy_packet, fr_c, friendcon_id); 546 }
473 friend_con->crypt_connection_id = id;
474 547
475 if (n_c->source.ip.family != AF_INET && n_c->source.ip.family != AF_INET6) { 548 connection_status_handler(fr_c->net_crypto, id, &handle_status, fr_c, friendcon_id);
476 set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0); 549 connection_data_handler(fr_c->net_crypto, id, &handle_packet, fr_c, friendcon_id);
477 } else { 550 connection_lossy_data_handler(fr_c->net_crypto, id, &handle_lossy_packet, fr_c, friendcon_id);
478 friend_con->dht_ip_port = n_c->source; 551 friend_con->crypt_connection_id = id;
479 friend_con->dht_ip_port_lastrecv = unix_time();
480 }
481 552
482 if (public_key_cmp(friend_con->dht_temp_pk, n_c->dht_public_key) != 0) { 553 if (!net_family_is_ipv4(n_c->source.ip.family) && !net_family_is_ipv6(n_c->source.ip.family)) {
483 change_dht_pk(fr_c, friendcon_id, n_c->dht_public_key); 554 set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0);
484 } 555 } else {
556 friend_con->dht_ip_port = n_c->source;
557 friend_con->dht_ip_port_lastrecv = unix_time();
558 }
485 559
486 nc_dht_pk_callback(fr_c->net_crypto, id, &dht_pk_callback, fr_c, friendcon_id); 560 if (public_key_cmp(friend_con->dht_temp_pk, n_c->dht_public_key) != 0) {
487 return 0; 561 change_dht_pk(fr_c, friendcon_id, n_c->dht_public_key);
488 } 562 }
489 563
490 return -1; 564 nc_dht_pk_callback(fr_c->net_crypto, id, &dht_pk_callback, fr_c, friendcon_id);
565 return 0;
491} 566}
492 567
493static int friend_new_connection(Friend_Connections *fr_c, int friendcon_id) 568static int friend_new_connection(Friend_Connections *fr_c, int friendcon_id)
494{ 569{
495 Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); 570 Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id);
496 571
497 if (!friend_con) 572 if (!friend_con) {
498 return -1; 573 return -1;
574 }
499 575
500 if (friend_con->crypt_connection_id != -1) { 576 if (friend_con->crypt_connection_id != -1) {
501 return -1; 577 return -1;
@@ -506,10 +582,11 @@ static int friend_new_connection(Friend_Connections *fr_c, int friendcon_id)
506 return -1; 582 return -1;
507 } 583 }
508 584
509 int id = new_crypto_connection(fr_c->net_crypto, friend_con->real_public_key, friend_con->dht_temp_pk); 585 const int id = new_crypto_connection(fr_c->net_crypto, friend_con->real_public_key, friend_con->dht_temp_pk);
510 586
511 if (id == -1) 587 if (id == -1) {
512 return -1; 588 return -1;
589 }
513 590
514 friend_con->crypt_connection_id = id; 591 friend_con->crypt_connection_id = id;
515 connection_status_handler(fr_c->net_crypto, id, &handle_status, fr_c, friendcon_id); 592 connection_status_handler(fr_c->net_crypto, id, &handle_status, fr_c, friendcon_id);
@@ -522,13 +599,14 @@ static int friend_new_connection(Friend_Connections *fr_c, int friendcon_id)
522 599
523static int send_ping(const Friend_Connections *fr_c, int friendcon_id) 600static int send_ping(const Friend_Connections *fr_c, int friendcon_id)
524{ 601{
525 Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); 602 Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id);
526 603
527 if (!friend_con) 604 if (!friend_con) {
528 return -1; 605 return -1;
606 }
529 607
530 uint8_t ping = PACKET_ID_ALIVE; 608 const uint8_t ping = PACKET_ID_ALIVE;
531 int64_t ret = write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, &ping, sizeof(ping), 0); 609 const int64_t ret = write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, &ping, sizeof(ping), 0);
532 610
533 if (ret != -1) { 611 if (ret != -1) {
534 friend_con->ping_lastsent = unix_time(); 612 friend_con->ping_lastsent = unix_time();
@@ -545,10 +623,11 @@ static int send_ping(const Friend_Connections *fr_c, int friendcon_id)
545 */ 623 */
546int friend_connection_lock(Friend_Connections *fr_c, int friendcon_id) 624int friend_connection_lock(Friend_Connections *fr_c, int friendcon_id)
547{ 625{
548 Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); 626 Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id);
549 627
550 if (!friend_con) 628 if (!friend_con) {
551 return -1; 629 return -1;
630 }
552 631
553 ++friend_con->lock_count; 632 ++friend_con->lock_count;
554 return 0; 633 return 0;
@@ -560,10 +639,11 @@ int friend_connection_lock(Friend_Connections *fr_c, int friendcon_id)
560 */ 639 */
561unsigned int friend_con_connected(Friend_Connections *fr_c, int friendcon_id) 640unsigned int friend_con_connected(Friend_Connections *fr_c, int friendcon_id)
562{ 641{
563 Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); 642 const Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id);
564 643
565 if (!friend_con) 644 if (!friend_con) {
566 return 0; 645 return 0;
646 }
567 647
568 return friend_con->status; 648 return friend_con->status;
569} 649}
@@ -575,25 +655,28 @@ unsigned int friend_con_connected(Friend_Connections *fr_c, int friendcon_id)
575 */ 655 */
576int get_friendcon_public_keys(uint8_t *real_pk, uint8_t *dht_temp_pk, Friend_Connections *fr_c, int friendcon_id) 656int get_friendcon_public_keys(uint8_t *real_pk, uint8_t *dht_temp_pk, Friend_Connections *fr_c, int friendcon_id)
577{ 657{
578 Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); 658 const Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id);
579 659
580 if (!friend_con) 660 if (!friend_con) {
581 return -1; 661 return -1;
662 }
582 663
583 if (real_pk) 664 if (real_pk) {
584 memcpy(real_pk, friend_con->real_public_key, crypto_box_PUBLICKEYBYTES); 665 memcpy(real_pk, friend_con->real_public_key, CRYPTO_PUBLIC_KEY_SIZE);
666 }
585 667
586 if (dht_temp_pk) 668 if (dht_temp_pk) {
587 memcpy(dht_temp_pk, friend_con->dht_temp_pk, crypto_box_PUBLICKEYBYTES); 669 memcpy(dht_temp_pk, friend_con->dht_temp_pk, CRYPTO_PUBLIC_KEY_SIZE);
670 }
588 671
589 return 0; 672 return 0;
590} 673}
591 674
592/* Set temp dht key for connection. 675/* Set temp dht key for connection.
593 */ 676 */
594void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_temp_pk) 677void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_temp_pk, void *userdata)
595{ 678{
596 dht_pk_callback(fr_c, friendcon_id, dht_temp_pk); 679 dht_pk_callback(fr_c, friendcon_id, dht_temp_pk, userdata);
597} 680}
598 681
599/* Set the callbacks for the friend connection. 682/* Set the callbacks for the friend connection.
@@ -603,29 +686,28 @@ void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *
603 * return -1 on failure 686 * return -1 on failure
604 */ 687 */
605int friend_connection_callbacks(Friend_Connections *fr_c, int friendcon_id, unsigned int index, 688int friend_connection_callbacks(Friend_Connections *fr_c, int friendcon_id, unsigned int index,
606 int (*status_callback)(void *object, int id, uint8_t status), int (*data_callback)(void *object, int id, uint8_t *data, 689 int (*status_callback)(void *object, int id, uint8_t status, void *userdata),
607 uint16_t length), int (*lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length), void *object, 690 int (*data_callback)(void *object, int id, const uint8_t *data, uint16_t len, void *userdata),
608 int number) 691 int (*lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata),
692 void *object, int number)
609{ 693{
610 Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); 694 Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id);
611 695
612 if (!friend_con) 696 if (!friend_con) {
613 return -1; 697 return -1;
698 }
614 699
615 if (index >= MAX_FRIEND_CONNECTION_CALLBACKS) 700 if (index >= MAX_FRIEND_CONNECTION_CALLBACKS) {
616 return -1; 701 return -1;
702 }
617 703
618 friend_con->callbacks[index].status_callback = status_callback; 704 friend_con->callbacks[index].status_callback = status_callback;
619 friend_con->callbacks[index].data_callback = data_callback; 705 friend_con->callbacks[index].data_callback = data_callback;
620 friend_con->callbacks[index].lossy_data_callback = lossy_data_callback; 706 friend_con->callbacks[index].lossy_data_callback = lossy_data_callback;
621 707
622 friend_con->callbacks[index].status_callback_object = 708 friend_con->callbacks[index].callback_object = object;
623 friend_con->callbacks[index].data_callback_object = 709 friend_con->callbacks[index].callback_id = number;
624 friend_con->callbacks[index].lossy_data_callback_object = object;
625 710
626 friend_con->callbacks[index].status_callback_id =
627 friend_con->callbacks[index].data_callback_id =
628 friend_con->callbacks[index].lossy_data_callback_id = number;
629 return 0; 711 return 0;
630} 712}
631 713
@@ -636,10 +718,11 @@ int friend_connection_callbacks(Friend_Connections *fr_c, int friendcon_id, unsi
636 */ 718 */
637int friend_connection_crypt_connection_id(Friend_Connections *fr_c, int friendcon_id) 719int friend_connection_crypt_connection_id(Friend_Connections *fr_c, int friendcon_id)
638{ 720{
639 Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); 721 const Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id);
640 722
641 if (!friend_con) 723 if (!friend_con) {
642 return -1; 724 return -1;
725 }
643 726
644 return friend_con->crypt_connection_id; 727 return friend_con->crypt_connection_id;
645} 728}
@@ -661,19 +744,21 @@ int new_friend_connection(Friend_Connections *fr_c, const uint8_t *real_public_k
661 744
662 friendcon_id = create_friend_conn(fr_c); 745 friendcon_id = create_friend_conn(fr_c);
663 746
664 if (friendcon_id == -1) 747 if (friendcon_id == -1) {
665 return -1; 748 return -1;
749 }
666 750
667 int32_t onion_friendnum = onion_addfriend(fr_c->onion_c, real_public_key); 751 const int32_t onion_friendnum = onion_addfriend(fr_c->onion_c, real_public_key);
668 752
669 if (onion_friendnum == -1) 753 if (onion_friendnum == -1) {
670 return -1; 754 return -1;
755 }
671 756
672 Friend_Conn *friend_con = &fr_c->conns[friendcon_id]; 757 Friend_Conn *const friend_con = &fr_c->conns[friendcon_id];
673 758
674 friend_con->crypt_connection_id = -1; 759 friend_con->crypt_connection_id = -1;
675 friend_con->status = FRIENDCONN_STATUS_CONNECTING; 760 friend_con->status = FRIENDCONN_STATUS_CONNECTING;
676 memcpy(friend_con->real_public_key, real_public_key, crypto_box_PUBLICKEYBYTES); 761 memcpy(friend_con->real_public_key, real_public_key, CRYPTO_PUBLIC_KEY_SIZE);
677 friend_con->onion_friendnum = onion_friendnum; 762 friend_con->onion_friendnum = onion_friendnum;
678 763
679 recv_tcp_relay_handler(fr_c->onion_c, onion_friendnum, &tcp_relay_node_callback, fr_c, friendcon_id); 764 recv_tcp_relay_handler(fr_c->onion_c, onion_friendnum, &tcp_relay_node_callback, fr_c, friendcon_id);
@@ -689,10 +774,11 @@ int new_friend_connection(Friend_Connections *fr_c, const uint8_t *real_public_k
689 */ 774 */
690int kill_friend_connection(Friend_Connections *fr_c, int friendcon_id) 775int kill_friend_connection(Friend_Connections *fr_c, int friendcon_id)
691{ 776{
692 Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); 777 Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id);
693 778
694 if (!friend_con) 779 if (!friend_con) {
695 return -1; 780 return -1;
781 }
696 782
697 if (friend_con->lock_count) { 783 if (friend_con->lock_count) {
698 --friend_con->lock_count; 784 --friend_con->lock_count;
@@ -715,7 +801,7 @@ int kill_friend_connection(Friend_Connections *fr_c, int friendcon_id)
715 * This function will be called every time a friend request packet is received. 801 * This function will be called every time a friend request packet is received.
716 */ 802 */
717void set_friend_request_callback(Friend_Connections *fr_c, int (*fr_request_callback)(void *, const uint8_t *, 803void set_friend_request_callback(Friend_Connections *fr_c, int (*fr_request_callback)(void *, const uint8_t *,
718 const uint8_t *, uint16_t), void *object) 804 const uint8_t *, uint16_t, void *), void *object)
719{ 805{
720 fr_c->fr_request_callback = fr_request_callback; 806 fr_c->fr_request_callback = fr_request_callback;
721 fr_c->fr_request_object = object; 807 fr_c->fr_request_object = object;
@@ -731,49 +817,60 @@ void set_friend_request_callback(Friend_Connections *fr_c, int (*fr_request_call
731int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint32_t nospam_num, const uint8_t *data, 817int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint32_t nospam_num, const uint8_t *data,
732 uint16_t length) 818 uint16_t length)
733{ 819{
734 if (1 + sizeof(nospam_num) + length > ONION_CLIENT_MAX_DATA_SIZE || length == 0) 820 if (1 + sizeof(nospam_num) + length > ONION_CLIENT_MAX_DATA_SIZE || length == 0) {
735 return -1; 821 return -1;
822 }
736 823
737 Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); 824 const Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id);
738 825
739 if (!friend_con) 826 if (!friend_con) {
740 return -1; 827 return -1;
828 }
741 829
742 uint8_t packet[1 + sizeof(nospam_num) + length]; 830 VLA(uint8_t, packet, 1 + sizeof(nospam_num) + length);
743 memcpy(packet + 1, &nospam_num, sizeof(nospam_num)); 831 memcpy(packet + 1, &nospam_num, sizeof(nospam_num));
744 memcpy(packet + 1 + sizeof(nospam_num), data, length); 832 memcpy(packet + 1 + sizeof(nospam_num), data, length);
745 833
746 if (friend_con->status == FRIENDCONN_STATUS_CONNECTED) { 834 if (friend_con->status == FRIENDCONN_STATUS_CONNECTED) {
747 packet[0] = PACKET_ID_FRIEND_REQUESTS; 835 packet[0] = PACKET_ID_FRIEND_REQUESTS;
748 return write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, packet, sizeof(packet), 0) != -1; 836 return write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, packet, SIZEOF_VLA(packet), 0) != -1;
749 } else { 837 }
750 packet[0] = CRYPTO_PACKET_FRIEND_REQ;
751 int num = send_onion_data(fr_c->onion_c, friend_con->onion_friendnum, packet, sizeof(packet));
752 838
753 if (num <= 0) 839 packet[0] = CRYPTO_PACKET_FRIEND_REQ;
754 return -1; 840 const int num = send_onion_data(fr_c->onion_c, friend_con->onion_friendnum, packet, SIZEOF_VLA(packet));
755 841
756 return num; 842 if (num <= 0) {
843 return -1;
757 } 844 }
845
846 return num;
758} 847}
759 848
760/* Create new friend_connections instance. */ 849/* Create new friend_connections instance. */
761Friend_Connections *new_friend_connections(Onion_Client *onion_c) 850Friend_Connections *new_friend_connections(Onion_Client *onion_c, bool local_discovery_enabled)
762{ 851{
763 if (!onion_c) 852 if (onion_c == nullptr) {
764 return NULL; 853 return nullptr;
854 }
765 855
766 Friend_Connections *temp = calloc(1, sizeof(Friend_Connections)); 856 Friend_Connections *const temp = (Friend_Connections *)calloc(1, sizeof(Friend_Connections));
767 857
768 if (temp == NULL) 858 if (temp == nullptr) {
769 return NULL; 859 return nullptr;
860 }
770 861
771 temp->dht = onion_c->dht; 862 temp->dht = onion_get_dht(onion_c);
772 temp->net_crypto = onion_c->c; 863 temp->net_crypto = onion_get_net_crypto(onion_c);
773 temp->onion_c = onion_c; 864 temp->onion_c = onion_c;
865 temp->local_discovery_enabled = local_discovery_enabled;
866 // Don't include default port in port range
867 temp->next_LANport = TOX_PORTRANGE_FROM + 1;
774 868
775 new_connection_handler(temp->net_crypto, &handle_new_connections, temp); 869 new_connection_handler(temp->net_crypto, &handle_new_connections, temp);
776 LANdiscovery_init(temp->dht); 870
871 if (temp->local_discovery_enabled) {
872 lan_discovery_init(temp->dht);
873 }
777 874
778 return temp; 875 return temp;
779} 876}
@@ -782,19 +879,31 @@ Friend_Connections *new_friend_connections(Onion_Client *onion_c)
782static void LANdiscovery(Friend_Connections *fr_c) 879static void LANdiscovery(Friend_Connections *fr_c)
783{ 880{
784 if (fr_c->last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time()) { 881 if (fr_c->last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time()) {
785 send_LANdiscovery(htons(TOX_PORT_DEFAULT), fr_c->dht); 882 const uint16_t first = fr_c->next_LANport;
883 uint16_t last = first + PORTS_PER_DISCOVERY;
884 last = last > TOX_PORTRANGE_TO ? TOX_PORTRANGE_TO : last;
885
886 // Always send to default port
887 lan_discovery_send(net_htons(TOX_PORT_DEFAULT), fr_c->dht);
888
889 // And check some extra ports
890 for (uint16_t port = first; port < last; port++) {
891 lan_discovery_send(net_htons(port), fr_c->dht);
892 }
893
894 // Don't include default port in port range
895 fr_c->next_LANport = last != TOX_PORTRANGE_TO ? last : TOX_PORTRANGE_FROM + 1;
786 fr_c->last_LANdiscovery = unix_time(); 896 fr_c->last_LANdiscovery = unix_time();
787 } 897 }
788} 898}
789 899
790/* main friend_connections loop. */ 900/* main friend_connections loop. */
791void do_friend_connections(Friend_Connections *fr_c) 901void do_friend_connections(Friend_Connections *fr_c, void *userdata)
792{ 902{
793 uint32_t i; 903 const uint64_t temp_time = unix_time();
794 uint64_t temp_time = unix_time();
795 904
796 for (i = 0; i < fr_c->num_cons; ++i) { 905 for (uint32_t i = 0; i < fr_c->num_cons; ++i) {
797 Friend_Conn *friend_con = get_conn(fr_c, i); 906 Friend_Conn *const friend_con = get_conn(fr_c, i);
798 907
799 if (friend_con) { 908 if (friend_con) {
800 if (friend_con->status == FRIENDCONN_STATUS_CONNECTING) { 909 if (friend_con->status == FRIENDCONN_STATUS_CONNECTING) {
@@ -802,11 +911,12 @@ void do_friend_connections(Friend_Connections *fr_c)
802 if (friend_con->dht_lock) { 911 if (friend_con->dht_lock) {
803 DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock); 912 DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock);
804 friend_con->dht_lock = 0; 913 friend_con->dht_lock = 0;
914 memset(friend_con->dht_temp_pk, 0, CRYPTO_PUBLIC_KEY_SIZE);
805 } 915 }
806 } 916 }
807 917
808 if (friend_con->dht_ip_port_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) { 918 if (friend_con->dht_ip_port_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
809 friend_con->dht_ip_port.ip.family = 0; 919 friend_con->dht_ip_port.ip.family = net_family_unspec;
810 } 920 }
811 921
812 if (friend_con->dht_lock) { 922 if (friend_con->dht_lock) {
@@ -815,7 +925,6 @@ void do_friend_connections(Friend_Connections *fr_c)
815 connect_to_saved_tcp_relays(fr_c, i, (MAX_FRIEND_TCP_CONNECTIONS / 2)); /* Only fill it half up. */ 925 connect_to_saved_tcp_relays(fr_c, i, (MAX_FRIEND_TCP_CONNECTIONS / 2)); /* Only fill it half up. */
816 } 926 }
817 } 927 }
818
819 } else if (friend_con->status == FRIENDCONN_STATUS_CONNECTED) { 928 } else if (friend_con->status == FRIENDCONN_STATUS_CONNECTED) {
820 if (friend_con->ping_lastsent + FRIEND_PING_INTERVAL < temp_time) { 929 if (friend_con->ping_lastsent + FRIEND_PING_INTERVAL < temp_time) {
821 send_ping(fr_c, i); 930 send_ping(fr_c, i);
@@ -829,27 +938,31 @@ void do_friend_connections(Friend_Connections *fr_c)
829 /* If we stopped receiving ping packets, kill it. */ 938 /* If we stopped receiving ping packets, kill it. */
830 crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id); 939 crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);
831 friend_con->crypt_connection_id = -1; 940 friend_con->crypt_connection_id = -1;
832 handle_status(fr_c, i, 0); /* Going offline. */ 941 handle_status(fr_c, i, 0, userdata); /* Going offline. */
833 } 942 }
834 } 943 }
835 } 944 }
836 } 945 }
837 946
838 LANdiscovery(fr_c); 947 if (fr_c->local_discovery_enabled) {
948 LANdiscovery(fr_c);
949 }
839} 950}
840 951
841/* Free everything related with friend_connections. */ 952/* Free everything related with friend_connections. */
842void kill_friend_connections(Friend_Connections *fr_c) 953void kill_friend_connections(Friend_Connections *fr_c)
843{ 954{
844 if (!fr_c) 955 if (!fr_c) {
845 return; 956 return;
957 }
846 958
847 uint32_t i; 959 for (uint32_t i = 0; i < fr_c->num_cons; ++i) {
848
849 for (i = 0; i < fr_c->num_cons; ++i) {
850 kill_friend_connection(fr_c, i); 960 kill_friend_connection(fr_c, i);
851 } 961 }
852 962
853 LANdiscovery_kill(fr_c->dht); 963 if (fr_c->local_discovery_enabled) {
964 lan_discovery_kill(fr_c->dht);
965 }
966
854 free(fr_c); 967 free(fr_c);
855} 968}
diff --git a/toxcore/friend_connection.h b/toxcore/friend_connection.h
index 044b8d7f..f4d53c7a 100644
--- a/toxcore/friend_connection.h
+++ b/toxcore/friend_connection.h
@@ -1,36 +1,34 @@
1/* friend_connection.h 1/*
2 *
3 * Connection to friends. 2 * Connection to friends.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2014 Tox project.
4 * 8 *
5 * Copyright (C) 2014 Tox project All Rights Reserved. 9 * This file is part of Tox, the free peer to peer instant messenger.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23
24
25#ifndef FRIEND_CONNECTION_H 24#ifndef FRIEND_CONNECTION_H
26#define FRIEND_CONNECTION_H 25#define FRIEND_CONNECTION_H
27 26
28#include "net_crypto.h"
29#include "DHT.h" 27#include "DHT.h"
30#include "LAN_discovery.h" 28#include "LAN_discovery.h"
29#include "net_crypto.h"
31#include "onion_client.h" 30#include "onion_client.h"
32 31
33
34#define MAX_FRIEND_CONNECTION_CALLBACKS 2 32#define MAX_FRIEND_CONNECTION_CALLBACKS 2
35#define MESSENGER_CALLBACK_INDEX 0 33#define MESSENGER_CALLBACK_INDEX 0
36#define GROUPCHAT_CALLBACK_INDEX 1 34#define GROUPCHAT_CALLBACK_INDEX 1
@@ -63,57 +61,9 @@ enum {
63 FRIENDCONN_STATUS_CONNECTED 61 FRIENDCONN_STATUS_CONNECTED
64}; 62};
65 63
66typedef struct { 64typedef struct Friend_Connections Friend_Connections;
67 uint8_t status;
68
69 uint8_t real_public_key[crypto_box_PUBLICKEYBYTES];
70 uint8_t dht_temp_pk[crypto_box_PUBLICKEYBYTES];
71 uint16_t dht_lock;
72 IP_Port dht_ip_port;
73 uint64_t dht_pk_lastrecv, dht_ip_port_lastrecv;
74
75 int onion_friendnum;
76 int crypt_connection_id;
77
78 uint64_t ping_lastrecv, ping_lastsent;
79 uint64_t share_relays_lastsent;
80
81 struct {
82 int (*status_callback)(void *object, int id, uint8_t status);
83 void *status_callback_object;
84 int status_callback_id;
85
86 int (*data_callback)(void *object, int id, uint8_t *data, uint16_t length);
87 void *data_callback_object;
88 int data_callback_id;
89
90 int (*lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length);
91 void *lossy_data_callback_object;
92 int lossy_data_callback_id;
93 } callbacks[MAX_FRIEND_CONNECTION_CALLBACKS];
94
95 uint16_t lock_count;
96
97 Node_format tcp_relays[FRIEND_MAX_STORED_TCP_RELAYS];
98 uint16_t tcp_relay_counter;
99
100 _Bool hosting_tcp_relay;
101} Friend_Conn;
102
103
104typedef struct {
105 Net_Crypto *net_crypto;
106 DHT *dht;
107 Onion_Client *onion_c;
108
109 Friend_Conn *conns;
110 uint32_t num_cons;
111
112 int (*fr_request_callback)(void *object, const uint8_t *source_pubkey, const uint8_t *data, uint16_t len);
113 void *fr_request_object;
114 65
115 uint64_t last_LANdiscovery; 66Net_Crypto *friendconn_net_crypto(const Friend_Connections *fr_c);
116} Friend_Connections;
117 67
118/* return friendcon_id corresponding to the real public key on success. 68/* return friendcon_id corresponding to the real public key on success.
119 * return -1 on failure. 69 * return -1 on failure.
@@ -142,7 +92,7 @@ int get_friendcon_public_keys(uint8_t *real_pk, uint8_t *dht_temp_pk, Friend_Con
142 92
143/* Set temp dht key for connection. 93/* Set temp dht key for connection.
144 */ 94 */
145void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_temp_pk); 95void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_temp_pk, void *userdata);
146 96
147/* Add a TCP relay associated to the friend. 97/* Add a TCP relay associated to the friend.
148 * 98 *
@@ -158,9 +108,10 @@ int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, IP_Port ip_
158 * return -1 on failure 108 * return -1 on failure
159 */ 109 */
160int friend_connection_callbacks(Friend_Connections *fr_c, int friendcon_id, unsigned int index, 110int friend_connection_callbacks(Friend_Connections *fr_c, int friendcon_id, unsigned int index,
161 int (*status_callback)(void *object, int id, uint8_t status), int (*data_callback)(void *object, int id, uint8_t *data, 111 int (*status_callback)(void *object, int id, uint8_t status, void *userdata),
162 uint16_t length), int (*lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length), void *object, 112 int (*data_callback)(void *object, int id, const uint8_t *data, uint16_t len, void *userdata),
163 int number); 113 int (*lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata),
114 void *object, int number);
164 115
165/* return the crypt_connection_id for the connection. 116/* return the crypt_connection_id for the connection.
166 * 117 *
@@ -198,13 +149,13 @@ int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint3
198 * This function will be called every time a friend request is received. 149 * This function will be called every time a friend request is received.
199 */ 150 */
200void set_friend_request_callback(Friend_Connections *fr_c, int (*fr_request_callback)(void *, const uint8_t *, 151void set_friend_request_callback(Friend_Connections *fr_c, int (*fr_request_callback)(void *, const uint8_t *,
201 const uint8_t *, uint16_t), void *object); 152 const uint8_t *, uint16_t, void *), void *object);
202 153
203/* Create new friend_connections instance. */ 154/* Create new friend_connections instance. */
204Friend_Connections *new_friend_connections(Onion_Client *onion_c); 155Friend_Connections *new_friend_connections(Onion_Client *onion_c, bool local_discovery_enabled);
205 156
206/* main friend_connections loop. */ 157/* main friend_connections loop. */
207void do_friend_connections(Friend_Connections *fr_c); 158void do_friend_connections(Friend_Connections *fr_c, void *userdata);
208 159
209/* Free everything related with friend_connections. */ 160/* Free everything related with friend_connections. */
210void kill_friend_connections(Friend_Connections *fr_c); 161void kill_friend_connections(Friend_Connections *fr_c);
diff --git a/toxcore/friend_requests.c b/toxcore/friend_requests.c
index 7d4fecd1..3123e4ff 100644
--- a/toxcore/friend_requests.c
+++ b/toxcore/friend_requests.c
@@ -1,33 +1,54 @@
1/* friend_requests.c 1/*
2 *
3 * Handle friend requests. 2 * Handle friend requests.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2013 Tox project.
4 * 8 *
5 * Copyright (C) 2013 Tox project All Rights Reserved. 9 * This file is part of Tox, the free peer to peer instant messenger.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23
24#ifdef HAVE_CONFIG_H 24#ifdef HAVE_CONFIG_H
25#include "config.h" 25#include "config.h"
26#endif 26#endif
27 27
28#include "friend_requests.h" 28#include "friend_requests.h"
29
30#include <stdlib.h>
31#include <string.h>
32
29#include "util.h" 33#include "util.h"
30 34
35struct Friend_Requests {
36 uint32_t nospam;
37 void (*handle_friendrequest)(void *, const uint8_t *, const uint8_t *, size_t, void *);
38 uint8_t handle_friendrequest_isset;
39 void *handle_friendrequest_object;
40
41 int (*filter_function)(const uint8_t *, void *);
42 void *filter_function_userdata;
43 /* NOTE: The following is just a temporary fix for the multiple friend requests received at the same time problem.
44 * TODO(irungentoo): Make this better (This will most likely tie in with the way we will handle spam.)
45 */
46
47#define MAX_RECEIVED_STORED 32
48
49 uint8_t received_requests[MAX_RECEIVED_STORED][CRYPTO_PUBLIC_KEY_SIZE];
50 uint16_t received_requests_index;
51};
31 52
32/* Set and get the nospam variable used to prevent one type of friend request spam. */ 53/* Set and get the nospam variable used to prevent one type of friend request spam. */
33void set_nospam(Friend_Requests *fr, uint32_t num) 54void set_nospam(Friend_Requests *fr, uint32_t num)
@@ -43,13 +64,13 @@ uint32_t get_nospam(const Friend_Requests *fr)
43 64
44/* Set the function that will be executed when a friend request is received. */ 65/* Set the function that will be executed when a friend request is received. */
45void callback_friendrequest(Friend_Requests *fr, void (*function)(void *, const uint8_t *, const uint8_t *, size_t, 66void callback_friendrequest(Friend_Requests *fr, void (*function)(void *, const uint8_t *, const uint8_t *, size_t,
46 void *), void *object, void *userdata) 67 void *), void *object)
47{ 68{
48 fr->handle_friendrequest = function; 69 fr->handle_friendrequest = function;
49 fr->handle_friendrequest_isset = 1; 70 fr->handle_friendrequest_isset = 1;
50 fr->handle_friendrequest_object = object; 71 fr->handle_friendrequest_object = object;
51 fr->handle_friendrequest_userdata = userdata;
52} 72}
73
53/* Set the function used to check if a friend request should be displayed to the user or not. */ 74/* Set the function used to check if a friend request should be displayed to the user or not. */
54void set_filter_function(Friend_Requests *fr, int (*function)(const uint8_t *, void *), void *userdata) 75void set_filter_function(Friend_Requests *fr, int (*function)(const uint8_t *, void *), void *userdata)
55{ 76{
@@ -60,8 +81,9 @@ void set_filter_function(Friend_Requests *fr, int (*function)(const uint8_t *, v
60/* Add to list of received friend requests. */ 81/* Add to list of received friend requests. */
61static void addto_receivedlist(Friend_Requests *fr, const uint8_t *real_pk) 82static void addto_receivedlist(Friend_Requests *fr, const uint8_t *real_pk)
62{ 83{
63 if (fr->received_requests_index >= MAX_RECEIVED_STORED) 84 if (fr->received_requests_index >= MAX_RECEIVED_STORED) {
64 fr->received_requests_index = 0; 85 fr->received_requests_index = 0;
86 }
65 87
66 id_copy(fr->received_requests[fr->received_requests_index], real_pk); 88 id_copy(fr->received_requests[fr->received_requests_index], real_pk);
67 ++fr->received_requests_index; 89 ++fr->received_requests_index;
@@ -69,18 +91,18 @@ static void addto_receivedlist(Friend_Requests *fr, const uint8_t *real_pk)
69 91
70/* Check if a friend request was already received. 92/* Check if a friend request was already received.
71 * 93 *
72 * return 0 if it did not. 94 * return false if it did not.
73 * return 1 if it did. 95 * return true if it did.
74 */ 96 */
75static int request_received(Friend_Requests *fr, const uint8_t *real_pk) 97static bool request_received(const Friend_Requests *fr, const uint8_t *real_pk)
76{ 98{
77 uint32_t i; 99 for (uint32_t i = 0; i < MAX_RECEIVED_STORED; ++i) {
78 100 if (id_equal(fr->received_requests[i], real_pk)) {
79 for (i = 0; i < MAX_RECEIVED_STORED; ++i) 101 return true;
80 if (id_equal(fr->received_requests[i], real_pk)) 102 }
81 return 1; 103 }
82 104
83 return 0; 105 return false;
84} 106}
85 107
86/* Remove real pk from received_requests list. 108/* Remove real pk from received_requests list.
@@ -90,11 +112,9 @@ static int request_received(Friend_Requests *fr, const uint8_t *real_pk)
90 */ 112 */
91int remove_request_received(Friend_Requests *fr, const uint8_t *real_pk) 113int remove_request_received(Friend_Requests *fr, const uint8_t *real_pk)
92{ 114{
93 uint32_t i; 115 for (uint32_t i = 0; i < MAX_RECEIVED_STORED; ++i) {
94
95 for (i = 0; i < MAX_RECEIVED_STORED; ++i) {
96 if (id_equal(fr->received_requests[i], real_pk)) { 116 if (id_equal(fr->received_requests[i], real_pk)) {
97 sodium_memzero(fr->received_requests[i], crypto_box_PUBLICKEYBYTES); 117 crypto_memzero(fr->received_requests[i], CRYPTO_PUBLIC_KEY_SIZE);
98 return 0; 118 return 0;
99 } 119 }
100 } 120 }
@@ -103,38 +123,44 @@ int remove_request_received(Friend_Requests *fr, const uint8_t *real_pk)
103} 123}
104 124
105 125
106static int friendreq_handlepacket(void *object, const uint8_t *source_pubkey, const uint8_t *packet, uint16_t length) 126static int friendreq_handlepacket(void *object, const uint8_t *source_pubkey, const uint8_t *packet, uint16_t length,
127 void *userdata)
107{ 128{
108 Friend_Requests *fr = object; 129 Friend_Requests *const fr = (Friend_Requests *)object;
109 130
110 if (length <= 1 + sizeof(fr->nospam) || length > ONION_CLIENT_MAX_DATA_SIZE) 131 if (length <= 1 + sizeof(fr->nospam) || length > ONION_CLIENT_MAX_DATA_SIZE) {
111 return 1; 132 return 1;
133 }
112 134
113 ++packet; 135 ++packet;
114 --length; 136 --length;
115 137
116 if (fr->handle_friendrequest_isset == 0) 138 if (fr->handle_friendrequest_isset == 0) {
117 return 1; 139 return 1;
140 }
118 141
119 if (request_received(fr, source_pubkey)) 142 if (request_received(fr, source_pubkey)) {
120 return 1; 143 return 1;
144 }
121 145
122 if (memcmp(packet, &fr->nospam, sizeof(fr->nospam)) != 0) 146 if (memcmp(packet, &fr->nospam, sizeof(fr->nospam)) != 0) {
123 return 1; 147 return 1;
148 }
124 149
125 if (fr->filter_function) 150 if (fr->filter_function) {
126 if ((*fr->filter_function)(source_pubkey, fr->filter_function_userdata) != 0) 151 if (fr->filter_function(source_pubkey, fr->filter_function_userdata) != 0) {
127 return 1; 152 return 1;
153 }
154 }
128 155
129 addto_receivedlist(fr, source_pubkey); 156 addto_receivedlist(fr, source_pubkey);
130 157
131 uint32_t message_len = length - sizeof(fr->nospam); 158 const uint32_t message_len = length - sizeof(fr->nospam);
132 uint8_t message[message_len + 1]; 159 VLA(uint8_t, message, message_len + 1);
133 memcpy(message, packet + sizeof(fr->nospam), message_len); 160 memcpy(message, packet + sizeof(fr->nospam), message_len);
134 message[sizeof(message) - 1] = 0; /* Be sure the message is null terminated. */ 161 message[SIZEOF_VLA(message) - 1] = 0; /* Be sure the message is null terminated. */
135 162
136 (*fr->handle_friendrequest)(fr->handle_friendrequest_object, source_pubkey, message, message_len, 163 fr->handle_friendrequest(fr->handle_friendrequest_object, source_pubkey, message, message_len, userdata);
137 fr->handle_friendrequest_userdata);
138 return 0; 164 return 0;
139} 165}
140 166
@@ -142,3 +168,13 @@ void friendreq_init(Friend_Requests *fr, Friend_Connections *fr_c)
142{ 168{
143 set_friend_request_callback(fr_c, &friendreq_handlepacket, fr); 169 set_friend_request_callback(fr_c, &friendreq_handlepacket, fr);
144} 170}
171
172Friend_Requests *friendreq_new(void)
173{
174 return (Friend_Requests *)calloc(1, sizeof(Friend_Requests));
175}
176
177void friendreq_kill(Friend_Requests *fr)
178{
179 free(fr);
180}
diff --git a/toxcore/friend_requests.h b/toxcore/friend_requests.h
index ae21f7dc..e6948b6c 100644
--- a/toxcore/friend_requests.h
+++ b/toxcore/friend_requests.h
@@ -1,26 +1,26 @@
1/* friend_requests.h 1/*
2 *
3 * Handle friend requests. 2 * Handle friend requests.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2014 Tox project.
4 * 8 *
5 * Copyright (C) 2013 Tox project All Rights Reserved. 9 * This file is part of Tox, the free peer to peer instant messenger.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23
24#ifndef FRIEND_REQUESTS_H 24#ifndef FRIEND_REQUESTS_H
25#define FRIEND_REQUESTS_H 25#define FRIEND_REQUESTS_H
26 26
@@ -28,24 +28,7 @@
28 28
29#define MAX_FRIEND_REQUEST_DATA_SIZE (ONION_CLIENT_MAX_DATA_SIZE - (1 + sizeof(uint32_t))) 29#define MAX_FRIEND_REQUEST_DATA_SIZE (ONION_CLIENT_MAX_DATA_SIZE - (1 + sizeof(uint32_t)))
30 30
31typedef struct { 31typedef struct Friend_Requests Friend_Requests;
32 uint32_t nospam;
33 void (*handle_friendrequest)(void *, const uint8_t *, const uint8_t *, size_t, void *);
34 uint8_t handle_friendrequest_isset;
35 void *handle_friendrequest_object;
36 void *handle_friendrequest_userdata;
37
38 int (*filter_function)(const uint8_t *, void *);
39 void *filter_function_userdata;
40 /* NOTE: The following is just a temporary fix for the multiple friend requests received at the same time problem.
41 * TODO: Make this better (This will most likely tie in with the way we will handle spam.)
42 */
43
44#define MAX_RECEIVED_STORED 32
45
46 uint8_t received_requests[MAX_RECEIVED_STORED][crypto_box_PUBLICKEYBYTES];
47 uint16_t received_requests_index;
48} Friend_Requests;
49 32
50/* Set and get the nospam variable used to prevent one type of friend request spam. */ 33/* Set and get the nospam variable used to prevent one type of friend request spam. */
51void set_nospam(Friend_Requests *fr, uint32_t num); 34void set_nospam(Friend_Requests *fr, uint32_t num);
@@ -62,7 +45,7 @@ int remove_request_received(Friend_Requests *fr, const uint8_t *real_pk);
62 * Function format is function(uint8_t * public_key, uint8_t * data, size_t length, void * userdata) 45 * Function format is function(uint8_t * public_key, uint8_t * data, size_t length, void * userdata)
63 */ 46 */
64void callback_friendrequest(Friend_Requests *fr, void (*function)(void *, const uint8_t *, const uint8_t *, size_t, 47void callback_friendrequest(Friend_Requests *fr, void (*function)(void *, const uint8_t *, const uint8_t *, size_t,
65 void *), void *object, void *userdata); 48 void *), void *object);
66 49
67/* Set the function used to check if a friend request should be displayed to the user or not. 50/* Set the function used to check if a friend request should be displayed to the user or not.
68 * Function format is int function(uint8_t * public_key, void * userdata) 51 * Function format is int function(uint8_t * public_key, void * userdata)
@@ -73,5 +56,7 @@ void set_filter_function(Friend_Requests *fr, int (*function)(const uint8_t *, v
73/* Sets up friendreq packet handlers. */ 56/* Sets up friendreq packet handlers. */
74void friendreq_init(Friend_Requests *fr, Friend_Connections *fr_c); 57void friendreq_init(Friend_Requests *fr, Friend_Connections *fr_c);
75 58
59Friend_Requests *friendreq_new(void);
60void friendreq_kill(Friend_Requests *fr);
76 61
77#endif 62#endif
diff --git a/toxcore/group.c b/toxcore/group.c
index 9313a24b..b77ae38a 100644
--- a/toxcore/group.c
+++ b/toxcore/group.c
@@ -1,46 +1,53 @@
1/* group.c 1/*
2 *
3 * Slightly better groupchats implementation. 2 * Slightly better groupchats implementation.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2014 Tox project.
4 * 8 *
5 * Copyright (C) 2014 Tox project All Rights Reserved. 9 * This file is part of Tox, the free peer to peer instant messenger.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23
24#ifdef HAVE_CONFIG_H 24#ifdef HAVE_CONFIG_H
25#include "config.h" 25#include "config.h"
26#endif 26#endif
27 27
28#include "group.h" 28#include "group.h"
29
30#include <stdlib.h>
31#include <string.h>
32
29#include "util.h" 33#include "util.h"
30 34
31/* return 1 if the groupnumber is not valid. 35/* return 1 if the groupnumber is not valid.
32 * return 0 if the groupnumber is valid. 36 * return 0 if the groupnumber is valid.
33 */ 37 */
34static uint8_t groupnumber_not_valid(const Group_Chats *g_c, int groupnumber) 38static uint8_t groupnumber_not_valid(const Group_Chats *g_c, uint32_t groupnumber)
35{ 39{
36 if ((unsigned int)groupnumber >= g_c->num_chats) 40 if (groupnumber >= g_c->num_chats) {
37 return 1; 41 return 1;
42 }
38 43
39 if (g_c->chats == NULL) 44 if (g_c->chats == nullptr) {
40 return 1; 45 return 1;
46 }
41 47
42 if (g_c->chats[groupnumber].status == GROUPCHAT_STATUS_NONE) 48 if (g_c->chats[groupnumber].status == GROUPCHAT_STATUS_NONE) {
43 return 1; 49 return 1;
50 }
44 51
45 return 0; 52 return 0;
46} 53}
@@ -55,14 +62,15 @@ static int realloc_groupchats(Group_Chats *g_c, uint32_t num)
55{ 62{
56 if (num == 0) { 63 if (num == 0) {
57 free(g_c->chats); 64 free(g_c->chats);
58 g_c->chats = NULL; 65 g_c->chats = nullptr;
59 return 0; 66 return 0;
60 } 67 }
61 68
62 Group_c *newgroup_chats = realloc(g_c->chats, num * sizeof(Group_c)); 69 Group_c *newgroup_chats = (Group_c *)realloc(g_c->chats, num * sizeof(Group_c));
63 70
64 if (newgroup_chats == NULL) 71 if (newgroup_chats == nullptr) {
65 return -1; 72 return -1;
73 }
66 74
67 g_c->chats = newgroup_chats; 75 g_c->chats = newgroup_chats;
68 return 0; 76 return 0;
@@ -79,8 +87,9 @@ static int create_group_chat(Group_Chats *g_c)
79 uint32_t i; 87 uint32_t i;
80 88
81 for (i = 0; i < g_c->num_chats; ++i) { 89 for (i = 0; i < g_c->num_chats; ++i) {
82 if (g_c->chats[i].status == GROUPCHAT_STATUS_NONE) 90 if (g_c->chats[i].status == GROUPCHAT_STATUS_NONE) {
83 return i; 91 return i;
92 }
84 } 93 }
85 94
86 int id = -1; 95 int id = -1;
@@ -88,7 +97,7 @@ static int create_group_chat(Group_Chats *g_c)
88 if (realloc_groupchats(g_c, g_c->num_chats + 1) == 0) { 97 if (realloc_groupchats(g_c, g_c->num_chats + 1) == 0) {
89 id = g_c->num_chats; 98 id = g_c->num_chats;
90 ++g_c->num_chats; 99 ++g_c->num_chats;
91 memset(&(g_c->chats[id]), 0, sizeof(Group_c)); 100 memset(&g_c->chats[id], 0, sizeof(Group_c));
92 } 101 }
93 102
94 return id; 103 return id;
@@ -100,17 +109,19 @@ static int create_group_chat(Group_Chats *g_c)
100 * return -1 on failure. 109 * return -1 on failure.
101 * return 0 on success. 110 * return 0 on success.
102 */ 111 */
103static int wipe_group_chat(Group_Chats *g_c, int groupnumber) 112static int wipe_group_chat(Group_Chats *g_c, uint32_t groupnumber)
104{ 113{
105 if (groupnumber_not_valid(g_c, groupnumber)) 114 if (groupnumber_not_valid(g_c, groupnumber)) {
106 return -1; 115 return -1;
116 }
107 117
108 uint32_t i; 118 uint32_t i;
109 sodium_memzero(&(g_c->chats[groupnumber]), sizeof(Group_c)); 119 crypto_memzero(&g_c->chats[groupnumber], sizeof(Group_c));
110 120
111 for (i = g_c->num_chats; i != 0; --i) { 121 for (i = g_c->num_chats; i != 0; --i) {
112 if (g_c->chats[i - 1].status != GROUPCHAT_STATUS_NONE) 122 if (g_c->chats[i - 1].status != GROUPCHAT_STATUS_NONE) {
113 break; 123 break;
124 }
114 } 125 }
115 126
116 if (g_c->num_chats != i) { 127 if (g_c->num_chats != i) {
@@ -121,10 +132,11 @@ static int wipe_group_chat(Group_Chats *g_c, int groupnumber)
121 return 0; 132 return 0;
122} 133}
123 134
124static Group_c *get_group_c(const Group_Chats *g_c, int groupnumber) 135static Group_c *get_group_c(const Group_Chats *g_c, uint32_t groupnumber)
125{ 136{
126 if (groupnumber_not_valid(g_c, groupnumber)) 137 if (groupnumber_not_valid(g_c, groupnumber)) {
127 return 0; 138 return nullptr;
139 }
128 140
129 return &g_c->chats[groupnumber]; 141 return &g_c->chats[groupnumber];
130} 142}
@@ -135,16 +147,18 @@ static Group_c *get_group_c(const Group_Chats *g_c, int groupnumber)
135 * return peer index if peer is in chat. 147 * return peer index if peer is in chat.
136 * return -1 if peer is not in chat. 148 * return -1 if peer is not in chat.
137 * 149 *
138 * TODO: make this more efficient. 150 * TODO(irungentoo): make this more efficient.
139 */ 151 */
140 152
141static int peer_in_chat(const Group_c *chat, const uint8_t *real_pk) 153static int peer_in_chat(const Group_c *chat, const uint8_t *real_pk)
142{ 154{
143 uint32_t i; 155 uint32_t i;
144 156
145 for (i = 0; i < chat->numpeers; ++i) 157 for (i = 0; i < chat->numpeers; ++i) {
146 if (id_equal(chat->group[i].real_pk, real_pk)) 158 if (id_equal(chat->group[i].real_pk, real_pk)) {
147 return i; 159 return i;
160 }
161 }
148 162
149 return -1; 163 return -1;
150} 164}
@@ -155,15 +169,17 @@ static int peer_in_chat(const Group_c *chat, const uint8_t *real_pk)
155 * return group number if peer is in list. 169 * return group number if peer is in list.
156 * return -1 if group is not in list. 170 * return -1 if group is not in list.
157 * 171 *
158 * TODO: make this more efficient and maybe use constant time comparisons? 172 * TODO(irungentoo): make this more efficient and maybe use constant time comparisons?
159 */ 173 */
160static int get_group_num(const Group_Chats *g_c, const uint8_t *identifier) 174static int get_group_num(const Group_Chats *g_c, const uint8_t *identifier)
161{ 175{
162 uint32_t i; 176 uint32_t i;
163 177
164 for (i = 0; i < g_c->num_chats; ++i) 178 for (i = 0; i < g_c->num_chats; ++i) {
165 if (sodium_memcmp(g_c->chats[i].identifier, identifier, GROUP_IDENTIFIER_LENGTH) == 0) 179 if (crypto_memcmp(g_c->chats[i].identifier, identifier, GROUP_IDENTIFIER_LENGTH) == 0) {
166 return i; 180 return i;
181 }
182 }
167 183
168 return -1; 184 return -1;
169} 185}
@@ -174,15 +190,17 @@ static int get_group_num(const Group_Chats *g_c, const uint8_t *identifier)
174 * return peer number if peer is in chat. 190 * return peer number if peer is in chat.
175 * return -1 if peer is not in chat. 191 * return -1 if peer is not in chat.
176 * 192 *
177 * TODO: make this more efficient. 193 * TODO(irungentoo): make this more efficient.
178 */ 194 */
179static int get_peer_index(Group_c *g, uint16_t peer_number) 195static int get_peer_index(Group_c *g, uint16_t peer_number)
180{ 196{
181 uint32_t i; 197 uint32_t i;
182 198
183 for (i = 0; i < g->numpeers; ++i) 199 for (i = 0; i < g->numpeers; ++i) {
184 if (g->group[i].peer_number == peer_number) 200 if (g->group[i].peer_number == peer_number) {
185 return i; 201 return i;
202 }
203 }
186 204
187 return -1; 205 return -1;
188} 206}
@@ -209,17 +227,20 @@ enum {
209}; 227};
210 228
211static int friend_in_close(Group_c *g, int friendcon_id); 229static int friend_in_close(Group_c *g, int friendcon_id);
212static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnumber, uint8_t closest, uint8_t lock); 230static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, uint32_t groupnumber, uint8_t closest,
231 uint8_t lock);
213 232
214static int add_to_closest(Group_Chats *g_c, int groupnumber, const uint8_t *real_pk, const uint8_t *temp_pk) 233static int add_to_closest(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_pk, const uint8_t *temp_pk)
215{ 234{
216 Group_c *g = get_group_c(g_c, groupnumber); 235 Group_c *g = get_group_c(g_c, groupnumber);
217 236
218 if (!g) 237 if (!g) {
219 return -1; 238 return -1;
239 }
220 240
221 if (public_key_cmp(g->real_pk, real_pk) == 0) 241 if (public_key_cmp(g->real_pk, real_pk) == 0) {
222 return -1; 242 return -1;
243 }
223 244
224 unsigned int i; 245 unsigned int i;
225 unsigned int index = DESIRED_CLOSE_CONNECTIONS; 246 unsigned int index = DESIRED_CLOSE_CONNECTIONS;
@@ -267,26 +288,27 @@ static int add_to_closest(Group_Chats *g_c, int groupnumber, const uint8_t *real
267 return -1; 288 return -1;
268 } 289 }
269 290
270 uint8_t old_real_pk[crypto_box_PUBLICKEYBYTES]; 291 uint8_t old_real_pk[CRYPTO_PUBLIC_KEY_SIZE];
271 uint8_t old_temp_pk[crypto_box_PUBLICKEYBYTES]; 292 uint8_t old_temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
272 uint8_t old = 0; 293 uint8_t old = 0;
273 294
274 if (g->closest_peers[index].entry) { 295 if (g->closest_peers[index].entry) {
275 memcpy(old_real_pk, g->closest_peers[index].real_pk, crypto_box_PUBLICKEYBYTES); 296 memcpy(old_real_pk, g->closest_peers[index].real_pk, CRYPTO_PUBLIC_KEY_SIZE);
276 memcpy(old_temp_pk, g->closest_peers[index].temp_pk, crypto_box_PUBLICKEYBYTES); 297 memcpy(old_temp_pk, g->closest_peers[index].temp_pk, CRYPTO_PUBLIC_KEY_SIZE);
277 old = 1; 298 old = 1;
278 } 299 }
279 300
280 g->closest_peers[index].entry = 1; 301 g->closest_peers[index].entry = 1;
281 memcpy(g->closest_peers[index].real_pk, real_pk, crypto_box_PUBLICKEYBYTES); 302 memcpy(g->closest_peers[index].real_pk, real_pk, CRYPTO_PUBLIC_KEY_SIZE);
282 memcpy(g->closest_peers[index].temp_pk, temp_pk, crypto_box_PUBLICKEYBYTES); 303 memcpy(g->closest_peers[index].temp_pk, temp_pk, CRYPTO_PUBLIC_KEY_SIZE);
283 304
284 if (old) { 305 if (old) {
285 add_to_closest(g_c, groupnumber, old_real_pk, old_temp_pk); 306 add_to_closest(g_c, groupnumber, old_real_pk, old_temp_pk);
286 } 307 }
287 308
288 if (!g->changed) 309 if (!g->changed) {
289 g->changed = GROUPCHAT_CLOSEST_ADDED; 310 g->changed = GROUPCHAT_CLOSEST_ADDED;
311 }
290 312
291 return 0; 313 return 0;
292} 314}
@@ -296,12 +318,13 @@ static unsigned int pk_in_closest_peers(Group_c *g, uint8_t *real_pk)
296 unsigned int i; 318 unsigned int i;
297 319
298 for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) { 320 for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) {
299 if (!g->closest_peers[i].entry) 321 if (!g->closest_peers[i].entry) {
300 continue; 322 continue;
323 }
301 324
302 if (public_key_cmp(g->closest_peers[i].real_pk, real_pk) == 0) 325 if (public_key_cmp(g->closest_peers[i].real_pk, real_pk) == 0) {
303 return 1; 326 return 1;
304 327 }
305 } 328 }
306 329
307 return 0; 330 return 0;
@@ -309,15 +332,17 @@ static unsigned int pk_in_closest_peers(Group_c *g, uint8_t *real_pk)
309 332
310static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t *identifier); 333static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t *identifier);
311 334
312static int connect_to_closest(Group_Chats *g_c, int groupnumber) 335static int connect_to_closest(Group_Chats *g_c, uint32_t groupnumber, void *userdata)
313{ 336{
314 Group_c *g = get_group_c(g_c, groupnumber); 337 Group_c *g = get_group_c(g_c, groupnumber);
315 338
316 if (!g) 339 if (!g) {
317 return -1; 340 return -1;
341 }
318 342
319 if (!g->changed) 343 if (!g->changed) {
320 return 0; 344 return 0;
345 }
321 346
322 unsigned int i; 347 unsigned int i;
323 348
@@ -328,14 +353,16 @@ static int connect_to_closest(Group_Chats *g_c, int groupnumber)
328 } 353 }
329 354
330 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { 355 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
331 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) 356 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
332 continue; 357 continue;
358 }
333 359
334 if (!g->close[i].closest) 360 if (!g->close[i].closest) {
335 continue; 361 continue;
362 }
336 363
337 uint8_t real_pk[crypto_box_PUBLICKEYBYTES]; 364 uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
338 uint8_t dht_temp_pk[crypto_box_PUBLICKEYBYTES]; 365 uint8_t dht_temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
339 get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[i].number); 366 get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[i].number);
340 367
341 if (!pk_in_closest_peers(g, real_pk)) { 368 if (!pk_in_closest_peers(g, real_pk)) {
@@ -345,8 +372,9 @@ static int connect_to_closest(Group_Chats *g_c, int groupnumber)
345 } 372 }
346 373
347 for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) { 374 for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) {
348 if (!g->closest_peers[i].entry) 375 if (!g->closest_peers[i].entry) {
349 continue; 376 continue;
377 }
350 378
351 int friendcon_id = getfriend_conn_id_pk(g_c->fr_c, g->closest_peers[i].real_pk); 379 int friendcon_id = getfriend_conn_id_pk(g_c->fr_c, g->closest_peers[i].real_pk);
352 380
@@ -360,7 +388,7 @@ static int connect_to_closest(Group_Chats *g_c, int groupnumber)
360 continue; 388 continue;
361 } 389 }
362 390
363 set_dht_temp_pk(g_c->fr_c, friendcon_id, g->closest_peers[i].temp_pk); 391 set_dht_temp_pk(g_c->fr_c, friendcon_id, g->closest_peers[i].temp_pk, userdata);
364 } 392 }
365 393
366 add_conn_to_groupchat(g_c, friendcon_id, groupnumber, 1, lock); 394 add_conn_to_groupchat(g_c, friendcon_id, groupnumber, 1, lock);
@@ -375,44 +403,50 @@ static int connect_to_closest(Group_Chats *g_c, int groupnumber)
375 return 0; 403 return 0;
376} 404}
377 405
378/* 406/* Add a peer to the group chat.
379 * Add a peer to the group chat. 407 *
408 * do_gc_callback indicates whether we want to trigger callbacks set by the client
409 * via the public API. This should be set to false if this function is called
410 * from outside of the tox_iterate() loop.
380 * 411 *
381 * return peer_index if success or peer already in chat. 412 * return peer_index if success or peer already in chat.
382 * return -1 if error. 413 * return -1 if error.
383 */ 414 */
384static int addpeer(Group_Chats *g_c, int groupnumber, const uint8_t *real_pk, const uint8_t *temp_pk, 415static int addpeer(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_pk, const uint8_t *temp_pk,
385 uint16_t peer_number) 416 uint16_t peer_number, void *userdata, bool do_gc_callback)
386{ 417{
387 Group_c *g = get_group_c(g_c, groupnumber); 418 Group_c *g = get_group_c(g_c, groupnumber);
388 419
389 if (!g) 420 if (!g) {
390 return -1; 421 return -1;
422 }
391 423
392 //TODO 424 // TODO(irungentoo):
393 int peer_index = peer_in_chat(g, real_pk); 425 int peer_index = peer_in_chat(g, real_pk);
394 426
395 if (peer_index != -1) { 427 if (peer_index != -1) {
396 id_copy(g->group[peer_index].temp_pk, temp_pk); 428 id_copy(g->group[peer_index].temp_pk, temp_pk);
397 429
398 if (g->group[peer_index].peer_number != peer_number) 430 if (g->group[peer_index].peer_number != peer_number) {
399 return -1; 431 return -1;
432 }
400 433
401 return peer_index; 434 return peer_index;
402 } 435 }
403 436
404 peer_index = get_peer_index(g, peer_number); 437 peer_index = get_peer_index(g, peer_number);
405 438
406 if (peer_index != -1) 439 if (peer_index != -1) {
407 return -1; 440 return -1;
441 }
408 442
409 Group_Peer *temp; 443 Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * (g->numpeers + 1));
410 temp = realloc(g->group, sizeof(Group_Peer) * (g->numpeers + 1));
411 444
412 if (temp == NULL) 445 if (temp == nullptr) {
413 return -1; 446 return -1;
447 }
414 448
415 memset(&(temp[g->numpeers]), 0, sizeof(Group_Peer)); 449 memset(&temp[g->numpeers], 0, sizeof(Group_Peer));
416 g->group = temp; 450 g->group = temp;
417 451
418 id_copy(g->group[g->numpeers].real_pk, real_pk); 452 id_copy(g->group[g->numpeers].real_pk, real_pk);
@@ -424,28 +458,31 @@ static int addpeer(Group_Chats *g_c, int groupnumber, const uint8_t *real_pk, co
424 458
425 add_to_closest(g_c, groupnumber, real_pk, temp_pk); 459 add_to_closest(g_c, groupnumber, real_pk, temp_pk);
426 460
427 if (g_c->peer_namelistchange) 461 if (do_gc_callback && g_c->peer_list_changed_callback) {
428 g_c->peer_namelistchange(g_c->m, groupnumber, g->numpeers - 1, CHAT_CHANGE_PEER_ADD, 462 g_c->peer_list_changed_callback(g_c->m, groupnumber, userdata);
429 g_c->group_namelistchange_userdata); 463 }
430 464
431 if (g->peer_on_join) 465 if (g->peer_on_join) {
432 g->peer_on_join(g->object, groupnumber, g->numpeers - 1); 466 g->peer_on_join(g->object, groupnumber, g->numpeers - 1);
467 }
433 468
434 return (g->numpeers - 1); 469 return (g->numpeers - 1);
435} 470}
436 471
437static int remove_close_conn(Group_Chats *g_c, int groupnumber, int friendcon_id) 472static int remove_close_conn(Group_Chats *g_c, uint32_t groupnumber, int friendcon_id)
438{ 473{
439 Group_c *g = get_group_c(g_c, groupnumber); 474 Group_c *g = get_group_c(g_c, groupnumber);
440 475
441 if (!g) 476 if (!g) {
442 return -1; 477 return -1;
478 }
443 479
444 uint32_t i; 480 uint32_t i;
445 481
446 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { 482 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
447 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) 483 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
448 continue; 484 continue;
485 }
449 486
450 if (g->close[i].number == (unsigned int)friendcon_id) { 487 if (g->close[i].number == (unsigned int)friendcon_id) {
451 g->close[i].type = GROUPCHAT_CLOSE_NONE; 488 g->close[i].type = GROUPCHAT_CLOSE_NONE;
@@ -464,12 +501,13 @@ static int remove_close_conn(Group_Chats *g_c, int groupnumber, int friendcon_id
464 * return 0 if success 501 * return 0 if success
465 * return -1 if error. 502 * return -1 if error.
466 */ 503 */
467static int delpeer(Group_Chats *g_c, int groupnumber, int peer_index) 504static int delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void *userdata)
468{ 505{
469 Group_c *g = get_group_c(g_c, groupnumber); 506 Group_c *g = get_group_c(g_c, groupnumber);
470 507
471 if (!g) 508 if (!g) {
472 return -1; 509 return -1;
510 }
473 511
474 uint32_t i; 512 uint32_t i;
475 513
@@ -487,99 +525,126 @@ static int delpeer(Group_Chats *g_c, int groupnumber, int peer_index)
487 remove_close_conn(g_c, groupnumber, friendcon_id); 525 remove_close_conn(g_c, groupnumber, friendcon_id);
488 } 526 }
489 527
490 Group_Peer *temp;
491 --g->numpeers; 528 --g->numpeers;
492 529
493 void *peer_object = g->group[peer_index].object; 530 void *peer_object = g->group[peer_index].object;
494 531
495 if (g->numpeers == 0) { 532 if (g->numpeers == 0) {
496 free(g->group); 533 free(g->group);
497 g->group = NULL; 534 g->group = nullptr;
498 } else { 535 } else {
499 if (g->numpeers != (uint32_t)peer_index) 536 if (g->numpeers != (uint32_t)peer_index) {
500 memcpy(&g->group[peer_index], &g->group[g->numpeers], sizeof(Group_Peer)); 537 memcpy(&g->group[peer_index], &g->group[g->numpeers], sizeof(Group_Peer));
538 }
501 539
502 temp = realloc(g->group, sizeof(Group_Peer) * (g->numpeers)); 540 Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * (g->numpeers));
503 541
504 if (temp == NULL) 542 if (temp == nullptr) {
505 return -1; 543 return -1;
544 }
506 545
507 g->group = temp; 546 g->group = temp;
508 } 547 }
509 548
510 if (g_c->peer_namelistchange) 549 if (g_c->peer_list_changed_callback) {
511 g_c->peer_namelistchange(g_c->m, groupnumber, peer_index, CHAT_CHANGE_PEER_DEL, g_c->group_namelistchange_userdata); 550 g_c->peer_list_changed_callback(g_c->m, groupnumber, userdata);
551 }
512 552
513 if (g->peer_on_leave) 553 if (g->peer_on_leave) {
514 g->peer_on_leave(g->object, groupnumber, peer_index, peer_object); 554 g->peer_on_leave(g->object, groupnumber, peer_index, peer_object);
555 }
515 556
516 return 0; 557 return 0;
517} 558}
518 559
519static int setnick(Group_Chats *g_c, int groupnumber, int peer_index, const uint8_t *nick, uint16_t nick_len) 560/* Set the nick for a peer.
561 *
562 * do_gc_callback indicates whether we want to trigger callbacks set by the client
563 * via the public API. This should be set to false if this function is called
564 * from outside of the tox_iterate() loop.
565 *
566 * return 0 on success.
567 * return -1 if error.
568 */
569static int setnick(Group_Chats *g_c, uint32_t groupnumber, int peer_index, const uint8_t *nick, uint16_t nick_len,
570 void *userdata, bool do_gc_callback)
520{ 571{
521 if (nick_len > MAX_NAME_LENGTH) 572 if (nick_len > MAX_NAME_LENGTH) {
522 return -1; 573 return -1;
574 }
523 575
524 Group_c *g = get_group_c(g_c, groupnumber); 576 Group_c *g = get_group_c(g_c, groupnumber);
525 577
526 if (!g) 578 if (!g) {
527 return -1; 579 return -1;
580 }
528 581
529 /* same name as already stored? */ 582 /* same name as already stored? */
530 if (g->group[peer_index].nick_len == nick_len) 583 if (g->group[peer_index].nick_len == nick_len) {
531 if (nick_len == 0 || !memcmp(g->group[peer_index].nick, nick, nick_len)) 584 if (nick_len == 0 || !memcmp(g->group[peer_index].nick, nick, nick_len)) {
532 return 0; 585 return 0;
586 }
587 }
533 588
534 if (nick_len) 589 if (nick_len) {
535 memcpy(g->group[peer_index].nick, nick, nick_len); 590 memcpy(g->group[peer_index].nick, nick, nick_len);
591 }
536 592
537 g->group[peer_index].nick_len = nick_len; 593 g->group[peer_index].nick_len = nick_len;
538 594
539 if (g_c->peer_namelistchange) 595 if (do_gc_callback && g_c->peer_name_callback) {
540 g_c->peer_namelistchange(g_c->m, groupnumber, peer_index, CHAT_CHANGE_PEER_NAME, g_c->group_namelistchange_userdata); 596 g_c->peer_name_callback(g_c->m, groupnumber, peer_index, nick, nick_len, userdata);
597 }
541 598
542 return 0; 599 return 0;
543} 600}
544 601
545static int settitle(Group_Chats *g_c, int groupnumber, int peer_index, const uint8_t *title, uint8_t title_len) 602static int settitle(Group_Chats *g_c, uint32_t groupnumber, int peer_index, const uint8_t *title, uint8_t title_len,
603 void *userdata)
546{ 604{
547 if (title_len > MAX_NAME_LENGTH || title_len == 0) 605 if (title_len > MAX_NAME_LENGTH || title_len == 0) {
548 return -1; 606 return -1;
607 }
549 608
550 Group_c *g = get_group_c(g_c, groupnumber); 609 Group_c *g = get_group_c(g_c, groupnumber);
551 610
552 if (!g) 611 if (!g) {
553 return -1; 612 return -1;
613 }
554 614
555 /* same as already set? */ 615 /* same as already set? */
556 if (g->title_len == title_len && !memcmp(g->title, title, title_len)) 616 if (g->title_len == title_len && !memcmp(g->title, title, title_len)) {
557 return 0; 617 return 0;
618 }
558 619
559 memcpy(g->title, title, title_len); 620 memcpy(g->title, title, title_len);
560 g->title_len = title_len; 621 g->title_len = title_len;
561 622
562 if (g_c->title_callback) 623 if (g_c->title_callback) {
563 g_c->title_callback(g_c->m, groupnumber, peer_index, title, title_len, g_c->title_callback_userdata); 624 g_c->title_callback(g_c->m, groupnumber, peer_index, title, title_len, userdata);
625 }
564 626
565 return 0; 627 return 0;
566} 628}
567 629
568static void set_conns_type_close(Group_Chats *g_c, int groupnumber, int friendcon_id, uint8_t type) 630static void set_conns_type_close(Group_Chats *g_c, uint32_t groupnumber, int friendcon_id, uint8_t type)
569{ 631{
570 Group_c *g = get_group_c(g_c, groupnumber); 632 Group_c *g = get_group_c(g_c, groupnumber);
571 633
572 if (!g) 634 if (!g) {
573 return; 635 return;
636 }
574 637
575 uint32_t i; 638 uint32_t i;
576 639
577 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { 640 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
578 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) 641 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
579 continue; 642 continue;
643 }
580 644
581 if (g->close[i].number != (unsigned int)friendcon_id) 645 if (g->close[i].number != (unsigned int)friendcon_id) {
582 continue; 646 continue;
647 }
583 648
584 if (type == GROUPCHAT_CLOSE_ONLINE) { 649 if (type == GROUPCHAT_CLOSE_ONLINE) {
585 send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->identifier); 650 send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->identifier);
@@ -598,34 +663,36 @@ static void set_conns_status_groups(Group_Chats *g_c, int friendcon_id, uint8_t
598 } 663 }
599} 664}
600 665
601static int handle_status(void *object, int friendcon_id, uint8_t status) 666static int g_handle_status(void *object, int friendcon_id, uint8_t status, void *userdata)
602{ 667{
603 Group_Chats *g_c = object; 668 Group_Chats *g_c = (Group_Chats *)object;
604 669
605 if (status) { /* Went online */ 670 if (status) { /* Went online */
606 set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_ONLINE); 671 set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_ONLINE);
607 } else { /* Went offline */ 672 } else { /* Went offline */
608 set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_CONNECTION); 673 set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_CONNECTION);
609 //TODO remove timedout connections? 674 // TODO(irungentoo): remove timedout connections?
610 } 675 }
611 676
612 return 0; 677 return 0;
613} 678}
614 679
615static int handle_packet(void *object, int friendcon_id, uint8_t *data, uint16_t length); 680static int g_handle_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata);
616static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uint16_t length); 681static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata);
617 682
618/* Add friend to group chat. 683/* Add friend to group chat.
619 * 684 *
620 * return close index on success 685 * return close index on success
621 * return -1 on failure. 686 * return -1 on failure.
622 */ 687 */
623static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnumber, uint8_t closest, uint8_t lock) 688static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, uint32_t groupnumber, uint8_t closest,
689 uint8_t lock)
624{ 690{
625 Group_c *g = get_group_c(g_c, groupnumber); 691 Group_c *g = get_group_c(g_c, groupnumber);
626 692
627 if (!g) 693 if (!g) {
628 return -1; 694 return -1;
695 }
629 696
630 uint16_t i, ind = MAX_GROUP_CONNECTIONS; 697 uint16_t i, ind = MAX_GROUP_CONNECTIONS;
631 698
@@ -641,17 +708,19 @@ static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnu
641 } 708 }
642 } 709 }
643 710
644 if (ind == MAX_GROUP_CONNECTIONS) 711 if (ind == MAX_GROUP_CONNECTIONS) {
645 return -1; 712 return -1;
713 }
646 714
647 if (lock) 715 if (lock) {
648 friend_connection_lock(g_c->fr_c, friendcon_id); 716 friend_connection_lock(g_c->fr_c, friendcon_id);
717 }
649 718
650 g->close[ind].type = GROUPCHAT_CLOSE_CONNECTION; 719 g->close[ind].type = GROUPCHAT_CLOSE_CONNECTION;
651 g->close[ind].number = friendcon_id; 720 g->close[ind].number = friendcon_id;
652 g->close[ind].closest = closest; 721 g->close[ind].closest = closest;
653 //TODO 722 // TODO(irungentoo):
654 friend_connection_callbacks(g_c->m->fr_c, friendcon_id, GROUPCHAT_CALLBACK_INDEX, &handle_status, &handle_packet, 723 friend_connection_callbacks(g_c->m->fr_c, friendcon_id, GROUPCHAT_CALLBACK_INDEX, &g_handle_status, &g_handle_packet,
655 &handle_lossy, g_c, friendcon_id); 724 &handle_lossy, g_c, friendcon_id);
656 725
657 return ind; 726 return ind;
@@ -668,8 +737,9 @@ int add_groupchat(Group_Chats *g_c, uint8_t type)
668{ 737{
669 int groupnumber = create_group_chat(g_c); 738 int groupnumber = create_group_chat(g_c);
670 739
671 if (groupnumber == -1) 740 if (groupnumber == -1) {
672 return -1; 741 return -1;
742 }
673 743
674 Group_c *g = &g_c->chats[groupnumber]; 744 Group_c *g = &g_c->chats[groupnumber];
675 745
@@ -678,95 +748,129 @@ int add_groupchat(Group_Chats *g_c, uint8_t type)
678 new_symmetric_key(g->identifier + 1); 748 new_symmetric_key(g->identifier + 1);
679 g->identifier[0] = type; 749 g->identifier[0] = type;
680 g->peer_number = 0; /* Founder is peer 0. */ 750 g->peer_number = 0; /* Founder is peer 0. */
681 memcpy(g->real_pk, g_c->m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES); 751 memcpy(g->real_pk, nc_get_self_public_key(g_c->m->net_crypto), CRYPTO_PUBLIC_KEY_SIZE);
682 int peer_index = addpeer(g_c, groupnumber, g->real_pk, g_c->m->dht->self_public_key, 0); 752 int peer_index = addpeer(g_c, groupnumber, g->real_pk, dht_get_self_public_key(g_c->m->dht), 0, nullptr, false);
683 753
684 if (peer_index == -1) { 754 if (peer_index == -1) {
685 return -1; 755 return -1;
686 } 756 }
687 757
688 setnick(g_c, groupnumber, peer_index, g_c->m->name, g_c->m->name_length); 758 setnick(g_c, groupnumber, peer_index, g_c->m->name, g_c->m->name_length, nullptr, false);
689 759
690 return groupnumber; 760 return groupnumber;
691} 761}
692 762
693static int group_kill_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_num); 763static int group_kill_peer_send(const Group_Chats *g_c, uint32_t groupnumber, uint16_t peer_num);
694/* Delete a groupchat from the chats array. 764/* Delete a groupchat from the chats array.
695 * 765 *
696 * return 0 on success. 766 * return 0 on success.
697 * return -1 if failure. 767 * return -1 if groupnumber is invalid.
698 */ 768 */
699int del_groupchat(Group_Chats *g_c, int groupnumber) 769int del_groupchat(Group_Chats *g_c, uint32_t groupnumber)
700{ 770{
701 Group_c *g = get_group_c(g_c, groupnumber); 771 Group_c *g = get_group_c(g_c, groupnumber);
702 772
703 if (!g) 773 if (!g) {
704 return -1; 774 return -1;
775 }
705 776
706 group_kill_peer_send(g_c, groupnumber, g->peer_number); 777 group_kill_peer_send(g_c, groupnumber, g->peer_number);
707 778
708 unsigned int i; 779 unsigned int i;
709 780
710 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { 781 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
711 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) 782 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
712 continue; 783 continue;
784 }
713 785
714 g->close[i].type = GROUPCHAT_CLOSE_NONE; 786 g->close[i].type = GROUPCHAT_CLOSE_NONE;
715 kill_friend_connection(g_c->fr_c, g->close[i].number); 787 kill_friend_connection(g_c->fr_c, g->close[i].number);
716 } 788 }
717 789
718 for (i = 0; i < g->numpeers; ++i) { 790 for (i = 0; i < g->numpeers; ++i) {
719 if (g->peer_on_leave) 791 if (g->peer_on_leave) {
720 g->peer_on_leave(g->object, groupnumber, i, g->group[i].object); 792 g->peer_on_leave(g->object, groupnumber, i, g->group[i].object);
793 }
721 } 794 }
722 795
723 free(g->group); 796 free(g->group);
724 797
725 if (g->group_on_delete) 798 if (g->group_on_delete) {
726 g->group_on_delete(g->object, groupnumber); 799 g->group_on_delete(g->object, groupnumber);
800 }
727 801
728 return wipe_group_chat(g_c, groupnumber); 802 return wipe_group_chat(g_c, groupnumber);
729} 803}
730 804
731/* Copy the public key of peernumber who is in groupnumber to pk. 805/* Copy the public key of peernumber who is in groupnumber to pk.
732 * pk must be crypto_box_PUBLICKEYBYTES long. 806 * pk must be CRYPTO_PUBLIC_KEY_SIZE long.
733 * 807 *
734 * returns 0 on success 808 * return 0 on success
735 * returns -1 on failure 809 * return -1 if groupnumber is invalid.
810 * return -2 if peernumber is invalid.
736 */ 811 */
737int group_peer_pubkey(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *pk) 812int group_peer_pubkey(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, uint8_t *pk)
738{ 813{
739 Group_c *g = get_group_c(g_c, groupnumber); 814 Group_c *g = get_group_c(g_c, groupnumber);
740 815
741 if (!g) 816 if (!g) {
742 return -1; 817 return -1;
818 }
743 819
744 if ((uint32_t)peernumber >= g->numpeers) 820 if ((uint32_t)peernumber >= g->numpeers) {
745 return -1; 821 return -2;
822 }
746 823
747 memcpy(pk, g->group[peernumber].real_pk, crypto_box_PUBLICKEYBYTES); 824 memcpy(pk, g->group[peernumber].real_pk, CRYPTO_PUBLIC_KEY_SIZE);
748 return 0; 825 return 0;
749} 826}
750 827
828/*
829 * Return the size of peernumber's name.
830 *
831 * return -1 if groupnumber is invalid.
832 * return -2 if peernumber is invalid.
833 */
834int group_peername_size(const Group_Chats *g_c, uint32_t groupnumber, int peernumber)
835{
836 Group_c *g = get_group_c(g_c, groupnumber);
837
838 if (!g) {
839 return -1;
840 }
841
842 if ((uint32_t)peernumber >= g->numpeers) {
843 return -2;
844 }
845
846 if (g->group[peernumber].nick_len == 0) {
847 return 0;
848 }
849
850 return g->group[peernumber].nick_len;
851}
852
751/* Copy the name of peernumber who is in groupnumber to name. 853/* Copy the name of peernumber who is in groupnumber to name.
752 * name must be at least MAX_NAME_LENGTH long. 854 * name must be at least MAX_NAME_LENGTH long.
753 * 855 *
754 * return length of name if success 856 * return length of name if success
755 * return -1 if failure 857 * return -1 if groupnumber is invalid.
858 * return -2 if peernumber is invalid.
756 */ 859 */
757int group_peername(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *name) 860int group_peername(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, uint8_t *name)
758{ 861{
759 Group_c *g = get_group_c(g_c, groupnumber); 862 Group_c *g = get_group_c(g_c, groupnumber);
760 863
761 if (!g) 864 if (!g) {
762 return -1; 865 return -1;
866 }
763 867
764 if ((uint32_t)peernumber >= g->numpeers) 868 if ((uint32_t)peernumber >= g->numpeers) {
765 return -1; 869 return -2;
870 }
766 871
767 if (g->group[peernumber].nick_len == 0) { 872 if (g->group[peernumber].nick_len == 0) {
768 memcpy(name, "Tox User", 8); 873 return 0;
769 return 8;
770 } 874 }
771 875
772 memcpy(name, g->group[peernumber].nick, g->group[peernumber].nick_len); 876 memcpy(name, g->group[peernumber].nick, g->group[peernumber].nick_len);
@@ -783,13 +887,14 @@ int group_peername(const Group_Chats *g_c, int groupnumber, int peernumber, uint
783 * 887 *
784 * return -1 on failure. 888 * return -1 on failure.
785 */ 889 */
786int group_names(const Group_Chats *g_c, int groupnumber, uint8_t names[][MAX_NAME_LENGTH], uint16_t lengths[], 890int group_names(const Group_Chats *g_c, uint32_t groupnumber, uint8_t names[][MAX_NAME_LENGTH], uint16_t lengths[],
787 uint16_t length) 891 uint16_t length)
788{ 892{
789 Group_c *g = get_group_c(g_c, groupnumber); 893 Group_c *g = get_group_c(g_c, groupnumber);
790 894
791 if (!g) 895 if (!g) {
792 return -1; 896 return -1;
897 }
793 898
794 unsigned int i; 899 unsigned int i;
795 900
@@ -801,33 +906,40 @@ int group_names(const Group_Chats *g_c, int groupnumber, uint8_t names[][MAX_NAM
801} 906}
802 907
803/* Return the number of peers in the group chat on success. 908/* Return the number of peers in the group chat on success.
804 * return -1 on failure 909 * return -1 if groupnumber is invalid.
805 */ 910 */
806int group_number_peers(const Group_Chats *g_c, int groupnumber) 911int group_number_peers(const Group_Chats *g_c, uint32_t groupnumber)
807{ 912{
808 Group_c *g = get_group_c(g_c, groupnumber); 913 Group_c *g = get_group_c(g_c, groupnumber);
809 914
810 if (!g) 915 if (!g) {
811 return -1; 916 return -1;
917 }
812 918
813 return g->numpeers; 919 return g->numpeers;
814} 920}
815 921
816/* return 1 if the peernumber corresponds to ours. 922/* return 1 if the peernumber corresponds to ours.
817 * return 0 on failure. 923 * return 0 if the peernumber is not ours.
924 * return -1 if groupnumber is invalid.
925 * return -2 if peernumber is invalid.
926 * return -3 if we are not connected to the group chat.
818 */ 927 */
819unsigned int group_peernumber_is_ours(const Group_Chats *g_c, int groupnumber, int peernumber) 928int group_peernumber_is_ours(const Group_Chats *g_c, uint32_t groupnumber, int peernumber)
820{ 929{
821 Group_c *g = get_group_c(g_c, groupnumber); 930 Group_c *g = get_group_c(g_c, groupnumber);
822 931
823 if (!g) 932 if (!g) {
824 return 0; 933 return -1;
934 }
825 935
826 if (g->status != GROUPCHAT_STATUS_CONNECTED) 936 if ((uint32_t)peernumber >= g->numpeers) {
827 return 0; 937 return -2;
938 }
828 939
829 if ((uint32_t)peernumber >= g->numpeers) 940 if (g->status != GROUPCHAT_STATUS_CONNECTED) {
830 return 0; 941 return -3;
942 }
831 943
832 return g->peer_number == g->group[peernumber].peer_number; 944 return g->peer_number == g->group[peernumber].peer_number;
833} 945}
@@ -837,12 +949,13 @@ unsigned int group_peernumber_is_ours(const Group_Chats *g_c, int groupnumber, i
837 * return -1 on failure. 949 * return -1 on failure.
838 * return type on success. 950 * return type on success.
839 */ 951 */
840int group_get_type(const Group_Chats *g_c, int groupnumber) 952int group_get_type(const Group_Chats *g_c, uint32_t groupnumber)
841{ 953{
842 Group_c *g = get_group_c(g_c, groupnumber); 954 Group_c *g = get_group_c(g_c, groupnumber);
843 955
844 if (!g) 956 if (!g) {
845 return -1; 957 return -1;
958 }
846 959
847 return g->identifier[0]; 960 return g->identifier[0];
848} 961}
@@ -855,16 +968,17 @@ int group_get_type(const Group_Chats *g_c, int groupnumber)
855static unsigned int send_packet_group_peer(Friend_Connections *fr_c, int friendcon_id, uint8_t packet_id, 968static unsigned int send_packet_group_peer(Friend_Connections *fr_c, int friendcon_id, uint8_t packet_id,
856 uint16_t group_num, const uint8_t *data, uint16_t length) 969 uint16_t group_num, const uint8_t *data, uint16_t length)
857{ 970{
858 if (1 + sizeof(uint16_t) + length > MAX_CRYPTO_DATA_SIZE) 971 if (1 + sizeof(uint16_t) + length > MAX_CRYPTO_DATA_SIZE) {
859 return 0; 972 return 0;
973 }
860 974
861 group_num = htons(group_num); 975 group_num = net_htons(group_num);
862 uint8_t packet[1 + sizeof(uint16_t) + length]; 976 VLA(uint8_t, packet, 1 + sizeof(uint16_t) + length);
863 packet[0] = packet_id; 977 packet[0] = packet_id;
864 memcpy(packet + 1, &group_num, sizeof(uint16_t)); 978 memcpy(packet + 1, &group_num, sizeof(uint16_t));
865 memcpy(packet + 1 + sizeof(uint16_t), data, length); 979 memcpy(packet + 1 + sizeof(uint16_t), data, length);
866 return write_cryptpacket(fr_c->net_crypto, friend_connection_crypt_connection_id(fr_c, friendcon_id), packet, 980 return write_cryptpacket(friendconn_net_crypto(fr_c), friend_connection_crypt_connection_id(fr_c, friendcon_id), packet,
867 sizeof(packet), 0) != -1; 981 SIZEOF_VLA(packet), 0) != -1;
868} 982}
869 983
870/* Send a group lossy packet to friendcon_id. 984/* Send a group lossy packet to friendcon_id.
@@ -875,16 +989,17 @@ static unsigned int send_packet_group_peer(Friend_Connections *fr_c, int friendc
875static unsigned int send_lossy_group_peer(Friend_Connections *fr_c, int friendcon_id, uint8_t packet_id, 989static unsigned int send_lossy_group_peer(Friend_Connections *fr_c, int friendcon_id, uint8_t packet_id,
876 uint16_t group_num, const uint8_t *data, uint16_t length) 990 uint16_t group_num, const uint8_t *data, uint16_t length)
877{ 991{
878 if (1 + sizeof(uint16_t) + length > MAX_CRYPTO_DATA_SIZE) 992 if (1 + sizeof(uint16_t) + length > MAX_CRYPTO_DATA_SIZE) {
879 return 0; 993 return 0;
994 }
880 995
881 group_num = htons(group_num); 996 group_num = net_htons(group_num);
882 uint8_t packet[1 + sizeof(uint16_t) + length]; 997 VLA(uint8_t, packet, 1 + sizeof(uint16_t) + length);
883 packet[0] = packet_id; 998 packet[0] = packet_id;
884 memcpy(packet + 1, &group_num, sizeof(uint16_t)); 999 memcpy(packet + 1, &group_num, sizeof(uint16_t));
885 memcpy(packet + 1 + sizeof(uint16_t), data, length); 1000 memcpy(packet + 1 + sizeof(uint16_t), data, length);
886 return send_lossy_cryptpacket(fr_c->net_crypto, friend_connection_crypt_connection_id(fr_c, friendcon_id), packet, 1001 return send_lossy_cryptpacket(friendconn_net_crypto(fr_c), friend_connection_crypt_connection_id(fr_c, friendcon_id),
887 sizeof(packet)) != -1; 1002 packet, SIZEOF_VLA(packet)) != -1;
888} 1003}
889 1004
890#define INVITE_PACKET_SIZE (1 + sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH) 1005#define INVITE_PACKET_SIZE (1 + sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH)
@@ -893,29 +1008,32 @@ static unsigned int send_lossy_group_peer(Friend_Connections *fr_c, int friendco
893#define INVITE_RESPONSE_PACKET_SIZE (1 + sizeof(uint16_t) * 2 + GROUP_IDENTIFIER_LENGTH) 1008#define INVITE_RESPONSE_PACKET_SIZE (1 + sizeof(uint16_t) * 2 + GROUP_IDENTIFIER_LENGTH)
894#define INVITE_RESPONSE_ID 1 1009#define INVITE_RESPONSE_ID 1
895 1010
896/* invite friendnumber to groupnumber 1011/* invite friendnumber to groupnumber.
897 * return 0 on success 1012 *
898 * return -1 on failure 1013 * return 0 on success.
1014 * return -1 if groupnumber is invalid.
1015 * return -2 if invite packet failed to send.
899 */ 1016 */
900int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber) 1017int invite_friend(Group_Chats *g_c, uint32_t friendnumber, uint32_t groupnumber)
901{ 1018{
902 Group_c *g = get_group_c(g_c, groupnumber); 1019 Group_c *g = get_group_c(g_c, groupnumber);
903 1020
904 if (!g) 1021 if (!g) {
905 return -1; 1022 return -1;
1023 }
906 1024
907 uint8_t invite[INVITE_PACKET_SIZE]; 1025 uint8_t invite[INVITE_PACKET_SIZE];
908 invite[0] = INVITE_ID; 1026 invite[0] = INVITE_ID;
909 uint16_t groupchat_num = htons((uint16_t)groupnumber); 1027 uint16_t groupchat_num = net_htons((uint16_t)groupnumber);
910 memcpy(invite + 1, &groupchat_num, sizeof(groupchat_num)); 1028 memcpy(invite + 1, &groupchat_num, sizeof(groupchat_num));
911 memcpy(invite + 1 + sizeof(groupchat_num), g->identifier, GROUP_IDENTIFIER_LENGTH); 1029 memcpy(invite + 1 + sizeof(groupchat_num), g->identifier, GROUP_IDENTIFIER_LENGTH);
912 1030
913 if (send_group_invite_packet(g_c->m, friendnumber, invite, sizeof(invite))) { 1031 if (send_conference_invite_packet(g_c->m, friendnumber, invite, sizeof(invite))) {
914 return 0; 1032 return 0;
915 } else {
916 wipe_group_chat(g_c, groupnumber);
917 return -1;
918 } 1033 }
1034
1035 wipe_group_chat(g_c, groupnumber);
1036 return -2;
919} 1037}
920 1038
921static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num); 1039static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num);
@@ -924,46 +1042,56 @@ static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t
924 * 1042 *
925 * expected_type is the groupchat type we expect the chat we are joining is. 1043 * expected_type is the groupchat type we expect the chat we are joining is.
926 * 1044 *
927 * returns group number on success 1045 * return group number on success.
928 * returns -1 on failure. 1046 * return -1 if data length is invalid.
1047 * return -2 if group is not the expected type.
1048 * return -3 if friendnumber is invalid.
1049 * return -4 if client is already in this group.
1050 * return -5 if group instance failed to initialize.
1051 * return -6 if join packet fails to send.
929 */ 1052 */
930int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t expected_type, const uint8_t *data, uint16_t length) 1053int join_groupchat(Group_Chats *g_c, uint32_t friendnumber, uint8_t expected_type, const uint8_t *data, uint16_t length)
931{ 1054{
932 if (length != sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH) 1055 if (length != sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH) {
933 return -1; 1056 return -1;
1057 }
934 1058
935 if (data[sizeof(uint16_t)] != expected_type) 1059 if (data[sizeof(uint16_t)] != expected_type) {
936 return -1; 1060 return -2;
1061 }
937 1062
938 int friendcon_id = getfriendcon_id(g_c->m, friendnumber); 1063 int friendcon_id = getfriendcon_id(g_c->m, friendnumber);
939 1064
940 if (friendcon_id == -1) 1065 if (friendcon_id == -1) {
941 return -1; 1066 return -3;
1067 }
942 1068
943 if (get_group_num(g_c, data + sizeof(uint16_t)) != -1) 1069 if (get_group_num(g_c, data + sizeof(uint16_t)) != -1) {
944 return -1; 1070 return -4;
1071 }
945 1072
946 int groupnumber = create_group_chat(g_c); 1073 int groupnumber = create_group_chat(g_c);
947 1074
948 if (groupnumber == -1) 1075 if (groupnumber == -1) {
949 return -1; 1076 return -5;
1077 }
950 1078
951 Group_c *g = &g_c->chats[groupnumber]; 1079 Group_c *g = &g_c->chats[groupnumber];
952 1080
953 uint16_t group_num = htons(groupnumber); 1081 uint16_t group_num = net_htons(groupnumber);
954 g->status = GROUPCHAT_STATUS_VALID; 1082 g->status = GROUPCHAT_STATUS_VALID;
955 g->number_joined = -1; 1083 g->number_joined = -1;
956 memcpy(g->real_pk, g_c->m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES); 1084 memcpy(g->real_pk, nc_get_self_public_key(g_c->m->net_crypto), CRYPTO_PUBLIC_KEY_SIZE);
957 1085
958 uint8_t response[INVITE_RESPONSE_PACKET_SIZE]; 1086 uint8_t response[INVITE_RESPONSE_PACKET_SIZE];
959 response[0] = INVITE_RESPONSE_ID; 1087 response[0] = INVITE_RESPONSE_ID;
960 memcpy(response + 1, &group_num, sizeof(uint16_t)); 1088 memcpy(response + 1, &group_num, sizeof(uint16_t));
961 memcpy(response + 1 + sizeof(uint16_t), data, sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH); 1089 memcpy(response + 1 + sizeof(uint16_t), data, sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH);
962 1090
963 if (send_group_invite_packet(g_c->m, friendnumber, response, sizeof(response))) { 1091 if (send_conference_invite_packet(g_c->m, friendnumber, response, sizeof(response))) {
964 uint16_t other_groupnum; 1092 uint16_t other_groupnum;
965 memcpy(&other_groupnum, data, sizeof(other_groupnum)); 1093 memcpy(&other_groupnum, data, sizeof(other_groupnum));
966 other_groupnum = ntohs(other_groupnum); 1094 other_groupnum = net_ntohs(other_groupnum);
967 memcpy(g->identifier, data + sizeof(uint16_t), GROUP_IDENTIFIER_LENGTH); 1095 memcpy(g->identifier, data + sizeof(uint16_t), GROUP_IDENTIFIER_LENGTH);
968 int close_index = add_conn_to_groupchat(g_c, friendcon_id, groupnumber, 0, 1); 1096 int close_index = add_conn_to_groupchat(g_c, friendcon_id, groupnumber, 0, 1);
969 1097
@@ -975,96 +1103,96 @@ int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t expected_type
975 1103
976 send_peer_query(g_c, friendcon_id, other_groupnum); 1104 send_peer_query(g_c, friendcon_id, other_groupnum);
977 return groupnumber; 1105 return groupnumber;
978 } else {
979 g->status = GROUPCHAT_STATUS_NONE;
980 return -1;
981 } 1106 }
1107
1108 g->status = GROUPCHAT_STATUS_NONE;
1109 return -6;
982} 1110}
983 1111
984/* Set the callback for group invites. 1112/* Set handlers for custom lossy packets.
985 * 1113 *
986 * Function(Group_Chats *g_c, int32_t friendnumber, uint8_t type, uint8_t *data, uint16_t length, void *userdata) 1114 * NOTE: Handler must return 0 if packet is to be relayed, -1 if the packet should not be relayed.
987 * 1115 *
988 * data of length is what needs to be passed to join_groupchat(). 1116 * Function(void *group object (set with group_set_object), uint32_t groupnumber, uint32_t friendgroupnumber, void *group peer object (set with group_peer_set_object), const uint8_t *packet, uint16_t length)
989 */ 1117 */
990void g_callback_group_invite(Group_Chats *g_c, void (*function)(Messenger *m, int32_t, uint8_t, const uint8_t *, 1118void group_lossy_packet_registerhandler(Group_Chats *g_c, uint8_t byte, int (*function)(void *, uint32_t, uint32_t,
991 uint16_t, void *), void *userdata) 1119 void *,
1120 const uint8_t *, uint16_t))
992{ 1121{
993 g_c->invite_callback = function; 1122 g_c->lossy_packethandlers[byte].function = function;
994 g_c->invite_callback_userdata = userdata;
995} 1123}
996 1124
997/* Set the callback for group messages. 1125/* Set the callback for group invites.
1126 *
1127 * Function(Group_Chats *g_c, int32_t friendnumber, uint8_t type, uint8_t *data, size_t length, void *userdata)
998 * 1128 *
999 * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata) 1129 * data of length is what needs to be passed to join_groupchat().
1000 */ 1130 */
1001void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t, 1131void g_callback_group_invite(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, int, const uint8_t *,
1002 void *), void *userdata) 1132 size_t, void *))
1003{ 1133{
1004 g_c->message_callback = function; 1134 g_c->invite_callback = function;
1005 g_c->message_callback_userdata = userdata;
1006} 1135}
1007 1136
1008/* Set the callback for group actions. 1137// TODO(sudden6): function signatures in comments are incorrect
1138/* Set the callback for group messages.
1009 * 1139 *
1010 * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata) 1140 * Function(Group_Chats *g_c, uint32_t groupnumber, uint32_t friendgroupnumber, uint8_t * message, size_t length, void *userdata)
1011 */ 1141 */
1012void g_callback_group_action(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t, 1142void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, int, const uint8_t *,
1013 void *), void *userdata) 1143 size_t, void *))
1014{ 1144{
1015 g_c->action_callback = function; 1145 g_c->message_callback = function;
1016 g_c->action_callback_userdata = userdata;
1017} 1146}
1018 1147
1019/* Set handlers for custom lossy packets. 1148/* Set callback function for peer nickname changes.
1020 *
1021 * NOTE: Handler must return 0 if packet is to be relayed, -1 if the packet should not be relayed.
1022 * 1149 *
1023 * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber, void *group peer object (set with group_peer_set_object), const uint8_t *packet, uint16_t length) 1150 * It gets called every time a peer changes their nickname.
1151 * Function(Group_Chats *g_c, uint32_t groupnumber, uint32_t peernumber, const uint8_t *nick, size_t nick_len, void *userdata)
1024 */ 1152 */
1025void group_lossy_packet_registerhandler(Group_Chats *g_c, uint8_t byte, int (*function)(void *, int, int, void *, 1153void g_callback_peer_name(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, const uint8_t *,
1026 const uint8_t *, uint16_t)) 1154 size_t, void *))
1027{ 1155{
1028 g_c->lossy_packethandlers[byte].function = function; 1156 g_c->peer_name_callback = function;
1029} 1157}
1030 1158
1031/* Set callback function for peer name list changes. 1159/* Set callback function for peer list changes.
1032 * 1160 *
1033 * It gets called every time the name list changes(new peer/name, deleted peer) 1161 * It gets called every time the name list changes(new peer, deleted peer)
1034 * Function(Group_Chats *g_c, int groupnumber, int peernumber, TOX_CHAT_CHANGE change, void *userdata) 1162 * Function(Group_Chats *g_c, uint32_t groupnumber, void *userdata)
1035 */ 1163 */
1036void g_callback_group_namelistchange(Group_Chats *g_c, void (*function)(Messenger *m, int, int, uint8_t, void *), 1164void g_callback_peer_list_changed(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, void *))
1037 void *userdata)
1038{ 1165{
1039 g_c->peer_namelistchange = function; 1166 g_c->peer_list_changed_callback = function;
1040 g_c->group_namelistchange_userdata = userdata;
1041} 1167}
1042 1168
1169// TODO(sudden6): function signatures are incorrect
1043/* Set callback function for title changes. 1170/* Set callback function for title changes.
1044 * 1171 *
1045 * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * title, uint8_t length, void *userdata) 1172 * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * title, uint8_t length, void *userdata)
1046 * if friendgroupnumber == -1, then author is unknown (e.g. initial joining the group) 1173 * if friendgroupnumber == -1, then author is unknown (e.g. initial joining the group)
1047 */ 1174 */
1048void g_callback_group_title(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint8_t, 1175void g_callback_group_title(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, const uint8_t *,
1049 void *), void *userdata) 1176 size_t, void *))
1050{ 1177{
1051 g_c->title_callback = function; 1178 g_c->title_callback = function;
1052 g_c->title_callback_userdata = userdata;
1053} 1179}
1054 1180
1055/* Set a function to be called when a new peer joins a group chat. 1181/* Set a function to be called when a new peer joins a group chat.
1056 * 1182 *
1057 * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber) 1183 * Function(void *group object (set with group_set_object), uint32_t groupnumber, uint32_t friendgroupnumber)
1058 * 1184 *
1059 * return 0 on success. 1185 * return 0 on success.
1060 * return -1 on failure. 1186 * return -1 on failure.
1061 */ 1187 */
1062int callback_groupchat_peer_new(const Group_Chats *g_c, int groupnumber, void (*function)(void *, int, int)) 1188int callback_groupchat_peer_new(const Group_Chats *g_c, uint32_t groupnumber, void (*function)(void *, uint32_t,
1189 uint32_t))
1063{ 1190{
1064 Group_c *g = get_group_c(g_c, groupnumber); 1191 Group_c *g = get_group_c(g_c, groupnumber);
1065 1192
1066 if (!g) 1193 if (!g) {
1067 return -1; 1194 return -1;
1195 }
1068 1196
1069 g->peer_on_join = function; 1197 g->peer_on_join = function;
1070 return 0; 1198 return 0;
@@ -1072,17 +1200,19 @@ int callback_groupchat_peer_new(const Group_Chats *g_c, int groupnumber, void (*
1072 1200
1073/* Set a function to be called when a peer leaves a group chat. 1201/* Set a function to be called when a peer leaves a group chat.
1074 * 1202 *
1075 * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber, void *group peer object (set with group_peer_set_object)) 1203 * Function(void *group object (set with group_set_object), uint32_t groupnumber, uint32_t friendgroupnumber, void *group peer object (set with group_peer_set_object))
1076 * 1204 *
1077 * return 0 on success. 1205 * return 0 on success.
1078 * return -1 on failure. 1206 * return -1 on failure.
1079 */ 1207 */
1080int callback_groupchat_peer_delete(Group_Chats *g_c, int groupnumber, void (*function)(void *, int, int, void *)) 1208int callback_groupchat_peer_delete(Group_Chats *g_c, uint32_t groupnumber, void (*function)(void *, uint32_t, uint32_t,
1209 void *))
1081{ 1210{
1082 Group_c *g = get_group_c(g_c, groupnumber); 1211 Group_c *g = get_group_c(g_c, groupnumber);
1083 1212
1084 if (!g) 1213 if (!g) {
1085 return -1; 1214 return -1;
1215 }
1086 1216
1087 g->peer_on_leave = function; 1217 g->peer_on_leave = function;
1088 return 0; 1218 return 0;
@@ -1095,51 +1225,52 @@ int callback_groupchat_peer_delete(Group_Chats *g_c, int groupnumber, void (*fun
1095 * return 0 on success. 1225 * return 0 on success.
1096 * return -1 on failure. 1226 * return -1 on failure.
1097 */ 1227 */
1098int callback_groupchat_delete(Group_Chats *g_c, int groupnumber, void (*function)(void *, int)) 1228int callback_groupchat_delete(Group_Chats *g_c, uint32_t groupnumber, void (*function)(void *, uint32_t))
1099{ 1229{
1100 Group_c *g = get_group_c(g_c, groupnumber); 1230 Group_c *g = get_group_c(g_c, groupnumber);
1101 1231
1102 if (!g) 1232 if (!g) {
1103 return -1; 1233 return -1;
1234 }
1104 1235
1105 g->group_on_delete = function; 1236 g->group_on_delete = function;
1106 return 0; 1237 return 0;
1107} 1238}
1108 1239
1109static unsigned int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data, 1240static int send_message_group(const Group_Chats *g_c, uint32_t groupnumber, uint8_t message_id, const uint8_t *data,
1110 uint16_t len); 1241 uint16_t len);
1111 1242
1112#define GROUP_MESSAGE_PING_ID 0 1243#define GROUP_MESSAGE_PING_ID 0
1113int group_ping_send(const Group_Chats *g_c, int groupnumber) 1244static int group_ping_send(const Group_Chats *g_c, uint32_t groupnumber)
1114{ 1245{
1115 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_PING_ID, 0, 0)) { 1246 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_PING_ID, nullptr, 0) > 0) {
1116 return 0; 1247 return 0;
1117 } else {
1118 return -1;
1119 } 1248 }
1249
1250 return -1;
1120} 1251}
1121 1252
1122#define GROUP_MESSAGE_NEW_PEER_ID 16 1253#define GROUP_MESSAGE_NEW_PEER_ID 16
1123#define GROUP_MESSAGE_NEW_PEER_LENGTH (sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES * 2) 1254#define GROUP_MESSAGE_NEW_PEER_LENGTH (sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE * 2)
1124/* send a new_peer message 1255/* send a new_peer message
1125 * return 0 on success 1256 * return 0 on success
1126 * return -1 on failure 1257 * return -1 on failure
1127 */ 1258 */
1128int group_new_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_num, const uint8_t *real_pk, 1259static int group_new_peer_send(const Group_Chats *g_c, uint32_t groupnumber, uint16_t peer_num, const uint8_t *real_pk,
1129 uint8_t *temp_pk) 1260 uint8_t *temp_pk)
1130{ 1261{
1131 uint8_t packet[GROUP_MESSAGE_NEW_PEER_LENGTH]; 1262 uint8_t packet[GROUP_MESSAGE_NEW_PEER_LENGTH];
1132 1263
1133 peer_num = htons(peer_num); 1264 peer_num = net_htons(peer_num);
1134 memcpy(packet, &peer_num, sizeof(uint16_t)); 1265 memcpy(packet, &peer_num, sizeof(uint16_t));
1135 memcpy(packet + sizeof(uint16_t), real_pk, crypto_box_PUBLICKEYBYTES); 1266 memcpy(packet + sizeof(uint16_t), real_pk, CRYPTO_PUBLIC_KEY_SIZE);
1136 memcpy(packet + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES, temp_pk, crypto_box_PUBLICKEYBYTES); 1267 memcpy(packet + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE, temp_pk, CRYPTO_PUBLIC_KEY_SIZE);
1137 1268
1138 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_NEW_PEER_ID, packet, sizeof(packet))) { 1269 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_NEW_PEER_ID, packet, sizeof(packet)) > 0) {
1139 return 0; 1270 return 0;
1140 } else {
1141 return -1;
1142 } 1271 }
1272
1273 return -1;
1143} 1274}
1144 1275
1145#define GROUP_MESSAGE_KILL_PEER_ID 17 1276#define GROUP_MESSAGE_KILL_PEER_ID 17
@@ -1149,18 +1280,18 @@ int group_new_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_n
1149 * return 0 on success 1280 * return 0 on success
1150 * return -1 on failure 1281 * return -1 on failure
1151 */ 1282 */
1152static int group_kill_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_num) 1283static int group_kill_peer_send(const Group_Chats *g_c, uint32_t groupnumber, uint16_t peer_num)
1153{ 1284{
1154 uint8_t packet[GROUP_MESSAGE_KILL_PEER_LENGTH]; 1285 uint8_t packet[GROUP_MESSAGE_KILL_PEER_LENGTH];
1155 1286
1156 peer_num = htons(peer_num); 1287 peer_num = net_htons(peer_num);
1157 memcpy(packet, &peer_num, sizeof(uint16_t)); 1288 memcpy(packet, &peer_num, sizeof(uint16_t));
1158 1289
1159 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_KILL_PEER_ID, packet, sizeof(packet))) { 1290 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_KILL_PEER_ID, packet, sizeof(packet)) > 0) {
1160 return 0; 1291 return 0;
1161 } else {
1162 return -1;
1163 } 1292 }
1293
1294 return -1;
1164} 1295}
1165 1296
1166#define GROUP_MESSAGE_NAME_ID 48 1297#define GROUP_MESSAGE_NAME_ID 48
@@ -1169,94 +1300,124 @@ static int group_kill_peer_send(const Group_Chats *g_c, int groupnumber, uint16_
1169 * return 0 on success 1300 * return 0 on success
1170 * return -1 on failure 1301 * return -1 on failure
1171 */ 1302 */
1172static int group_name_send(const Group_Chats *g_c, int groupnumber, const uint8_t *nick, uint16_t nick_len) 1303static int group_name_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *nick, uint16_t nick_len)
1173{ 1304{
1174 if (nick_len > MAX_NAME_LENGTH) 1305 if (nick_len > MAX_NAME_LENGTH) {
1175 return -1; 1306 return -1;
1307 }
1176 1308
1177 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_NAME_ID, nick, nick_len)) { 1309 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_NAME_ID, nick, nick_len) > 0) {
1178 return 0; 1310 return 0;
1179 } else {
1180 return -1;
1181 } 1311 }
1312
1313 return -1;
1182} 1314}
1183 1315
1184#define GROUP_MESSAGE_TITLE_ID 49 1316#define GROUP_MESSAGE_TITLE_ID 49
1185 1317
1186/* set the group's title, limited to MAX_NAME_LENGTH 1318/* set the group's title, limited to MAX_NAME_LENGTH
1187 * return 0 on success 1319 * return 0 on success
1188 * return -1 on failure 1320 * return -1 if groupnumber is invalid.
1321 * return -2 if title is too long or empty.
1322 * return -3 if packet fails to send.
1189 */ 1323 */
1190int group_title_send(const Group_Chats *g_c, int groupnumber, const uint8_t *title, uint8_t title_len) 1324int group_title_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *title, uint8_t title_len)
1191{ 1325{
1192 if (title_len > MAX_NAME_LENGTH || title_len == 0)
1193 return -1;
1194
1195 Group_c *g = get_group_c(g_c, groupnumber); 1326 Group_c *g = get_group_c(g_c, groupnumber);
1196 1327
1197 if (!g) 1328 if (!g) {
1198 return -1; 1329 return -1;
1330 }
1331
1332 if (title_len > MAX_NAME_LENGTH || title_len == 0) {
1333 return -2;
1334 }
1199 1335
1200 /* same as already set? */ 1336 /* same as already set? */
1201 if (g->title_len == title_len && !memcmp(g->title, title, title_len)) 1337 if (g->title_len == title_len && !memcmp(g->title, title, title_len)) {
1202 return 0; 1338 return 0;
1339 }
1203 1340
1204 memcpy(g->title, title, title_len); 1341 memcpy(g->title, title, title_len);
1205 g->title_len = title_len; 1342 g->title_len = title_len;
1206 1343
1207 if (g->numpeers == 1) 1344 if (g->numpeers == 1) {
1208 return 0; 1345 return 0;
1346 }
1209 1347
1210 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_TITLE_ID, title, title_len)) 1348 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_TITLE_ID, title, title_len) > 0) {
1211 return 0; 1349 return 0;
1212 else 1350 }
1351
1352 return -3;
1353}
1354
1355/* return the group's title size.
1356 * return -1 of groupnumber is invalid.
1357 * return -2 if title is too long or empty.
1358 */
1359int group_title_get_size(const Group_Chats *g_c, uint32_t groupnumber)
1360{
1361 Group_c *g = get_group_c(g_c, groupnumber);
1362
1363 if (!g) {
1213 return -1; 1364 return -1;
1365 }
1366
1367 if (g->title_len == 0 || g->title_len > MAX_NAME_LENGTH) {
1368 return -2;
1369 }
1370
1371 return g->title_len;
1214} 1372}
1215 1373
1216/* Get group title from groupnumber and put it in title. 1374/* Get group title from groupnumber and put it in title.
1217 * title needs to be a valid memory location with a max_length size of at least MAX_NAME_LENGTH (128) bytes. 1375 * Title needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
1218 * 1376 *
1219 * return length of copied title if success. 1377 * return length of copied title if success.
1220 * return -1 if failure. 1378 * return -1 if groupnumber is invalid.
1379 * return -2 if title is too long or empty.
1221 */ 1380 */
1222int group_title_get(const Group_Chats *g_c, int groupnumber, uint8_t *title, uint32_t max_length) 1381int group_title_get(const Group_Chats *g_c, uint32_t groupnumber, uint8_t *title)
1223{ 1382{
1224 Group_c *g = get_group_c(g_c, groupnumber); 1383 Group_c *g = get_group_c(g_c, groupnumber);
1225 1384
1226 if (!g) 1385 if (!g) {
1227 return -1;
1228
1229 if (g->title_len == 0 || g->title_len > MAX_NAME_LENGTH)
1230 return -1; 1386 return -1;
1387 }
1231 1388
1232 if (max_length > g->title_len) 1389 if (g->title_len == 0 || g->title_len > MAX_NAME_LENGTH) {
1233 max_length = g->title_len; 1390 return -2;
1391 }
1234 1392
1235 memcpy(title, g->title, max_length); 1393 memcpy(title, g->title, g->title_len);
1236 return max_length; 1394 return g->title_len;
1237} 1395}
1238 1396
1239static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length) 1397static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length,
1398 void *userdata)
1240{ 1399{
1241 Group_Chats *g_c = m->group_chat_object; 1400 Group_Chats *g_c = (Group_Chats *)m->conferences_object;
1242 1401
1243 if (length <= 1) 1402 if (length <= 1) {
1244 return; 1403 return;
1404 }
1245 1405
1246 const uint8_t *invite_data = data + 1; 1406 const uint8_t *invite_data = data + 1;
1247 uint16_t invite_length = length - 1; 1407 uint16_t invite_length = length - 1;
1248 1408
1249 switch (data[0]) { 1409 switch (data[0]) {
1250 case INVITE_ID: { 1410 case INVITE_ID: {
1251 if (length != INVITE_PACKET_SIZE) 1411 if (length != INVITE_PACKET_SIZE) {
1252 return; 1412 return;
1413 }
1253 1414
1254 int groupnumber = get_group_num(g_c, data + 1 + sizeof(uint16_t)); 1415 int groupnumber = get_group_num(g_c, data + 1 + sizeof(uint16_t));
1255 1416
1256 if (groupnumber == -1) { 1417 if (groupnumber == -1) {
1257 if (g_c->invite_callback) 1418 if (g_c->invite_callback) {
1258 g_c->invite_callback(m, friendnumber, *(invite_data + sizeof(uint16_t)), invite_data, invite_length, 1419 g_c->invite_callback(m, friendnumber, *(invite_data + sizeof(uint16_t)), invite_data, invite_length, userdata);
1259 g_c->invite_callback_userdata); 1420 }
1260 1421
1261 return; 1422 return;
1262 } 1423 }
@@ -1265,23 +1426,27 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con
1265 } 1426 }
1266 1427
1267 case INVITE_RESPONSE_ID: { 1428 case INVITE_RESPONSE_ID: {
1268 if (length != INVITE_RESPONSE_PACKET_SIZE) 1429 if (length != INVITE_RESPONSE_PACKET_SIZE) {
1269 return; 1430 return;
1431 }
1270 1432
1271 uint16_t other_groupnum, groupnum; 1433 uint16_t other_groupnum, groupnum;
1272 memcpy(&groupnum, data + 1 + sizeof(uint16_t), sizeof(uint16_t)); 1434 memcpy(&groupnum, data + 1 + sizeof(uint16_t), sizeof(uint16_t));
1273 groupnum = ntohs(groupnum); 1435 groupnum = net_ntohs(groupnum);
1274 1436
1275 Group_c *g = get_group_c(g_c, groupnum); 1437 Group_c *g = get_group_c(g_c, groupnum);
1276 1438
1277 if (!g) 1439 if (!g) {
1278 return; 1440 return;
1441 }
1279 1442
1280 if (sodium_memcmp(data + 1 + sizeof(uint16_t) * 2, g->identifier, GROUP_IDENTIFIER_LENGTH) != 0) 1443 if (crypto_memcmp(data + 1 + sizeof(uint16_t) * 2, g->identifier, GROUP_IDENTIFIER_LENGTH) != 0) {
1281 return; 1444 return;
1445 }
1282 1446
1283 uint16_t peer_number = rand(); /* TODO: what if two people enter the group at the same time and 1447 /* TODO(irungentoo): what if two people enter the group at the same time and
1284 are given the same peer_number by different nodes? */ 1448 are given the same peer_number by different nodes? */
1449 uint16_t peer_number = rand();
1285 1450
1286 unsigned int tries = 0; 1451 unsigned int tries = 0;
1287 1452
@@ -1289,18 +1454,19 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con
1289 peer_number = rand(); 1454 peer_number = rand();
1290 ++tries; 1455 ++tries;
1291 1456
1292 if (tries > 32) 1457 if (tries > 32) {
1293 return; 1458 return;
1459 }
1294 } 1460 }
1295 1461
1296 memcpy(&other_groupnum, data + 1, sizeof(uint16_t)); 1462 memcpy(&other_groupnum, data + 1, sizeof(uint16_t));
1297 other_groupnum = ntohs(other_groupnum); 1463 other_groupnum = net_ntohs(other_groupnum);
1298 1464
1299 int friendcon_id = getfriendcon_id(m, friendnumber); 1465 int friendcon_id = getfriendcon_id(m, friendnumber);
1300 uint8_t real_pk[crypto_box_PUBLICKEYBYTES], temp_pk[crypto_box_PUBLICKEYBYTES]; 1466 uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE], temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
1301 get_friendcon_public_keys(real_pk, temp_pk, g_c->fr_c, friendcon_id); 1467 get_friendcon_public_keys(real_pk, temp_pk, g_c->fr_c, friendcon_id);
1302 1468
1303 addpeer(g_c, groupnum, real_pk, temp_pk, peer_number); 1469 addpeer(g_c, groupnum, real_pk, temp_pk, peer_number, userdata, true);
1304 int close_index = add_conn_to_groupchat(g_c, friendcon_id, groupnum, 0, 1); 1470 int close_index = add_conn_to_groupchat(g_c, friendcon_id, groupnum, 0, 1);
1305 1471
1306 if (close_index != -1) { 1472 if (close_index != -1) {
@@ -1327,11 +1493,13 @@ static int friend_in_close(Group_c *g, int friendcon_id)
1327 unsigned int i; 1493 unsigned int i;
1328 1494
1329 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { 1495 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
1330 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) 1496 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
1331 continue; 1497 continue;
1498 }
1332 1499
1333 if (g->close[i].number != (uint32_t)friendcon_id) 1500 if (g->close[i].number != (uint32_t)friendcon_id) {
1334 continue; 1501 continue;
1502 }
1335 1503
1336 return i; 1504 return i;
1337 } 1505 }
@@ -1359,35 +1527,43 @@ static unsigned int count_close_connected(Group_c *g)
1359static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t *identifier) 1527static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t *identifier)
1360{ 1528{
1361 uint8_t packet[1 + ONLINE_PACKET_DATA_SIZE]; 1529 uint8_t packet[1 + ONLINE_PACKET_DATA_SIZE];
1362 group_num = htons(group_num); 1530 group_num = net_htons(group_num);
1363 packet[0] = PACKET_ID_ONLINE_PACKET; 1531 packet[0] = PACKET_ID_ONLINE_PACKET;
1364 memcpy(packet + 1, &group_num, sizeof(uint16_t)); 1532 memcpy(packet + 1, &group_num, sizeof(uint16_t));
1365 memcpy(packet + 1 + sizeof(uint16_t), identifier, GROUP_IDENTIFIER_LENGTH); 1533 memcpy(packet + 1 + sizeof(uint16_t), identifier, GROUP_IDENTIFIER_LENGTH);
1366 return write_cryptpacket(fr_c->net_crypto, friend_connection_crypt_connection_id(fr_c, friendcon_id), packet, 1534 return write_cryptpacket(friendconn_net_crypto(fr_c), friend_connection_crypt_connection_id(fr_c, friendcon_id), packet,
1367 sizeof(packet), 0) != -1; 1535 sizeof(packet), 0) != -1;
1368} 1536}
1369 1537
1370static unsigned int send_peer_kill(Group_Chats *g_c, int friendcon_id, uint16_t group_num); 1538static unsigned int send_peer_kill(Group_Chats *g_c, int friendcon_id, uint16_t group_num);
1371 1539
1372static int handle_packet_online(Group_Chats *g_c, int friendcon_id, uint8_t *data, uint16_t length) 1540static int handle_packet_online(Group_Chats *g_c, int friendcon_id, const uint8_t *data, uint16_t length)
1373{ 1541{
1374 if (length != ONLINE_PACKET_DATA_SIZE) 1542 if (length != ONLINE_PACKET_DATA_SIZE) {
1375 return -1; 1543 return -1;
1544 }
1376 1545
1377 int groupnumber = get_group_num(g_c, data + sizeof(uint16_t)); 1546 int groupnumber = get_group_num(g_c, data + sizeof(uint16_t));
1547
1548 if (groupnumber == -1) {
1549 return -1;
1550 }
1551
1378 uint16_t other_groupnum; 1552 uint16_t other_groupnum;
1379 memcpy(&other_groupnum, data, sizeof(uint16_t)); 1553 memcpy(&other_groupnum, data, sizeof(uint16_t));
1380 other_groupnum = ntohs(other_groupnum); 1554 other_groupnum = net_ntohs(other_groupnum);
1381 1555
1382 Group_c *g = get_group_c(g_c, groupnumber); 1556 Group_c *g = get_group_c(g_c, groupnumber);
1383 1557
1384 if (!g) 1558 if (!g) {
1385 return -1; 1559 return -1;
1560 }
1386 1561
1387 int index = friend_in_close(g, friendcon_id); 1562 int index = friend_in_close(g, friendcon_id);
1388 1563
1389 if (index == -1) 1564 if (index == -1) {
1390 return -1; 1565 return -1;
1566 }
1391 1567
1392 if (g->close[index].type == GROUPCHAT_CLOSE_ONLINE) { 1568 if (g->close[index].type == GROUPCHAT_CLOSE_ONLINE) {
1393 return -1; 1569 return -1;
@@ -1404,8 +1580,9 @@ static int handle_packet_online(Group_Chats *g_c, int friendcon_id, uint8_t *dat
1404 if (g->number_joined != -1 && count_close_connected(g) >= DESIRED_CLOSE_CONNECTIONS) { 1580 if (g->number_joined != -1 && count_close_connected(g) >= DESIRED_CLOSE_CONNECTIONS) {
1405 int fr_close_index = friend_in_close(g, g->number_joined); 1581 int fr_close_index = friend_in_close(g, g->number_joined);
1406 1582
1407 if (fr_close_index == -1) 1583 if (fr_close_index == -1) {
1408 return -1; 1584 return -1;
1585 }
1409 1586
1410 if (!g->close[fr_close_index].closest) { 1587 if (!g->close[fr_close_index].closest) {
1411 g->close[fr_close_index].type = GROUPCHAT_CLOSE_NONE; 1588 g->close[fr_close_index].type = GROUPCHAT_CLOSE_NONE;
@@ -1431,7 +1608,7 @@ static unsigned int send_peer_kill(Group_Chats *g_c, int friendcon_id, uint16_t
1431{ 1608{
1432 uint8_t packet[1]; 1609 uint8_t packet[1];
1433 packet[0] = PEER_KILL_ID; 1610 packet[0] = PEER_KILL_ID;
1434 return send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_GROUPCHAT, group_num, packet, sizeof(packet)); 1611 return send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, packet, sizeof(packet));
1435} 1612}
1436 1613
1437 1614
@@ -1442,18 +1619,19 @@ static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t
1442{ 1619{
1443 uint8_t packet[1]; 1620 uint8_t packet[1];
1444 packet[0] = PEER_QUERY_ID; 1621 packet[0] = PEER_QUERY_ID;
1445 return send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_GROUPCHAT, group_num, packet, sizeof(packet)); 1622 return send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, packet, sizeof(packet));
1446} 1623}
1447 1624
1448/* return number of peers sent on success. 1625/* return number of peers sent on success.
1449 * return 0 on failure. 1626 * return 0 on failure.
1450 */ 1627 */
1451static unsigned int send_peers(Group_Chats *g_c, int groupnumber, int friendcon_id, uint16_t group_num) 1628static unsigned int send_peers(Group_Chats *g_c, uint32_t groupnumber, int friendcon_id, uint16_t group_num)
1452{ 1629{
1453 Group_c *g = get_group_c(g_c, groupnumber); 1630 Group_c *g = get_group_c(g_c, groupnumber);
1454 1631
1455 if (!g) 1632 if (!g) {
1456 return -1; 1633 return 0;
1634 }
1457 1635
1458 uint8_t packet[MAX_CRYPTO_DATA_SIZE - (1 + sizeof(uint16_t))]; 1636 uint8_t packet[MAX_CRYPTO_DATA_SIZE - (1 + sizeof(uint16_t))];
1459 packet[0] = PEER_RESPONSE_ID; 1637 packet[0] = PEER_RESPONSE_ID;
@@ -1463,8 +1641,8 @@ static unsigned int send_peers(Group_Chats *g_c, int groupnumber, int friendcon_
1463 unsigned int i; 1641 unsigned int i;
1464 1642
1465 for (i = 0; i < g->numpeers; ++i) { 1643 for (i = 0; i < g->numpeers; ++i) {
1466 if ((p - packet) + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES * 2 + 1 + g->group[i].nick_len > sizeof(packet)) { 1644 if ((p - packet) + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE * 2 + 1 + g->group[i].nick_len > sizeof(packet)) {
1467 if (send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_GROUPCHAT, group_num, packet, (p - packet))) { 1645 if (send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, packet, (p - packet))) {
1468 sent = i; 1646 sent = i;
1469 } else { 1647 } else {
1470 return sent; 1648 return sent;
@@ -1473,13 +1651,13 @@ static unsigned int send_peers(Group_Chats *g_c, int groupnumber, int friendcon_
1473 p = packet + 1; 1651 p = packet + 1;
1474 } 1652 }
1475 1653
1476 uint16_t peer_num = htons(g->group[i].peer_number); 1654 uint16_t peer_num = net_htons(g->group[i].peer_number);
1477 memcpy(p, &peer_num, sizeof(peer_num)); 1655 memcpy(p, &peer_num, sizeof(peer_num));
1478 p += sizeof(peer_num); 1656 p += sizeof(peer_num);
1479 memcpy(p, g->group[i].real_pk, crypto_box_PUBLICKEYBYTES); 1657 memcpy(p, g->group[i].real_pk, CRYPTO_PUBLIC_KEY_SIZE);
1480 p += crypto_box_PUBLICKEYBYTES; 1658 p += CRYPTO_PUBLIC_KEY_SIZE;
1481 memcpy(p, g->group[i].temp_pk, crypto_box_PUBLICKEYBYTES); 1659 memcpy(p, g->group[i].temp_pk, CRYPTO_PUBLIC_KEY_SIZE);
1482 p += crypto_box_PUBLICKEYBYTES; 1660 p += CRYPTO_PUBLIC_KEY_SIZE;
1483 *p = g->group[i].nick_len; 1661 *p = g->group[i].nick_len;
1484 p += 1; 1662 p += 1;
1485 memcpy(p, g->group[i].nick, g->group[i].nick_len); 1663 memcpy(p, g->group[i].nick, g->group[i].nick_len);
@@ -1487,76 +1665,83 @@ static unsigned int send_peers(Group_Chats *g_c, int groupnumber, int friendcon_
1487 } 1665 }
1488 1666
1489 if (sent != i) { 1667 if (sent != i) {
1490 if (send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_GROUPCHAT, group_num, packet, (p - packet))) { 1668 if (send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, packet, (p - packet))) {
1491 sent = i; 1669 sent = i;
1492 } 1670 }
1493 } 1671 }
1494 1672
1495 if (g->title_len) { 1673 if (g->title_len) {
1496 uint8_t Packet[1 + g->title_len]; 1674 VLA(uint8_t, Packet, 1 + g->title_len);
1497 Packet[0] = PEER_TITLE_ID; 1675 Packet[0] = PEER_TITLE_ID;
1498 memcpy(Packet + 1, g->title, g->title_len); 1676 memcpy(Packet + 1, g->title, g->title_len);
1499 send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_GROUPCHAT, group_num, Packet, sizeof(Packet)); 1677 send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, Packet, SIZEOF_VLA(Packet));
1500 } 1678 }
1501 1679
1502 return sent; 1680 return sent;
1503} 1681}
1504 1682
1505static int handle_send_peers(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length) 1683static int handle_send_peers(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *data, uint16_t length,
1684 void *userdata)
1506{ 1685{
1507 if (length == 0) 1686 if (length == 0) {
1508 return -1; 1687 return -1;
1688 }
1509 1689
1510 Group_c *g = get_group_c(g_c, groupnumber); 1690 Group_c *g = get_group_c(g_c, groupnumber);
1511 1691
1512 if (!g) 1692 if (!g) {
1513 return -1; 1693 return -1;
1694 }
1514 1695
1515 const uint8_t *d = data; 1696 const uint8_t *d = data;
1516 1697
1517 while ((unsigned int)(length - (d - data)) >= sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES * 2 + 1) { 1698 while ((unsigned int)(length - (d - data)) >= sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE * 2 + 1) {
1518 uint16_t peer_num; 1699 uint16_t peer_num;
1519 memcpy(&peer_num, d, sizeof(peer_num)); 1700 memcpy(&peer_num, d, sizeof(peer_num));
1520 peer_num = ntohs(peer_num); 1701 peer_num = net_ntohs(peer_num);
1521 d += sizeof(uint16_t); 1702 d += sizeof(uint16_t);
1522 int peer_index = addpeer(g_c, groupnumber, d, d + crypto_box_PUBLICKEYBYTES, peer_num); 1703 int peer_index = addpeer(g_c, groupnumber, d, d + CRYPTO_PUBLIC_KEY_SIZE, peer_num, userdata, true);
1523 1704
1524 if (peer_index == -1) 1705 if (peer_index == -1) {
1525 return -1; 1706 return -1;
1707 }
1526 1708
1527 if (g->status == GROUPCHAT_STATUS_VALID 1709 if (g->status == GROUPCHAT_STATUS_VALID
1528 && public_key_cmp(d, g_c->m->net_crypto->self_public_key) == 0) { 1710 && public_key_cmp(d, nc_get_self_public_key(g_c->m->net_crypto)) == 0) {
1529 g->peer_number = peer_num; 1711 g->peer_number = peer_num;
1530 g->status = GROUPCHAT_STATUS_CONNECTED; 1712 g->status = GROUPCHAT_STATUS_CONNECTED;
1531 group_name_send(g_c, groupnumber, g_c->m->name, g_c->m->name_length); 1713 group_name_send(g_c, groupnumber, g_c->m->name, g_c->m->name_length);
1532 } 1714 }
1533 1715
1534 d += crypto_box_PUBLICKEYBYTES * 2; 1716 d += CRYPTO_PUBLIC_KEY_SIZE * 2;
1535 uint8_t name_length = *d; 1717 uint8_t name_length = *d;
1536 d += 1; 1718 d += 1;
1537 1719
1538 if (name_length > (length - (d - data)) || name_length > MAX_NAME_LENGTH) 1720 if (name_length > (length - (d - data)) || name_length > MAX_NAME_LENGTH) {
1539 return -1; 1721 return -1;
1722 }
1540 1723
1541 setnick(g_c, groupnumber, peer_index, d, name_length); 1724 setnick(g_c, groupnumber, peer_index, d, name_length, userdata, true);
1542 d += name_length; 1725 d += name_length;
1543 } 1726 }
1544 1727
1545 return 0; 1728 return 0;
1546} 1729}
1547 1730
1548static void handle_direct_packet(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length, 1731static void handle_direct_packet(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *data, uint16_t length,
1549 int close_index) 1732 int close_index, void *userdata)
1550{ 1733{
1551 if (length == 0) 1734 if (length == 0) {
1552 return; 1735 return;
1736 }
1553 1737
1554 switch (data[0]) { 1738 switch (data[0]) {
1555 case PEER_KILL_ID: { 1739 case PEER_KILL_ID: {
1556 Group_c *g = get_group_c(g_c, groupnumber); 1740 Group_c *g = get_group_c(g_c, groupnumber);
1557 1741
1558 if (!g) 1742 if (!g) {
1559 return; 1743 return;
1744 }
1560 1745
1561 if (!g->close[close_index].closest) { 1746 if (!g->close[close_index].closest) {
1562 g->close[close_index].type = GROUPCHAT_CLOSE_NONE; 1747 g->close[close_index].type = GROUPCHAT_CLOSE_NONE;
@@ -1569,8 +1754,9 @@ static void handle_direct_packet(Group_Chats *g_c, int groupnumber, const uint8_
1569 case PEER_QUERY_ID: { 1754 case PEER_QUERY_ID: {
1570 Group_c *g = get_group_c(g_c, groupnumber); 1755 Group_c *g = get_group_c(g_c, groupnumber);
1571 1756
1572 if (!g) 1757 if (!g) {
1573 return; 1758 return;
1759 }
1574 1760
1575 send_peers(g_c, groupnumber, g->close[close_index].number, g->close[close_index].group_number); 1761 send_peers(g_c, groupnumber, g->close[close_index].number, g->close[close_index].group_number);
1576 } 1762 }
@@ -1578,13 +1764,13 @@ static void handle_direct_packet(Group_Chats *g_c, int groupnumber, const uint8_
1578 break; 1764 break;
1579 1765
1580 case PEER_RESPONSE_ID: { 1766 case PEER_RESPONSE_ID: {
1581 handle_send_peers(g_c, groupnumber, data + 1, length - 1); 1767 handle_send_peers(g_c, groupnumber, data + 1, length - 1, userdata);
1582 } 1768 }
1583 1769
1584 break; 1770 break;
1585 1771
1586 case PEER_TITLE_ID: { 1772 case PEER_TITLE_ID: {
1587 settitle(g_c, groupnumber, -1, data + 1, length - 1); 1773 settitle(g_c, groupnumber, -1, data + 1, length - 1, userdata);
1588 } 1774 }
1589 1775
1590 break; 1776 break;
@@ -1598,26 +1784,30 @@ static void handle_direct_packet(Group_Chats *g_c, int groupnumber, const uint8_
1598 * 1784 *
1599 * return number of messages sent. 1785 * return number of messages sent.
1600 */ 1786 */
1601static unsigned int send_message_all_close(const Group_Chats *g_c, int groupnumber, const uint8_t *data, 1787static unsigned int send_message_all_close(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *data,
1602 uint16_t length, int receiver) 1788 uint16_t length, int receiver)
1603{ 1789{
1604 Group_c *g = get_group_c(g_c, groupnumber); 1790 Group_c *g = get_group_c(g_c, groupnumber);
1605 1791
1606 if (!g) 1792 if (!g) {
1607 return 0; 1793 return 0;
1794 }
1608 1795
1609 uint16_t i, sent = 0; 1796 uint16_t i, sent = 0;
1610 1797
1611 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { 1798 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
1612 if (g->close[i].type != GROUPCHAT_CLOSE_ONLINE) 1799 if (g->close[i].type != GROUPCHAT_CLOSE_ONLINE) {
1613 continue; 1800 continue;
1801 }
1614 1802
1615 if ((int)i == receiver) 1803 if ((int)i == receiver) {
1616 continue; 1804 continue;
1805 }
1617 1806
1618 if (send_packet_group_peer(g_c->fr_c, g->close[i].number, PACKET_ID_MESSAGE_GROUPCHAT, g->close[i].group_number, data, 1807 if (send_packet_group_peer(g_c->fr_c, g->close[i].number, PACKET_ID_MESSAGE_CONFERENCE, g->close[i].group_number, data,
1619 length)) 1808 length)) {
1620 ++sent; 1809 ++sent;
1810 }
1621 } 1811 }
1622 1812
1623 return sent; 1813 return sent;
@@ -1628,22 +1818,26 @@ static unsigned int send_message_all_close(const Group_Chats *g_c, int groupnumb
1628 * 1818 *
1629 * return number of messages sent. 1819 * return number of messages sent.
1630 */ 1820 */
1631static unsigned int send_lossy_all_close(const Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length, 1821static unsigned int send_lossy_all_close(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *data,
1822 uint16_t length,
1632 int receiver) 1823 int receiver)
1633{ 1824{
1634 Group_c *g = get_group_c(g_c, groupnumber); 1825 Group_c *g = get_group_c(g_c, groupnumber);
1635 1826
1636 if (!g) 1827 if (!g) {
1637 return 0; 1828 return 0;
1829 }
1638 1830
1639 unsigned int i, sent = 0, num_connected_closest = 0, connected_closest[DESIRED_CLOSE_CONNECTIONS]; 1831 unsigned int i, sent = 0, num_connected_closest = 0, connected_closest[DESIRED_CLOSE_CONNECTIONS];
1640 1832
1641 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { 1833 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
1642 if (g->close[i].type != GROUPCHAT_CLOSE_ONLINE) 1834 if (g->close[i].type != GROUPCHAT_CLOSE_ONLINE) {
1643 continue; 1835 continue;
1836 }
1644 1837
1645 if ((int)i == receiver) 1838 if ((int)i == receiver) {
1646 continue; 1839 continue;
1840 }
1647 1841
1648 if (g->close[i].closest) { 1842 if (g->close[i].closest) {
1649 connected_closest[num_connected_closest] = i; 1843 connected_closest[num_connected_closest] = i;
@@ -1651,9 +1845,10 @@ static unsigned int send_lossy_all_close(const Group_Chats *g_c, int groupnumber
1651 continue; 1845 continue;
1652 } 1846 }
1653 1847
1654 if (send_lossy_group_peer(g_c->fr_c, g->close[i].number, PACKET_ID_LOSSY_GROUPCHAT, g->close[i].group_number, data, 1848 if (send_lossy_group_peer(g_c->fr_c, g->close[i].number, PACKET_ID_LOSSY_CONFERENCE, g->close[i].group_number, data,
1655 length)) 1849 length)) {
1656 ++sent; 1850 ++sent;
1851 }
1657 } 1852 }
1658 1853
1659 if (!num_connected_closest) { 1854 if (!num_connected_closest) {
@@ -1664,8 +1859,8 @@ static unsigned int send_lossy_all_close(const Group_Chats *g_c, int groupnumber
1664 uint64_t comp_val_old = ~0; 1859 uint64_t comp_val_old = ~0;
1665 1860
1666 for (i = 0; i < num_connected_closest; ++i) { 1861 for (i = 0; i < num_connected_closest; ++i) {
1667 uint8_t real_pk[crypto_box_PUBLICKEYBYTES]; 1862 uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE] = {0};
1668 uint8_t dht_temp_pk[crypto_box_PUBLICKEYBYTES]; 1863 uint8_t dht_temp_pk[CRYPTO_PUBLIC_KEY_SIZE] = {0};
1669 get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[connected_closest[i]].number); 1864 get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[connected_closest[i]].number);
1670 uint64_t comp_val = calculate_comp_value(g->real_pk, real_pk); 1865 uint64_t comp_val = calculate_comp_value(g->real_pk, real_pk);
1671 1866
@@ -1675,7 +1870,7 @@ static unsigned int send_lossy_all_close(const Group_Chats *g_c, int groupnumber
1675 } 1870 }
1676 } 1871 }
1677 1872
1678 if (send_lossy_group_peer(g_c->fr_c, g->close[to_send].number, PACKET_ID_LOSSY_GROUPCHAT, 1873 if (send_lossy_group_peer(g_c->fr_c, g->close[to_send].number, PACKET_ID_LOSSY_CONFERENCE,
1679 g->close[to_send].group_number, data, length)) { 1874 g->close[to_send].group_number, data, length)) {
1680 ++sent; 1875 ++sent;
1681 } 1876 }
@@ -1684,8 +1879,8 @@ static unsigned int send_lossy_all_close(const Group_Chats *g_c, int groupnumber
1684 comp_val_old = ~0; 1879 comp_val_old = ~0;
1685 1880
1686 for (i = 0; i < num_connected_closest; ++i) { 1881 for (i = 0; i < num_connected_closest; ++i) {
1687 uint8_t real_pk[crypto_box_PUBLICKEYBYTES]; 1882 uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE] = {0};
1688 uint8_t dht_temp_pk[crypto_box_PUBLICKEYBYTES]; 1883 uint8_t dht_temp_pk[CRYPTO_PUBLIC_KEY_SIZE] = {0};
1689 get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[connected_closest[i]].number); 1884 get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[connected_closest[i]].number);
1690 uint64_t comp_val = calculate_comp_value(real_pk, g->real_pk); 1885 uint64_t comp_val = calculate_comp_value(real_pk, g->real_pk);
1691 1886
@@ -1699,7 +1894,7 @@ static unsigned int send_lossy_all_close(const Group_Chats *g_c, int groupnumber
1699 return sent; 1894 return sent;
1700 } 1895 }
1701 1896
1702 if (send_lossy_group_peer(g_c->fr_c, g->close[to_send_other].number, PACKET_ID_LOSSY_GROUPCHAT, 1897 if (send_lossy_group_peer(g_c->fr_c, g->close[to_send_other].number, PACKET_ID_LOSSY_CONFERENCE,
1703 g->close[to_send_other].group_number, data, length)) { 1898 g->close[to_send_other].group_number, data, length)) {
1704 ++sent; 1899 ++sent;
1705 } 1900 }
@@ -1712,66 +1907,80 @@ static unsigned int send_lossy_all_close(const Group_Chats *g_c, int groupnumber
1712/* Send data of len with message_id to groupnumber. 1907/* Send data of len with message_id to groupnumber.
1713 * 1908 *
1714 * return number of peers it was sent to on success. 1909 * return number of peers it was sent to on success.
1715 * return 0 on failure. 1910 * return -1 if groupnumber is invalid.
1911 * return -2 if message is too long.
1912 * return -3 if we are not connected to the group.
1913 * reutrn -4 if message failed to send.
1716 */ 1914 */
1717static unsigned int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data, 1915static int send_message_group(const Group_Chats *g_c, uint32_t groupnumber, uint8_t message_id, const uint8_t *data,
1718 uint16_t len) 1916 uint16_t len)
1719{ 1917{
1720 if (len > MAX_GROUP_MESSAGE_DATA_LEN)
1721 return 0;
1722
1723 Group_c *g = get_group_c(g_c, groupnumber); 1918 Group_c *g = get_group_c(g_c, groupnumber);
1724 1919
1725 if (!g) 1920 if (!g) {
1726 return 0; 1921 return -1;
1922 }
1727 1923
1728 if (g->status != GROUPCHAT_STATUS_CONNECTED) 1924 if (len > MAX_GROUP_MESSAGE_DATA_LEN) {
1729 return 0; 1925 return -2;
1926 }
1927
1928 if (g->status != GROUPCHAT_STATUS_CONNECTED) {
1929 return -3;
1930 }
1730 1931
1731 uint8_t packet[sizeof(uint16_t) + sizeof(uint32_t) + 1 + len]; 1932 VLA(uint8_t, packet, sizeof(uint16_t) + sizeof(uint32_t) + 1 + len);
1732 uint16_t peer_num = htons(g->peer_number); 1933 uint16_t peer_num = net_htons(g->peer_number);
1733 memcpy(packet, &peer_num, sizeof(peer_num)); 1934 memcpy(packet, &peer_num, sizeof(peer_num));
1734 1935
1735 ++g->message_number; 1936 ++g->message_number;
1736 1937
1737 if (!g->message_number) 1938 if (!g->message_number) {
1738 ++g->message_number; 1939 ++g->message_number;
1940 }
1739 1941
1740 uint32_t message_num = htonl(g->message_number); 1942 uint32_t message_num = net_htonl(g->message_number);
1741 memcpy(packet + sizeof(uint16_t), &message_num, sizeof(message_num)); 1943 memcpy(packet + sizeof(uint16_t), &message_num, sizeof(message_num));
1742 1944
1743 packet[sizeof(uint16_t) + sizeof(uint32_t)] = message_id; 1945 packet[sizeof(uint16_t) + sizeof(uint32_t)] = message_id;
1744 1946
1745 if (len) 1947 if (len) {
1746 memcpy(packet + sizeof(uint16_t) + sizeof(uint32_t) + 1, data, len); 1948 memcpy(packet + sizeof(uint16_t) + sizeof(uint32_t) + 1, data, len);
1949 }
1747 1950
1748 return send_message_all_close(g_c, groupnumber, packet, sizeof(packet), -1); 1951 unsigned int ret = send_message_all_close(g_c, groupnumber, packet, SIZEOF_VLA(packet), -1);
1952
1953 return (ret == 0) ? -4 : ret;
1749} 1954}
1750 1955
1751/* send a group message 1956/* send a group message
1752 * return 0 on success 1957 * return 0 on success
1753 * return -1 on failure 1958 * see: send_message_group() for error codes.
1754 */ 1959 */
1755int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *message, uint16_t length) 1960int group_message_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *message, uint16_t length)
1756{ 1961{
1757 if (send_message_group(g_c, groupnumber, PACKET_ID_MESSAGE, message, length)) { 1962 int ret = send_message_group(g_c, groupnumber, PACKET_ID_MESSAGE, message, length);
1963
1964 if (ret > 0) {
1758 return 0; 1965 return 0;
1759 } else {
1760 return -1;
1761 } 1966 }
1967
1968 return ret;
1762} 1969}
1763 1970
1764/* send a group action 1971/* send a group action
1765 * return 0 on success 1972 * return 0 on success
1766 * return -1 on failure 1973 * see: send_message_group() for error codes.
1767 */ 1974 */
1768int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *action, uint16_t length) 1975int group_action_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *action, uint16_t length)
1769{ 1976{
1770 if (send_message_group(g_c, groupnumber, PACKET_ID_ACTION, action, length)) { 1977 int ret = send_message_group(g_c, groupnumber, PACKET_ID_ACTION, action, length);
1978
1979 if (ret > 0) {
1771 return 0; 1980 return 0;
1772 } else {
1773 return -1;
1774 } 1981 }
1982
1983 return ret;
1775} 1984}
1776 1985
1777/* High level function to send custom lossy packets. 1986/* High level function to send custom lossy packets.
@@ -1779,22 +1988,23 @@ int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *ac
1779 * return -1 on failure. 1988 * return -1 on failure.
1780 * return 0 on success. 1989 * return 0 on success.
1781 */ 1990 */
1782int send_group_lossy_packet(const Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length) 1991int send_group_lossy_packet(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *data, uint16_t length)
1783{ 1992{
1784 //TODO: length check here? 1993 // TODO(irungentoo): length check here?
1785 Group_c *g = get_group_c(g_c, groupnumber); 1994 Group_c *g = get_group_c(g_c, groupnumber);
1786 1995
1787 if (!g) 1996 if (!g) {
1788 return -1; 1997 return -1;
1998 }
1789 1999
1790 uint8_t packet[sizeof(uint16_t) * 2 + length]; 2000 VLA(uint8_t, packet, sizeof(uint16_t) * 2 + length);
1791 uint16_t peer_number = htons(g->peer_number); 2001 uint16_t peer_number = net_htons(g->peer_number);
1792 memcpy(packet, &peer_number, sizeof(uint16_t)); 2002 memcpy(packet, &peer_number, sizeof(uint16_t));
1793 uint16_t message_num = htons(g->lossy_message_number); 2003 uint16_t message_num = net_htons(g->lossy_message_number);
1794 memcpy(packet + sizeof(uint16_t), &message_num, sizeof(uint16_t)); 2004 memcpy(packet + sizeof(uint16_t), &message_num, sizeof(uint16_t));
1795 memcpy(packet + sizeof(uint16_t) * 2, data, length); 2005 memcpy(packet + sizeof(uint16_t) * 2, data, length);
1796 2006
1797 if (send_lossy_all_close(g_c, groupnumber, packet, sizeof(packet), -1) == 0) { 2007 if (send_lossy_all_close(g_c, groupnumber, packet, SIZEOF_VLA(packet), -1) == 0) {
1798 return -1; 2008 return -1;
1799 } 2009 }
1800 2010
@@ -1802,20 +2012,22 @@ int send_group_lossy_packet(const Group_Chats *g_c, int groupnumber, const uint8
1802 return 0; 2012 return 0;
1803} 2013}
1804 2014
1805static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length, 2015static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *data, uint16_t length,
1806 int close_index) 2016 int close_index, void *userdata)
1807{ 2017{
1808 if (length < sizeof(uint16_t) + sizeof(uint32_t) + 1) 2018 if (length < sizeof(uint16_t) + sizeof(uint32_t) + 1) {
1809 return; 2019 return;
2020 }
1810 2021
1811 Group_c *g = get_group_c(g_c, groupnumber); 2022 Group_c *g = get_group_c(g_c, groupnumber);
1812 2023
1813 if (!g) 2024 if (!g) {
1814 return; 2025 return;
2026 }
1815 2027
1816 uint16_t peer_number; 2028 uint16_t peer_number;
1817 memcpy(&peer_number, data, sizeof(uint16_t)); 2029 memcpy(&peer_number, data, sizeof(uint16_t));
1818 peer_number = ntohs(peer_number); 2030 peer_number = net_ntohs(peer_number);
1819 2031
1820 int index = get_peer_index(g, peer_number); 2032 int index = get_peer_index(g, peer_number);
1821 2033
@@ -1828,7 +2040,7 @@ static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const
1828 2040
1829 uint32_t message_number; 2041 uint32_t message_number;
1830 memcpy(&message_number, data + sizeof(uint16_t), sizeof(message_number)); 2042 memcpy(&message_number, data + sizeof(uint16_t), sizeof(message_number));
1831 message_number = ntohl(message_number); 2043 message_number = net_ntohl(message_number);
1832 2044
1833 if (g->group[index].last_message_number == 0) { 2045 if (g->group[index].last_message_number == 0) {
1834 g->group[index].last_message_number = message_number; 2046 g->group[index].last_message_number = message_number;
@@ -1845,80 +2057,89 @@ static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const
1845 2057
1846 switch (message_id) { 2058 switch (message_id) {
1847 case GROUP_MESSAGE_PING_ID: { 2059 case GROUP_MESSAGE_PING_ID: {
1848 if (msg_data_len != 0) 2060 if (msg_data_len != 0) {
1849 return; 2061 return;
2062 }
1850 2063
1851 g->group[index].last_recv = unix_time(); 2064 g->group[index].last_recv = unix_time();
1852 } 2065 }
1853 break; 2066 break;
1854 2067
1855 case GROUP_MESSAGE_NEW_PEER_ID: { 2068 case GROUP_MESSAGE_NEW_PEER_ID: {
1856 if (msg_data_len != GROUP_MESSAGE_NEW_PEER_LENGTH) 2069 if (msg_data_len != GROUP_MESSAGE_NEW_PEER_LENGTH) {
1857 return; 2070 return;
2071 }
1858 2072
1859 uint16_t new_peer_number; 2073 uint16_t new_peer_number;
1860 memcpy(&new_peer_number, msg_data, sizeof(uint16_t)); 2074 memcpy(&new_peer_number, msg_data, sizeof(uint16_t));
1861 new_peer_number = ntohs(new_peer_number); 2075 new_peer_number = net_ntohs(new_peer_number);
1862 addpeer(g_c, groupnumber, msg_data + sizeof(uint16_t), msg_data + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES, 2076 addpeer(g_c, groupnumber, msg_data + sizeof(uint16_t), msg_data + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE,
1863 new_peer_number); 2077 new_peer_number, userdata, true);
1864 } 2078 }
1865 break; 2079 break;
1866 2080
1867 case GROUP_MESSAGE_KILL_PEER_ID: { 2081 case GROUP_MESSAGE_KILL_PEER_ID: {
1868 if (msg_data_len != GROUP_MESSAGE_KILL_PEER_LENGTH) 2082 if (msg_data_len != GROUP_MESSAGE_KILL_PEER_LENGTH) {
1869 return; 2083 return;
2084 }
1870 2085
1871 uint16_t kill_peer_number; 2086 uint16_t kill_peer_number;
1872 memcpy(&kill_peer_number, msg_data, sizeof(uint16_t)); 2087 memcpy(&kill_peer_number, msg_data, sizeof(uint16_t));
1873 kill_peer_number = ntohs(kill_peer_number); 2088 kill_peer_number = net_ntohs(kill_peer_number);
1874 2089
1875 if (peer_number == kill_peer_number) { 2090 if (peer_number == kill_peer_number) {
1876 delpeer(g_c, groupnumber, index); 2091 delpeer(g_c, groupnumber, index, userdata);
1877 } else { 2092 } else {
1878 return; 2093 return;
1879 //TODO 2094 // TODO(irungentoo):
1880 } 2095 }
1881 } 2096 }
1882 break; 2097 break;
1883 2098
1884 case GROUP_MESSAGE_NAME_ID: { 2099 case GROUP_MESSAGE_NAME_ID: {
1885 if (setnick(g_c, groupnumber, index, msg_data, msg_data_len) == -1) 2100 if (setnick(g_c, groupnumber, index, msg_data, msg_data_len, userdata, true) == -1) {
1886 return; 2101 return;
2102 }
1887 } 2103 }
1888 break; 2104 break;
1889 2105
1890 case GROUP_MESSAGE_TITLE_ID: { 2106 case GROUP_MESSAGE_TITLE_ID: {
1891 if (settitle(g_c, groupnumber, index, msg_data, msg_data_len) == -1) 2107 if (settitle(g_c, groupnumber, index, msg_data, msg_data_len, userdata) == -1) {
1892 return; 2108 return;
2109 }
1893 } 2110 }
1894 break; 2111 break;
1895 2112
1896 case PACKET_ID_MESSAGE: { 2113 case PACKET_ID_MESSAGE: {
1897 if (msg_data_len == 0) 2114 if (msg_data_len == 0) {
1898 return; 2115 return;
2116 }
1899 2117
1900 uint8_t newmsg[msg_data_len + 1]; 2118 VLA(uint8_t, newmsg, msg_data_len + 1);
1901 memcpy(newmsg, msg_data, msg_data_len); 2119 memcpy(newmsg, msg_data, msg_data_len);
1902 newmsg[msg_data_len] = 0; 2120 newmsg[msg_data_len] = 0;
1903 2121
1904 //TODO 2122 // TODO(irungentoo):
1905 if (g_c->message_callback) 2123 if (g_c->message_callback) {
1906 g_c->message_callback(g_c->m, groupnumber, index, newmsg, msg_data_len, g_c->message_callback_userdata); 2124 g_c->message_callback(g_c->m, groupnumber, index, 0, newmsg, msg_data_len, userdata);
2125 }
1907 2126
1908 break; 2127 break;
1909 } 2128 }
1910 2129
1911 case PACKET_ID_ACTION: { 2130 case PACKET_ID_ACTION: {
1912 if (msg_data_len == 0) 2131 if (msg_data_len == 0) {
1913 return; 2132 return;
2133 }
1914 2134
1915 uint8_t newmsg[msg_data_len + 1]; 2135 VLA(uint8_t, newmsg, msg_data_len + 1);
1916 memcpy(newmsg, msg_data, msg_data_len); 2136 memcpy(newmsg, msg_data, msg_data_len);
1917 newmsg[msg_data_len] = 0; 2137 newmsg[msg_data_len] = 0;
1918 2138
1919 //TODO 2139 // TODO(irungentoo):
1920 if (g_c->action_callback) 2140 if (g_c->message_callback) {
1921 g_c->action_callback(g_c->m, groupnumber, index, newmsg, msg_data_len, g_c->action_callback_userdata); 2141 g_c->message_callback(g_c->m, groupnumber, index, 1, newmsg, msg_data_len, userdata);
2142 }
1922 2143
1923 break; 2144 break;
1924 } 2145 }
@@ -1927,44 +2148,49 @@ static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const
1927 return; 2148 return;
1928 } 2149 }
1929 2150
1930 send_message_all_close(g_c, groupnumber, data, length, -1/*TODO close_index*/); 2151 send_message_all_close(g_c, groupnumber, data, length, -1/* TODO(irungentoo) close_index */);
1931} 2152}
1932 2153
1933static int handle_packet(void *object, int friendcon_id, uint8_t *data, uint16_t length) 2154static int g_handle_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata)
1934{ 2155{
1935 Group_Chats *g_c = object; 2156 Group_Chats *g_c = (Group_Chats *)object;
1936 2157
1937 if (length < 1 + sizeof(uint16_t) + 1) 2158 if (length < 1 + sizeof(uint16_t) + 1) {
1938 return -1; 2159 return -1;
2160 }
1939 2161
1940 if (data[0] == PACKET_ID_ONLINE_PACKET) { 2162 if (data[0] == PACKET_ID_ONLINE_PACKET) {
1941 return handle_packet_online(g_c, friendcon_id, data + 1, length - 1); 2163 return handle_packet_online(g_c, friendcon_id, data + 1, length - 1);
1942 } 2164 }
1943 2165
1944 if (data[0] != PACKET_ID_DIRECT_GROUPCHAT && data[0] != PACKET_ID_MESSAGE_GROUPCHAT) 2166 if (data[0] != PACKET_ID_DIRECT_CONFERENCE && data[0] != PACKET_ID_MESSAGE_CONFERENCE) {
1945 return -1; 2167 return -1;
2168 }
1946 2169
1947 uint16_t groupnumber; 2170 uint16_t groupnumber;
1948 memcpy(&groupnumber, data + 1, sizeof(uint16_t)); 2171 memcpy(&groupnumber, data + 1, sizeof(uint16_t));
1949 groupnumber = ntohs(groupnumber); 2172 groupnumber = net_ntohs(groupnumber);
1950 Group_c *g = get_group_c(g_c, groupnumber); 2173 Group_c *g = get_group_c(g_c, groupnumber);
1951 2174
1952 if (!g) 2175 if (!g) {
1953 return -1; 2176 return -1;
2177 }
1954 2178
1955 int index = friend_in_close(g, friendcon_id); 2179 int index = friend_in_close(g, friendcon_id);
1956 2180
1957 if (index == -1) 2181 if (index == -1) {
1958 return -1; 2182 return -1;
2183 }
1959 2184
1960 switch (data[0]) { 2185 switch (data[0]) {
1961 case PACKET_ID_DIRECT_GROUPCHAT: { 2186 case PACKET_ID_DIRECT_CONFERENCE: {
1962 handle_direct_packet(g_c, groupnumber, data + 1 + sizeof(uint16_t), length - (1 + sizeof(uint16_t)), index); 2187 handle_direct_packet(g_c, groupnumber, data + 1 + sizeof(uint16_t), length - (1 + sizeof(uint16_t)), index, userdata);
1963 break; 2188 break;
1964 } 2189 }
1965 2190
1966 case PACKET_ID_MESSAGE_GROUPCHAT: { 2191 case PACKET_ID_MESSAGE_CONFERENCE: {
1967 handle_message_packet_group(g_c, groupnumber, data + 1 + sizeof(uint16_t), length - (1 + sizeof(uint16_t)), index); 2192 handle_message_packet_group(g_c, groupnumber, data + 1 + sizeof(uint16_t), length - (1 + sizeof(uint16_t)), index,
2193 userdata);
1968 break; 2194 break;
1969 } 2195 }
1970 2196
@@ -1982,12 +2208,14 @@ static int handle_packet(void *object, int friendcon_id, uint8_t *data, uint16_t
1982 * return 0 if packet was not received. 2208 * return 0 if packet was not received.
1983 * return 1 if packet was received. 2209 * return 1 if packet was received.
1984 * 2210 *
1985 * TODO: test this 2211 * TODO(irungentoo): test this
1986 */ 2212 */
1987static unsigned int lossy_packet_not_received(Group_c *g, int peer_index, uint16_t message_number) 2213static unsigned int lossy_packet_not_received(Group_c *g, int peer_index, uint16_t message_number)
1988{ 2214{
1989 if (peer_index == -1) 2215 if (peer_index == -1) {
2216 // TODO(sudden6): invalid return value
1990 return -1; 2217 return -1;
2218 }
1991 2219
1992 if (g->group[peer_index].bottom_lossy_number == g->group[peer_index].top_lossy_number) { 2220 if (g->group[peer_index].bottom_lossy_number == g->group[peer_index].top_lossy_number) {
1993 g->group[peer_index].top_lossy_number = message_number; 2221 g->group[peer_index].top_lossy_number = message_number;
@@ -2005,20 +2233,21 @@ static unsigned int lossy_packet_not_received(Group_c *g, int peer_index, uint16
2005 return 0; 2233 return 0;
2006 } 2234 }
2007 2235
2008 if ((uint16_t)(message_number - g->group[peer_index].bottom_lossy_number) > (1 << 15)) 2236 if ((uint16_t)(message_number - g->group[peer_index].bottom_lossy_number) > (1 << 15)) {
2237 // TODO(sudden6): invalid return value
2009 return -1; 2238 return -1;
2239 }
2010 2240
2011 uint16_t top_distance = message_number - g->group[peer_index].top_lossy_number; 2241 uint16_t top_distance = message_number - g->group[peer_index].top_lossy_number;
2012 2242
2013 if (top_distance >= MAX_LOSSY_COUNT) { 2243 if (top_distance >= MAX_LOSSY_COUNT) {
2014 sodium_memzero(g->group[peer_index].recv_lossy, sizeof(g->group[peer_index].recv_lossy)); 2244 crypto_memzero(g->group[peer_index].recv_lossy, sizeof(g->group[peer_index].recv_lossy));
2015 g->group[peer_index].top_lossy_number = message_number; 2245 g->group[peer_index].top_lossy_number = message_number;
2016 g->group[peer_index].bottom_lossy_number = (message_number - MAX_LOSSY_COUNT) + 1; 2246 g->group[peer_index].bottom_lossy_number = (message_number - MAX_LOSSY_COUNT) + 1;
2017 g->group[peer_index].recv_lossy[message_number % MAX_LOSSY_COUNT] = 1; 2247 g->group[peer_index].recv_lossy[message_number % MAX_LOSSY_COUNT] = 1;
2018 return 0;
2019 }
2020 2248
2021 if (top_distance < MAX_LOSSY_COUNT) { 2249 return 0;
2250 } else { // top_distance < MAX_LOSSY_COUNT
2022 unsigned int i; 2251 unsigned int i;
2023 2252
2024 for (i = g->group[peer_index].bottom_lossy_number; i != (g->group[peer_index].bottom_lossy_number + top_distance); 2253 for (i = g->group[peer_index].bottom_lossy_number; i != (g->group[peer_index].bottom_lossy_number + top_distance);
@@ -2029,50 +2258,56 @@ static unsigned int lossy_packet_not_received(Group_c *g, int peer_index, uint16
2029 g->group[peer_index].top_lossy_number = message_number; 2258 g->group[peer_index].top_lossy_number = message_number;
2030 g->group[peer_index].bottom_lossy_number = (message_number - MAX_LOSSY_COUNT) + 1; 2259 g->group[peer_index].bottom_lossy_number = (message_number - MAX_LOSSY_COUNT) + 1;
2031 g->group[peer_index].recv_lossy[message_number % MAX_LOSSY_COUNT] = 1; 2260 g->group[peer_index].recv_lossy[message_number % MAX_LOSSY_COUNT] = 1;
2261
2032 return 0; 2262 return 0;
2033 } 2263 }
2034
2035 return -1;
2036} 2264}
2037 2265
2038static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uint16_t length) 2266static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata)
2039{ 2267{
2040 Group_Chats *g_c = object; 2268 Group_Chats *g_c = (Group_Chats *)object;
2041 2269
2042 if (length < 1 + sizeof(uint16_t) * 3 + 1) 2270 if (length < 1 + sizeof(uint16_t) * 3 + 1) {
2043 return -1; 2271 return -1;
2272 }
2044 2273
2045 if (data[0] != PACKET_ID_LOSSY_GROUPCHAT) 2274 if (data[0] != PACKET_ID_LOSSY_CONFERENCE) {
2046 return -1; 2275 return -1;
2276 }
2047 2277
2048 uint16_t groupnumber, peer_number, message_number; 2278 uint16_t groupnumber, peer_number, message_number;
2049 memcpy(&groupnumber, data + 1, sizeof(uint16_t)); 2279 memcpy(&groupnumber, data + 1, sizeof(uint16_t));
2050 memcpy(&peer_number, data + 1 + sizeof(uint16_t), sizeof(uint16_t)); 2280 memcpy(&peer_number, data + 1 + sizeof(uint16_t), sizeof(uint16_t));
2051 memcpy(&message_number, data + 1 + sizeof(uint16_t) * 2, sizeof(uint16_t)); 2281 memcpy(&message_number, data + 1 + sizeof(uint16_t) * 2, sizeof(uint16_t));
2052 groupnumber = ntohs(groupnumber); 2282 groupnumber = net_ntohs(groupnumber);
2053 peer_number = ntohs(peer_number); 2283 peer_number = net_ntohs(peer_number);
2054 message_number = ntohs(message_number); 2284 message_number = net_ntohs(message_number);
2055 2285
2056 Group_c *g = get_group_c(g_c, groupnumber); 2286 Group_c *g = get_group_c(g_c, groupnumber);
2057 2287
2058 if (!g) 2288 if (!g) {
2059 return -1; 2289 return -1;
2290 }
2060 2291
2061 int index = friend_in_close(g, friendcon_id); 2292 int index = friend_in_close(g, friendcon_id);
2062 2293
2063 if (index == -1) 2294 if (index == -1) {
2064 return -1; 2295 return -1;
2296 }
2065 2297
2066 if (peer_number == g->peer_number) 2298 if (peer_number == g->peer_number) {
2067 return -1; 2299 return -1;
2300 }
2068 2301
2069 int peer_index = get_peer_index(g, peer_number); 2302 int peer_index = get_peer_index(g, peer_number);
2070 2303
2071 if (peer_index == -1) 2304 if (peer_index == -1) {
2072 return -1; 2305 return -1;
2306 }
2073 2307
2074 if (lossy_packet_not_received(g, peer_index, message_number)) 2308 if (lossy_packet_not_received(g, peer_index, message_number)) {
2075 return -1; 2309 return -1;
2310 }
2076 2311
2077 const uint8_t *lossy_data = data + 1 + sizeof(uint16_t) * 3; 2312 const uint8_t *lossy_data = data + 1 + sizeof(uint16_t) * 3;
2078 uint16_t lossy_length = length - (1 + sizeof(uint16_t) * 3); 2313 uint16_t lossy_length = length - (1 + sizeof(uint16_t) * 3);
@@ -2098,12 +2333,13 @@ static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uin
2098 * return 0 on success. 2333 * return 0 on success.
2099 * return -1 on failure 2334 * return -1 on failure
2100 */ 2335 */
2101int group_set_object(const Group_Chats *g_c, int groupnumber, void *object) 2336int group_set_object(const Group_Chats *g_c, uint32_t groupnumber, void *object)
2102{ 2337{
2103 Group_c *g = get_group_c(g_c, groupnumber); 2338 Group_c *g = get_group_c(g_c, groupnumber);
2104 2339
2105 if (!g) 2340 if (!g) {
2106 return -1; 2341 return -1;
2342 }
2107 2343
2108 g->object = object; 2344 g->object = object;
2109 return 0; 2345 return 0;
@@ -2114,15 +2350,17 @@ int group_set_object(const Group_Chats *g_c, int groupnumber, void *object)
2114 * return 0 on success. 2350 * return 0 on success.
2115 * return -1 on failure 2351 * return -1 on failure
2116 */ 2352 */
2117int group_peer_set_object(const Group_Chats *g_c, int groupnumber, int peernumber, void *object) 2353int group_peer_set_object(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, void *object)
2118{ 2354{
2119 Group_c *g = get_group_c(g_c, groupnumber); 2355 Group_c *g = get_group_c(g_c, groupnumber);
2120 2356
2121 if (!g) 2357 if (!g) {
2122 return -1; 2358 return -1;
2359 }
2123 2360
2124 if ((uint32_t)peernumber >= g->numpeers) 2361 if ((uint32_t)peernumber >= g->numpeers) {
2125 return -1; 2362 return -1;
2363 }
2126 2364
2127 g->group[peernumber].object = object; 2365 g->group[peernumber].object = object;
2128 return 0; 2366 return 0;
@@ -2133,12 +2371,13 @@ int group_peer_set_object(const Group_Chats *g_c, int groupnumber, int peernumbe
2133 * return NULL on failure. 2371 * return NULL on failure.
2134 * return object on success. 2372 * return object on success.
2135 */ 2373 */
2136void *group_get_object(const Group_Chats *g_c, int groupnumber) 2374void *group_get_object(const Group_Chats *g_c, uint32_t groupnumber)
2137{ 2375{
2138 Group_c *g = get_group_c(g_c, groupnumber); 2376 Group_c *g = get_group_c(g_c, groupnumber);
2139 2377
2140 if (!g) 2378 if (!g) {
2141 return NULL; 2379 return nullptr;
2380 }
2142 2381
2143 return g->object; 2382 return g->object;
2144} 2383}
@@ -2148,15 +2387,17 @@ void *group_get_object(const Group_Chats *g_c, int groupnumber)
2148 * return NULL on failure. 2387 * return NULL on failure.
2149 * return object on success. 2388 * return object on success.
2150 */ 2389 */
2151void *group_peer_get_object(const Group_Chats *g_c, int groupnumber, int peernumber) 2390void *group_peer_get_object(const Group_Chats *g_c, uint32_t groupnumber, int peernumber)
2152{ 2391{
2153 Group_c *g = get_group_c(g_c, groupnumber); 2392 Group_c *g = get_group_c(g_c, groupnumber);
2154 2393
2155 if (!g) 2394 if (!g) {
2156 return NULL; 2395 return nullptr;
2396 }
2157 2397
2158 if ((uint32_t)peernumber >= g->numpeers) 2398 if ((uint32_t)peernumber >= g->numpeers) {
2159 return NULL; 2399 return nullptr;
2400 }
2160 2401
2161 return g->group[peernumber].object; 2402 return g->group[peernumber].object;
2162} 2403}
@@ -2164,37 +2405,41 @@ void *group_peer_get_object(const Group_Chats *g_c, int groupnumber, int peernum
2164/* Interval in seconds to send ping messages */ 2405/* Interval in seconds to send ping messages */
2165#define GROUP_PING_INTERVAL 20 2406#define GROUP_PING_INTERVAL 20
2166 2407
2167static int ping_groupchat(Group_Chats *g_c, int groupnumber) 2408static int ping_groupchat(Group_Chats *g_c, uint32_t groupnumber)
2168{ 2409{
2169 Group_c *g = get_group_c(g_c, groupnumber); 2410 Group_c *g = get_group_c(g_c, groupnumber);
2170 2411
2171 if (!g) 2412 if (!g) {
2172 return -1; 2413 return -1;
2414 }
2173 2415
2174 if (is_timeout(g->last_sent_ping, GROUP_PING_INTERVAL)) { 2416 if (is_timeout(g->last_sent_ping, GROUP_PING_INTERVAL)) {
2175 if (group_ping_send(g_c, groupnumber) != -1) /* Ping */ 2417 if (group_ping_send(g_c, groupnumber) != -1) { /* Ping */
2176 g->last_sent_ping = unix_time(); 2418 g->last_sent_ping = unix_time();
2419 }
2177 } 2420 }
2178 2421
2179 return 0; 2422 return 0;
2180} 2423}
2181 2424
2182static int groupchat_clear_timedout(Group_Chats *g_c, int groupnumber) 2425static int groupchat_clear_timedout(Group_Chats *g_c, uint32_t groupnumber, void *userdata)
2183{ 2426{
2184 Group_c *g = get_group_c(g_c, groupnumber); 2427 Group_c *g = get_group_c(g_c, groupnumber);
2185 2428
2186 if (!g) 2429 if (!g) {
2187 return -1; 2430 return -1;
2431 }
2188 2432
2189 uint32_t i; 2433 uint32_t i;
2190 2434
2191 for (i = 0; i < g->numpeers; ++i) { 2435 for (i = 0; i < g->numpeers; ++i) {
2192 if (g->peer_number != g->group[i].peer_number && is_timeout(g->group[i].last_recv, GROUP_PING_INTERVAL * 3)) { 2436 if (g->peer_number != g->group[i].peer_number && is_timeout(g->group[i].last_recv, GROUP_PING_INTERVAL * 3)) {
2193 delpeer(g_c, groupnumber, i); 2437 delpeer(g_c, groupnumber, i, userdata);
2194 } 2438 }
2195 2439
2196 if (g->group == NULL || i >= g->numpeers) 2440 if (g->group == nullptr || i >= g->numpeers) {
2197 break; 2441 break;
2442 }
2198 } 2443 }
2199 2444
2200 return 0; 2445 return 0;
@@ -2209,8 +2454,9 @@ void send_name_all_groups(Group_Chats *g_c)
2209 for (i = 0; i < g_c->num_chats; ++i) { 2454 for (i = 0; i < g_c->num_chats; ++i) {
2210 Group_c *g = get_group_c(g_c, i); 2455 Group_c *g = get_group_c(g_c, i);
2211 2456
2212 if (!g) 2457 if (!g) {
2213 continue; 2458 continue;
2459 }
2214 2460
2215 if (g->status == GROUPCHAT_STATUS_CONNECTED) { 2461 if (g->status == GROUPCHAT_STATUS_CONNECTED) {
2216 group_name_send(g_c, i, g_c->m->name, g_c->m->name_length); 2462 group_name_send(g_c, i, g_c->m->name, g_c->m->name_length);
@@ -2221,41 +2467,44 @@ void send_name_all_groups(Group_Chats *g_c)
2221/* Create new groupchat instance. */ 2467/* Create new groupchat instance. */
2222Group_Chats *new_groupchats(Messenger *m) 2468Group_Chats *new_groupchats(Messenger *m)
2223{ 2469{
2224 if (!m) 2470 if (!m) {
2225 return NULL; 2471 return nullptr;
2472 }
2226 2473
2227 Group_Chats *temp = calloc(1, sizeof(Group_Chats)); 2474 Group_Chats *temp = (Group_Chats *)calloc(1, sizeof(Group_Chats));
2228 2475
2229 if (temp == NULL) 2476 if (temp == nullptr) {
2230 return NULL; 2477 return nullptr;
2478 }
2231 2479
2232 temp->m = m; 2480 temp->m = m;
2233 temp->fr_c = m->fr_c; 2481 temp->fr_c = m->fr_c;
2234 m->group_chat_object = temp; 2482 m->conferences_object = temp;
2235 m_callback_group_invite(m, &handle_friend_invite_packet); 2483 m_callback_conference_invite(m, &handle_friend_invite_packet);
2236 2484
2237 return temp; 2485 return temp;
2238} 2486}
2239 2487
2240/* main groupchats loop. */ 2488/* main groupchats loop. */
2241void do_groupchats(Group_Chats *g_c) 2489void do_groupchats(Group_Chats *g_c, void *userdata)
2242{ 2490{
2243 unsigned int i; 2491 unsigned int i;
2244 2492
2245 for (i = 0; i < g_c->num_chats; ++i) { 2493 for (i = 0; i < g_c->num_chats; ++i) {
2246 Group_c *g = get_group_c(g_c, i); 2494 Group_c *g = get_group_c(g_c, i);
2247 2495
2248 if (!g) 2496 if (!g) {
2249 continue; 2497 continue;
2498 }
2250 2499
2251 if (g->status == GROUPCHAT_STATUS_CONNECTED) { 2500 if (g->status == GROUPCHAT_STATUS_CONNECTED) {
2252 connect_to_closest(g_c, i); 2501 connect_to_closest(g_c, i, userdata);
2253 ping_groupchat(g_c, i); 2502 ping_groupchat(g_c, i);
2254 groupchat_clear_timedout(g_c, i); 2503 groupchat_clear_timedout(g_c, i, userdata);
2255 } 2504 }
2256 } 2505 }
2257 2506
2258 //TODO 2507 // TODO(irungentoo):
2259} 2508}
2260 2509
2261/* Free everything related with group chats. */ 2510/* Free everything related with group chats. */
@@ -2267,8 +2516,8 @@ void kill_groupchats(Group_Chats *g_c)
2267 del_groupchat(g_c, i); 2516 del_groupchat(g_c, i);
2268 } 2517 }
2269 2518
2270 m_callback_group_invite(g_c->m, NULL); 2519 m_callback_conference_invite(g_c->m, nullptr);
2271 g_c->m->group_chat_object = 0; 2520 g_c->m->conferences_object = nullptr;
2272 free(g_c); 2521 free(g_c);
2273} 2522}
2274 2523
@@ -2295,7 +2544,7 @@ uint32_t count_chatlist(Group_Chats *g_c)
2295 * Otherwise, returns the number of elements copied. 2544 * Otherwise, returns the number of elements copied.
2296 * If the array was too small, the contents 2545 * If the array was too small, the contents
2297 * of out_list will be truncated to list_size. */ 2546 * of out_list will be truncated to list_size. */
2298uint32_t copy_chatlist(Group_Chats *g_c, int32_t *out_list, uint32_t list_size) 2547uint32_t copy_chatlist(Group_Chats *g_c, uint32_t *out_list, uint32_t list_size)
2299{ 2548{
2300 if (!out_list) { 2549 if (!out_list) {
2301 return 0; 2550 return 0;
diff --git a/toxcore/group.h b/toxcore/group.h
index 8ae0e40e..a81dac39 100644
--- a/toxcore/group.h
+++ b/toxcore/group.h
@@ -1,27 +1,26 @@
1/* group.h 1/*
2 *
3 * Slightly better groupchats implementation. 2 * Slightly better groupchats implementation.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2014 Tox project.
4 * 8 *
5 * Copyright (C) 2014 Tox project All Rights Reserved. 9 * This file is part of Tox, the free peer to peer instant messenger.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23
24
25#ifndef GROUP_H 24#ifndef GROUP_H
26#define GROUP_H 25#define GROUP_H
27 26
@@ -41,8 +40,8 @@ enum {
41#define MAX_LOSSY_COUNT 256 40#define MAX_LOSSY_COUNT 256
42 41
43typedef struct { 42typedef struct {
44 uint8_t real_pk[crypto_box_PUBLICKEYBYTES]; 43 uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
45 uint8_t temp_pk[crypto_box_PUBLICKEYBYTES]; 44 uint8_t temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
46 45
47 uint64_t last_recv; 46 uint64_t last_recv;
48 uint32_t last_message_number; 47 uint32_t last_message_number;
@@ -60,7 +59,7 @@ typedef struct {
60 59
61#define DESIRED_CLOSE_CONNECTIONS 4 60#define DESIRED_CLOSE_CONNECTIONS 4
62#define MAX_GROUP_CONNECTIONS 16 61#define MAX_GROUP_CONNECTIONS 16
63#define GROUP_IDENTIFIER_LENGTH (1 + crypto_box_KEYBYTES) /* type + crypto_box_KEYBYTES so we can use new_symmetric_key(...) to fill it */ 62#define GROUP_IDENTIFIER_LENGTH (1 + CRYPTO_SYMMETRIC_KEY_SIZE) /* type + CRYPTO_SYMMETRIC_KEY_SIZE so we can use new_symmetric_key(...) to fill it */
64 63
65enum { 64enum {
66 GROUPCHAT_CLOSE_NONE, 65 GROUPCHAT_CLOSE_NONE,
@@ -81,11 +80,11 @@ typedef struct {
81 uint16_t group_number; 80 uint16_t group_number;
82 } close[MAX_GROUP_CONNECTIONS]; 81 } close[MAX_GROUP_CONNECTIONS];
83 82
84 uint8_t real_pk[crypto_box_PUBLICKEYBYTES]; 83 uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
85 struct { 84 struct {
86 uint8_t entry; 85 uint8_t entry;
87 uint8_t real_pk[crypto_box_PUBLICKEYBYTES]; 86 uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
88 uint8_t temp_pk[crypto_box_PUBLICKEYBYTES]; 87 uint8_t temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
89 } closest_peers[DESIRED_CLOSE_CONNECTIONS]; 88 } closest_peers[DESIRED_CLOSE_CONNECTIONS];
90 uint8_t changed; 89 uint8_t changed;
91 90
@@ -104,9 +103,9 @@ typedef struct {
104 103
105 void *object; 104 void *object;
106 105
107 void (*peer_on_join)(void *, int, int); 106 void (*peer_on_join)(void *, uint32_t, uint32_t);
108 void (*peer_on_leave)(void *, int, int, void *); 107 void (*peer_on_leave)(void *, uint32_t, uint32_t, void *);
109 void (*group_on_delete)(void *, int); 108 void (*group_on_delete)(void *, uint32_t);
110} Group_c; 109} Group_c;
111 110
112typedef struct { 111typedef struct {
@@ -116,65 +115,56 @@ typedef struct {
116 Group_c *chats; 115 Group_c *chats;
117 uint32_t num_chats; 116 uint32_t num_chats;
118 117
119 void (*invite_callback)(Messenger *m, int32_t, uint8_t, const uint8_t *, uint16_t, void *); 118 void (*invite_callback)(Messenger *m, uint32_t, int, const uint8_t *, size_t, void *);
120 void *invite_callback_userdata; 119 void (*message_callback)(Messenger *m, uint32_t, uint32_t, int, const uint8_t *, size_t, void *);
121 void (*message_callback)(Messenger *m, int, int, const uint8_t *, uint16_t, void *); 120 void (*peer_name_callback)(Messenger *m, uint32_t, uint32_t, const uint8_t *, size_t, void *);
122 void *message_callback_userdata; 121 void (*peer_list_changed_callback)(Messenger *m, uint32_t, void *);
123 void (*action_callback)(Messenger *m, int, int, const uint8_t *, uint16_t, void *); 122 void (*title_callback)(Messenger *m, uint32_t, uint32_t, const uint8_t *, size_t, void *);
124 void *action_callback_userdata;
125 void (*peer_namelistchange)(Messenger *m, int, int, uint8_t, void *);
126 void *group_namelistchange_userdata;
127 void (*title_callback)(Messenger *m, int, int, const uint8_t *, uint8_t, void *);
128 void *title_callback_userdata;
129 123
130 struct { 124 struct {
131 int (*function)(void *, int, int, void *, const uint8_t *, uint16_t); 125 int (*function)(void *, uint32_t, uint32_t, void *, const uint8_t *, uint16_t);
132 } lossy_packethandlers[256]; 126 } lossy_packethandlers[256];
133} Group_Chats; 127} Group_Chats;
134 128
135/* Set the callback for group invites. 129/* Set the callback for group invites.
136 * 130 *
137 * Function(Group_Chats *g_c, int32_t friendnumber, uint8_t type, uint8_t *data, uint16_t length, void *userdata) 131 * Function(Group_Chats *g_c, uint32_t friendnumber, uint8_t type, uint8_t *data, uint16_t length, void *userdata)
138 * 132 *
139 * data of length is what needs to be passed to join_groupchat(). 133 * data of length is what needs to be passed to join_groupchat().
140 */ 134 */
141void g_callback_group_invite(Group_Chats *g_c, void (*function)(Messenger *m, int32_t, uint8_t, const uint8_t *, 135void g_callback_group_invite(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, int, const uint8_t *,
142 uint16_t, void *), void *userdata); 136 size_t, void *));
143 137
144/* Set the callback for group messages. 138/* Set the callback for group messages.
145 * 139 *
146 * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata) 140 * Function(Group_Chats *g_c, uint32_t groupnumber, uint32_t friendgroupnumber, uint8_t * message, uint16_t length, void *userdata)
147 */ 141 */
148void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t, 142void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, int, const uint8_t *,
149 void *), void *userdata); 143 size_t, void *));
150 144
151/* Set the callback for group actions.
152 *
153 * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata)
154 */
155void g_callback_group_action(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t,
156 void *), void *userdata);
157 145
158/* Set callback function for title changes. 146/* Set callback function for title changes.
159 * 147 *
160 * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * title, uint8_t length, void *userdata) 148 * Function(Group_Chats *g_c, uint32_t groupnumber, uint32_t friendgroupnumber, uint8_t * title, uint8_t length, void *userdata)
161 * if friendgroupnumber == -1, then author is unknown (e.g. initial joining the group) 149 * if friendgroupnumber == -1, then author is unknown (e.g. initial joining the group)
162 */ 150 */
163void g_callback_group_title(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint8_t, 151void g_callback_group_title(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, const uint8_t *,
164 void *), void *userdata); 152 size_t, void *));
165 153
166/* Set callback function for peer name list changes. 154/* Set callback function for peer nickname changes.
167 * 155 *
168 * It gets called every time the name list changes(new peer/name, deleted peer) 156 * It gets called every time a peer changes their nickname.
169 * Function(Group_Chats *g_c, int groupnumber, int peernumber, TOX_CHAT_CHANGE change, void *userdata) 157 * Function(Group_Chats *g_c, uint32_t groupnumber, uint32_t peernumber, const uint8_t *nick, size_t nick_len, void *userdata)
170 */ 158 */
171enum { 159void g_callback_peer_name(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, const uint8_t *,
172 CHAT_CHANGE_PEER_ADD, 160 size_t, void *));
173 CHAT_CHANGE_PEER_DEL, 161
174 CHAT_CHANGE_PEER_NAME, 162/* Set callback function for peer list changes.
175}; 163 *
176void g_callback_group_namelistchange(Group_Chats *g_c, void (*function)(Messenger *m, int, int, uint8_t, void *), 164 * It gets called every time the name list changes(new peer, deleted peer)
177 void *userdata); 165 * Function(Group_Chats *g_c, uint32_t groupnumber, void *userdata)
166 */
167void g_callback_peer_list_changed(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, void *));
178 168
179/* Creates a new groupchat and puts it in the chats array. 169/* Creates a new groupchat and puts it in the chats array.
180 * 170 *
@@ -188,77 +178,107 @@ int add_groupchat(Group_Chats *g_c, uint8_t type);
188/* Delete a groupchat from the chats array. 178/* Delete a groupchat from the chats array.
189 * 179 *
190 * return 0 on success. 180 * return 0 on success.
191 * return -1 if failure. 181 * return -1 if groupnumber is invalid.
192 */ 182 */
193int del_groupchat(Group_Chats *g_c, int groupnumber); 183int del_groupchat(Group_Chats *g_c, uint32_t groupnumber);
194 184
195/* Copy the public key of peernumber who is in groupnumber to pk. 185/* Copy the public key of peernumber who is in groupnumber to pk.
196 * pk must be crypto_box_PUBLICKEYBYTES long. 186 * pk must be CRYPTO_PUBLIC_KEY_SIZE long.
197 * 187 *
198 * returns 0 on success 188 * return 0 on success
199 * returns -1 on failure 189 * return -1 if groupnumber is invalid.
190 * return -2 if peernumber is invalid.
200 */ 191 */
201int group_peer_pubkey(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *pk); 192int group_peer_pubkey(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, uint8_t *pk);
193
194/*
195 * Return the size of peernumber's name.
196 *
197 * return -1 if groupnumber is invalid.
198 * return -2 if peernumber is invalid.
199 */
200int group_peername_size(const Group_Chats *g_c, uint32_t groupnumber, int32_t peernumber);
202 201
203/* Copy the name of peernumber who is in groupnumber to name. 202/* Copy the name of peernumber who is in groupnumber to name.
204 * name must be at least MAX_NAME_LENGTH long. 203 * name must be at least MAX_NAME_LENGTH long.
205 * 204 *
206 * return length of name if success 205 * return length of name if success
207 * return -1 if failure 206 * return -1 if groupnumber is invalid.
207 * return -2 if peernumber is invalid.
208 */ 208 */
209int group_peername(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *name); 209int group_peername(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, uint8_t *name);
210 210
211/* invite friendnumber to groupnumber 211/* invite friendnumber to groupnumber
212 * return 0 on success 212 *
213 * return -1 on failure 213 * return 0 on success.
214 * return -1 if groupnumber is invalid.
215 * return -2 if invite packet failed to send.
214 */ 216 */
215int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber); 217int invite_friend(Group_Chats *g_c, uint32_t friendnumber, uint32_t groupnumber);
216 218
217/* Join a group (you need to have been invited first.) 219/* Join a group (you need to have been invited first.)
218 * 220 *
219 * expected_type is the groupchat type we expect the chat we are joining is. 221 * expected_type is the groupchat type we expect the chat we are joining is.
220 * 222 *
221 * returns group number on success 223 * return group number on success.
222 * returns -1 on failure. 224 * return -1 if data length is invalid.
225 * return -2 if group is not the expected type.
226 * return -3 if friendnumber is invalid.
227 * return -4 if client is already in this group.
228 * return -5 if group instance failed to initialize.
229 * return -6 if join packet fails to send.
223 */ 230 */
224int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t expected_type, const uint8_t *data, uint16_t length); 231int join_groupchat(Group_Chats *g_c, uint32_t friendnumber, uint8_t expected_type, const uint8_t *data,
232 uint16_t length);
225 233
226/* send a group message 234/* send a group message
227 * return 0 on success 235 * return 0 on success
228 * return -1 on failure 236 * see: send_message_group() for error codes.
229 */ 237 */
230int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *message, uint16_t length); 238int group_message_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *message, uint16_t length);
231 239
232/* send a group action 240/* send a group action
233 * return 0 on success 241 * return 0 on success
234 * return -1 on failure 242 * see: send_message_group() for error codes.
235 */ 243 */
236int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *action, uint16_t length); 244int group_action_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *action, uint16_t length);
237 245
238/* set the group's title, limited to MAX_NAME_LENGTH 246/* set the group's title, limited to MAX_NAME_LENGTH
239 * return 0 on success 247 * return 0 on success
240 * return -1 on failure 248 * return -1 if groupnumber is invalid.
249 * return -2 if title is too long or empty.
250 * return -3 if packet fails to send.
241 */ 251 */
242int group_title_send(const Group_Chats *g_c, int groupnumber, const uint8_t *title, uint8_t title_len); 252int group_title_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *title, uint8_t title_len);
243 253
244 254
255/* return the group's title size.
256 * return -1 of groupnumber is invalid.
257 * return -2 if title is too long or empty.
258 */
259int group_title_get_size(const Group_Chats *g_c, uint32_t groupnumber);
260
245/* Get group title from groupnumber and put it in title. 261/* Get group title from groupnumber and put it in title.
246 * title needs to be a valid memory location with a max_length size of at least MAX_NAME_LENGTH (128) bytes. 262 * Title needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
247 * 263 *
248 * return length of copied title if success. 264 * return length of copied title if success.
249 * return -1 if failure. 265 * return -1 if groupnumber is invalid.
266 * return -2 if title is too long or empty.
250 */ 267 */
251int group_title_get(const Group_Chats *g_c, int groupnumber, uint8_t *title, uint32_t max_length); 268int group_title_get(const Group_Chats *g_c, uint32_t groupnumber, uint8_t *title);
252 269
253/* Return the number of peers in the group chat on success. 270/* Return the number of peers in the group chat on success.
254 * return -1 on failure 271 * return -1 if groupnumber is invalid.
255 */ 272 */
256int group_number_peers(const Group_Chats *g_c, int groupnumber); 273int group_number_peers(const Group_Chats *g_c, uint32_t groupnumber);
257 274
258/* return 1 if the peernumber corresponds to ours. 275/* return 1 if the peernumber corresponds to ours.
259 * return 0 on failure. 276 * return 0 if the peernumber is not ours.
277 * return -1 if groupnumber is invalid.
278 * return -2 if peernumber is invalid.
279 * return -3 if we are not connected to the group chat.
260 */ 280 */
261unsigned int group_peernumber_is_ours(const Group_Chats *g_c, int groupnumber, int peernumber); 281int group_peernumber_is_ours(const Group_Chats *g_c, uint32_t groupnumber, int peernumber);
262 282
263/* List all the peers in the group chat. 283/* List all the peers in the group chat.
264 * 284 *
@@ -270,16 +290,17 @@ unsigned int group_peernumber_is_ours(const Group_Chats *g_c, int groupnumber, i
270 * 290 *
271 * return -1 on failure. 291 * return -1 on failure.
272 */ 292 */
273int group_names(const Group_Chats *g_c, int groupnumber, uint8_t names[][MAX_NAME_LENGTH], uint16_t lengths[], 293int group_names(const Group_Chats *g_c, uint32_t groupnumber, uint8_t names[][MAX_NAME_LENGTH], uint16_t lengths[],
274 uint16_t length); 294 uint16_t length);
275 295
276/* Set handlers for custom lossy packets. 296/* Set handlers for custom lossy packets.
277 * 297 *
278 * NOTE: Handler must return 0 if packet is to be relayed, -1 if the packet should not be relayed. 298 * NOTE: Handler must return 0 if packet is to be relayed, -1 if the packet should not be relayed.
279 * 299 *
280 * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber, void *group peer object (set with group_peer_set_object), const uint8_t *packet, uint16_t length) 300 * Function(void *group object (set with group_set_object), uint32_t groupnumber, uint32_t friendgroupnumber, void *group peer object (set with group_peer_set_object), const uint8_t *packet, uint16_t length)
281 */ 301 */
282void group_lossy_packet_registerhandler(Group_Chats *g_c, uint8_t byte, int (*function)(void *, int, int, void *, 302void group_lossy_packet_registerhandler(Group_Chats *g_c, uint8_t byte, int (*function)(void *, uint32_t, uint32_t,
303 void *,
283 const uint8_t *, uint16_t)); 304 const uint8_t *, uint16_t));
284 305
285/* High level function to send custom lossy packets. 306/* High level function to send custom lossy packets.
@@ -287,7 +308,7 @@ void group_lossy_packet_registerhandler(Group_Chats *g_c, uint8_t byte, int (*fu
287 * return -1 on failure. 308 * return -1 on failure.
288 * return 0 on success. 309 * return 0 on success.
289 */ 310 */
290int send_group_lossy_packet(const Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length); 311int send_group_lossy_packet(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *data, uint16_t length);
291 312
292/* Return the number of chats in the instance m. 313/* Return the number of chats in the instance m.
293 * You should use this to determine how much memory to allocate 314 * You should use this to determine how much memory to allocate
@@ -300,14 +321,14 @@ uint32_t count_chatlist(Group_Chats *g_c);
300 * Otherwise, returns the number of elements copied. 321 * Otherwise, returns the number of elements copied.
301 * If the array was too small, the contents 322 * If the array was too small, the contents
302 * of out_list will be truncated to list_size. */ 323 * of out_list will be truncated to list_size. */
303uint32_t copy_chatlist(Group_Chats *g_c, int32_t *out_list, uint32_t list_size); 324uint32_t copy_chatlist(Group_Chats *g_c, uint32_t *out_list, uint32_t list_size);
304 325
305/* return the type of groupchat (GROUPCHAT_TYPE_) that groupnumber is. 326/* return the type of groupchat (GROUPCHAT_TYPE_) that groupnumber is.
306 * 327 *
307 * return -1 on failure. 328 * return -1 on failure.
308 * return type on success. 329 * return type on success.
309 */ 330 */
310int group_get_type(const Group_Chats *g_c, int groupnumber); 331int group_get_type(const Group_Chats *g_c, uint32_t groupnumber);
311 332
312/* Send current name (set in messenger) to all online groups. 333/* Send current name (set in messenger) to all online groups.
313 */ 334 */
@@ -318,28 +339,28 @@ void send_name_all_groups(Group_Chats *g_c);
318 * return 0 on success. 339 * return 0 on success.
319 * return -1 on failure 340 * return -1 on failure
320 */ 341 */
321int group_set_object(const Group_Chats *g_c, int groupnumber, void *object); 342int group_set_object(const Group_Chats *g_c, uint32_t groupnumber, void *object);
322 343
323/* Set the object that is tied to the group peer. 344/* Set the object that is tied to the group peer.
324 * 345 *
325 * return 0 on success. 346 * return 0 on success.
326 * return -1 on failure 347 * return -1 on failure
327 */ 348 */
328int group_peer_set_object(const Group_Chats *g_c, int groupnumber, int peernumber, void *object); 349int group_peer_set_object(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, void *object);
329 350
330/* Return the object tide to the group chat previously set by group_set_object. 351/* Return the object tide to the group chat previously set by group_set_object.
331 * 352 *
332 * return NULL on failure. 353 * return NULL on failure.
333 * return object on success. 354 * return object on success.
334 */ 355 */
335void *group_get_object(const Group_Chats *g_c, int groupnumber); 356void *group_get_object(const Group_Chats *g_c, uint32_t groupnumber);
336 357
337/* Return the object tide to the group chat peer previously set by group_peer_set_object. 358/* Return the object tide to the group chat peer previously set by group_peer_set_object.
338 * 359 *
339 * return NULL on failure. 360 * return NULL on failure.
340 * return object on success. 361 * return object on success.
341 */ 362 */
342void *group_peer_get_object(const Group_Chats *g_c, int groupnumber, int peernumber); 363void *group_peer_get_object(const Group_Chats *g_c, uint32_t groupnumber, int peernumber);
343 364
344/* Set a function to be called when a new peer joins a group chat. 365/* Set a function to be called when a new peer joins a group chat.
345 * 366 *
@@ -348,31 +369,33 @@ void *group_peer_get_object(const Group_Chats *g_c, int groupnumber, int peernum
348 * return 0 on success. 369 * return 0 on success.
349 * return -1 on failure. 370 * return -1 on failure.
350 */ 371 */
351int callback_groupchat_peer_new(const Group_Chats *g_c, int groupnumber, void (*function)(void *, int, int)); 372int callback_groupchat_peer_new(const Group_Chats *g_c, uint32_t groupnumber, void (*function)(void *, uint32_t,
373 uint32_t));
352 374
353/* Set a function to be called when a peer leaves a group chat. 375/* Set a function to be called when a peer leaves a group chat.
354 * 376 *
355 * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber, void *group peer object (set with group_peer_set_object)) 377 * Function(void *group object (set with group_set_object), uint32_t groupnumber, uint32_t friendgroupnumber, void *group peer object (set with group_peer_set_object))
356 * 378 *
357 * return 0 on success. 379 * return 0 on success.
358 * return -1 on failure. 380 * return -1 on failure.
359 */ 381 */
360int callback_groupchat_peer_delete(Group_Chats *g_c, int groupnumber, void (*function)(void *, int, int, void *)); 382int callback_groupchat_peer_delete(Group_Chats *g_c, uint32_t groupnumber, void (*function)(void *, uint32_t, uint32_t,
383 void *));
361 384
362/* Set a function to be called when the group chat is deleted. 385/* Set a function to be called when the group chat is deleted.
363 * 386 *
364 * Function(void *group object (set with group_set_object), int groupnumber) 387 * Function(void *group object (set with group_set_object), uint32_t groupnumber)
365 * 388 *
366 * return 0 on success. 389 * return 0 on success.
367 * return -1 on failure. 390 * return -1 on failure.
368 */ 391 */
369int callback_groupchat_delete(Group_Chats *g_c, int groupnumber, void (*function)(void *, int)); 392int callback_groupchat_delete(Group_Chats *g_c, uint32_t groupnumber, void (*function)(void *, uint32_t));
370 393
371/* Create new groupchat instance. */ 394/* Create new groupchat instance. */
372Group_Chats *new_groupchats(Messenger *m); 395Group_Chats *new_groupchats(Messenger *m);
373 396
374/* main groupchats loop. */ 397/* main groupchats loop. */
375void do_groupchats(Group_Chats *g_c); 398void do_groupchats(Group_Chats *g_c, void *userdata);
376 399
377/* Free everything related with group chats. */ 400/* Free everything related with group chats. */
378void kill_groupchats(Group_Chats *g_c); 401void kill_groupchats(Group_Chats *g_c);
diff --git a/toxcore/list.c b/toxcore/list.c
index b97727f8..7b65e184 100644
--- a/toxcore/list.c
+++ b/toxcore/list.c
@@ -1,30 +1,39 @@
1/* list.h 1/*
2 *
3 * Simple struct with functions to create a list which associates ids with data 2 * Simple struct with functions to create a list which associates ids with data
4 * -Allows for finding ids associated with data such as IPs or public keys in a short time 3 * -Allows for finding ids associated with data such as IPs or public keys in a short time
5 * -Should only be used if there are relatively few add/remove calls to the list 4 * -Should only be used if there are relatively few add/remove calls to the list
5 */
6
7/*
8 * Copyright © 2016-2017 The TokTok team.
9 * Copyright © 2014 Tox project.
6 * 10 *
7 * Copyright (C) 2014 Tox project All Rights Reserved. 11 * This file is part of Tox, the free peer to peer instant messenger.
8 *
9 * This file is part of Tox.
10 *
11 * Tox is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 * 12 *
16 * Tox is distributed in the hope that it will be useful, 13 * Tox is free software: you can redistribute it and/or modify
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * it under the terms of the GNU General Public License as published by
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * the Free Software Foundation, either version 3 of the License, or
19 * GNU General Public License for more details. 16 * (at your option) any later version.
20 * 17 *
21 * You should have received a copy of the GNU General Public License 18 * Tox is distributed in the hope that it will be useful,
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * 22 *
23 * You should have received a copy of the GNU General Public License
24 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
24 */ 25 */
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#endif
25 29
26#include "list.h" 30#include "list.h"
27 31
32#include <stdlib.h>
33#include <string.h>
34
35#include "ccompat.h"
36
28/* Basically, the elements in the list are placed in order so that they can be searched for easily 37/* Basically, the elements in the list are placed in order so that they can be searched for easily
29 * -each element is seen as a big-endian integer when ordering them 38 * -each element is seen as a big-endian integer when ordering them
30 * -the ids array is maintained so that each id always matches 39 * -the ids array is maintained so that each id always matches
@@ -113,24 +122,27 @@ static int find(const BS_LIST *list, const uint8_t *data)
113 */ 122 */
114static int resize(BS_LIST *list, uint32_t new_size) 123static int resize(BS_LIST *list, uint32_t new_size)
115{ 124{
116 void *p; 125 if (new_size == 0) {
126 bs_list_free(list);
127 return 1;
128 }
117 129
118 p = realloc(list->data, list->element_size * new_size); 130 uint8_t *data = (uint8_t *)realloc(list->data, list->element_size * new_size);
119 131
120 if (!p) { 132 if (!data) {
121 return 0; 133 return 0;
122 } else {
123 list->data = p;
124 } 134 }
125 135
126 p = realloc(list->ids, sizeof(int) * new_size); 136 list->data = data;
137
138 int *ids = (int *)realloc(list->ids, sizeof(int) * new_size);
127 139
128 if (!p) { 140 if (!ids) {
129 return 0; 141 return 0;
130 } else {
131 list->ids = p;
132 } 142 }
133 143
144 list->ids = ids;
145
134 return 1; 146 return 1;
135} 147}
136 148
@@ -141,8 +153,8 @@ int bs_list_init(BS_LIST *list, uint32_t element_size, uint32_t initial_capacity
141 list->n = 0; 153 list->n = 0;
142 list->element_size = element_size; 154 list->element_size = element_size;
143 list->capacity = 0; 155 list->capacity = 0;
144 list->data = NULL; 156 list->data = nullptr;
145 list->ids = NULL; 157 list->ids = nullptr;
146 158
147 if (initial_capacity != 0) { 159 if (initial_capacity != 0) {
148 if (!resize(list, initial_capacity)) { 160 if (!resize(list, initial_capacity)) {
@@ -159,7 +171,10 @@ void bs_list_free(BS_LIST *list)
159{ 171{
160 //free both arrays 172 //free both arrays
161 free(list->data); 173 free(list->data);
174 list->data = nullptr;
175
162 free(list->ids); 176 free(list->ids);
177 list->ids = nullptr;
163} 178}
164 179
165int bs_list_find(const BS_LIST *list, const uint8_t *data) 180int bs_list_find(const BS_LIST *list, const uint8_t *data)
diff --git a/toxcore/list.h b/toxcore/list.h
index b04177e1..9ad8f44d 100644
--- a/toxcore/list.h
+++ b/toxcore/list.h
@@ -1,34 +1,32 @@
1/* list.h 1/*
2 *
3 * Simple struct with functions to create a list which associates ids with data 2 * Simple struct with functions to create a list which associates ids with data
4 * -Allows for finding ids associated with data such as IPs or public keys in a short time 3 * -Allows for finding ids associated with data such as IPs or public keys in a short time
5 * -Should only be used if there are relatively few add/remove calls to the list 4 * -Should only be used if there are relatively few add/remove calls to the list
5 */
6
7/*
8 * Copyright © 2016-2017 The TokTok team.
9 * Copyright © 2014 Tox project.
6 * 10 *
7 * Copyright (C) 2014 Tox project All Rights Reserved. 11 * This file is part of Tox, the free peer to peer instant messenger.
8 *
9 * This file is part of Tox.
10 *
11 * Tox is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 * 12 *
16 * Tox is distributed in the hope that it will be useful, 13 * Tox is free software: you can redistribute it and/or modify
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * it under the terms of the GNU General Public License as published by
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * the Free Software Foundation, either version 3 of the License, or
19 * GNU General Public License for more details. 16 * (at your option) any later version.
20 * 17 *
21 * You should have received a copy of the GNU General Public License 18 * Tox is distributed in the hope that it will be useful,
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * 22 *
23 * You should have received a copy of the GNU General Public License
24 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
24 */ 25 */
25
26#ifndef LIST_H 26#ifndef LIST_H
27#define LIST_H 27#define LIST_H
28 28
29#include <stdlib.h>
30#include <stdint.h> 29#include <stdint.h>
31#include <string.h>
32 30
33typedef struct { 31typedef struct {
34 uint32_t n; //number of elements 32 uint32_t n; //number of elements
diff --git a/toxcore/logger.c b/toxcore/logger.c
index f19f76b1..edde806f 100644
--- a/toxcore/logger.c
+++ b/toxcore/logger.c
@@ -1,237 +1,135 @@
1/* logger.c 1/*
2 * 2 * Text logging abstraction.
3 * Copyright (C) 2013, 2015 Tox project All Rights Reserved. 3 */
4 * 4
5 * This file is part of Tox. 5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2013,2015 Tox project.
6 * 8 *
7 * Tox is free software: you can redistribute it and/or modify 9 * This file is part of Tox, the free peer to peer instant messenger.
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 * 10 *
12 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
15 * GNU General Public License for more details. 14 * (at your option) any later version.
16 * 15 *
17 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
18 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
19 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
20 */ 23 */
21
22#ifdef HAVE_CONFIG_H 24#ifdef HAVE_CONFIG_H
23#include "config.h" 25#include "config.h"
24#endif /* HAVE_CONFIG_H */ 26#endif
25 27
26#include "logger.h" 28#include "logger.h"
27#include "crypto_core.h" /* for random_int() */
28 29
30#include <assert.h>
31#include <stdarg.h>
29#include <stdio.h> 32#include <stdio.h>
30#include <errno.h>
31#include <stdlib.h> 33#include <stdlib.h>
32#include <stdarg.h> 34#include <string.h>
33#include <inttypes.h>
34#include <time.h>
35#include <pthread.h>
36
37#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
38# define getpid() ((unsigned) GetCurrentProcessId())
39# define SFILE(FILE__M) (strrchr(FILE__M, '\\') ? strrchr(FILE__M, '\\') + 1 : FILE__M)
40# define WIN_CR "\r"
41#else
42# define SFILE(FILE__M) (strrchr(FILE__M, '/') ? strrchr(FILE__M, '/') + 1 : FILE__M)
43# define WIN_CR ""
44#endif
45 35
46 36
47struct Logger { 37struct Logger {
48 FILE *log_file; 38 logger_cb *callback;
49 LOG_LEVEL level; 39 void *context;
50 uint64_t start_time; /* Time when lib loaded */ 40 void *userdata;
51 char *id;
52
53 /* Allocate these once */
54 char *tstr;
55 char *posstr;
56 char *msg;
57
58 /* For thread synchronisation */
59 pthread_mutex_t mutex[1];
60};
61
62Logger *global = NULL;
63
64const char *LOG_LEVEL_STR [] = {
65 [LOG_TRACE] = "TRACE",
66 [LOG_DEBUG] = "DEBUG",
67 [LOG_INFO] = "INFO" ,
68 [LOG_WARNING] = "WARN" ,
69 [LOG_ERROR] = "ERROR",
70}; 41};
71 42
72char *strtime(char *dest, size_t max_len) 43#ifdef USE_STDERR_LOGGER
73{ 44static const char *logger_level_name(LOGGER_LEVEL level)
74 time_t timer;
75 struct tm *tm_info;
76
77 time(&timer);
78 tm_info = localtime(&timer);
79
80 strftime(dest, max_len, "%m:%d %H:%M:%S", tm_info);
81 return dest;
82}
83
84
85/**
86 * Public Functions
87 */
88Logger *logger_new (const char *file_name, LOG_LEVEL level, const char *id)
89{ 45{
90#ifndef TOX_LOGGER /* Disabled */ 46 switch (level) {
91 return NULL; 47 case LOG_TRACE:
92#endif 48 return "TRACE";
93
94 Logger *retu = calloc(1, sizeof(Logger));
95 49
96 if (!retu) 50 case LOG_DEBUG:
97 return NULL; 51 return "DEBUG";
98 52
99 if (pthread_mutex_init(retu->mutex, NULL) != 0) { 53 case LOG_INFO:
100 free(retu); 54 return "INFO";
101 return NULL;
102 }
103
104 if (!(retu->log_file = fopen(file_name, "ab"))) {
105 fprintf(stderr, "Error opening logger file: %s; info: %s" WIN_CR "\n", file_name, strerror(errno));
106 free(retu);
107 pthread_mutex_destroy(retu->mutex);
108 return NULL;
109 }
110
111 if (!(retu->tstr = calloc(16, sizeof (char))) ||
112 !(retu->posstr = calloc(300, sizeof (char))) ||
113 !(retu->msg = calloc(4096, sizeof (char))))
114 goto FAILURE;
115 55
116 if (id) { 56 case LOG_WARNING:
117 if (!(retu->id = calloc(strlen(id) + 1, 1))) 57 return "WARNING";
118 goto FAILURE;
119 58
120 strcpy(retu->id, id); 59 case LOG_ERROR:
121 } else { 60 return "ERROR";
122 if (!(retu->id = malloc(8)))
123 goto FAILURE;
124
125 snprintf(retu->id, 8, "%u", random_int());
126 } 61 }
127 62
128 retu->level = level; 63 return "<unknown>";
129 retu->start_time = current_time_monotonic();
130
131 fprintf(retu->log_file, "Successfully created and running logger id: %s; time: %s" WIN_CR "\n",
132 retu->id, strtime(retu->tstr, 16));
133
134 return retu;
135
136FAILURE:
137 fprintf(stderr, "Failed to create logger!" WIN_CR "\n");
138 pthread_mutex_destroy(retu->mutex);
139 fclose(retu->log_file);
140 free(retu->tstr);
141 free(retu->posstr);
142 free(retu->msg);
143 free(retu->id);
144 free(retu);
145 return NULL;
146} 64}
147 65
148void logger_kill(Logger *log) 66static void logger_stderr_handler(void *context, LOGGER_LEVEL level, const char *file, int line, const char *func,
67 const char *message, void *userdata)
149{ 68{
150#ifndef TOX_LOGGER /* Disabled */ 69 // GL stands for "global logger".
151 return; 70 fprintf(stderr, "[GL] %s %s:%d(%s): %s\n", logger_level_name(level), file, line, func, message);
152#endif
153
154 if (!log)
155 return;
156
157 pthread_mutex_lock(log->mutex);
158 free(log->id);
159 free(log->tstr);
160 free(log->posstr);
161 free(log->msg);
162
163 if (fclose(log->log_file) != 0)
164 perror("Could not close log file");
165
166 pthread_mutex_unlock(log->mutex);
167 pthread_mutex_destroy(log->mutex);
168
169 free(log);
170} 71}
171 72
172void logger_kill_global(void) 73static const Logger logger_stderr = {
74 logger_stderr_handler,
75 nullptr,
76 nullptr,
77};
78#endif
79
80/**
81 * Public Functions
82 */
83Logger *logger_new(void)
173{ 84{
174 logger_kill(global); 85 return (Logger *)calloc(1, sizeof(Logger));
175 global = NULL;
176} 86}
177 87
178void logger_set_global(Logger *log) 88void logger_kill(Logger *log)
179{ 89{
180#ifndef TOX_LOGGER /* Disabled */ 90 free(log);
181 return;
182#endif
183
184 global = log;
185} 91}
186 92
187Logger *logger_get_global(void) 93void logger_callback_log(Logger *log, logger_cb *function, void *context, void *userdata)
188{ 94{
189#ifndef TOX_LOGGER /* Disabled */ 95 log->callback = function;
190 return NULL; 96 log->context = context;
191#endif 97 log->userdata = userdata;
192
193 return global;
194} 98}
195 99
196void logger_write (Logger *log, LOG_LEVEL level, const char *file, int line, const char *format, ...) 100void logger_write(const Logger *log, LOGGER_LEVEL level, const char *file, int line, const char *func,
101 const char *format, ...)
197{ 102{
198#ifndef TOX_LOGGER /* Disabled */ 103 if (!log) {
199 return; 104#ifdef USE_STDERR_LOGGER
105 log = &logger_stderr;
106#else
107 assert(!"NULL logger not permitted");
200#endif 108#endif
109 }
201 110
202 static const char *logger_format = 111 if (!log->callback) {
203 "%s " /* Logger id string */
204 "%-16s" /* Time string of format: %m:%d %H:%M:%S */
205 "%-12u " /* Thread id */
206 "%-5s " /* Logger lever string */
207 "%-20s " /* File:line string */
208 "- %s" /* Output message */
209 WIN_CR "\n"; /* Every new print new line */
210
211
212 Logger *this_log = log ? log : global;
213
214 if (!this_log)
215 return;
216
217 /* Don't print levels lesser than set one */
218 if (this_log->level > level)
219 return; 112 return;
113 }
220 114
221 pthread_mutex_lock(this_log->mutex); 115 // Only pass the file name, not the entire file path, for privacy reasons.
222 116 // The full path may contain PII of the person compiling toxcore (their
223 /* Set position str */ 117 // username and directory layout).
224 snprintf(this_log->posstr, 300, "%s:%d", SFILE(file), line); 118 const char *filename = strrchr(file, '/');
119 file = filename ? filename + 1 : file;
120#if defined(_WIN32) || defined(__CYGWIN__)
121 // On Windows, the path separator *may* be a backslash, so we look for that
122 // one too.
123 const char *windows_filename = strrchr(file, '\\');
124 file = windows_filename ? windows_filename + 1 : file;
125#endif
225 126
226 /* Set message */ 127 // Format message
128 char msg[1024];
227 va_list args; 129 va_list args;
228 va_start (args, format); 130 va_start(args, format);
229 vsnprintf(this_log->msg, 4096, format, args); 131 vsnprintf(msg, sizeof msg, format, args);
230 va_end (args); 132 va_end(args);
231
232 fprintf(this_log->log_file, logger_format, this_log->id, strtime(this_log->tstr, 16), pthread_self(),
233 LOG_LEVEL_STR[level], this_log->posstr, this_log->msg);
234 fflush(this_log->log_file);
235 133
236 pthread_mutex_unlock(this_log->mutex); 134 log->callback(log->context, level, file, line, func, msg, log->userdata);
237} 135}
diff --git a/toxcore/logger.h b/toxcore/logger.h
index 4d3e3b54..acd21fb8 100644
--- a/toxcore/logger.h
+++ b/toxcore/logger.h
@@ -1,94 +1,93 @@
1/* logger.h 1/*
2 * 2 * Logger abstraction backed by callbacks for writing.
3 * Copyright (C) 2013 Tox project All Rights Reserved. 3 */
4 * 4
5 * This file is part of Tox. 5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2013 Tox project.
6 * 8 *
7 * Tox is free software: you can redistribute it and/or modify 9 * This file is part of Tox, the free peer to peer instant messenger.
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 * 10 *
12 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
15 * GNU General Public License for more details. 14 * (at your option) any later version.
16 * 15 *
17 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
18 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
19 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
20 */ 23 */
21
22
23#ifndef TOXLOGGER_H 24#ifndef TOXLOGGER_H
24#define TOXLOGGER_H 25#define TOXLOGGER_H
25 26
26#include <string.h> 27#include <stdint.h>
27 28
28/* In case these are undefined; define 'empty' */ 29#include "ccompat.h"
29#ifndef LOGGER_OUTPUT_FILE
30# define LOGGER_OUTPUT_FILE ""
31#endif
32 30
33#ifndef LOGGER_LEVEL 31#ifndef MIN_LOGGER_LEVEL
34# define LOGGER_LEVEL LOG_ERROR 32#define MIN_LOGGER_LEVEL LOG_INFO
35#endif 33#endif
36 34
37
38typedef enum { 35typedef enum {
39 LOG_TRACE, 36 LOG_TRACE,
40 LOG_DEBUG, 37 LOG_DEBUG,
41 LOG_INFO, 38 LOG_INFO,
42 LOG_WARNING, 39 LOG_WARNING,
43 LOG_ERROR 40 LOG_ERROR
44} LOG_LEVEL; 41} LOGGER_LEVEL;
45 42
46typedef struct Logger Logger; 43typedef struct Logger Logger;
47 44
45typedef void logger_cb(void *context, LOGGER_LEVEL level, const char *file, int line,
46 const char *func, const char *message, void *userdata);
47
48/** 48/**
49 * Set 'level' as the lowest printable level. If id == NULL, random number is used. 49 * Creates a new logger with logging disabled (callback is NULL) by default.
50 */ 50 */
51Logger *logger_new (const char *file_name, LOG_LEVEL level, const char *id); 51Logger *logger_new(void);
52 52
53void logger_kill (Logger *log); 53/**
54void logger_kill_global (void); 54 * Frees all resources associated with the logger.
55 */
56void logger_kill(Logger *log);
55 57
56/** 58/**
57 * Global logger setter and getter. 59 * Sets the logger callback. Disables logging if set to NULL.
60 * The context parameter is passed to the callback as first argument.
58 */ 61 */
59void logger_set_global (Logger *log); 62void logger_callback_log(Logger *log, logger_cb *function, void *context, void *userdata);
60Logger *logger_get_global (void);
61 63
62/** 64/**
63 * Main write function. If logging disabled does nothing. If log == NULL uses global logger. 65 * Main write function. If logging is disabled, this does nothing.
66 *
67 * If the logger is NULL, this writes to stderr. This behaviour should not be
68 * used in production code, but can be useful for temporarily debugging a
69 * function that does not have a logger available. It's essentially
70 * fprintf(stderr, ...), but with timestamps and source location. Toxcore must
71 * be built with -DUSE_STDERR_LOGGER for this to work. It will cause an
72 * assertion failure otherwise.
64 */ 73 */
65void logger_write (Logger *log, LOG_LEVEL level, const char *file, int line, const char *format, ...); 74void logger_write(
75 const Logger *log, LOGGER_LEVEL level, const char *file, int line, const char *func,
76 const char *format, ...) GNU_PRINTF(6, 7);
66 77
67 78
68/* To do some checks or similar only when logging, use this */ 79#define LOGGER_WRITE(log, level, ...) \
69#ifdef TOX_LOGGER 80 do { \
70# define LOGGER_SCOPE(__SCOPE_DO__) do { __SCOPE_DO__ } while(0) 81 if (level >= MIN_LOGGER_LEVEL) { \
71# define LOGGER_WRITE(log, level, format, ...) \ 82 logger_write(log, level, __FILE__, __LINE__, __func__, __VA_ARGS__); \
72 logger_write(log, level, __FILE__, __LINE__, format, ##__VA_ARGS__) 83 } \
73#else 84 } while (0)
74/* # warning "Logging disabled" */
75# define LOGGER_SCOPE(__SCOPE_DO__) do {} while(0)
76# define LOGGER_WRITE(log, level, format, ...) do {} while(0)
77#endif /* TOX_LOGGER */
78 85
79/* To log with an logger */ 86/* To log with an logger */
80#define LOGGER_TRACE_(log, format, ...) LOGGER_WRITE(log, LOG_TRACE, format, ##__VA_ARGS__) 87#define LOGGER_TRACE(log, ...) LOGGER_WRITE(log, LOG_TRACE , __VA_ARGS__)
81#define LOGGER_DEBUG_(log, format, ...) LOGGER_WRITE(log, LOG_DEBUG, format, ##__VA_ARGS__) 88#define LOGGER_DEBUG(log, ...) LOGGER_WRITE(log, LOG_DEBUG , __VA_ARGS__)
82#define LOGGER_INFO_(log, format, ...) LOGGER_WRITE(log, LOG_INFO, format, ##__VA_ARGS__) 89#define LOGGER_INFO(log, ...) LOGGER_WRITE(log, LOG_INFO , __VA_ARGS__)
83#define LOGGER_WARNING_(log, format, ...) LOGGER_WRITE(log, LOG_WARNING, format, ##__VA_ARGS__) 90#define LOGGER_WARNING(log, ...) LOGGER_WRITE(log, LOG_WARNING, __VA_ARGS__)
84#define LOGGER_ERROR_(log, format, ...) LOGGER_WRITE(log, LOG_ERROR, format, ##__VA_ARGS__) 91#define LOGGER_ERROR(log, ...) LOGGER_WRITE(log, LOG_ERROR , __VA_ARGS__)
85
86/* To log with the global logger */
87#define LOGGER_TRACE(format, ...) LOGGER_TRACE_(NULL, format, ##__VA_ARGS__)
88#define LOGGER_DEBUG(format, ...) LOGGER_DEBUG_(NULL, format, ##__VA_ARGS__)
89#define LOGGER_INFO(format, ...) LOGGER_INFO_(NULL, format, ##__VA_ARGS__)
90#define LOGGER_WARNING(format, ...) LOGGER_WARNING_(NULL, format, ##__VA_ARGS__)
91#define LOGGER_ERROR(format, ...) LOGGER_ERROR_(NULL, format, ##__VA_ARGS__)
92
93 92
94#endif /* TOXLOGGER_H */ 93#endif /* TOXLOGGER_H */
diff --git a/toxcore/misc_tools.h b/toxcore/misc_tools.h
deleted file mode 100644
index 543338b5..00000000
--- a/toxcore/misc_tools.h
+++ /dev/null
@@ -1,70 +0,0 @@
1/* misc_tools.h
2 *
3 * Miscellaneous functions and data structures for doing random things.
4 *
5 * Copyright (C) 2013 Tox project All Rights Reserved.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * Tox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#ifndef MISC_TOOLS_H
25#define MISC_TOOLS_H
26
27/****************************Algorithms***************************
28 * Macro/generic definitions for useful algorithms
29 *****************************************************************/
30
31/* Creates a new quick_sort implementation for arrays of the specified type.
32 * For a type T (eg: int, char), creates a function named T_quick_sort.
33 *
34 * Quick Sort: Complexity O(nlogn)
35 * arr - the array to sort
36 * n - the sort index (should be called with n = length(arr))
37 * cmpfn - a function that compares two values of type type.
38 * Must return -1, 0, 1 for a < b, a == b, and a > b respectively.
39 */
40/* Must be called in the header file. */
41#define declare_quick_sort(type) \
42void type##_quick_sort(type *arr, int n, int (*cmpfn)(type, type));
43
44/* Must be called in the C file. */
45#define make_quick_sort(type) \
46void type##_quick_sort(type *arr, int n, int (*cmpfn)(type, type)) \
47{ \
48 if ((n) < 2) \
49 return; \
50 type _p_ = (arr)[(n) / 2]; \
51 type *_l_ = (arr); \
52 type *_r_ = (arr) + n - 1; \
53 while (_l_ <= _r_) { \
54 if (cmpfn(*_l_, _p_) == -1) { \
55 ++_l_; \
56 continue; \
57 } \
58 if (cmpfn(*_r_, _p_) == 1) { \
59 --_r_; \
60 continue; \
61 } \
62 type _t_ = *_l_; \
63 *_l_++ = *_r_; \
64 *_r_-- = _t_; \
65 } \
66 type##_quick_sort((arr), _r_ - (arr) + 1, cmpfn); \
67 type##_quick_sort(_l_, (arr) + n - _l_, cmpfn); \
68}
69
70#endif // MISC_TOOLS_H
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c
index f8a85adf..ead5a04c 100644
--- a/toxcore/net_crypto.c
+++ b/toxcore/net_crypto.c
@@ -1,60 +1,207 @@
1/* net_crypto.c 1/*
2 *
3 * Functions for the core network crypto. 2 * Functions for the core network crypto.
4 * 3 *
5 * NOTE: This code has to be perfect. We don't mess around with encryption. 4 * NOTE: This code has to be perfect. We don't mess around with encryption.
5 */
6
7/*
8 * Copyright © 2016-2017 The TokTok team.
9 * Copyright © 2013 Tox project.
6 * 10 *
7 * Copyright (C) 2013 Tox project All Rights Reserved. 11 * This file is part of Tox, the free peer to peer instant messenger.
8 *
9 * This file is part of Tox.
10 *
11 * Tox is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 * 12 *
16 * Tox is distributed in the hope that it will be useful, 13 * Tox is free software: you can redistribute it and/or modify
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * it under the terms of the GNU General Public License as published by
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * the Free Software Foundation, either version 3 of the License, or
19 * GNU General Public License for more details. 16 * (at your option) any later version.
20 * 17 *
21 * You should have received a copy of the GNU General Public License 18 * Tox is distributed in the hope that it will be useful,
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * 22 *
23 * You should have received a copy of the GNU General Public License
24 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
24 */ 25 */
25
26#ifdef HAVE_CONFIG_H 26#ifdef HAVE_CONFIG_H
27#include "config.h" 27#include "config.h"
28#endif 28#endif
29 29
30#include "net_crypto.h" 30#include "net_crypto.h"
31
32#include <math.h>
33#include <stdlib.h>
34#include <string.h>
35
31#include "util.h" 36#include "util.h"
32#include "math.h" 37
33#include "logger.h" 38typedef struct {
39 uint64_t sent_time;
40 uint16_t length;
41 uint8_t data[MAX_CRYPTO_DATA_SIZE];
42} Packet_Data;
43
44typedef struct {
45 Packet_Data *buffer[CRYPTO_PACKET_BUFFER_SIZE];
46 uint32_t buffer_start;
47 uint32_t buffer_end; /* packet numbers in array: {buffer_start, buffer_end) */
48} Packets_Array;
49
50typedef struct {
51 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The real public key of the peer. */
52 uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of received packets. */
53 uint8_t sent_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of sent packets. */
54 uint8_t sessionpublic_key[CRYPTO_PUBLIC_KEY_SIZE]; /* Our public key for this session. */
55 uint8_t sessionsecret_key[CRYPTO_SECRET_KEY_SIZE]; /* Our private key for this session. */
56 uint8_t peersessionpublic_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The public key of the peer. */
57 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; /* The precomputed shared key from encrypt_precompute. */
58 uint8_t status; /* 0 if no connection, 1 we are sending cookie request packets,
59 * 2 if we are sending handshake packets
60 * 3 if connection is not confirmed yet (we have received a handshake but no data packets yet),
61 * 4 if the connection is established.
62 */
63 uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */
64 uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The dht public key of the peer */
65
66 uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */
67 uint16_t temp_packet_length;
68 uint64_t temp_packet_sent_time; /* The time at which the last temp_packet was sent in ms. */
69 uint32_t temp_packet_num_sent;
70
71 IP_Port ip_portv4; /* The ip and port to contact this guy directly.*/
72 IP_Port ip_portv6;
73 uint64_t direct_lastrecv_timev4; /* The Time at which we last received a direct packet in ms. */
74 uint64_t direct_lastrecv_timev6;
75
76 uint64_t last_tcp_sent; /* Time the last TCP packet was sent. */
77
78 Packets_Array send_array;
79 Packets_Array recv_array;
80
81 int (*connection_status_callback)(void *object, int id, uint8_t status, void *userdata);
82 void *connection_status_callback_object;
83 int connection_status_callback_id;
84
85 int (*connection_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
86 void *connection_data_callback_object;
87 int connection_data_callback_id;
88
89 int (*connection_lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
90 void *connection_lossy_data_callback_object;
91 int connection_lossy_data_callback_id;
92
93 uint64_t last_request_packet_sent;
94 uint64_t direct_send_attempt_time;
95
96 uint32_t packet_counter;
97 double packet_recv_rate;
98 uint64_t packet_counter_set;
99
100 double packet_send_rate;
101 uint32_t packets_left;
102 uint64_t last_packets_left_set;
103 double last_packets_left_rem;
104
105 double packet_send_rate_requested;
106 uint32_t packets_left_requested;
107 uint64_t last_packets_left_requested_set;
108 double last_packets_left_requested_rem;
109
110 uint32_t last_sendqueue_size[CONGESTION_QUEUE_ARRAY_SIZE], last_sendqueue_counter;
111 long signed int last_num_packets_sent[CONGESTION_LAST_SENT_ARRAY_SIZE],
112 last_num_packets_resent[CONGESTION_LAST_SENT_ARRAY_SIZE];
113 uint32_t packets_sent, packets_resent;
114 uint64_t last_congestion_event;
115 uint64_t rtt_time;
116
117 /* TCP_connection connection_number */
118 unsigned int connection_number_tcp;
119
120 uint8_t maximum_speed_reached;
121
122 pthread_mutex_t mutex;
123
124 void (*dht_pk_callback)(void *data, int32_t number, const uint8_t *dht_public_key, void *userdata);
125 void *dht_pk_callback_object;
126 uint32_t dht_pk_callback_number;
127} Crypto_Connection;
128
129struct Net_Crypto {
130 Logger *log;
131
132 DHT *dht;
133 TCP_Connections *tcp_c;
134
135 Crypto_Connection *crypto_connections;
136 pthread_mutex_t tcp_mutex;
137
138 pthread_mutex_t connections_mutex;
139 unsigned int connection_use_counter;
140
141 uint32_t crypto_connections_length; /* Length of connections array. */
142
143 /* Our public and secret keys. */
144 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
145 uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
146
147 /* The secret key used for cookies */
148 uint8_t secret_symmetric_key[CRYPTO_SYMMETRIC_KEY_SIZE];
149
150 int (*new_connection_callback)(void *object, New_Connection *n_c);
151 void *new_connection_callback_object;
152
153 /* The current optimal sleep time */
154 uint32_t current_sleep_time;
155
156 BS_LIST ip_port_list;
157};
158
159const uint8_t *nc_get_self_public_key(const Net_Crypto *c)
160{
161 return c->self_public_key;
162}
163
164const uint8_t *nc_get_self_secret_key(const Net_Crypto *c)
165{
166 return c->self_secret_key;
167}
168
169TCP_Connections *nc_get_tcp_c(const Net_Crypto *c)
170{
171 return c->tcp_c;
172}
173
174DHT *nc_get_dht(const Net_Crypto *c)
175{
176 return c->dht;
177}
34 178
35static uint8_t crypt_connection_id_not_valid(const Net_Crypto *c, int crypt_connection_id) 179static uint8_t crypt_connection_id_not_valid(const Net_Crypto *c, int crypt_connection_id)
36{ 180{
37 if ((uint32_t)crypt_connection_id >= c->crypto_connections_length) 181 if ((uint32_t)crypt_connection_id >= c->crypto_connections_length) {
38 return 1; 182 return 1;
183 }
39 184
40 if (c->crypto_connections == NULL) 185 if (c->crypto_connections == nullptr) {
41 return 1; 186 return 1;
187 }
42 188
43 if (c->crypto_connections[crypt_connection_id].status == CRYPTO_CONN_NO_CONNECTION) 189 if (c->crypto_connections[crypt_connection_id].status == CRYPTO_CONN_NO_CONNECTION) {
44 return 1; 190 return 1;
191 }
45 192
46 return 0; 193 return 0;
47} 194}
48 195
49/* cookie timeout in seconds */ 196/* cookie timeout in seconds */
50#define COOKIE_TIMEOUT 15 197#define COOKIE_TIMEOUT 15
51#define COOKIE_DATA_LENGTH (crypto_box_PUBLICKEYBYTES * 2) 198#define COOKIE_DATA_LENGTH (CRYPTO_PUBLIC_KEY_SIZE * 2)
52#define COOKIE_CONTENTS_LENGTH (sizeof(uint64_t) + COOKIE_DATA_LENGTH) 199#define COOKIE_CONTENTS_LENGTH (sizeof(uint64_t) + COOKIE_DATA_LENGTH)
53#define COOKIE_LENGTH (crypto_box_NONCEBYTES + COOKIE_CONTENTS_LENGTH + crypto_box_MACBYTES) 200#define COOKIE_LENGTH (CRYPTO_NONCE_SIZE + COOKIE_CONTENTS_LENGTH + CRYPTO_MAC_SIZE)
54 201
55#define COOKIE_REQUEST_PLAIN_LENGTH (COOKIE_DATA_LENGTH + sizeof(uint64_t)) 202#define COOKIE_REQUEST_PLAIN_LENGTH (COOKIE_DATA_LENGTH + sizeof(uint64_t))
56#define COOKIE_REQUEST_LENGTH (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + COOKIE_REQUEST_PLAIN_LENGTH + crypto_box_MACBYTES) 203#define COOKIE_REQUEST_LENGTH (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE)
57#define COOKIE_RESPONSE_LENGTH (1 + crypto_box_NONCEBYTES + COOKIE_LENGTH + sizeof(uint64_t) + crypto_box_MACBYTES) 204#define COOKIE_RESPONSE_LENGTH (1 + CRYPTO_NONCE_SIZE + COOKIE_LENGTH + sizeof(uint64_t) + CRYPTO_MAC_SIZE)
58 205
59/* Create a cookie request packet and put it in packet. 206/* Create a cookie request packet and put it in packet.
60 * dht_public_key is the dht public key of the other 207 * dht_public_key is the dht public key of the other
@@ -68,25 +215,26 @@ static int create_cookie_request(const Net_Crypto *c, uint8_t *packet, uint8_t *
68 uint8_t *shared_key) 215 uint8_t *shared_key)
69{ 216{
70 uint8_t plain[COOKIE_REQUEST_PLAIN_LENGTH]; 217 uint8_t plain[COOKIE_REQUEST_PLAIN_LENGTH];
71 uint8_t padding[crypto_box_PUBLICKEYBYTES] = {0}; 218 uint8_t padding[CRYPTO_PUBLIC_KEY_SIZE] = {0};
72 219
73 memcpy(plain, c->self_public_key, crypto_box_PUBLICKEYBYTES); 220 memcpy(plain, c->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
74 memcpy(plain + crypto_box_PUBLICKEYBYTES, padding, crypto_box_PUBLICKEYBYTES); 221 memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, padding, CRYPTO_PUBLIC_KEY_SIZE);
75 memcpy(plain + (crypto_box_PUBLICKEYBYTES * 2), &number, sizeof(uint64_t)); 222 memcpy(plain + (CRYPTO_PUBLIC_KEY_SIZE * 2), &number, sizeof(uint64_t));
76 223
77 DHT_get_shared_key_sent(c->dht, shared_key, dht_public_key); 224 DHT_get_shared_key_sent(c->dht, shared_key, dht_public_key);
78 uint8_t nonce[crypto_box_NONCEBYTES]; 225 uint8_t nonce[CRYPTO_NONCE_SIZE];
79 new_nonce(nonce); 226 random_nonce(nonce);
80 packet[0] = NET_PACKET_COOKIE_REQUEST; 227 packet[0] = NET_PACKET_COOKIE_REQUEST;
81 memcpy(packet + 1, c->dht->self_public_key, crypto_box_PUBLICKEYBYTES); 228 memcpy(packet + 1, dht_get_self_public_key(c->dht), CRYPTO_PUBLIC_KEY_SIZE);
82 memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); 229 memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
83 int len = encrypt_data_symmetric(shared_key, nonce, plain, sizeof(plain), 230 int len = encrypt_data_symmetric(shared_key, nonce, plain, sizeof(plain),
84 packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); 231 packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
85 232
86 if (len != COOKIE_REQUEST_PLAIN_LENGTH + crypto_box_MACBYTES) 233 if (len != COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE) {
87 return -1; 234 return -1;
235 }
88 236
89 return (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + len); 237 return (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + len);
90} 238}
91 239
92/* Create cookie of length COOKIE_LENGTH from bytes of length COOKIE_DATA_LENGTH using encryption_key 240/* Create cookie of length COOKIE_LENGTH from bytes of length COOKIE_DATA_LENGTH using encryption_key
@@ -100,11 +248,12 @@ static int create_cookie(uint8_t *cookie, const uint8_t *bytes, const uint8_t *e
100 uint64_t temp_time = unix_time(); 248 uint64_t temp_time = unix_time();
101 memcpy(contents, &temp_time, sizeof(temp_time)); 249 memcpy(contents, &temp_time, sizeof(temp_time));
102 memcpy(contents + sizeof(temp_time), bytes, COOKIE_DATA_LENGTH); 250 memcpy(contents + sizeof(temp_time), bytes, COOKIE_DATA_LENGTH);
103 new_nonce(cookie); 251 random_nonce(cookie);
104 int len = encrypt_data_symmetric(encryption_key, cookie, contents, sizeof(contents), cookie + crypto_box_NONCEBYTES); 252 int len = encrypt_data_symmetric(encryption_key, cookie, contents, sizeof(contents), cookie + CRYPTO_NONCE_SIZE);
105 253
106 if (len != COOKIE_LENGTH - crypto_box_NONCEBYTES) 254 if (len != COOKIE_LENGTH - CRYPTO_NONCE_SIZE) {
107 return -1; 255 return -1;
256 }
108 257
109 return 0; 258 return 0;
110} 259}
@@ -117,18 +266,20 @@ static int create_cookie(uint8_t *cookie, const uint8_t *bytes, const uint8_t *e
117static int open_cookie(uint8_t *bytes, const uint8_t *cookie, const uint8_t *encryption_key) 266static int open_cookie(uint8_t *bytes, const uint8_t *cookie, const uint8_t *encryption_key)
118{ 267{
119 uint8_t contents[COOKIE_CONTENTS_LENGTH]; 268 uint8_t contents[COOKIE_CONTENTS_LENGTH];
120 int len = decrypt_data_symmetric(encryption_key, cookie, cookie + crypto_box_NONCEBYTES, 269 int len = decrypt_data_symmetric(encryption_key, cookie, cookie + CRYPTO_NONCE_SIZE,
121 COOKIE_LENGTH - crypto_box_NONCEBYTES, contents); 270 COOKIE_LENGTH - CRYPTO_NONCE_SIZE, contents);
122 271
123 if (len != sizeof(contents)) 272 if (len != sizeof(contents)) {
124 return -1; 273 return -1;
274 }
125 275
126 uint64_t cookie_time; 276 uint64_t cookie_time;
127 memcpy(&cookie_time, contents, sizeof(cookie_time)); 277 memcpy(&cookie_time, contents, sizeof(cookie_time));
128 uint64_t temp_time = unix_time(); 278 uint64_t temp_time = unix_time();
129 279
130 if (cookie_time + COOKIE_TIMEOUT < temp_time || temp_time < cookie_time) 280 if (cookie_time + COOKIE_TIMEOUT < temp_time || temp_time < cookie_time) {
131 return -1; 281 return -1;
282 }
132 283
133 memcpy(bytes, contents + sizeof(cookie_time), COOKIE_DATA_LENGTH); 284 memcpy(bytes, contents + sizeof(cookie_time), COOKIE_DATA_LENGTH);
134 return 0; 285 return 0;
@@ -146,27 +297,29 @@ static int create_cookie_response(const Net_Crypto *c, uint8_t *packet, const ui
146 const uint8_t *shared_key, const uint8_t *dht_public_key) 297 const uint8_t *shared_key, const uint8_t *dht_public_key)
147{ 298{
148 uint8_t cookie_plain[COOKIE_DATA_LENGTH]; 299 uint8_t cookie_plain[COOKIE_DATA_LENGTH];
149 memcpy(cookie_plain, request_plain, crypto_box_PUBLICKEYBYTES); 300 memcpy(cookie_plain, request_plain, CRYPTO_PUBLIC_KEY_SIZE);
150 memcpy(cookie_plain + crypto_box_PUBLICKEYBYTES, dht_public_key, crypto_box_PUBLICKEYBYTES); 301 memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);
151 uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)]; 302 uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)];
152 303
153 if (create_cookie(plain, cookie_plain, c->secret_symmetric_key) != 0) 304 if (create_cookie(plain, cookie_plain, c->secret_symmetric_key) != 0) {
154 return -1; 305 return -1;
306 }
155 307
156 memcpy(plain + COOKIE_LENGTH, request_plain + COOKIE_DATA_LENGTH, sizeof(uint64_t)); 308 memcpy(plain + COOKIE_LENGTH, request_plain + COOKIE_DATA_LENGTH, sizeof(uint64_t));
157 packet[0] = NET_PACKET_COOKIE_RESPONSE; 309 packet[0] = NET_PACKET_COOKIE_RESPONSE;
158 new_nonce(packet + 1); 310 random_nonce(packet + 1);
159 int len = encrypt_data_symmetric(shared_key, packet + 1, plain, sizeof(plain), packet + 1 + crypto_box_NONCEBYTES); 311 int len = encrypt_data_symmetric(shared_key, packet + 1, plain, sizeof(plain), packet + 1 + CRYPTO_NONCE_SIZE);
160 312
161 if (len != COOKIE_RESPONSE_LENGTH - (1 + crypto_box_NONCEBYTES)) 313 if (len != COOKIE_RESPONSE_LENGTH - (1 + CRYPTO_NONCE_SIZE)) {
162 return -1; 314 return -1;
315 }
163 316
164 return COOKIE_RESPONSE_LENGTH; 317 return COOKIE_RESPONSE_LENGTH;
165} 318}
166 319
167/* Handle the cookie request packet of length length. 320/* Handle the cookie request packet of length length.
168 * Put what was in the request in request_plain (must be of size COOKIE_REQUEST_PLAIN_LENGTH) 321 * Put what was in the request in request_plain (must be of size COOKIE_REQUEST_PLAIN_LENGTH)
169 * Put the key used to decrypt the request into shared_key (of size crypto_box_BEFORENMBYTES) for use in the response. 322 * Put the key used to decrypt the request into shared_key (of size CRYPTO_SHARED_KEY_SIZE) for use in the response.
170 * 323 *
171 * return -1 on failure. 324 * return -1 on failure.
172 * return 0 on success. 325 * return 0 on success.
@@ -174,40 +327,46 @@ static int create_cookie_response(const Net_Crypto *c, uint8_t *packet, const ui
174static int handle_cookie_request(const Net_Crypto *c, uint8_t *request_plain, uint8_t *shared_key, 327static int handle_cookie_request(const Net_Crypto *c, uint8_t *request_plain, uint8_t *shared_key,
175 uint8_t *dht_public_key, const uint8_t *packet, uint16_t length) 328 uint8_t *dht_public_key, const uint8_t *packet, uint16_t length)
176{ 329{
177 if (length != COOKIE_REQUEST_LENGTH) 330 if (length != COOKIE_REQUEST_LENGTH) {
178 return -1; 331 return -1;
332 }
179 333
180 memcpy(dht_public_key, packet + 1, crypto_box_PUBLICKEYBYTES); 334 memcpy(dht_public_key, packet + 1, CRYPTO_PUBLIC_KEY_SIZE);
181 DHT_get_shared_key_sent(c->dht, shared_key, dht_public_key); 335 DHT_get_shared_key_sent(c->dht, shared_key, dht_public_key);
182 int len = decrypt_data_symmetric(shared_key, packet + 1 + crypto_box_PUBLICKEYBYTES, 336 int len = decrypt_data_symmetric(shared_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
183 packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, COOKIE_REQUEST_PLAIN_LENGTH + crypto_box_MACBYTES, 337 packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE,
184 request_plain); 338 request_plain);
185 339
186 if (len != COOKIE_REQUEST_PLAIN_LENGTH) 340 if (len != COOKIE_REQUEST_PLAIN_LENGTH) {
187 return -1; 341 return -1;
342 }
188 343
189 return 0; 344 return 0;
190} 345}
191 346
192/* Handle the cookie request packet (for raw UDP) 347/* Handle the cookie request packet (for raw UDP)
193 */ 348 */
194static int udp_handle_cookie_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length) 349static int udp_handle_cookie_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length,
350 void *userdata)
195{ 351{
196 Net_Crypto *c = object; 352 Net_Crypto *c = (Net_Crypto *)object;
197 uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH]; 353 uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH];
198 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 354 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
199 uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; 355 uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];
200 356
201 if (handle_cookie_request(c, request_plain, shared_key, dht_public_key, packet, length) != 0) 357 if (handle_cookie_request(c, request_plain, shared_key, dht_public_key, packet, length) != 0) {
202 return 1; 358 return 1;
359 }
203 360
204 uint8_t data[COOKIE_RESPONSE_LENGTH]; 361 uint8_t data[COOKIE_RESPONSE_LENGTH];
205 362
206 if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) 363 if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) {
207 return 1; 364 return 1;
365 }
208 366
209 if ((uint32_t)sendpacket(c->dht->net, source, data, sizeof(data)) != sizeof(data)) 367 if ((uint32_t)sendpacket(dht_get_net(c->dht), source, data, sizeof(data)) != sizeof(data)) {
210 return 1; 368 return 1;
369 }
211 370
212 return 0; 371 return 0;
213} 372}
@@ -217,16 +376,18 @@ static int udp_handle_cookie_request(void *object, IP_Port source, const uint8_t
217static int tcp_handle_cookie_request(Net_Crypto *c, int connections_number, const uint8_t *packet, uint16_t length) 376static int tcp_handle_cookie_request(Net_Crypto *c, int connections_number, const uint8_t *packet, uint16_t length)
218{ 377{
219 uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH]; 378 uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH];
220 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 379 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
221 uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; 380 uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];
222 381
223 if (handle_cookie_request(c, request_plain, shared_key, dht_public_key, packet, length) != 0) 382 if (handle_cookie_request(c, request_plain, shared_key, dht_public_key, packet, length) != 0) {
224 return -1; 383 return -1;
384 }
225 385
226 uint8_t data[COOKIE_RESPONSE_LENGTH]; 386 uint8_t data[COOKIE_RESPONSE_LENGTH];
227 387
228 if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) 388 if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) {
229 return -1; 389 return -1;
390 }
230 391
231 int ret = send_packet_tcp_connection(c->tcp_c, connections_number, data, sizeof(data)); 392 int ret = send_packet_tcp_connection(c->tcp_c, connections_number, data, sizeof(data));
232 return ret; 393 return ret;
@@ -238,19 +399,22 @@ static int tcp_oob_handle_cookie_request(const Net_Crypto *c, unsigned int tcp_c
238 const uint8_t *dht_public_key, const uint8_t *packet, uint16_t length) 399 const uint8_t *dht_public_key, const uint8_t *packet, uint16_t length)
239{ 400{
240 uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH]; 401 uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH];
241 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 402 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
242 uint8_t dht_public_key_temp[crypto_box_PUBLICKEYBYTES]; 403 uint8_t dht_public_key_temp[CRYPTO_PUBLIC_KEY_SIZE];
243 404
244 if (handle_cookie_request(c, request_plain, shared_key, dht_public_key_temp, packet, length) != 0) 405 if (handle_cookie_request(c, request_plain, shared_key, dht_public_key_temp, packet, length) != 0) {
245 return -1; 406 return -1;
407 }
246 408
247 if (public_key_cmp(dht_public_key, dht_public_key_temp) != 0) 409 if (public_key_cmp(dht_public_key, dht_public_key_temp) != 0) {
248 return -1; 410 return -1;
411 }
249 412
250 uint8_t data[COOKIE_RESPONSE_LENGTH]; 413 uint8_t data[COOKIE_RESPONSE_LENGTH];
251 414
252 if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) 415 if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) {
253 return -1; 416 return -1;
417 }
254 418
255 int ret = tcp_send_oob_packet(c->tcp_c, tcp_connections_number, dht_public_key, data, sizeof(data)); 419 int ret = tcp_send_oob_packet(c->tcp_c, tcp_connections_number, dht_public_key, data, sizeof(data));
256 return ret; 420 return ret;
@@ -267,22 +431,24 @@ static int tcp_oob_handle_cookie_request(const Net_Crypto *c, unsigned int tcp_c
267static int handle_cookie_response(uint8_t *cookie, uint64_t *number, const uint8_t *packet, uint16_t length, 431static int handle_cookie_response(uint8_t *cookie, uint64_t *number, const uint8_t *packet, uint16_t length,
268 const uint8_t *shared_key) 432 const uint8_t *shared_key)
269{ 433{
270 if (length != COOKIE_RESPONSE_LENGTH) 434 if (length != COOKIE_RESPONSE_LENGTH) {
271 return -1; 435 return -1;
436 }
272 437
273 uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)]; 438 uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)];
274 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES, 439 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
275 length - (1 + crypto_box_NONCEBYTES), plain); 440 length - (1 + CRYPTO_NONCE_SIZE), plain);
276 441
277 if (len != sizeof(plain)) 442 if (len != sizeof(plain)) {
278 return -1; 443 return -1;
444 }
279 445
280 memcpy(cookie, plain, COOKIE_LENGTH); 446 memcpy(cookie, plain, COOKIE_LENGTH);
281 memcpy(number, plain + COOKIE_LENGTH, sizeof(uint64_t)); 447 memcpy(number, plain + COOKIE_LENGTH, sizeof(uint64_t));
282 return COOKIE_LENGTH; 448 return COOKIE_LENGTH;
283} 449}
284 450
285#define HANDSHAKE_PACKET_LENGTH (1 + COOKIE_LENGTH + crypto_box_NONCEBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_hash_sha512_BYTES + COOKIE_LENGTH + crypto_box_MACBYTES) 451#define HANDSHAKE_PACKET_LENGTH (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH + CRYPTO_MAC_SIZE)
286 452
287/* Create a handshake packet and put it in packet. 453/* Create a handshake packet and put it in packet.
288 * cookie must be COOKIE_LENGTH bytes. 454 * cookie must be COOKIE_LENGTH bytes.
@@ -294,24 +460,26 @@ static int handle_cookie_response(uint8_t *cookie, uint64_t *number, const uint8
294static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const uint8_t *cookie, const uint8_t *nonce, 460static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const uint8_t *cookie, const uint8_t *nonce,
295 const uint8_t *session_pk, const uint8_t *peer_real_pk, const uint8_t *peer_dht_pubkey) 461 const uint8_t *session_pk, const uint8_t *peer_real_pk, const uint8_t *peer_dht_pubkey)
296{ 462{
297 uint8_t plain[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_hash_sha512_BYTES + COOKIE_LENGTH]; 463 uint8_t plain[CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH];
298 memcpy(plain, nonce, crypto_box_NONCEBYTES); 464 memcpy(plain, nonce, CRYPTO_NONCE_SIZE);
299 memcpy(plain + crypto_box_NONCEBYTES, session_pk, crypto_box_PUBLICKEYBYTES); 465 memcpy(plain + CRYPTO_NONCE_SIZE, session_pk, CRYPTO_PUBLIC_KEY_SIZE);
300 crypto_hash_sha512(plain + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, cookie, COOKIE_LENGTH); 466 crypto_sha512(plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, cookie, COOKIE_LENGTH);
301 uint8_t cookie_plain[COOKIE_DATA_LENGTH]; 467 uint8_t cookie_plain[COOKIE_DATA_LENGTH];
302 memcpy(cookie_plain, peer_real_pk, crypto_box_PUBLICKEYBYTES); 468 memcpy(cookie_plain, peer_real_pk, CRYPTO_PUBLIC_KEY_SIZE);
303 memcpy(cookie_plain + crypto_box_PUBLICKEYBYTES, peer_dht_pubkey, crypto_box_PUBLICKEYBYTES); 469 memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, peer_dht_pubkey, CRYPTO_PUBLIC_KEY_SIZE);
304 470
305 if (create_cookie(plain + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_hash_sha512_BYTES, cookie_plain, 471 if (create_cookie(plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE, cookie_plain,
306 c->secret_symmetric_key) != 0) 472 c->secret_symmetric_key) != 0) {
307 return -1; 473 return -1;
474 }
308 475
309 new_nonce(packet + 1 + COOKIE_LENGTH); 476 random_nonce(packet + 1 + COOKIE_LENGTH);
310 int len = encrypt_data(peer_real_pk, c->self_secret_key, packet + 1 + COOKIE_LENGTH, plain, sizeof(plain), 477 int len = encrypt_data(peer_real_pk, c->self_secret_key, packet + 1 + COOKIE_LENGTH, plain, sizeof(plain),
311 packet + 1 + COOKIE_LENGTH + crypto_box_NONCEBYTES); 478 packet + 1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE);
312 479
313 if (len != HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + crypto_box_NONCEBYTES)) 480 if (len != HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE)) {
314 return -1; 481 return -1;
482 }
315 483
316 packet[0] = NET_PACKET_CRYPTO_HS; 484 packet[0] = NET_PACKET_CRYPTO_HS;
317 memcpy(packet + 1, cookie, COOKIE_LENGTH); 485 memcpy(packet + 1, cookie, COOKIE_LENGTH);
@@ -329,9 +497,9 @@ static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const u
329 * if expected_real_pk isn't NULL it denotes the real public key 497 * if expected_real_pk isn't NULL it denotes the real public key
330 * the packet should be from. 498 * the packet should be from.
331 * 499 *
332 * nonce must be at least crypto_box_NONCEBYTES 500 * nonce must be at least CRYPTO_NONCE_SIZE
333 * session_pk must be at least crypto_box_PUBLICKEYBYTES 501 * session_pk must be at least CRYPTO_PUBLIC_KEY_SIZE
334 * peer_real_pk must be at least crypto_box_PUBLICKEYBYTES 502 * peer_real_pk must be at least CRYPTO_PUBLIC_KEY_SIZE
335 * cookie must be at least COOKIE_LENGTH 503 * cookie must be at least COOKIE_LENGTH
336 * 504 *
337 * return -1 on failure. 505 * return -1 on failure.
@@ -340,46 +508,53 @@ static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const u
340static int handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t *session_pk, uint8_t *peer_real_pk, 508static int handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t *session_pk, uint8_t *peer_real_pk,
341 uint8_t *dht_public_key, uint8_t *cookie, const uint8_t *packet, uint16_t length, const uint8_t *expected_real_pk) 509 uint8_t *dht_public_key, uint8_t *cookie, const uint8_t *packet, uint16_t length, const uint8_t *expected_real_pk)
342{ 510{
343 if (length != HANDSHAKE_PACKET_LENGTH) 511 if (length != HANDSHAKE_PACKET_LENGTH) {
344 return -1; 512 return -1;
513 }
345 514
346 uint8_t cookie_plain[COOKIE_DATA_LENGTH]; 515 uint8_t cookie_plain[COOKIE_DATA_LENGTH];
347 516
348 if (open_cookie(cookie_plain, packet + 1, c->secret_symmetric_key) != 0) 517 if (open_cookie(cookie_plain, packet + 1, c->secret_symmetric_key) != 0) {
349 return -1; 518 return -1;
519 }
350 520
351 if (expected_real_pk) 521 if (expected_real_pk) {
352 if (public_key_cmp(cookie_plain, expected_real_pk) != 0) 522 if (public_key_cmp(cookie_plain, expected_real_pk) != 0) {
353 return -1; 523 return -1;
524 }
525 }
354 526
355 uint8_t cookie_hash[crypto_hash_sha512_BYTES]; 527 uint8_t cookie_hash[CRYPTO_SHA512_SIZE];
356 crypto_hash_sha512(cookie_hash, packet + 1, COOKIE_LENGTH); 528 crypto_sha512(cookie_hash, packet + 1, COOKIE_LENGTH);
357 529
358 uint8_t plain[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_hash_sha512_BYTES + COOKIE_LENGTH]; 530 uint8_t plain[CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH];
359 int len = decrypt_data(cookie_plain, c->self_secret_key, packet + 1 + COOKIE_LENGTH, 531 int len = decrypt_data(cookie_plain, c->self_secret_key, packet + 1 + COOKIE_LENGTH,
360 packet + 1 + COOKIE_LENGTH + crypto_box_NONCEBYTES, 532 packet + 1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE,
361 HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + crypto_box_NONCEBYTES), plain); 533 HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE), plain);
362 534
363 if (len != sizeof(plain)) 535 if (len != sizeof(plain)) {
364 return -1; 536 return -1;
537 }
365 538
366 if (sodium_memcmp(cookie_hash, plain + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, 539 if (crypto_memcmp(cookie_hash, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
367 crypto_hash_sha512_BYTES) != 0) 540 CRYPTO_SHA512_SIZE) != 0) {
368 return -1; 541 return -1;
542 }
369 543
370 memcpy(nonce, plain, crypto_box_NONCEBYTES); 544 memcpy(nonce, plain, CRYPTO_NONCE_SIZE);
371 memcpy(session_pk, plain + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES); 545 memcpy(session_pk, plain + CRYPTO_NONCE_SIZE, CRYPTO_PUBLIC_KEY_SIZE);
372 memcpy(cookie, plain + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_hash_sha512_BYTES, COOKIE_LENGTH); 546 memcpy(cookie, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE, COOKIE_LENGTH);
373 memcpy(peer_real_pk, cookie_plain, crypto_box_PUBLICKEYBYTES); 547 memcpy(peer_real_pk, cookie_plain, CRYPTO_PUBLIC_KEY_SIZE);
374 memcpy(dht_public_key, cookie_plain + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); 548 memcpy(dht_public_key, cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_PUBLIC_KEY_SIZE);
375 return 0; 549 return 0;
376} 550}
377 551
378 552
379static Crypto_Connection *get_crypto_connection(const Net_Crypto *c, int crypt_connection_id) 553static Crypto_Connection *get_crypto_connection(const Net_Crypto *c, int crypt_connection_id)
380{ 554{
381 if (crypt_connection_id_not_valid(c, crypt_connection_id)) 555 if (crypt_connection_id_not_valid(c, crypt_connection_id)) {
382 return 0; 556 return nullptr;
557 }
383 558
384 return &c->crypto_connections[crypt_connection_id]; 559 return &c->crypto_connections[crypt_connection_id];
385} 560}
@@ -394,22 +569,25 @@ static int add_ip_port_connection(Net_Crypto *c, int crypt_connection_id, IP_Por
394{ 569{
395 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 570 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
396 571
397 if (conn == 0) 572 if (conn == nullptr) {
398 return -1; 573 return -1;
574 }
399 575
400 if (ip_port.ip.family == AF_INET) { 576 if (net_family_is_ipv4(ip_port.ip.family)) {
401 if (!ipport_equal(&ip_port, &conn->ip_portv4) && LAN_ip(conn->ip_portv4.ip) != 0) { 577 if (!ipport_equal(&ip_port, &conn->ip_portv4) && ip_is_lan(conn->ip_portv4.ip) != 0) {
402 if (!bs_list_add(&c->ip_port_list, (uint8_t *)&ip_port, crypt_connection_id)) 578 if (!bs_list_add(&c->ip_port_list, (uint8_t *)&ip_port, crypt_connection_id)) {
403 return -1; 579 return -1;
580 }
404 581
405 bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv4, crypt_connection_id); 582 bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv4, crypt_connection_id);
406 conn->ip_portv4 = ip_port; 583 conn->ip_portv4 = ip_port;
407 return 0; 584 return 0;
408 } 585 }
409 } else if (ip_port.ip.family == AF_INET6) { 586 } else if (net_family_is_ipv6(ip_port.ip.family)) {
410 if (!ipport_equal(&ip_port, &conn->ip_portv6)) { 587 if (!ipport_equal(&ip_port, &conn->ip_portv6)) {
411 if (!bs_list_add(&c->ip_port_list, (uint8_t *)&ip_port, crypt_connection_id)) 588 if (!bs_list_add(&c->ip_port_list, (uint8_t *)&ip_port, crypt_connection_id)) {
412 return -1; 589 return -1;
590 }
413 591
414 bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv6, crypt_connection_id); 592 bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv6, crypt_connection_id);
415 conn->ip_portv6 = ip_port; 593 conn->ip_portv6 = ip_port;
@@ -425,18 +603,18 @@ static int add_ip_port_connection(Net_Crypto *c, int crypt_connection_id, IP_Por
425 * return IP_Port with family 0 on failure. 603 * return IP_Port with family 0 on failure.
426 * return IP_Port on success. 604 * return IP_Port on success.
427 */ 605 */
428IP_Port return_ip_port_connection(Net_Crypto *c, int crypt_connection_id) 606static IP_Port return_ip_port_connection(Net_Crypto *c, int crypt_connection_id)
429{ 607{
430 IP_Port empty; 608 const IP_Port empty = {{{0}}};
431 empty.ip.family = 0;
432 609
433 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 610 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
434 611
435 if (conn == 0) 612 if (conn == nullptr) {
436 return empty; 613 return empty;
614 }
437 615
438 uint64_t current_time = unix_time(); 616 uint64_t current_time = unix_time();
439 _Bool v6 = 0, v4 = 0; 617 bool v6 = 0, v4 = 0;
440 618
441 if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) { 619 if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) {
442 v4 = 1; 620 v4 = 1;
@@ -446,15 +624,19 @@ IP_Port return_ip_port_connection(Net_Crypto *c, int crypt_connection_id)
446 v6 = 1; 624 v6 = 1;
447 } 625 }
448 626
449 if (v4 && LAN_ip(conn->ip_portv4.ip) == 0) { 627 if (v4 && ip_is_lan(conn->ip_portv4.ip) == 0) {
450 return conn->ip_portv4; 628 return conn->ip_portv4;
451 } else if (v6 && conn->ip_portv6.ip.family == AF_INET6) { 629 }
630
631 if (v6 && net_family_is_ipv6(conn->ip_portv6.ip.family)) {
452 return conn->ip_portv6; 632 return conn->ip_portv6;
453 } else if (conn->ip_portv4.ip.family == AF_INET) { 633 }
634
635 if (net_family_is_ipv4(conn->ip_portv4.ip.family)) {
454 return conn->ip_portv4; 636 return conn->ip_portv4;
455 } else {
456 return empty;
457 } 637 }
638
639 return empty;
458} 640}
459 641
460/* Sends a packet to the peer using the fastest route. 642/* Sends a packet to the peer using the fastest route.
@@ -464,38 +646,39 @@ IP_Port return_ip_port_connection(Net_Crypto *c, int crypt_connection_id)
464 */ 646 */
465static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length) 647static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length)
466{ 648{
467//TODO TCP, etc... 649// TODO(irungentoo): TCP, etc...
468 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 650 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
469 651
470 if (conn == 0) 652 if (conn == nullptr) {
471 return -1; 653 return -1;
654 }
472 655
473 int direct_send_attempt = 0; 656 int direct_send_attempt = 0;
474 657
475 pthread_mutex_lock(&conn->mutex); 658 pthread_mutex_lock(&conn->mutex);
476 IP_Port ip_port = return_ip_port_connection(c, crypt_connection_id); 659 IP_Port ip_port = return_ip_port_connection(c, crypt_connection_id);
477 660
478 //TODO: on bad networks, direct connections might not last indefinitely. 661 // TODO(irungentoo): on bad networks, direct connections might not last indefinitely.
479 if (ip_port.ip.family != 0) { 662 if (!net_family_is_unspec(ip_port.ip.family)) {
480 _Bool direct_connected = 0; 663 bool direct_connected = 0;
481 crypto_connection_status(c, crypt_connection_id, &direct_connected, NULL); 664 crypto_connection_status(c, crypt_connection_id, &direct_connected, nullptr);
482 665
483 if (direct_connected) { 666 if (direct_connected) {
484 if ((uint32_t)sendpacket(c->dht->net, ip_port, data, length) == length) { 667 if ((uint32_t)sendpacket(dht_get_net(c->dht), ip_port, data, length) == length) {
485 pthread_mutex_unlock(&conn->mutex); 668 pthread_mutex_unlock(&conn->mutex);
486 return 0; 669 return 0;
487 } else {
488 pthread_mutex_unlock(&conn->mutex);
489 return -1;
490 } 670 }
671
672 pthread_mutex_unlock(&conn->mutex);
673 return -1;
491 } 674 }
492 675
493 //TODO: a better way of sending packets directly to confirm the others ip. 676 // TODO(irungentoo): a better way of sending packets directly to confirm the others ip.
494 uint64_t current_time = unix_time(); 677 uint64_t current_time = unix_time();
495 678
496 if ((((UDP_DIRECT_TIMEOUT / 2) + conn->direct_send_attempt_time) > current_time && length < 96) 679 if ((((UDP_DIRECT_TIMEOUT / 2) + conn->direct_send_attempt_time) > current_time && length < 96)
497 || data[0] == NET_PACKET_COOKIE_REQUEST || data[0] == NET_PACKET_CRYPTO_HS) { 680 || data[0] == NET_PACKET_COOKIE_REQUEST || data[0] == NET_PACKET_CRYPTO_HS) {
498 if ((uint32_t)sendpacket(c->dht->net, ip_port, data, length) == length) { 681 if ((uint32_t)sendpacket(dht_get_net(c->dht), ip_port, data, length) == length) {
499 direct_send_attempt = 1; 682 direct_send_attempt = 1;
500 conn->direct_send_attempt_time = unix_time(); 683 conn->direct_send_attempt_time = unix_time();
501 } 684 }
@@ -540,24 +723,28 @@ static uint32_t num_packets_array(const Packets_Array *array)
540 */ 723 */
541static int add_data_to_buffer(Packets_Array *array, uint32_t number, const Packet_Data *data) 724static int add_data_to_buffer(Packets_Array *array, uint32_t number, const Packet_Data *data)
542{ 725{
543 if (number - array->buffer_start > CRYPTO_PACKET_BUFFER_SIZE) 726 if (number - array->buffer_start > CRYPTO_PACKET_BUFFER_SIZE) {
544 return -1; 727 return -1;
728 }
545 729
546 uint32_t num = number % CRYPTO_PACKET_BUFFER_SIZE; 730 uint32_t num = number % CRYPTO_PACKET_BUFFER_SIZE;
547 731
548 if (array->buffer[num]) 732 if (array->buffer[num]) {
549 return -1; 733 return -1;
734 }
550 735
551 Packet_Data *new_d = malloc(sizeof(Packet_Data)); 736 Packet_Data *new_d = (Packet_Data *)malloc(sizeof(Packet_Data));
552 737
553 if (new_d == NULL) 738 if (new_d == nullptr) {
554 return -1; 739 return -1;
740 }
555 741
556 memcpy(new_d, data, sizeof(Packet_Data)); 742 memcpy(new_d, data, sizeof(Packet_Data));
557 array->buffer[num] = new_d; 743 array->buffer[num] = new_d;
558 744
559 if ((number - array->buffer_start) >= (array->buffer_end - array->buffer_start)) 745 if ((number - array->buffer_start) >= (array->buffer_end - array->buffer_start)) {
560 array->buffer_end = number + 1; 746 array->buffer_end = number + 1;
747 }
561 748
562 return 0; 749 return 0;
563} 750}
@@ -572,13 +759,15 @@ static int get_data_pointer(const Packets_Array *array, Packet_Data **data, uint
572{ 759{
573 uint32_t num_spots = array->buffer_end - array->buffer_start; 760 uint32_t num_spots = array->buffer_end - array->buffer_start;
574 761
575 if (array->buffer_end - number > num_spots || number - array->buffer_start >= num_spots) 762 if (array->buffer_end - number > num_spots || number - array->buffer_start >= num_spots) {
576 return -1; 763 return -1;
764 }
577 765
578 uint32_t num = number % CRYPTO_PACKET_BUFFER_SIZE; 766 uint32_t num = number % CRYPTO_PACKET_BUFFER_SIZE;
579 767
580 if (!array->buffer[num]) 768 if (!array->buffer[num]) {
581 return 0; 769 return 0;
770 }
582 771
583 *data = array->buffer[num]; 772 *data = array->buffer[num];
584 return 1; 773 return 1;
@@ -591,13 +780,15 @@ static int get_data_pointer(const Packets_Array *array, Packet_Data **data, uint
591 */ 780 */
592static int64_t add_data_end_of_buffer(Packets_Array *array, const Packet_Data *data) 781static int64_t add_data_end_of_buffer(Packets_Array *array, const Packet_Data *data)
593{ 782{
594 if (num_packets_array(array) >= CRYPTO_PACKET_BUFFER_SIZE) 783 if (num_packets_array(array) >= CRYPTO_PACKET_BUFFER_SIZE) {
595 return -1; 784 return -1;
785 }
596 786
597 Packet_Data *new_d = malloc(sizeof(Packet_Data)); 787 Packet_Data *new_d = (Packet_Data *)malloc(sizeof(Packet_Data));
598 788
599 if (new_d == NULL) 789 if (new_d == nullptr) {
600 return -1; 790 return -1;
791 }
601 792
602 memcpy(new_d, data, sizeof(Packet_Data)); 793 memcpy(new_d, data, sizeof(Packet_Data));
603 uint32_t id = array->buffer_end; 794 uint32_t id = array->buffer_end;
@@ -613,19 +804,21 @@ static int64_t add_data_end_of_buffer(Packets_Array *array, const Packet_Data *d
613 */ 804 */
614static int64_t read_data_beg_buffer(Packets_Array *array, Packet_Data *data) 805static int64_t read_data_beg_buffer(Packets_Array *array, Packet_Data *data)
615{ 806{
616 if (array->buffer_end == array->buffer_start) 807 if (array->buffer_end == array->buffer_start) {
617 return -1; 808 return -1;
809 }
618 810
619 uint32_t num = array->buffer_start % CRYPTO_PACKET_BUFFER_SIZE; 811 uint32_t num = array->buffer_start % CRYPTO_PACKET_BUFFER_SIZE;
620 812
621 if (!array->buffer[num]) 813 if (!array->buffer[num]) {
622 return -1; 814 return -1;
815 }
623 816
624 memcpy(data, array->buffer[num], sizeof(Packet_Data)); 817 memcpy(data, array->buffer[num], sizeof(Packet_Data));
625 uint32_t id = array->buffer_start; 818 uint32_t id = array->buffer_start;
626 ++array->buffer_start; 819 ++array->buffer_start;
627 free(array->buffer[num]); 820 free(array->buffer[num]);
628 array->buffer[num] = NULL; 821 array->buffer[num] = nullptr;
629 return id; 822 return id;
630} 823}
631 824
@@ -638,8 +831,9 @@ static int clear_buffer_until(Packets_Array *array, uint32_t number)
638{ 831{
639 uint32_t num_spots = array->buffer_end - array->buffer_start; 832 uint32_t num_spots = array->buffer_end - array->buffer_start;
640 833
641 if (array->buffer_end - number >= num_spots || number - array->buffer_start > num_spots) 834 if (array->buffer_end - number >= num_spots || number - array->buffer_start > num_spots) {
642 return -1; 835 return -1;
836 }
643 837
644 uint32_t i; 838 uint32_t i;
645 839
@@ -648,7 +842,7 @@ static int clear_buffer_until(Packets_Array *array, uint32_t number)
648 842
649 if (array->buffer[num]) { 843 if (array->buffer[num]) {
650 free(array->buffer[num]); 844 free(array->buffer[num]);
651 array->buffer[num] = NULL; 845 array->buffer[num] = nullptr;
652 } 846 }
653 } 847 }
654 848
@@ -665,7 +859,7 @@ static int clear_buffer(Packets_Array *array)
665 859
666 if (array->buffer[num]) { 860 if (array->buffer[num]) {
667 free(array->buffer[num]); 861 free(array->buffer[num]);
668 array->buffer[num] = NULL; 862 array->buffer[num] = nullptr;
669 } 863 }
670 } 864 }
671 865
@@ -680,11 +874,13 @@ static int clear_buffer(Packets_Array *array)
680 */ 874 */
681static int set_buffer_end(Packets_Array *array, uint32_t number) 875static int set_buffer_end(Packets_Array *array, uint32_t number)
682{ 876{
683 if ((number - array->buffer_start) > CRYPTO_PACKET_BUFFER_SIZE) 877 if ((number - array->buffer_start) > CRYPTO_PACKET_BUFFER_SIZE) {
684 return -1; 878 return -1;
879 }
685 880
686 if ((number - array->buffer_end) > CRYPTO_PACKET_BUFFER_SIZE) 881 if ((number - array->buffer_end) > CRYPTO_PACKET_BUFFER_SIZE) {
687 return -1; 882 return -1;
883 }
688 884
689 array->buffer_end = number; 885 array->buffer_end = number;
690 return 0; 886 return 0;
@@ -698,18 +894,21 @@ static int set_buffer_end(Packets_Array *array, uint32_t number)
698 */ 894 */
699static int generate_request_packet(uint8_t *data, uint16_t length, const Packets_Array *recv_array) 895static int generate_request_packet(uint8_t *data, uint16_t length, const Packets_Array *recv_array)
700{ 896{
701 if (length == 0) 897 if (length == 0) {
702 return -1; 898 return -1;
899 }
703 900
704 data[0] = PACKET_ID_REQUEST; 901 data[0] = PACKET_ID_REQUEST;
705 902
706 uint16_t cur_len = 1; 903 uint16_t cur_len = 1;
707 904
708 if (recv_array->buffer_start == recv_array->buffer_end) 905 if (recv_array->buffer_start == recv_array->buffer_end) {
709 return cur_len; 906 return cur_len;
907 }
710 908
711 if (length <= cur_len) 909 if (length <= cur_len) {
712 return cur_len; 910 return cur_len;
911 }
713 912
714 uint32_t i, n = 1; 913 uint32_t i, n = 1;
715 914
@@ -721,16 +920,17 @@ static int generate_request_packet(uint8_t *data, uint16_t length, const Packets
721 n = 0; 920 n = 0;
722 ++cur_len; 921 ++cur_len;
723 922
724 if (length <= cur_len) 923 if (length <= cur_len) {
725 return cur_len; 924 return cur_len;
726 925 }
727 } else if (n == 255) { 926 } else if (n == 255) {
728 data[cur_len] = 0; 927 data[cur_len] = 0;
729 n = 0; 928 n = 0;
730 ++cur_len; 929 ++cur_len;
731 930
732 if (length <= cur_len) 931 if (length <= cur_len) {
733 return cur_len; 932 return cur_len;
933 }
734 } 934 }
735 935
736 ++n; 936 ++n;
@@ -748,14 +948,17 @@ static int generate_request_packet(uint8_t *data, uint16_t length, const Packets
748static int handle_request_packet(Packets_Array *send_array, const uint8_t *data, uint16_t length, 948static int handle_request_packet(Packets_Array *send_array, const uint8_t *data, uint16_t length,
749 uint64_t *latest_send_time, uint64_t rtt_time) 949 uint64_t *latest_send_time, uint64_t rtt_time)
750{ 950{
751 if (length < 1) 951 if (length < 1) {
752 return -1; 952 return -1;
953 }
753 954
754 if (data[0] != PACKET_ID_REQUEST) 955 if (data[0] != PACKET_ID_REQUEST) {
755 return -1; 956 return -1;
957 }
756 958
757 if (length == 1) 959 if (length == 1) {
758 return 0; 960 return 0;
961 }
759 962
760 ++data; 963 ++data;
761 --length; 964 --length;
@@ -767,8 +970,9 @@ static int handle_request_packet(Packets_Array *send_array, const uint8_t *data,
767 uint64_t l_sent_time = ~0; 970 uint64_t l_sent_time = ~0;
768 971
769 for (i = send_array->buffer_start; i != send_array->buffer_end; ++i) { 972 for (i = send_array->buffer_start; i != send_array->buffer_end; ++i) {
770 if (length == 0) 973 if (length == 0) {
771 break; 974 break;
975 }
772 976
773 uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE; 977 uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE;
774 978
@@ -789,19 +993,21 @@ static int handle_request_packet(Packets_Array *send_array, const uint8_t *data,
789 if (send_array->buffer[num]) { 993 if (send_array->buffer[num]) {
790 uint64_t sent_time = send_array->buffer[num]->sent_time; 994 uint64_t sent_time = send_array->buffer[num]->sent_time;
791 995
792 if (l_sent_time < sent_time) 996 if (l_sent_time < sent_time) {
793 l_sent_time = sent_time; 997 l_sent_time = sent_time;
998 }
794 999
795 free(send_array->buffer[num]); 1000 free(send_array->buffer[num]);
796 send_array->buffer[num] = NULL; 1001 send_array->buffer[num] = nullptr;
797 } 1002 }
798 } 1003 }
799 1004
800 if (n == 255) { 1005 if (n == 255) {
801 n = 1; 1006 n = 1;
802 1007
803 if (data[0] != 0) 1008 if (data[0] != 0) {
804 return -1; 1009 return -1;
1010 }
805 1011
806 ++data; 1012 ++data;
807 --length; 1013 --length;
@@ -810,15 +1016,16 @@ static int handle_request_packet(Packets_Array *send_array, const uint8_t *data,
810 } 1016 }
811 } 1017 }
812 1018
813 if (*latest_send_time < l_sent_time) 1019 if (*latest_send_time < l_sent_time) {
814 *latest_send_time = l_sent_time; 1020 *latest_send_time = l_sent_time;
1021 }
815 1022
816 return requested; 1023 return requested;
817} 1024}
818 1025
819/** END: Array Related functions **/ 1026/** END: Array Related functions **/
820 1027
821#define MAX_DATA_DATA_PACKET_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) 1028#define MAX_DATA_DATA_PACKET_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE))
822 1029
823/* Creates and sends a data packet to the peer using the fastest route. 1030/* Creates and sends a data packet to the peer using the fastest route.
824 * 1031 *
@@ -827,21 +1034,23 @@ static int handle_request_packet(Packets_Array *send_array, const uint8_t *data,
827 */ 1034 */
828static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length) 1035static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length)
829{ 1036{
830 if (length == 0 || length + (1 + sizeof(uint16_t) + crypto_box_MACBYTES) > MAX_CRYPTO_PACKET_SIZE) 1037 if (length == 0 || length + (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE) > MAX_CRYPTO_PACKET_SIZE) {
831 return -1; 1038 return -1;
1039 }
832 1040
833 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 1041 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
834 1042
835 if (conn == 0) 1043 if (conn == nullptr) {
836 return -1; 1044 return -1;
1045 }
837 1046
838 pthread_mutex_lock(&conn->mutex); 1047 pthread_mutex_lock(&conn->mutex);
839 uint8_t packet[1 + sizeof(uint16_t) + length + crypto_box_MACBYTES]; 1048 VLA(uint8_t, packet, 1 + sizeof(uint16_t) + length + CRYPTO_MAC_SIZE);
840 packet[0] = NET_PACKET_CRYPTO_DATA; 1049 packet[0] = NET_PACKET_CRYPTO_DATA;
841 memcpy(packet + 1, conn->sent_nonce + (crypto_box_NONCEBYTES - sizeof(uint16_t)), sizeof(uint16_t)); 1050 memcpy(packet + 1, conn->sent_nonce + (CRYPTO_NONCE_SIZE - sizeof(uint16_t)), sizeof(uint16_t));
842 int len = encrypt_data_symmetric(conn->shared_key, conn->sent_nonce, data, length, packet + 1 + sizeof(uint16_t)); 1051 int len = encrypt_data_symmetric(conn->shared_key, conn->sent_nonce, data, length, packet + 1 + sizeof(uint16_t));
843 1052
844 if (len + 1 + sizeof(uint16_t) != sizeof(packet)) { 1053 if (len + 1 + sizeof(uint16_t) != SIZEOF_VLA(packet)) {
845 pthread_mutex_unlock(&conn->mutex); 1054 pthread_mutex_unlock(&conn->mutex);
846 return -1; 1055 return -1;
847 } 1056 }
@@ -849,7 +1058,7 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_
849 increment_nonce(conn->sent_nonce); 1058 increment_nonce(conn->sent_nonce);
850 pthread_mutex_unlock(&conn->mutex); 1059 pthread_mutex_unlock(&conn->mutex);
851 1060
852 return send_packet_to(c, crypt_connection_id, packet, sizeof(packet)); 1061 return send_packet_to(c, crypt_connection_id, packet, SIZEOF_VLA(packet));
853} 1062}
854 1063
855/* Creates and sends a data packet with buffer_start and num to the peer using the fastest route. 1064/* Creates and sends a data packet with buffer_start and num to the peer using the fastest route.
@@ -860,32 +1069,34 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_
860static int send_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint32_t buffer_start, uint32_t num, 1069static int send_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint32_t buffer_start, uint32_t num,
861 const uint8_t *data, uint16_t length) 1070 const uint8_t *data, uint16_t length)
862{ 1071{
863 if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) 1072 if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) {
864 return -1; 1073 return -1;
1074 }
865 1075
866 num = htonl(num); 1076 num = net_htonl(num);
867 buffer_start = htonl(buffer_start); 1077 buffer_start = net_htonl(buffer_start);
868 uint16_t padding_length = (MAX_CRYPTO_DATA_SIZE - length) % CRYPTO_MAX_PADDING; 1078 uint16_t padding_length = (MAX_CRYPTO_DATA_SIZE - length) % CRYPTO_MAX_PADDING;
869 uint8_t packet[sizeof(uint32_t) + sizeof(uint32_t) + padding_length + length]; 1079 VLA(uint8_t, packet, sizeof(uint32_t) + sizeof(uint32_t) + padding_length + length);
870 memcpy(packet, &buffer_start, sizeof(uint32_t)); 1080 memcpy(packet, &buffer_start, sizeof(uint32_t));
871 memcpy(packet + sizeof(uint32_t), &num, sizeof(uint32_t)); 1081 memcpy(packet + sizeof(uint32_t), &num, sizeof(uint32_t));
872 memset(packet + (sizeof(uint32_t) * 2), PACKET_ID_PADDING, padding_length); 1082 memset(packet + (sizeof(uint32_t) * 2), PACKET_ID_PADDING, padding_length);
873 memcpy(packet + (sizeof(uint32_t) * 2) + padding_length, data, length); 1083 memcpy(packet + (sizeof(uint32_t) * 2) + padding_length, data, length);
874 1084
875 return send_data_packet(c, crypt_connection_id, packet, sizeof(packet)); 1085 return send_data_packet(c, crypt_connection_id, packet, SIZEOF_VLA(packet));
876} 1086}
877 1087
878static int reset_max_speed_reached(Net_Crypto *c, int crypt_connection_id) 1088static int reset_max_speed_reached(Net_Crypto *c, int crypt_connection_id)
879{ 1089{
880 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 1090 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
881 1091
882 if (conn == 0) 1092 if (conn == nullptr) {
883 return -1; 1093 return -1;
1094 }
884 1095
885 /* If last packet send failed, try to send packet again. 1096 /* If last packet send failed, try to send packet again.
886 If sending it fails we won't be able to send the new packet. */ 1097 If sending it fails we won't be able to send the new packet. */
887 if (conn->maximum_speed_reached) { 1098 if (conn->maximum_speed_reached) {
888 Packet_Data *dt = NULL; 1099 Packet_Data *dt = nullptr;
889 uint32_t packet_num = conn->send_array.buffer_end - 1; 1100 uint32_t packet_num = conn->send_array.buffer_end - 1;
890 int ret = get_data_pointer(&conn->send_array, &dt, packet_num); 1101 int ret = get_data_pointer(&conn->send_array, &dt, packet_num);
891 1102
@@ -918,13 +1129,15 @@ static int reset_max_speed_reached(Net_Crypto *c, int crypt_connection_id)
918static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length, 1129static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length,
919 uint8_t congestion_control) 1130 uint8_t congestion_control)
920{ 1131{
921 if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) 1132 if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) {
922 return -1; 1133 return -1;
1134 }
923 1135
924 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 1136 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
925 1137
926 if (conn == 0) 1138 if (conn == nullptr) {
927 return -1; 1139 return -1;
1140 }
928 1141
929 /* If last packet send failed, try to send packet again. 1142 /* If last packet send failed, try to send packet again.
930 If sending it fails we won't be able to send the new packet. */ 1143 If sending it fails we won't be able to send the new packet. */
@@ -942,21 +1155,23 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, cons
942 int64_t packet_num = add_data_end_of_buffer(&conn->send_array, &dt); 1155 int64_t packet_num = add_data_end_of_buffer(&conn->send_array, &dt);
943 pthread_mutex_unlock(&conn->mutex); 1156 pthread_mutex_unlock(&conn->mutex);
944 1157
945 if (packet_num == -1) 1158 if (packet_num == -1) {
946 return -1; 1159 return -1;
1160 }
947 1161
948 if (!congestion_control && conn->maximum_speed_reached) { 1162 if (!congestion_control && conn->maximum_speed_reached) {
949 return packet_num; 1163 return packet_num;
950 } 1164 }
951 1165
952 if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, data, length) == 0) { 1166 if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, data, length) == 0) {
953 Packet_Data *dt1 = NULL; 1167 Packet_Data *dt1 = nullptr;
954 1168
955 if (get_data_pointer(&conn->send_array, &dt1, packet_num) == 1) 1169 if (get_data_pointer(&conn->send_array, &dt1, packet_num) == 1) {
956 dt1->sent_time = current_time_monotonic(); 1170 dt1->sent_time = current_time_monotonic();
1171 }
957 } else { 1172 } else {
958 conn->maximum_speed_reached = 1; 1173 conn->maximum_speed_reached = 1;
959 LOGGER_ERROR("send_data_packet failed\n"); 1174 LOGGER_ERROR(c->log, "send_data_packet failed\n");
960 } 1175 }
961 1176
962 return packet_num; 1177 return packet_num;
@@ -968,8 +1183,8 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, cons
968static uint16_t get_nonce_uint16(const uint8_t *nonce) 1183static uint16_t get_nonce_uint16(const uint8_t *nonce)
969{ 1184{
970 uint16_t num; 1185 uint16_t num;
971 memcpy(&num, nonce + (crypto_box_NONCEBYTES - sizeof(uint16_t)), sizeof(uint16_t)); 1186 memcpy(&num, nonce + (CRYPTO_NONCE_SIZE - sizeof(uint16_t)), sizeof(uint16_t));
972 return ntohs(num); 1187 return net_ntohs(num);
973} 1188}
974 1189
975#define DATA_NUM_THRESHOLD 21845 1190#define DATA_NUM_THRESHOLD 21845
@@ -984,27 +1199,30 @@ static uint16_t get_nonce_uint16(const uint8_t *nonce)
984static int handle_data_packet(const Net_Crypto *c, int crypt_connection_id, uint8_t *data, const uint8_t *packet, 1199static int handle_data_packet(const Net_Crypto *c, int crypt_connection_id, uint8_t *data, const uint8_t *packet,
985 uint16_t length) 1200 uint16_t length)
986{ 1201{
987 if (length <= (1 + sizeof(uint16_t) + crypto_box_MACBYTES) || length > MAX_CRYPTO_PACKET_SIZE) 1202 if (length <= (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE) || length > MAX_CRYPTO_PACKET_SIZE) {
988 return -1; 1203 return -1;
1204 }
989 1205
990 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 1206 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
991 1207
992 if (conn == 0) 1208 if (conn == nullptr) {
993 return -1; 1209 return -1;
1210 }
994 1211
995 uint8_t nonce[crypto_box_NONCEBYTES]; 1212 uint8_t nonce[CRYPTO_NONCE_SIZE];
996 memcpy(nonce, conn->recv_nonce, crypto_box_NONCEBYTES); 1213 memcpy(nonce, conn->recv_nonce, CRYPTO_NONCE_SIZE);
997 uint16_t num_cur_nonce = get_nonce_uint16(nonce); 1214 uint16_t num_cur_nonce = get_nonce_uint16(nonce);
998 uint16_t num; 1215 uint16_t num;
999 memcpy(&num, packet + 1, sizeof(uint16_t)); 1216 memcpy(&num, packet + 1, sizeof(uint16_t));
1000 num = ntohs(num); 1217 num = net_ntohs(num);
1001 uint16_t diff = num - num_cur_nonce; 1218 uint16_t diff = num - num_cur_nonce;
1002 increment_nonce_number(nonce, diff); 1219 increment_nonce_number(nonce, diff);
1003 int len = decrypt_data_symmetric(conn->shared_key, nonce, packet + 1 + sizeof(uint16_t), 1220 int len = decrypt_data_symmetric(conn->shared_key, nonce, packet + 1 + sizeof(uint16_t),
1004 length - (1 + sizeof(uint16_t)), data); 1221 length - (1 + sizeof(uint16_t)), data);
1005 1222
1006 if ((unsigned int)len != length - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) 1223 if ((unsigned int)len != length - (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE)) {
1007 return -1; 1224 return -1;
1225 }
1008 1226
1009 if (diff > DATA_NUM_THRESHOLD * 2) { 1227 if (diff > DATA_NUM_THRESHOLD * 2) {
1010 increment_nonce_number(conn->recv_nonce, DATA_NUM_THRESHOLD); 1228 increment_nonce_number(conn->recv_nonce, DATA_NUM_THRESHOLD);
@@ -1022,14 +1240,16 @@ static int send_request_packet(Net_Crypto *c, int crypt_connection_id)
1022{ 1240{
1023 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 1241 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
1024 1242
1025 if (conn == 0) 1243 if (conn == nullptr) {
1026 return -1; 1244 return -1;
1245 }
1027 1246
1028 uint8_t data[MAX_CRYPTO_DATA_SIZE]; 1247 uint8_t data[MAX_CRYPTO_DATA_SIZE];
1029 int len = generate_request_packet(data, sizeof(data), &conn->recv_array); 1248 int len = generate_request_packet(data, sizeof(data), &conn->recv_array);
1030 1249
1031 if (len == -1) 1250 if (len == -1) {
1032 return -1; 1251 return -1;
1252 }
1033 1253
1034 return send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, conn->send_array.buffer_end, data, 1254 return send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, conn->send_array.buffer_end, data,
1035 len); 1255 len);
@@ -1042,13 +1262,15 @@ static int send_request_packet(Net_Crypto *c, int crypt_connection_id)
1042 */ 1262 */
1043static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32_t max_num) 1263static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32_t max_num)
1044{ 1264{
1045 if (max_num == 0) 1265 if (max_num == 0) {
1046 return -1; 1266 return -1;
1267 }
1047 1268
1048 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 1269 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
1049 1270
1050 if (conn == 0) 1271 if (conn == nullptr) {
1051 return -1; 1272 return -1;
1273 }
1052 1274
1053 uint64_t temp_time = current_time_monotonic(); 1275 uint64_t temp_time = current_time_monotonic();
1054 uint32_t i, num_sent = 0, array_size = num_packets_array(&conn->send_array); 1276 uint32_t i, num_sent = 0, array_size = num_packets_array(&conn->send_array);
@@ -1060,7 +1282,9 @@ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32
1060 1282
1061 if (ret == -1) { 1283 if (ret == -1) {
1062 return -1; 1284 return -1;
1063 } else if (ret == 0) { 1285 }
1286
1287 if (ret == 0) {
1064 continue; 1288 continue;
1065 } 1289 }
1066 1290
@@ -1074,8 +1298,9 @@ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32
1074 ++num_sent; 1298 ++num_sent;
1075 } 1299 }
1076 1300
1077 if (num_sent >= max_num) 1301 if (num_sent >= max_num) {
1078 break; 1302 break;
1303 }
1079 } 1304 }
1080 1305
1081 return num_sent; 1306 return num_sent;
@@ -1089,21 +1314,25 @@ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32
1089 */ 1314 */
1090static int new_temp_packet(const Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length) 1315static int new_temp_packet(const Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length)
1091{ 1316{
1092 if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) 1317 if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) {
1093 return -1; 1318 return -1;
1319 }
1094 1320
1095 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 1321 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
1096 1322
1097 if (conn == 0) 1323 if (conn == nullptr) {
1098 return -1; 1324 return -1;
1325 }
1099 1326
1100 uint8_t *temp_packet = malloc(length); 1327 uint8_t *temp_packet = (uint8_t *)malloc(length);
1101 1328
1102 if (temp_packet == 0) 1329 if (temp_packet == nullptr) {
1103 return -1; 1330 return -1;
1331 }
1104 1332
1105 if (conn->temp_packet) 1333 if (conn->temp_packet) {
1106 free(conn->temp_packet); 1334 free(conn->temp_packet);
1335 }
1107 1336
1108 memcpy(temp_packet, packet, length); 1337 memcpy(temp_packet, packet, length);
1109 conn->temp_packet = temp_packet; 1338 conn->temp_packet = temp_packet;
@@ -1122,13 +1351,15 @@ static int clear_temp_packet(const Net_Crypto *c, int crypt_connection_id)
1122{ 1351{
1123 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 1352 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
1124 1353
1125 if (conn == 0) 1354 if (conn == nullptr) {
1126 return -1; 1355 return -1;
1356 }
1127 1357
1128 if (conn->temp_packet) 1358 if (conn->temp_packet) {
1129 free(conn->temp_packet); 1359 free(conn->temp_packet);
1360 }
1130 1361
1131 conn->temp_packet = 0; 1362 conn->temp_packet = nullptr;
1132 conn->temp_packet_length = 0; 1363 conn->temp_packet_length = 0;
1133 conn->temp_packet_sent_time = 0; 1364 conn->temp_packet_sent_time = 0;
1134 conn->temp_packet_num_sent = 0; 1365 conn->temp_packet_num_sent = 0;
@@ -1145,14 +1376,17 @@ static int send_temp_packet(Net_Crypto *c, int crypt_connection_id)
1145{ 1376{
1146 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 1377 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
1147 1378
1148 if (conn == 0) 1379 if (conn == nullptr) {
1149 return -1; 1380 return -1;
1381 }
1150 1382
1151 if (!conn->temp_packet) 1383 if (!conn->temp_packet) {
1152 return -1; 1384 return -1;
1385 }
1153 1386
1154 if (send_packet_to(c, crypt_connection_id, conn->temp_packet, conn->temp_packet_length) != 0) 1387 if (send_packet_to(c, crypt_connection_id, conn->temp_packet, conn->temp_packet_length) != 0) {
1155 return -1; 1388 return -1;
1389 }
1156 1390
1157 conn->temp_packet_sent_time = current_time_monotonic(); 1391 conn->temp_packet_sent_time = current_time_monotonic();
1158 ++conn->temp_packet_num_sent; 1392 ++conn->temp_packet_num_sent;
@@ -1170,17 +1404,20 @@ static int create_send_handshake(Net_Crypto *c, int crypt_connection_id, const u
1170{ 1404{
1171 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 1405 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
1172 1406
1173 if (conn == 0) 1407 if (conn == nullptr) {
1174 return -1; 1408 return -1;
1409 }
1175 1410
1176 uint8_t handshake_packet[HANDSHAKE_PACKET_LENGTH]; 1411 uint8_t handshake_packet[HANDSHAKE_PACKET_LENGTH];
1177 1412
1178 if (create_crypto_handshake(c, handshake_packet, cookie, conn->sent_nonce, conn->sessionpublic_key, 1413 if (create_crypto_handshake(c, handshake_packet, cookie, conn->sent_nonce, conn->sessionpublic_key,
1179 conn->public_key, dht_public_key) != sizeof(handshake_packet)) 1414 conn->public_key, dht_public_key) != sizeof(handshake_packet)) {
1180 return -1; 1415 return -1;
1416 }
1181 1417
1182 if (new_temp_packet(c, crypt_connection_id, handshake_packet, sizeof(handshake_packet)) != 0) 1418 if (new_temp_packet(c, crypt_connection_id, handshake_packet, sizeof(handshake_packet)) != 0) {
1183 return -1; 1419 return -1;
1420 }
1184 1421
1185 send_temp_packet(c, crypt_connection_id); 1422 send_temp_packet(c, crypt_connection_id);
1186 return 0; 1423 return 0;
@@ -1195,23 +1432,26 @@ static int send_kill_packet(Net_Crypto *c, int crypt_connection_id)
1195{ 1432{
1196 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 1433 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
1197 1434
1198 if (conn == 0) 1435 if (conn == nullptr) {
1199 return -1; 1436 return -1;
1437 }
1200 1438
1201 uint8_t kill_packet = PACKET_ID_KILL; 1439 uint8_t kill_packet = PACKET_ID_KILL;
1202 return send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, conn->send_array.buffer_end, 1440 return send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, conn->send_array.buffer_end,
1203 &kill_packet, sizeof(kill_packet)); 1441 &kill_packet, sizeof(kill_packet));
1204} 1442}
1205 1443
1206static void connection_kill(Net_Crypto *c, int crypt_connection_id) 1444static void connection_kill(Net_Crypto *c, int crypt_connection_id, void *userdata)
1207{ 1445{
1208 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 1446 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
1209 1447
1210 if (conn == 0) 1448 if (conn == nullptr) {
1211 return; 1449 return;
1450 }
1212 1451
1213 if (conn->connection_status_callback) { 1452 if (conn->connection_status_callback) {
1214 conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 0); 1453 conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 0,
1454 userdata);
1215 } 1455 }
1216 1456
1217 crypto_kill(c, crypt_connection_id); 1457 crypto_kill(c, crypt_connection_id);
@@ -1222,28 +1462,31 @@ static void connection_kill(Net_Crypto *c, int crypt_connection_id)
1222 * return -1 on failure. 1462 * return -1 on failure.
1223 * return 0 on success. 1463 * return 0 on success.
1224 */ 1464 */
1225static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length, 1465static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length,
1226 _Bool udp) 1466 bool udp, void *userdata)
1227{ 1467{
1228 if (length > MAX_CRYPTO_PACKET_SIZE || length <= CRYPTO_DATA_PACKET_MIN_SIZE) 1468 if (length > MAX_CRYPTO_PACKET_SIZE || length <= CRYPTO_DATA_PACKET_MIN_SIZE) {
1229 return -1; 1469 return -1;
1470 }
1230 1471
1231 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 1472 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
1232 1473
1233 if (conn == 0) 1474 if (conn == nullptr) {
1234 return -1; 1475 return -1;
1476 }
1235 1477
1236 uint8_t data[MAX_DATA_DATA_PACKET_SIZE]; 1478 uint8_t data[MAX_DATA_DATA_PACKET_SIZE];
1237 int len = handle_data_packet(c, crypt_connection_id, data, packet, length); 1479 int len = handle_data_packet(c, crypt_connection_id, data, packet, length);
1238 1480
1239 if (len <= (int)(sizeof(uint32_t) * 2)) 1481 if (len <= (int)(sizeof(uint32_t) * 2)) {
1240 return -1; 1482 return -1;
1483 }
1241 1484
1242 uint32_t buffer_start, num; 1485 uint32_t buffer_start, num;
1243 memcpy(&buffer_start, data, sizeof(uint32_t)); 1486 memcpy(&buffer_start, data, sizeof(uint32_t));
1244 memcpy(&num, data + sizeof(uint32_t), sizeof(uint32_t)); 1487 memcpy(&num, data + sizeof(uint32_t), sizeof(uint32_t));
1245 buffer_start = ntohl(buffer_start); 1488 buffer_start = net_ntohl(buffer_start);
1246 num = ntohl(num); 1489 num = net_ntohl(num);
1247 1490
1248 uint64_t rtt_calc_time = 0; 1491 uint64_t rtt_calc_time = 0;
1249 1492
@@ -1266,12 +1509,13 @@ static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, con
1266 ++real_data; 1509 ++real_data;
1267 --real_length; 1510 --real_length;
1268 1511
1269 if (real_length == 0) 1512 if (real_length == 0) {
1270 return -1; 1513 return -1;
1514 }
1271 } 1515 }
1272 1516
1273 if (real_data[0] == PACKET_ID_KILL) { 1517 if (real_data[0] == PACKET_ID_KILL) {
1274 connection_kill(c, crypt_connection_id); 1518 connection_kill(c, crypt_connection_id, userdata);
1275 return 0; 1519 return 0;
1276 } 1520 }
1277 1521
@@ -1279,8 +1523,10 @@ static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, con
1279 clear_temp_packet(c, crypt_connection_id); 1523 clear_temp_packet(c, crypt_connection_id);
1280 conn->status = CRYPTO_CONN_ESTABLISHED; 1524 conn->status = CRYPTO_CONN_ESTABLISHED;
1281 1525
1282 if (conn->connection_status_callback) 1526 if (conn->connection_status_callback) {
1283 conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 1); 1527 conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 1,
1528 userdata);
1529 }
1284 } 1530 }
1285 1531
1286 if (real_data[0] == PACKET_ID_REQUEST) { 1532 if (real_data[0] == PACKET_ID_REQUEST) {
@@ -1296,8 +1542,6 @@ static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, con
1296 1542
1297 if (requested == -1) { 1543 if (requested == -1) {
1298 return -1; 1544 return -1;
1299 } else {
1300 //TODO?
1301 } 1545 }
1302 1546
1303 set_buffer_end(&conn->recv_array, num); 1547 set_buffer_end(&conn->recv_array, num);
@@ -1306,27 +1550,30 @@ static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, con
1306 dt.length = real_length; 1550 dt.length = real_length;
1307 memcpy(dt.data, real_data, real_length); 1551 memcpy(dt.data, real_data, real_length);
1308 1552
1309 if (add_data_to_buffer(&conn->recv_array, num, &dt) != 0) 1553 if (add_data_to_buffer(&conn->recv_array, num, &dt) != 0) {
1310 return -1; 1554 return -1;
1311 1555 }
1312 1556
1313 while (1) { 1557 while (1) {
1314 pthread_mutex_lock(&conn->mutex); 1558 pthread_mutex_lock(&conn->mutex);
1315 int ret = read_data_beg_buffer(&conn->recv_array, &dt); 1559 int ret = read_data_beg_buffer(&conn->recv_array, &dt);
1316 pthread_mutex_unlock(&conn->mutex); 1560 pthread_mutex_unlock(&conn->mutex);
1317 1561
1318 if (ret == -1) 1562 if (ret == -1) {
1319 break; 1563 break;
1564 }
1320 1565
1321 if (conn->connection_data_callback) 1566 if (conn->connection_data_callback) {
1322 conn->connection_data_callback(conn->connection_data_callback_object, conn->connection_data_callback_id, dt.data, 1567 conn->connection_data_callback(conn->connection_data_callback_object, conn->connection_data_callback_id, dt.data,
1323 dt.length); 1568 dt.length, userdata);
1569 }
1324 1570
1325 /* conn might get killed in callback. */ 1571 /* conn might get killed in callback. */
1326 conn = get_crypto_connection(c, crypt_connection_id); 1572 conn = get_crypto_connection(c, crypt_connection_id);
1327 1573
1328 if (conn == 0) 1574 if (conn == nullptr) {
1329 return -1; 1575 return -1;
1576 }
1330 } 1577 }
1331 1578
1332 /* Packet counter. */ 1579 /* Packet counter. */
@@ -1336,10 +1583,10 @@ static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, con
1336 1583
1337 set_buffer_end(&conn->recv_array, num); 1584 set_buffer_end(&conn->recv_array, num);
1338 1585
1339 if (conn->connection_lossy_data_callback) 1586 if (conn->connection_lossy_data_callback) {
1340 conn->connection_lossy_data_callback(conn->connection_lossy_data_callback_object, 1587 conn->connection_lossy_data_callback(conn->connection_lossy_data_callback_object,
1341 conn->connection_lossy_data_callback_id, real_data, real_length); 1588 conn->connection_lossy_data_callback_id, real_data, real_length, userdata);
1342 1589 }
1343 } else { 1590 } else {
1344 return -1; 1591 return -1;
1345 } 1592 }
@@ -1347,8 +1594,9 @@ static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, con
1347 if (rtt_calc_time != 0) { 1594 if (rtt_calc_time != 0) {
1348 uint64_t rtt_time = current_time_monotonic() - rtt_calc_time; 1595 uint64_t rtt_time = current_time_monotonic() - rtt_calc_time;
1349 1596
1350 if (rtt_time < conn->rtt_time) 1597 if (rtt_time < conn->rtt_time) {
1351 conn->rtt_time = rtt_time; 1598 conn->rtt_time = rtt_time;
1599 }
1352 } 1600 }
1353 1601
1354 return 0; 1602 return 0;
@@ -1360,32 +1608,38 @@ static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, con
1360 * return 0 on success. 1608 * return 0 on success.
1361 */ 1609 */
1362static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length, 1610static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length,
1363 _Bool udp) 1611 bool udp, void *userdata)
1364{ 1612{
1365 if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) 1613 if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) {
1366 return -1; 1614 return -1;
1615 }
1367 1616
1368 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 1617 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
1369 1618
1370 if (conn == 0) 1619 if (conn == nullptr) {
1371 return -1; 1620 return -1;
1621 }
1372 1622
1373 switch (packet[0]) { 1623 switch (packet[0]) {
1374 case NET_PACKET_COOKIE_RESPONSE: { 1624 case NET_PACKET_COOKIE_RESPONSE: {
1375 if (conn->status != CRYPTO_CONN_COOKIE_REQUESTING) 1625 if (conn->status != CRYPTO_CONN_COOKIE_REQUESTING) {
1376 return -1; 1626 return -1;
1627 }
1377 1628
1378 uint8_t cookie[COOKIE_LENGTH]; 1629 uint8_t cookie[COOKIE_LENGTH];
1379 uint64_t number; 1630 uint64_t number;
1380 1631
1381 if (handle_cookie_response(cookie, &number, packet, length, conn->shared_key) != sizeof(cookie)) 1632 if (handle_cookie_response(cookie, &number, packet, length, conn->shared_key) != sizeof(cookie)) {
1382 return -1; 1633 return -1;
1634 }
1383 1635
1384 if (number != conn->cookie_request_number) 1636 if (number != conn->cookie_request_number) {
1385 return -1; 1637 return -1;
1638 }
1386 1639
1387 if (create_send_handshake(c, crypt_connection_id, cookie, conn->dht_public_key) != 0) 1640 if (create_send_handshake(c, crypt_connection_id, cookie, conn->dht_public_key) != 0) {
1388 return -1; 1641 return -1;
1642 }
1389 1643
1390 conn->status = CRYPTO_CONN_HANDSHAKE_SENT; 1644 conn->status = CRYPTO_CONN_HANDSHAKE_SENT;
1391 return 0; 1645 return 0;
@@ -1394,28 +1648,30 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, cons
1394 case NET_PACKET_CRYPTO_HS: { 1648 case NET_PACKET_CRYPTO_HS: {
1395 if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT 1649 if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT
1396 || conn->status == CRYPTO_CONN_NOT_CONFIRMED) { 1650 || conn->status == CRYPTO_CONN_NOT_CONFIRMED) {
1397 uint8_t peer_real_pk[crypto_box_PUBLICKEYBYTES]; 1651 uint8_t peer_real_pk[CRYPTO_PUBLIC_KEY_SIZE];
1398 uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; 1652 uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];
1399 uint8_t cookie[COOKIE_LENGTH]; 1653 uint8_t cookie[COOKIE_LENGTH];
1400 1654
1401 if (handle_crypto_handshake(c, conn->recv_nonce, conn->peersessionpublic_key, peer_real_pk, dht_public_key, cookie, 1655 if (handle_crypto_handshake(c, conn->recv_nonce, conn->peersessionpublic_key, peer_real_pk, dht_public_key, cookie,
1402 packet, length, conn->public_key) != 0) 1656 packet, length, conn->public_key) != 0) {
1403 return -1; 1657 return -1;
1658 }
1404 1659
1405 if (public_key_cmp(dht_public_key, conn->dht_public_key) == 0) { 1660 if (public_key_cmp(dht_public_key, conn->dht_public_key) == 0) {
1406 encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key); 1661 encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key);
1407 1662
1408 if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING) { 1663 if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING) {
1409 if (create_send_handshake(c, crypt_connection_id, cookie, dht_public_key) != 0) 1664 if (create_send_handshake(c, crypt_connection_id, cookie, dht_public_key) != 0) {
1410 return -1; 1665 return -1;
1666 }
1411 } 1667 }
1412 1668
1413 conn->status = CRYPTO_CONN_NOT_CONFIRMED; 1669 conn->status = CRYPTO_CONN_NOT_CONFIRMED;
1414 } else { 1670 } else {
1415 if (conn->dht_pk_callback) 1671 if (conn->dht_pk_callback) {
1416 conn->dht_pk_callback(conn->dht_pk_callback_object, conn->dht_pk_callback_number, dht_public_key); 1672 conn->dht_pk_callback(conn->dht_pk_callback_object, conn->dht_pk_callback_number, dht_public_key, userdata);
1673 }
1417 } 1674 }
1418
1419 } else { 1675 } else {
1420 return -1; 1676 return -1;
1421 } 1677 }
@@ -1425,20 +1681,16 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, cons
1425 1681
1426 case NET_PACKET_CRYPTO_DATA: { 1682 case NET_PACKET_CRYPTO_DATA: {
1427 if (conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED) { 1683 if (conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED) {
1428 return handle_data_packet_helper(c, crypt_connection_id, packet, length, udp); 1684 return handle_data_packet_core(c, crypt_connection_id, packet, length, udp, userdata);
1429 } else {
1430 return -1;
1431 } 1685 }
1432 1686
1433 return 0; 1687 return -1;
1434 } 1688 }
1435 1689
1436 default: { 1690 default: {
1437 return -1; 1691 return -1;
1438 } 1692 }
1439 } 1693 }
1440
1441 return 0;
1442} 1694}
1443 1695
1444/* Set the size of the friend list to numfriends. 1696/* Set the size of the friend list to numfriends.
@@ -1450,14 +1702,16 @@ static int realloc_cryptoconnection(Net_Crypto *c, uint32_t num)
1450{ 1702{
1451 if (num == 0) { 1703 if (num == 0) {
1452 free(c->crypto_connections); 1704 free(c->crypto_connections);
1453 c->crypto_connections = NULL; 1705 c->crypto_connections = nullptr;
1454 return 0; 1706 return 0;
1455 } 1707 }
1456 1708
1457 Crypto_Connection *newcrypto_connections = realloc(c->crypto_connections, num * sizeof(Crypto_Connection)); 1709 Crypto_Connection *newcrypto_connections = (Crypto_Connection *)realloc(c->crypto_connections,
1710 num * sizeof(Crypto_Connection));
1458 1711
1459 if (newcrypto_connections == NULL) 1712 if (newcrypto_connections == nullptr) {
1460 return -1; 1713 return -1;
1714 }
1461 1715
1462 c->crypto_connections = newcrypto_connections; 1716 c->crypto_connections = newcrypto_connections;
1463 return 0; 1717 return 0;
@@ -1474,11 +1728,12 @@ static int create_crypto_connection(Net_Crypto *c)
1474 uint32_t i; 1728 uint32_t i;
1475 1729
1476 for (i = 0; i < c->crypto_connections_length; ++i) { 1730 for (i = 0; i < c->crypto_connections_length; ++i) {
1477 if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) 1731 if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) {
1478 return i; 1732 return i;
1733 }
1479 } 1734 }
1480 1735
1481 while (1) { /* TODO: is this really the best way to do this? */ 1736 while (1) { /* TODO(irungentoo): is this really the best way to do this? */
1482 pthread_mutex_lock(&c->connections_mutex); 1737 pthread_mutex_lock(&c->connections_mutex);
1483 1738
1484 if (!c->connection_use_counter) { 1739 if (!c->connection_use_counter) {
@@ -1493,9 +1748,15 @@ static int create_crypto_connection(Net_Crypto *c)
1493 if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == 0) { 1748 if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == 0) {
1494 id = c->crypto_connections_length; 1749 id = c->crypto_connections_length;
1495 ++c->crypto_connections_length; 1750 ++c->crypto_connections_length;
1496 memset(&(c->crypto_connections[id]), 0, sizeof(Crypto_Connection)); 1751 memset(&c->crypto_connections[id], 0, sizeof(Crypto_Connection));
1497 1752 // Memsetting float/double to 0 is non-portable, so we explicitly set them to 0
1498 if (pthread_mutex_init(&c->crypto_connections[id].mutex, NULL) != 0) { 1753 c->crypto_connections[id].packet_recv_rate = 0;
1754 c->crypto_connections[id].packet_send_rate = 0;
1755 c->crypto_connections[id].last_packets_left_rem = 0;
1756 c->crypto_connections[id].packet_send_rate_requested = 0;
1757 c->crypto_connections[id].last_packets_left_requested_rem = 0;
1758
1759 if (pthread_mutex_init(&c->crypto_connections[id].mutex, nullptr) != 0) {
1499 pthread_mutex_unlock(&c->connections_mutex); 1760 pthread_mutex_unlock(&c->connections_mutex);
1500 return -1; 1761 return -1;
1501 } 1762 }
@@ -1512,14 +1773,15 @@ static int create_crypto_connection(Net_Crypto *c)
1512 */ 1773 */
1513static int wipe_crypto_connection(Net_Crypto *c, int crypt_connection_id) 1774static int wipe_crypto_connection(Net_Crypto *c, int crypt_connection_id)
1514{ 1775{
1515 if (crypt_connection_id_not_valid(c, crypt_connection_id)) 1776 if (crypt_connection_id_not_valid(c, crypt_connection_id)) {
1516 return -1; 1777 return -1;
1778 }
1517 1779
1518 uint32_t i; 1780 uint32_t i;
1519 1781
1520 /* Keep mutex, only destroy it when connection is realloced out. */ 1782 /* Keep mutex, only destroy it when connection is realloced out. */
1521 pthread_mutex_t mutex = c->crypto_connections[crypt_connection_id].mutex; 1783 pthread_mutex_t mutex = c->crypto_connections[crypt_connection_id].mutex;
1522 sodium_memzero(&(c->crypto_connections[crypt_connection_id]), sizeof(Crypto_Connection)); 1784 crypto_memzero(&c->crypto_connections[crypt_connection_id], sizeof(Crypto_Connection));
1523 c->crypto_connections[crypt_connection_id].mutex = mutex; 1785 c->crypto_connections[crypt_connection_id].mutex = mutex;
1524 1786
1525 for (i = c->crypto_connections_length; i != 0; --i) { 1787 for (i = c->crypto_connections_length; i != 0; --i) {
@@ -1548,9 +1810,11 @@ static int getcryptconnection_id(const Net_Crypto *c, const uint8_t *public_key)
1548 uint32_t i; 1810 uint32_t i;
1549 1811
1550 for (i = 0; i < c->crypto_connections_length; ++i) { 1812 for (i = 0; i < c->crypto_connections_length; ++i) {
1551 if (c->crypto_connections[i].status != CRYPTO_CONN_NO_CONNECTION) 1813 if (c->crypto_connections[i].status != CRYPTO_CONN_NO_CONNECTION) {
1552 if (public_key_cmp(public_key, c->crypto_connections[i].public_key) == 0) 1814 if (public_key_cmp(public_key, c->crypto_connections[i].public_key) == 0) {
1553 return i; 1815 return i;
1816 }
1817 }
1554 } 1818 }
1555 1819
1556 return -1; 1820 return -1;
@@ -1567,23 +1831,28 @@ static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id,
1567{ 1831{
1568 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 1832 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
1569 1833
1570 if (conn == 0) 1834 if (conn == nullptr) {
1571 return -1; 1835 return -1;
1836 }
1572 1837
1573 if (source.ip.family == AF_INET || source.ip.family == AF_INET6) { 1838 if (net_family_is_ipv4(source.ip.family) || net_family_is_ipv6(source.ip.family)) {
1574 if (add_ip_port_connection(c, crypt_connection_id, source) != 0) 1839 if (add_ip_port_connection(c, crypt_connection_id, source) != 0) {
1575 return -1; 1840 return -1;
1841 }
1576 1842
1577 if (source.ip.family == AF_INET) { 1843 if (net_family_is_ipv4(source.ip.family)) {
1578 conn->direct_lastrecv_timev4 = unix_time(); 1844 conn->direct_lastrecv_timev4 = unix_time();
1579 } else { 1845 } else {
1580 conn->direct_lastrecv_timev6 = unix_time(); 1846 conn->direct_lastrecv_timev6 = unix_time();
1581 } 1847 }
1582 1848
1583 return 0; 1849 return 0;
1584 } else if (source.ip.family == TCP_FAMILY) { 1850 }
1585 if (add_tcp_number_relay_connection(c->tcp_c, conn->connection_number_tcp, source.ip.ip6.uint32[0]) == 0) 1851
1852 if (net_family_is_tcp_family(source.ip.family)) {
1853 if (add_tcp_number_relay_connection(c->tcp_c, conn->connection_number_tcp, source.ip.ip.v6.uint32[0]) == 0) {
1586 return 1; 1854 return 1;
1855 }
1587 } 1856 }
1588 1857
1589 return -1; 1858 return -1;
@@ -1609,19 +1878,21 @@ void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *
1609 * return -1 on failure. 1878 * return -1 on failure.
1610 * return 0 on success. 1879 * return 0 on success.
1611 */ 1880 */
1612static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, const uint8_t *data, uint16_t length) 1881static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, const uint8_t *data, uint16_t length,
1882 void *userdata)
1613{ 1883{
1614 New_Connection n_c; 1884 New_Connection n_c;
1615 n_c.cookie = malloc(COOKIE_LENGTH); 1885 n_c.cookie = (uint8_t *)malloc(COOKIE_LENGTH);
1616 1886
1617 if (n_c.cookie == NULL) 1887 if (n_c.cookie == nullptr) {
1618 return -1; 1888 return -1;
1889 }
1619 1890
1620 n_c.source = source; 1891 n_c.source = source;
1621 n_c.cookie_length = COOKIE_LENGTH; 1892 n_c.cookie_length = COOKIE_LENGTH;
1622 1893
1623 if (handle_crypto_handshake(c, n_c.recv_nonce, n_c.peersessionpublic_key, n_c.public_key, n_c.dht_public_key, 1894 if (handle_crypto_handshake(c, n_c.recv_nonce, n_c.peersessionpublic_key, n_c.public_key, n_c.dht_public_key,
1624 n_c.cookie, data, length, 0) != 0) { 1895 n_c.cookie, data, length, nullptr) != 0) {
1625 free(n_c.cookie); 1896 free(n_c.cookie);
1626 return -1; 1897 return -1;
1627 } 1898 }
@@ -1632,13 +1903,13 @@ static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, const
1632 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 1903 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
1633 1904
1634 if (public_key_cmp(n_c.dht_public_key, conn->dht_public_key) != 0) { 1905 if (public_key_cmp(n_c.dht_public_key, conn->dht_public_key) != 0) {
1635 connection_kill(c, crypt_connection_id); 1906 connection_kill(c, crypt_connection_id, userdata);
1636 } else { 1907 } else {
1637 int ret = -1; 1908 int ret = -1;
1638 1909
1639 if (conn && (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT)) { 1910 if (conn && (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT)) {
1640 memcpy(conn->recv_nonce, n_c.recv_nonce, crypto_box_NONCEBYTES); 1911 memcpy(conn->recv_nonce, n_c.recv_nonce, CRYPTO_NONCE_SIZE);
1641 memcpy(conn->peersessionpublic_key, n_c.peersessionpublic_key, crypto_box_PUBLICKEYBYTES); 1912 memcpy(conn->peersessionpublic_key, n_c.peersessionpublic_key, CRYPTO_PUBLIC_KEY_SIZE);
1642 encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key); 1913 encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key);
1643 1914
1644 crypto_connection_add_source(c, crypt_connection_id, source); 1915 crypto_connection_add_source(c, crypt_connection_id, source);
@@ -1666,32 +1937,36 @@ static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, const
1666 */ 1937 */
1667int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) 1938int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c)
1668{ 1939{
1669 if (getcryptconnection_id(c, n_c->public_key) != -1) 1940 if (getcryptconnection_id(c, n_c->public_key) != -1) {
1670 return -1; 1941 return -1;
1942 }
1671 1943
1672 int crypt_connection_id = create_crypto_connection(c); 1944 int crypt_connection_id = create_crypto_connection(c);
1673 1945
1674 if (crypt_connection_id == -1) 1946 if (crypt_connection_id == -1) {
1675 return -1; 1947 return -1;
1948 }
1676 1949
1677 Crypto_Connection *conn = &c->crypto_connections[crypt_connection_id]; 1950 Crypto_Connection *conn = &c->crypto_connections[crypt_connection_id];
1678 1951
1679 if (n_c->cookie_length != COOKIE_LENGTH) 1952 if (n_c->cookie_length != COOKIE_LENGTH) {
1680 return -1; 1953 return -1;
1954 }
1681 1955
1682 pthread_mutex_lock(&c->tcp_mutex); 1956 pthread_mutex_lock(&c->tcp_mutex);
1683 int connection_number_tcp = new_tcp_connection_to(c->tcp_c, n_c->dht_public_key, crypt_connection_id); 1957 int connection_number_tcp = new_tcp_connection_to(c->tcp_c, n_c->dht_public_key, crypt_connection_id);
1684 pthread_mutex_unlock(&c->tcp_mutex); 1958 pthread_mutex_unlock(&c->tcp_mutex);
1685 1959
1686 if (connection_number_tcp == -1) 1960 if (connection_number_tcp == -1) {
1687 return -1; 1961 return -1;
1962 }
1688 1963
1689 conn->connection_number_tcp = connection_number_tcp; 1964 conn->connection_number_tcp = connection_number_tcp;
1690 memcpy(conn->public_key, n_c->public_key, crypto_box_PUBLICKEYBYTES); 1965 memcpy(conn->public_key, n_c->public_key, CRYPTO_PUBLIC_KEY_SIZE);
1691 memcpy(conn->recv_nonce, n_c->recv_nonce, crypto_box_NONCEBYTES); 1966 memcpy(conn->recv_nonce, n_c->recv_nonce, CRYPTO_NONCE_SIZE);
1692 memcpy(conn->peersessionpublic_key, n_c->peersessionpublic_key, crypto_box_PUBLICKEYBYTES); 1967 memcpy(conn->peersessionpublic_key, n_c->peersessionpublic_key, CRYPTO_PUBLIC_KEY_SIZE);
1693 random_nonce(conn->sent_nonce); 1968 random_nonce(conn->sent_nonce);
1694 crypto_box_keypair(conn->sessionpublic_key, conn->sessionsecret_key); 1969 crypto_new_keypair(conn->sessionpublic_key, conn->sessionsecret_key);
1695 encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key); 1970 encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key);
1696 conn->status = CRYPTO_CONN_NOT_CONFIRMED; 1971 conn->status = CRYPTO_CONN_NOT_CONFIRMED;
1697 1972
@@ -1703,7 +1978,7 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c)
1703 return -1; 1978 return -1;
1704 } 1979 }
1705 1980
1706 memcpy(conn->dht_public_key, n_c->dht_public_key, crypto_box_PUBLICKEYBYTES); 1981 memcpy(conn->dht_public_key, n_c->dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);
1707 conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; 1982 conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE;
1708 conn->packet_send_rate_requested = CRYPTO_PACKET_MIN_RATE; 1983 conn->packet_send_rate_requested = CRYPTO_PACKET_MIN_RATE;
1709 conn->packets_left = CRYPTO_MIN_QUEUE_LENGTH; 1984 conn->packets_left = CRYPTO_MIN_QUEUE_LENGTH;
@@ -1722,38 +1997,42 @@ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const u
1722{ 1997{
1723 int crypt_connection_id = getcryptconnection_id(c, real_public_key); 1998 int crypt_connection_id = getcryptconnection_id(c, real_public_key);
1724 1999
1725 if (crypt_connection_id != -1) 2000 if (crypt_connection_id != -1) {
1726 return crypt_connection_id; 2001 return crypt_connection_id;
2002 }
1727 2003
1728 crypt_connection_id = create_crypto_connection(c); 2004 crypt_connection_id = create_crypto_connection(c);
1729 2005
1730 if (crypt_connection_id == -1) 2006 if (crypt_connection_id == -1) {
1731 return -1; 2007 return -1;
2008 }
1732 2009
1733 Crypto_Connection *conn = &c->crypto_connections[crypt_connection_id]; 2010 Crypto_Connection *conn = &c->crypto_connections[crypt_connection_id];
1734 2011
1735 if (conn == 0) 2012 if (conn == nullptr) {
1736 return -1; 2013 return -1;
2014 }
1737 2015
1738 pthread_mutex_lock(&c->tcp_mutex); 2016 pthread_mutex_lock(&c->tcp_mutex);
1739 int connection_number_tcp = new_tcp_connection_to(c->tcp_c, dht_public_key, crypt_connection_id); 2017 int connection_number_tcp = new_tcp_connection_to(c->tcp_c, dht_public_key, crypt_connection_id);
1740 pthread_mutex_unlock(&c->tcp_mutex); 2018 pthread_mutex_unlock(&c->tcp_mutex);
1741 2019
1742 if (connection_number_tcp == -1) 2020 if (connection_number_tcp == -1) {
1743 return -1; 2021 return -1;
2022 }
1744 2023
1745 conn->connection_number_tcp = connection_number_tcp; 2024 conn->connection_number_tcp = connection_number_tcp;
1746 memcpy(conn->public_key, real_public_key, crypto_box_PUBLICKEYBYTES); 2025 memcpy(conn->public_key, real_public_key, CRYPTO_PUBLIC_KEY_SIZE);
1747 random_nonce(conn->sent_nonce); 2026 random_nonce(conn->sent_nonce);
1748 crypto_box_keypair(conn->sessionpublic_key, conn->sessionsecret_key); 2027 crypto_new_keypair(conn->sessionpublic_key, conn->sessionsecret_key);
1749 conn->status = CRYPTO_CONN_COOKIE_REQUESTING; 2028 conn->status = CRYPTO_CONN_COOKIE_REQUESTING;
1750 conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; 2029 conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE;
1751 conn->packet_send_rate_requested = CRYPTO_PACKET_MIN_RATE; 2030 conn->packet_send_rate_requested = CRYPTO_PACKET_MIN_RATE;
1752 conn->packets_left = CRYPTO_MIN_QUEUE_LENGTH; 2031 conn->packets_left = CRYPTO_MIN_QUEUE_LENGTH;
1753 conn->rtt_time = DEFAULT_PING_CONNECTION; 2032 conn->rtt_time = DEFAULT_PING_CONNECTION;
1754 memcpy(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES); 2033 memcpy(conn->dht_public_key, dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);
1755 2034
1756 conn->cookie_request_number = random_64b(); 2035 conn->cookie_request_number = random_u64();
1757 uint8_t cookie_request[COOKIE_REQUEST_LENGTH]; 2036 uint8_t cookie_request[COOKIE_REQUEST_LENGTH];
1758 2037
1759 if (create_cookie_request(c, cookie_request, conn->dht_public_key, conn->cookie_request_number, 2038 if (create_cookie_request(c, cookie_request, conn->dht_public_key, conn->cookie_request_number,
@@ -1776,85 +2055,89 @@ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const u
1776 * return -1 on failure. 2055 * return -1 on failure.
1777 * return 0 on success. 2056 * return 0 on success.
1778 */ 2057 */
1779int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, _Bool connected) 2058int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, bool connected)
1780{ 2059{
1781 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 2060 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
1782 2061
1783 if (conn == 0) 2062 if (conn == nullptr) {
1784 return -1; 2063 return -1;
2064 }
1785 2065
1786 if (add_ip_port_connection(c, crypt_connection_id, ip_port) == 0) { 2066 if (add_ip_port_connection(c, crypt_connection_id, ip_port) != 0) {
1787 if (connected) { 2067 return -1;
1788 if (ip_port.ip.family == AF_INET) { 2068 }
1789 conn->direct_lastrecv_timev4 = unix_time();
1790 } else {
1791 conn->direct_lastrecv_timev6 = unix_time();
1792 }
1793 } else {
1794 if (ip_port.ip.family == AF_INET) {
1795 conn->direct_lastrecv_timev4 = 0;
1796 } else {
1797 conn->direct_lastrecv_timev6 = 0;
1798 }
1799 }
1800 2069
1801 return 0; 2070 const uint64_t direct_lastrecv_time = connected ? unix_time() : 0;
2071
2072 if (net_family_is_ipv4(ip_port.ip.family)) {
2073 conn->direct_lastrecv_timev4 = direct_lastrecv_time;
2074 } else {
2075 conn->direct_lastrecv_timev6 = direct_lastrecv_time;
1802 } 2076 }
1803 2077
1804 return -1; 2078 return 0;
1805} 2079}
1806 2080
1807 2081
1808static int tcp_data_callback(void *object, int id, const uint8_t *data, uint16_t length) 2082static int tcp_data_callback(void *object, int id, const uint8_t *data, uint16_t length, void *userdata)
1809{ 2083{
1810 if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) 2084 if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) {
1811 return -1; 2085 return -1;
2086 }
1812 2087
1813 Net_Crypto *c = object; 2088 Net_Crypto *c = (Net_Crypto *)object;
1814 2089
1815 Crypto_Connection *conn = get_crypto_connection(c, id); 2090 Crypto_Connection *conn = get_crypto_connection(c, id);
1816 2091
1817 if (conn == 0) 2092 if (conn == nullptr) {
1818 return -1; 2093 return -1;
2094 }
1819 2095
1820 if (data[0] == NET_PACKET_COOKIE_REQUEST) { 2096 if (data[0] == NET_PACKET_COOKIE_REQUEST) {
1821 return tcp_handle_cookie_request(c, conn->connection_number_tcp, data, length); 2097 return tcp_handle_cookie_request(c, conn->connection_number_tcp, data, length);
1822 } 2098 }
1823 2099
2100 // This unlocks the mutex that at this point is locked by do_tcp before
2101 // calling do_tcp_connections.
1824 pthread_mutex_unlock(&c->tcp_mutex); 2102 pthread_mutex_unlock(&c->tcp_mutex);
1825 int ret = handle_packet_connection(c, id, data, length, 0); 2103 int ret = handle_packet_connection(c, id, data, length, 0, userdata);
1826 pthread_mutex_lock(&c->tcp_mutex); 2104 pthread_mutex_lock(&c->tcp_mutex);
1827 2105
1828 if (ret != 0) 2106 if (ret != 0) {
1829 return -1; 2107 return -1;
2108 }
1830 2109
1831 //TODO detect and kill bad TCP connections. 2110 // TODO(irungentoo): detect and kill bad TCP connections.
1832 return 0; 2111 return 0;
1833} 2112}
1834 2113
1835static int tcp_oob_callback(void *object, const uint8_t *public_key, unsigned int tcp_connections_number, 2114static int tcp_oob_callback(void *object, const uint8_t *public_key, unsigned int tcp_connections_number,
1836 const uint8_t *data, uint16_t length) 2115 const uint8_t *data, uint16_t length, void *userdata)
1837{ 2116{
1838 if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) 2117 if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) {
1839 return -1; 2118 return -1;
2119 }
1840 2120
1841 Net_Crypto *c = object; 2121 Net_Crypto *c = (Net_Crypto *)object;
1842 2122
1843 if (data[0] == NET_PACKET_COOKIE_REQUEST) { 2123 if (data[0] == NET_PACKET_COOKIE_REQUEST) {
1844 return tcp_oob_handle_cookie_request(c, tcp_connections_number, public_key, data, length); 2124 return tcp_oob_handle_cookie_request(c, tcp_connections_number, public_key, data, length);
1845 } else if (data[0] == NET_PACKET_CRYPTO_HS) { 2125 }
2126
2127 if (data[0] == NET_PACKET_CRYPTO_HS) {
1846 IP_Port source; 2128 IP_Port source;
1847 source.port = 0; 2129 source.port = 0;
1848 source.ip.family = TCP_FAMILY; 2130 source.ip.family = net_family_tcp_family;
1849 source.ip.ip6.uint32[0] = tcp_connections_number; 2131 source.ip.ip.v6.uint32[0] = tcp_connections_number;
1850 2132
1851 if (handle_new_connection_handshake(c, source, data, length) != 0) 2133 if (handle_new_connection_handshake(c, source, data, length, userdata) != 0) {
1852 return -1; 2134 return -1;
2135 }
1853 2136
1854 return 0; 2137 return 0;
1855 } else {
1856 return -1;
1857 } 2138 }
2139
2140 return -1;
1858} 2141}
1859 2142
1860/* Add a tcp relay, associating it to a crypt_connection_id. 2143/* Add a tcp relay, associating it to a crypt_connection_id.
@@ -1866,8 +2149,9 @@ int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port,
1866{ 2149{
1867 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 2150 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
1868 2151
1869 if (conn == 0) 2152 if (conn == nullptr) {
1870 return -1; 2153 return -1;
2154 }
1871 2155
1872 pthread_mutex_lock(&c->tcp_mutex); 2156 pthread_mutex_lock(&c->tcp_mutex);
1873 int ret = add_tcp_relay_connection(c->tcp_c, conn->connection_number_tcp, ip_port, public_key); 2157 int ret = add_tcp_relay_connection(c->tcp_c, conn->connection_number_tcp, ip_port, public_key);
@@ -1890,7 +2174,7 @@ int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, const uint8_t *public_key)
1890 2174
1891/* Return a random TCP connection number for use in send_tcp_onion_request. 2175/* Return a random TCP connection number for use in send_tcp_onion_request.
1892 * 2176 *
1893 * TODO: This number is just the index of an array that the elements can 2177 * TODO(irungentoo): This number is just the index of an array that the elements can
1894 * change without warning. 2178 * change without warning.
1895 * 2179 *
1896 * return TCP connection number on success. 2180 * return TCP connection number on success.
@@ -1927,8 +2211,9 @@ int send_tcp_onion_request(Net_Crypto *c, unsigned int tcp_connections_number, c
1927 */ 2211 */
1928unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, uint16_t num) 2212unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, uint16_t num)
1929{ 2213{
1930 if (num == 0) 2214 if (num == 0) {
1931 return 0; 2215 return 0;
2216 }
1932 2217
1933 pthread_mutex_lock(&c->tcp_mutex); 2218 pthread_mutex_lock(&c->tcp_mutex);
1934 unsigned int ret = tcp_copy_connected_relays(c->tcp_c, tcp_relays, num); 2219 unsigned int ret = tcp_copy_connected_relays(c->tcp_c, tcp_relays, num);
@@ -1937,10 +2222,10 @@ unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, u
1937 return ret; 2222 return ret;
1938} 2223}
1939 2224
1940static void do_tcp(Net_Crypto *c) 2225static void do_tcp(Net_Crypto *c, void *userdata)
1941{ 2226{
1942 pthread_mutex_lock(&c->tcp_mutex); 2227 pthread_mutex_lock(&c->tcp_mutex);
1943 do_tcp_connections(c->tcp_c); 2228 do_tcp_connections(c->tcp_c, userdata);
1944 pthread_mutex_unlock(&c->tcp_mutex); 2229 pthread_mutex_unlock(&c->tcp_mutex);
1945 2230
1946 uint32_t i; 2231 uint32_t i;
@@ -1948,12 +2233,13 @@ static void do_tcp(Net_Crypto *c)
1948 for (i = 0; i < c->crypto_connections_length; ++i) { 2233 for (i = 0; i < c->crypto_connections_length; ++i) {
1949 Crypto_Connection *conn = get_crypto_connection(c, i); 2234 Crypto_Connection *conn = get_crypto_connection(c, i);
1950 2235
1951 if (conn == 0) 2236 if (conn == nullptr) {
1952 return; 2237 continue;
2238 }
1953 2239
1954 if (conn->status == CRYPTO_CONN_ESTABLISHED) { 2240 if (conn->status == CRYPTO_CONN_ESTABLISHED) {
1955 _Bool direct_connected = 0; 2241 bool direct_connected = 0;
1956 crypto_connection_status(c, i, &direct_connected, NULL); 2242 crypto_connection_status(c, i, &direct_connected, nullptr);
1957 2243
1958 if (direct_connected) { 2244 if (direct_connected) {
1959 pthread_mutex_lock(&c->tcp_mutex); 2245 pthread_mutex_lock(&c->tcp_mutex);
@@ -1979,12 +2265,13 @@ static void do_tcp(Net_Crypto *c)
1979 * return 0 on success. 2265 * return 0 on success.
1980 */ 2266 */
1981int connection_status_handler(const Net_Crypto *c, int crypt_connection_id, 2267int connection_status_handler(const Net_Crypto *c, int crypt_connection_id,
1982 int (*connection_status_callback)(void *object, int id, uint8_t status), void *object, int id) 2268 int (*connection_status_callback)(void *object, int id, uint8_t status, void *userdata), void *object, int id)
1983{ 2269{
1984 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 2270 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
1985 2271
1986 if (conn == 0) 2272 if (conn == nullptr) {
1987 return -1; 2273 return -1;
2274 }
1988 2275
1989 conn->connection_status_callback = connection_status_callback; 2276 conn->connection_status_callback = connection_status_callback;
1990 conn->connection_status_callback_object = object; 2277 conn->connection_status_callback_object = object;
@@ -2001,12 +2288,13 @@ int connection_status_handler(const Net_Crypto *c, int crypt_connection_id,
2001 * return 0 on success. 2288 * return 0 on success.
2002 */ 2289 */
2003int connection_data_handler(const Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object, 2290int connection_data_handler(const Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object,
2004 int id, uint8_t *data, uint16_t length), void *object, int id) 2291 int id, const uint8_t *data, uint16_t length, void *userdata), void *object, int id)
2005{ 2292{
2006 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 2293 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
2007 2294
2008 if (conn == 0) 2295 if (conn == nullptr) {
2009 return -1; 2296 return -1;
2297 }
2010 2298
2011 conn->connection_data_callback = connection_data_callback; 2299 conn->connection_data_callback = connection_data_callback;
2012 conn->connection_data_callback_object = object; 2300 conn->connection_data_callback_object = object;
@@ -2023,12 +2311,14 @@ int connection_data_handler(const Net_Crypto *c, int crypt_connection_id, int (*
2023 * return 0 on success. 2311 * return 0 on success.
2024 */ 2312 */
2025int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id, 2313int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id,
2026 int (*connection_lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length), void *object, int id) 2314 int (*connection_lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata),
2315 void *object, int id)
2027{ 2316{
2028 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 2317 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
2029 2318
2030 if (conn == 0) 2319 if (conn == nullptr) {
2031 return -1; 2320 return -1;
2321 }
2032 2322
2033 conn->connection_lossy_data_callback = connection_lossy_data_callback; 2323 conn->connection_lossy_data_callback = connection_lossy_data_callback;
2034 conn->connection_lossy_data_callback_object = object; 2324 conn->connection_lossy_data_callback_object = object;
@@ -2048,12 +2338,13 @@ int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id,
2048 * return 0 on success. 2338 * return 0 on success.
2049 */ 2339 */
2050int nc_dht_pk_callback(Net_Crypto *c, int crypt_connection_id, void (*function)(void *data, int32_t number, 2340int nc_dht_pk_callback(Net_Crypto *c, int crypt_connection_id, void (*function)(void *data, int32_t number,
2051 const uint8_t *dht_public_key), void *object, uint32_t number) 2341 const uint8_t *dht_public_key, void *userdata), void *object, uint32_t number)
2052{ 2342{
2053 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 2343 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
2054 2344
2055 if (conn == 0) 2345 if (conn == nullptr) {
2056 return -1; 2346 return -1;
2347 }
2057 2348
2058 conn->dht_pk_callback = function; 2349 conn->dht_pk_callback = function;
2059 conn->dht_pk_callback_object = object; 2350 conn->dht_pk_callback_object = object;
@@ -2071,7 +2362,7 @@ static int crypto_id_ip_port(const Net_Crypto *c, IP_Port ip_port)
2071 return bs_list_find(&c->ip_port_list, (uint8_t *)&ip_port); 2362 return bs_list_find(&c->ip_port_list, (uint8_t *)&ip_port);
2072} 2363}
2073 2364
2074#define CRYPTO_MIN_PACKET_SIZE (1 + sizeof(uint16_t) + crypto_box_MACBYTES) 2365#define CRYPTO_MIN_PACKET_SIZE (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE)
2075 2366
2076/* Handle raw UDP packets coming directly from the socket. 2367/* Handle raw UDP packets coming directly from the socket.
2077 * 2368 *
@@ -2081,35 +2372,40 @@ static int crypto_id_ip_port(const Net_Crypto *c, IP_Port ip_port)
2081 * Crypto data packets. 2372 * Crypto data packets.
2082 * 2373 *
2083 */ 2374 */
2084static int udp_handle_packet(void *object, IP_Port source, const uint8_t *packet, uint16_t length) 2375static int udp_handle_packet(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
2085{ 2376{
2086 if (length <= CRYPTO_MIN_PACKET_SIZE || length > MAX_CRYPTO_PACKET_SIZE) 2377 if (length <= CRYPTO_MIN_PACKET_SIZE || length > MAX_CRYPTO_PACKET_SIZE) {
2087 return 1; 2378 return 1;
2379 }
2088 2380
2089 Net_Crypto *c = object; 2381 Net_Crypto *c = (Net_Crypto *)object;
2090 int crypt_connection_id = crypto_id_ip_port(c, source); 2382 int crypt_connection_id = crypto_id_ip_port(c, source);
2091 2383
2092 if (crypt_connection_id == -1) { 2384 if (crypt_connection_id == -1) {
2093 if (packet[0] != NET_PACKET_CRYPTO_HS) 2385 if (packet[0] != NET_PACKET_CRYPTO_HS) {
2094 return 1; 2386 return 1;
2387 }
2095 2388
2096 if (handle_new_connection_handshake(c, source, packet, length) != 0) 2389 if (handle_new_connection_handshake(c, source, packet, length, userdata) != 0) {
2097 return 1; 2390 return 1;
2391 }
2098 2392
2099 return 0; 2393 return 0;
2100 } 2394 }
2101 2395
2102 if (handle_packet_connection(c, crypt_connection_id, packet, length, 1) != 0) 2396 if (handle_packet_connection(c, crypt_connection_id, packet, length, 1, userdata) != 0) {
2103 return 1; 2397 return 1;
2398 }
2104 2399
2105 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 2400 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
2106 2401
2107 if (conn == 0) 2402 if (conn == nullptr) {
2108 return -1; 2403 return -1;
2404 }
2109 2405
2110 pthread_mutex_lock(&conn->mutex); 2406 pthread_mutex_lock(&conn->mutex);
2111 2407
2112 if (source.ip.family == AF_INET) { 2408 if (net_family_is_ipv4(source.ip.family)) {
2113 conn->direct_lastrecv_timev4 = unix_time(); 2409 conn->direct_lastrecv_timev4 = unix_time();
2114 } else { 2410 } else {
2115 conn->direct_lastrecv_timev6 = unix_time(); 2411 conn->direct_lastrecv_timev6 = unix_time();
@@ -2147,37 +2443,40 @@ static void send_crypto_packets(Net_Crypto *c)
2147 for (i = 0; i < c->crypto_connections_length; ++i) { 2443 for (i = 0; i < c->crypto_connections_length; ++i) {
2148 Crypto_Connection *conn = get_crypto_connection(c, i); 2444 Crypto_Connection *conn = get_crypto_connection(c, i);
2149 2445
2150 if (conn == 0) 2446 if (conn == nullptr) {
2151 return; 2447 continue;
2448 }
2152 2449
2153 if (CRYPTO_SEND_PACKET_INTERVAL + conn->temp_packet_sent_time < temp_time) { 2450 if ((CRYPTO_SEND_PACKET_INTERVAL + conn->temp_packet_sent_time) < temp_time) {
2154 send_temp_packet(c, i); 2451 send_temp_packet(c, i);
2155 } 2452 }
2156 2453
2157 if ((conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED) 2454 if ((conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED)
2158 && ((CRYPTO_SEND_PACKET_INTERVAL) + conn->last_request_packet_sent) < temp_time) { 2455 && (CRYPTO_SEND_PACKET_INTERVAL + conn->last_request_packet_sent) < temp_time) {
2159 if (send_request_packet(c, i) == 0) { 2456 if (send_request_packet(c, i) == 0) {
2160 conn->last_request_packet_sent = temp_time; 2457 conn->last_request_packet_sent = temp_time;
2161 } 2458 }
2162
2163 } 2459 }
2164 2460
2165 if (conn->status == CRYPTO_CONN_ESTABLISHED) { 2461 if (conn->status == CRYPTO_CONN_ESTABLISHED) {
2166 if (conn->packet_recv_rate > CRYPTO_PACKET_MIN_RATE) { 2462 if (conn->packet_recv_rate > CRYPTO_PACKET_MIN_RATE) {
2167 double request_packet_interval = (REQUEST_PACKETS_COMPARE_CONSTANT / (((double)num_packets_array( 2463 double request_packet_interval = (REQUEST_PACKETS_COMPARE_CONSTANT / ((num_packets_array(
2168 &conn->recv_array) + 1.0) / (conn->packet_recv_rate + 1.0))); 2464 &conn->recv_array) + 1.0) / (conn->packet_recv_rate + 1.0)));
2169 2465
2170 double request_packet_interval2 = ((CRYPTO_PACKET_MIN_RATE / conn->packet_recv_rate) * 2466 double request_packet_interval2 = ((CRYPTO_PACKET_MIN_RATE / conn->packet_recv_rate) *
2171 (double)CRYPTO_SEND_PACKET_INTERVAL) + (double)PACKET_COUNTER_AVERAGE_INTERVAL; 2467 (double)CRYPTO_SEND_PACKET_INTERVAL) + (double)PACKET_COUNTER_AVERAGE_INTERVAL;
2172 2468
2173 if (request_packet_interval2 < request_packet_interval) 2469 if (request_packet_interval2 < request_packet_interval) {
2174 request_packet_interval = request_packet_interval2; 2470 request_packet_interval = request_packet_interval2;
2471 }
2175 2472
2176 if (request_packet_interval < PACKET_COUNTER_AVERAGE_INTERVAL) 2473 if (request_packet_interval < PACKET_COUNTER_AVERAGE_INTERVAL) {
2177 request_packet_interval = PACKET_COUNTER_AVERAGE_INTERVAL; 2474 request_packet_interval = PACKET_COUNTER_AVERAGE_INTERVAL;
2475 }
2178 2476
2179 if (request_packet_interval > CRYPTO_SEND_PACKET_INTERVAL) 2477 if (request_packet_interval > CRYPTO_SEND_PACKET_INTERVAL) {
2180 request_packet_interval = CRYPTO_SEND_PACKET_INTERVAL; 2478 request_packet_interval = CRYPTO_SEND_PACKET_INTERVAL;
2479 }
2181 2480
2182 if (temp_time - conn->last_request_packet_sent > (uint64_t)request_packet_interval) { 2481 if (temp_time - conn->last_request_packet_sent > (uint64_t)request_packet_interval) {
2183 if (send_request_packet(c, i) == 0) { 2482 if (send_request_packet(c, i) == 0) {
@@ -2212,7 +2511,6 @@ static void send_crypto_packets(Net_Crypto *c)
2212 conn->last_sendqueue_size[pos] = num_packets_array(&conn->send_array); 2511 conn->last_sendqueue_size[pos] = num_packets_array(&conn->send_array);
2213 ++conn->last_sendqueue_counter; 2512 ++conn->last_sendqueue_counter;
2214 2513
2215 unsigned int j;
2216 long signed int sum = 0; 2514 long signed int sum = 0;
2217 sum = (long signed int)conn->last_sendqueue_size[(pos) % CONGESTION_QUEUE_ARRAY_SIZE] - 2515 sum = (long signed int)conn->last_sendqueue_size[(pos) % CONGESTION_QUEUE_ARRAY_SIZE] -
2218 (long signed int)conn->last_sendqueue_size[(pos - (CONGESTION_QUEUE_ARRAY_SIZE - 1)) % CONGESTION_QUEUE_ARRAY_SIZE]; 2516 (long signed int)conn->last_sendqueue_size[(pos - (CONGESTION_QUEUE_ARRAY_SIZE - 1)) % CONGESTION_QUEUE_ARRAY_SIZE];
@@ -2221,15 +2519,15 @@ static void send_crypto_packets(Net_Crypto *c)
2221 conn->last_num_packets_sent[n_p_pos] = packets_sent; 2519 conn->last_num_packets_sent[n_p_pos] = packets_sent;
2222 conn->last_num_packets_resent[n_p_pos] = packets_resent; 2520 conn->last_num_packets_resent[n_p_pos] = packets_resent;
2223 2521
2224 _Bool direct_connected = 0; 2522 bool direct_connected = 0;
2225 crypto_connection_status(c, i, &direct_connected, NULL); 2523 crypto_connection_status(c, i, &direct_connected, nullptr);
2226 2524
2227 if (direct_connected && conn->last_tcp_sent + CONGESTION_EVENT_TIMEOUT > temp_time) { 2525 if (direct_connected && conn->last_tcp_sent + CONGESTION_EVENT_TIMEOUT > temp_time) {
2228 /* When switching from TCP to UDP, don't change the packet send rate for CONGESTION_EVENT_TIMEOUT ms. */ 2526 /* When switching from TCP to UDP, don't change the packet send rate for CONGESTION_EVENT_TIMEOUT ms. */
2229 } else { 2527 } else {
2230 long signed int total_sent = 0, total_resent = 0; 2528 long signed int total_sent = 0, total_resent = 0;
2231 2529
2232 //TODO use real delay 2530 // TODO(irungentoo): use real delay
2233 unsigned int delay = (unsigned int)((conn->rtt_time / PACKET_COUNTER_AVERAGE_INTERVAL) + 0.5); 2531 unsigned int delay = (unsigned int)((conn->rtt_time / PACKET_COUNTER_AVERAGE_INTERVAL) + 0.5);
2234 unsigned int packets_set_rem_array = (CONGESTION_LAST_SENT_ARRAY_SIZE - CONGESTION_QUEUE_ARRAY_SIZE); 2532 unsigned int packets_set_rem_array = (CONGESTION_LAST_SENT_ARRAY_SIZE - CONGESTION_QUEUE_ARRAY_SIZE);
2235 2533
@@ -2237,7 +2535,7 @@ static void send_crypto_packets(Net_Crypto *c)
2237 delay = packets_set_rem_array; 2535 delay = packets_set_rem_array;
2238 } 2536 }
2239 2537
2240 for (j = 0; j < CONGESTION_QUEUE_ARRAY_SIZE; ++j) { 2538 for (unsigned j = 0; j < CONGESTION_QUEUE_ARRAY_SIZE; ++j) {
2241 unsigned int ind = (j + (packets_set_rem_array - delay) + n_p_pos) % CONGESTION_LAST_SENT_ARRAY_SIZE; 2539 unsigned int ind = (j + (packets_set_rem_array - delay) + n_p_pos) % CONGESTION_LAST_SENT_ARRAY_SIZE;
2242 total_sent += conn->last_num_packets_sent[ind]; 2540 total_sent += conn->last_num_packets_sent[ind];
2243 total_resent += conn->last_num_packets_resent[ind]; 2541 total_resent += conn->last_num_packets_resent[ind];
@@ -2246,8 +2544,9 @@ static void send_crypto_packets(Net_Crypto *c)
2246 if (sum > 0) { 2544 if (sum > 0) {
2247 total_sent -= sum; 2545 total_sent -= sum;
2248 } else { 2546 } else {
2249 if (total_resent > -sum) 2547 if (total_resent > -sum) {
2250 total_resent = -sum; 2548 total_resent = -sum;
2549 }
2251 } 2550 }
2252 2551
2253 /* if queue is too big only allow resending packets. */ 2552 /* if queue is too big only allow resending packets. */
@@ -2258,12 +2557,13 @@ static void send_crypto_packets(Net_Crypto *c)
2258 double min_speed_request = 1000.0 * (((double)(total_sent + total_resent)) / ((double)( 2557 double min_speed_request = 1000.0 * (((double)(total_sent + total_resent)) / ((double)(
2259 CONGESTION_QUEUE_ARRAY_SIZE) * PACKET_COUNTER_AVERAGE_INTERVAL)); 2558 CONGESTION_QUEUE_ARRAY_SIZE) * PACKET_COUNTER_AVERAGE_INTERVAL));
2260 2559
2261 if (min_speed < CRYPTO_PACKET_MIN_RATE) 2560 if (min_speed < CRYPTO_PACKET_MIN_RATE) {
2262 min_speed = CRYPTO_PACKET_MIN_RATE; 2561 min_speed = CRYPTO_PACKET_MIN_RATE;
2562 }
2263 2563
2264 double send_array_ratio = (((double)npackets) / min_speed); 2564 double send_array_ratio = (((double)npackets) / min_speed);
2265 2565
2266 //TODO: Improve formula? 2566 // TODO(irungentoo): Improve formula?
2267 if (send_array_ratio > SEND_QUEUE_RATIO && CRYPTO_MIN_QUEUE_LENGTH < npackets) { 2567 if (send_array_ratio > SEND_QUEUE_RATIO && CRYPTO_MIN_QUEUE_LENGTH < npackets) {
2268 conn->packet_send_rate = min_speed * (1.0 / (send_array_ratio / SEND_QUEUE_RATIO)); 2568 conn->packet_send_rate = min_speed * (1.0 / (send_array_ratio / SEND_QUEUE_RATIO));
2269 } else if (conn->last_congestion_event + CONGESTION_EVENT_TIMEOUT < temp_time) { 2569 } else if (conn->last_congestion_event + CONGESTION_EVENT_TIMEOUT < temp_time) {
@@ -2282,7 +2582,6 @@ static void send_crypto_packets(Net_Crypto *c)
2282 conn->packet_send_rate_requested = conn->packet_send_rate; 2582 conn->packet_send_rate_requested = conn->packet_send_rate;
2283 } 2583 }
2284 } 2584 }
2285
2286 } 2585 }
2287 2586
2288 if (conn->last_packets_left_set == 0 || conn->last_packets_left_requested_set == 0) { 2587 if (conn->last_packets_left_set == 0 || conn->last_packets_left_requested_set == 0) {
@@ -2320,8 +2619,9 @@ static void send_crypto_packets(Net_Crypto *c)
2320 conn->last_packets_left_requested_rem = rem; 2619 conn->last_packets_left_requested_rem = rem;
2321 } 2620 }
2322 2621
2323 if (conn->packets_left > conn->packets_left_requested) 2622 if (conn->packets_left > conn->packets_left_requested) {
2324 conn->packets_left_requested = conn->packets_left; 2623 conn->packets_left_requested = conn->packets_left;
2624 }
2325 } 2625 }
2326 2626
2327 int ret = send_requested_packets(c, i, conn->packets_left_requested); 2627 int ret = send_requested_packets(c, i, conn->packets_left_requested);
@@ -2369,7 +2669,7 @@ static void send_crypto_packets(Net_Crypto *c)
2369/* Return 1 if max speed was reached for this connection (no more data can be physically through the pipe). 2669/* Return 1 if max speed was reached for this connection (no more data can be physically through the pipe).
2370 * Return 0 if it wasn't reached. 2670 * Return 0 if it wasn't reached.
2371 */ 2671 */
2372_Bool max_speed_reached(Net_Crypto *c, int crypt_connection_id) 2672bool max_speed_reached(Net_Crypto *c, int crypt_connection_id)
2373{ 2673{
2374 return reset_max_speed_reached(c, crypt_connection_id) != 0; 2674 return reset_max_speed_reached(c, crypt_connection_id) != 0;
2375} 2675}
@@ -2381,16 +2681,17 @@ uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connecti
2381{ 2681{
2382 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 2682 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
2383 2683
2384 if (conn == 0) 2684 if (conn == nullptr) {
2385 return 0; 2685 return 0;
2686 }
2386 2687
2387 uint32_t max_packets = CRYPTO_PACKET_BUFFER_SIZE - num_packets_array(&conn->send_array); 2688 uint32_t max_packets = CRYPTO_PACKET_BUFFER_SIZE - num_packets_array(&conn->send_array);
2388 2689
2389 if (conn->packets_left < max_packets) { 2690 if (conn->packets_left < max_packets) {
2390 return conn->packets_left; 2691 return conn->packets_left;
2391 } else {
2392 return max_packets;
2393 } 2692 }
2693
2694 return max_packets;
2394} 2695}
2395 2696
2396/* Sends a lossless cryptopacket. 2697/* Sends a lossless cryptopacket.
@@ -2403,30 +2704,37 @@ uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connecti
2403int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length, 2704int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length,
2404 uint8_t congestion_control) 2705 uint8_t congestion_control)
2405{ 2706{
2406 if (length == 0) 2707 if (length == 0) {
2407 return -1; 2708 return -1;
2709 }
2408 2710
2409 if (data[0] < CRYPTO_RESERVED_PACKETS) 2711 if (data[0] < CRYPTO_RESERVED_PACKETS) {
2410 return -1; 2712 return -1;
2713 }
2411 2714
2412 if (data[0] >= PACKET_ID_LOSSY_RANGE_START) 2715 if (data[0] >= PACKET_ID_LOSSY_RANGE_START) {
2413 return -1; 2716 return -1;
2717 }
2414 2718
2415 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 2719 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
2416 2720
2417 if (conn == 0) 2721 if (conn == nullptr) {
2418 return -1; 2722 return -1;
2723 }
2419 2724
2420 if (conn->status != CRYPTO_CONN_ESTABLISHED) 2725 if (conn->status != CRYPTO_CONN_ESTABLISHED) {
2421 return -1; 2726 return -1;
2727 }
2422 2728
2423 if (congestion_control && conn->packets_left == 0) 2729 if (congestion_control && conn->packets_left == 0) {
2424 return -1; 2730 return -1;
2731 }
2425 2732
2426 int64_t ret = send_lossless_packet(c, crypt_connection_id, data, length, congestion_control); 2733 int64_t ret = send_lossless_packet(c, crypt_connection_id, data, length, congestion_control);
2427 2734
2428 if (ret == -1) 2735 if (ret == -1) {
2429 return -1; 2736 return -1;
2737 }
2430 2738
2431 if (congestion_control) { 2739 if (congestion_control) {
2432 --conn->packets_left; 2740 --conn->packets_left;
@@ -2443,22 +2751,30 @@ int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t
2443 * 2751 *
2444 * return -1 on failure. 2752 * return -1 on failure.
2445 * return 0 on success. 2753 * return 0 on success.
2754 *
2755 * Note: The condition `buffer_end - buffer_start < packet_number - buffer_start` is
2756 * a trick which handles situations `buffer_end >= buffer_start` and
2757 * `buffer_end < buffer_start`(when buffer_end overflowed) both correctly
2758 *
2759 * It CANNOT be simplified to `packet_number < buffer_start`, as it will fail
2760 * when `buffer_end < buffer_start`.
2446 */ 2761 */
2447int cryptpacket_received(Net_Crypto *c, int crypt_connection_id, uint32_t packet_number) 2762int cryptpacket_received(Net_Crypto *c, int crypt_connection_id, uint32_t packet_number)
2448{ 2763{
2449 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 2764 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
2450 2765
2451 if (conn == 0) 2766 if (conn == nullptr) {
2452 return -1; 2767 return -1;
2768 }
2453 2769
2454 uint32_t num = conn->send_array.buffer_end - conn->send_array.buffer_start; 2770 uint32_t num = conn->send_array.buffer_end - conn->send_array.buffer_start;
2455 uint32_t num1 = packet_number - conn->send_array.buffer_start; 2771 uint32_t num1 = packet_number - conn->send_array.buffer_start;
2456 2772
2457 if (num < num1) { 2773 if (num < num1) {
2458 return 0; 2774 return 0;
2459 } else {
2460 return -1;
2461 } 2775 }
2776
2777 return -1;
2462} 2778}
2463 2779
2464/* return -1 on failure. 2780/* return -1 on failure.
@@ -2468,14 +2784,17 @@ int cryptpacket_received(Net_Crypto *c, int crypt_connection_id, uint32_t packet
2468 */ 2784 */
2469int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length) 2785int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length)
2470{ 2786{
2471 if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) 2787 if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) {
2472 return -1; 2788 return -1;
2789 }
2473 2790
2474 if (data[0] < PACKET_ID_LOSSY_RANGE_START) 2791 if (data[0] < PACKET_ID_LOSSY_RANGE_START) {
2475 return -1; 2792 return -1;
2793 }
2476 2794
2477 if (data[0] >= (PACKET_ID_LOSSY_RANGE_START + PACKET_ID_LOSSY_RANGE_SIZE)) 2795 if (data[0] >= (PACKET_ID_LOSSY_RANGE_START + PACKET_ID_LOSSY_RANGE_SIZE)) {
2478 return -1; 2796 return -1;
2797 }
2479 2798
2480 pthread_mutex_lock(&c->connections_mutex); 2799 pthread_mutex_lock(&c->connections_mutex);
2481 ++c->connection_use_counter; 2800 ++c->connection_use_counter;
@@ -2507,7 +2826,7 @@ int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t
2507 */ 2826 */
2508int crypto_kill(Net_Crypto *c, int crypt_connection_id) 2827int crypto_kill(Net_Crypto *c, int crypt_connection_id)
2509{ 2828{
2510 while (1) { /* TODO: is this really the best way to do this? */ 2829 while (1) { /* TODO(irungentoo): is this really the best way to do this? */
2511 pthread_mutex_lock(&c->connections_mutex); 2830 pthread_mutex_lock(&c->connections_mutex);
2512 2831
2513 if (!c->connection_use_counter) { 2832 if (!c->connection_use_counter) {
@@ -2522,8 +2841,9 @@ int crypto_kill(Net_Crypto *c, int crypt_connection_id)
2522 int ret = -1; 2841 int ret = -1;
2523 2842
2524 if (conn) { 2843 if (conn) {
2525 if (conn->status == CRYPTO_CONN_ESTABLISHED) 2844 if (conn->status == CRYPTO_CONN_ESTABLISHED) {
2526 send_kill_packet(c, crypt_connection_id); 2845 send_kill_packet(c, crypt_connection_id);
2846 }
2527 2847
2528 pthread_mutex_lock(&c->tcp_mutex); 2848 pthread_mutex_lock(&c->tcp_mutex);
2529 kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp); 2849 kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp);
@@ -2547,24 +2867,27 @@ int crypto_kill(Net_Crypto *c, int crypt_connection_id)
2547 * sets direct_connected to 1 if connection connects directly to other, 0 if it isn't. 2867 * sets direct_connected to 1 if connection connects directly to other, 0 if it isn't.
2548 * sets online_tcp_relays to the number of connected tcp relays this connection has. 2868 * sets online_tcp_relays to the number of connected tcp relays this connection has.
2549 */ 2869 */
2550unsigned int crypto_connection_status(const Net_Crypto *c, int crypt_connection_id, _Bool *direct_connected, 2870unsigned int crypto_connection_status(const Net_Crypto *c, int crypt_connection_id, bool *direct_connected,
2551 unsigned int *online_tcp_relays) 2871 unsigned int *online_tcp_relays)
2552{ 2872{
2553 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 2873 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
2554 2874
2555 if (conn == 0) 2875 if (conn == nullptr) {
2556 return CRYPTO_CONN_NO_CONNECTION; 2876 return CRYPTO_CONN_NO_CONNECTION;
2877 }
2557 2878
2558 if (direct_connected) { 2879 if (direct_connected) {
2559 *direct_connected = 0; 2880 *direct_connected = 0;
2560 2881
2561 uint64_t current_time = unix_time(); 2882 uint64_t current_time = unix_time();
2562 2883
2563 if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) 2884 if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) {
2564 *direct_connected = 1; 2885 *direct_connected = 1;
2886 }
2565 2887
2566 if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev6) > current_time) 2888 if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev6) > current_time) {
2567 *direct_connected = 1; 2889 *direct_connected = 1;
2890 }
2568 } 2891 }
2569 2892
2570 if (online_tcp_relays) { 2893 if (online_tcp_relays) {
@@ -2576,59 +2899,63 @@ unsigned int crypto_connection_status(const Net_Crypto *c, int crypt_connection_
2576 2899
2577void new_keys(Net_Crypto *c) 2900void new_keys(Net_Crypto *c)
2578{ 2901{
2579 crypto_box_keypair(c->self_public_key, c->self_secret_key); 2902 crypto_new_keypair(c->self_public_key, c->self_secret_key);
2580} 2903}
2581 2904
2582/* Save the public and private keys to the keys array. 2905/* Save the public and private keys to the keys array.
2583 * Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES. 2906 * Length must be CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE.
2584 * 2907 *
2585 * TODO: Save only secret key. 2908 * TODO(irungentoo): Save only secret key.
2586 */ 2909 */
2587void save_keys(const Net_Crypto *c, uint8_t *keys) 2910void save_keys(const Net_Crypto *c, uint8_t *keys)
2588{ 2911{
2589 memcpy(keys, c->self_public_key, crypto_box_PUBLICKEYBYTES); 2912 memcpy(keys, c->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
2590 memcpy(keys + crypto_box_PUBLICKEYBYTES, c->self_secret_key, crypto_box_SECRETKEYBYTES); 2913 memcpy(keys + CRYPTO_PUBLIC_KEY_SIZE, c->self_secret_key, CRYPTO_SECRET_KEY_SIZE);
2591} 2914}
2592 2915
2593/* Load the secret key. 2916/* Load the secret key.
2594 * Length must be crypto_box_SECRETKEYBYTES. 2917 * Length must be CRYPTO_SECRET_KEY_SIZE.
2595 */ 2918 */
2596void load_secret_key(Net_Crypto *c, const uint8_t *sk) 2919void load_secret_key(Net_Crypto *c, const uint8_t *sk)
2597{ 2920{
2598 memcpy(c->self_secret_key, sk, crypto_box_SECRETKEYBYTES); 2921 memcpy(c->self_secret_key, sk, CRYPTO_SECRET_KEY_SIZE);
2599 crypto_scalarmult_curve25519_base(c->self_public_key, c->self_secret_key); 2922 crypto_derive_public_key(c->self_public_key, c->self_secret_key);
2600} 2923}
2601 2924
2602/* Run this to (re)initialize net_crypto. 2925/* Run this to (re)initialize net_crypto.
2603 * Sets all the global connection variables to their default values. 2926 * Sets all the global connection variables to their default values.
2604 */ 2927 */
2605Net_Crypto *new_net_crypto(DHT *dht, TCP_Proxy_Info *proxy_info) 2928Net_Crypto *new_net_crypto(Logger *log, DHT *dht, TCP_Proxy_Info *proxy_info)
2606{ 2929{
2607 unix_time_update(); 2930 unix_time_update();
2608 2931
2609 if (dht == NULL) 2932 if (dht == nullptr) {
2610 return NULL; 2933 return nullptr;
2934 }
2935
2936 Net_Crypto *temp = (Net_Crypto *)calloc(1, sizeof(Net_Crypto));
2611 2937
2612 Net_Crypto *temp = calloc(1, sizeof(Net_Crypto)); 2938 if (temp == nullptr) {
2939 return nullptr;
2940 }
2613 2941
2614 if (temp == NULL) 2942 temp->log = log;
2615 return NULL;
2616 2943
2617 temp->tcp_c = new_tcp_connections(dht->self_secret_key, proxy_info); 2944 temp->tcp_c = new_tcp_connections(dht_get_self_secret_key(dht), proxy_info);
2618 2945
2619 if (temp->tcp_c == NULL) { 2946 if (temp->tcp_c == nullptr) {
2620 free(temp); 2947 free(temp);
2621 return NULL; 2948 return nullptr;
2622 } 2949 }
2623 2950
2624 set_packet_tcp_connection_callback(temp->tcp_c, &tcp_data_callback, temp); 2951 set_packet_tcp_connection_callback(temp->tcp_c, &tcp_data_callback, temp);
2625 set_oob_packet_tcp_connection_callback(temp->tcp_c, &tcp_oob_callback, temp); 2952 set_oob_packet_tcp_connection_callback(temp->tcp_c, &tcp_oob_callback, temp);
2626 2953
2627 if (create_recursive_mutex(&temp->tcp_mutex) != 0 || 2954 if (create_recursive_mutex(&temp->tcp_mutex) != 0 ||
2628 pthread_mutex_init(&temp->connections_mutex, NULL) != 0) { 2955 pthread_mutex_init(&temp->connections_mutex, nullptr) != 0) {
2629 kill_tcp_connections(temp->tcp_c); 2956 kill_tcp_connections(temp->tcp_c);
2630 free(temp); 2957 free(temp);
2631 return NULL; 2958 return nullptr;
2632 } 2959 }
2633 2960
2634 temp->dht = dht; 2961 temp->dht = dht;
@@ -2638,17 +2965,17 @@ Net_Crypto *new_net_crypto(DHT *dht, TCP_Proxy_Info *proxy_info)
2638 2965
2639 temp->current_sleep_time = CRYPTO_SEND_PACKET_INTERVAL; 2966 temp->current_sleep_time = CRYPTO_SEND_PACKET_INTERVAL;
2640 2967
2641 networking_registerhandler(dht->net, NET_PACKET_COOKIE_REQUEST, &udp_handle_cookie_request, temp); 2968 networking_registerhandler(dht_get_net(dht), NET_PACKET_COOKIE_REQUEST, &udp_handle_cookie_request, temp);
2642 networking_registerhandler(dht->net, NET_PACKET_COOKIE_RESPONSE, &udp_handle_packet, temp); 2969 networking_registerhandler(dht_get_net(dht), NET_PACKET_COOKIE_RESPONSE, &udp_handle_packet, temp);
2643 networking_registerhandler(dht->net, NET_PACKET_CRYPTO_HS, &udp_handle_packet, temp); 2970 networking_registerhandler(dht_get_net(dht), NET_PACKET_CRYPTO_HS, &udp_handle_packet, temp);
2644 networking_registerhandler(dht->net, NET_PACKET_CRYPTO_DATA, &udp_handle_packet, temp); 2971 networking_registerhandler(dht_get_net(dht), NET_PACKET_CRYPTO_DATA, &udp_handle_packet, temp);
2645 2972
2646 bs_list_init(&temp->ip_port_list, sizeof(IP_Port), 8); 2973 bs_list_init(&temp->ip_port_list, sizeof(IP_Port), 8);
2647 2974
2648 return temp; 2975 return temp;
2649} 2976}
2650 2977
2651static void kill_timedout(Net_Crypto *c) 2978static void kill_timedout(Net_Crypto *c, void *userdata)
2652{ 2979{
2653 uint32_t i; 2980 uint32_t i;
2654 //uint64_t temp_time = current_time_monotonic(); 2981 //uint64_t temp_time = current_time_monotonic();
@@ -2656,24 +2983,30 @@ static void kill_timedout(Net_Crypto *c)
2656 for (i = 0; i < c->crypto_connections_length; ++i) { 2983 for (i = 0; i < c->crypto_connections_length; ++i) {
2657 Crypto_Connection *conn = get_crypto_connection(c, i); 2984 Crypto_Connection *conn = get_crypto_connection(c, i);
2658 2985
2659 if (conn == 0) 2986 if (conn == nullptr) {
2660 return; 2987 continue;
2988 }
2661 2989
2662 if (conn->status == CRYPTO_CONN_NO_CONNECTION) 2990 if (conn->status == CRYPTO_CONN_NO_CONNECTION) {
2663 continue; 2991 continue;
2992 }
2664 2993
2665 if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT 2994 if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT
2666 || conn->status == CRYPTO_CONN_NOT_CONFIRMED) { 2995 || conn->status == CRYPTO_CONN_NOT_CONFIRMED) {
2667 if (conn->temp_packet_num_sent < MAX_NUM_SENDPACKET_TRIES) 2996 if (conn->temp_packet_num_sent < MAX_NUM_SENDPACKET_TRIES) {
2668 continue; 2997 continue;
2998 }
2669 2999
2670 connection_kill(c, i); 3000 connection_kill(c, i, userdata);
2671
2672 } 3001 }
2673 3002
3003#if 0
3004
2674 if (conn->status == CRYPTO_CONN_ESTABLISHED) { 3005 if (conn->status == CRYPTO_CONN_ESTABLISHED) {
2675 //TODO: add a timeout here? 3006 // TODO(irungentoo): add a timeout here?
2676 } 3007 }
3008
3009#endif
2677 } 3010 }
2678} 3011}
2679 3012
@@ -2685,11 +3018,11 @@ uint32_t crypto_run_interval(const Net_Crypto *c)
2685} 3018}
2686 3019
2687/* Main loop. */ 3020/* Main loop. */
2688void do_net_crypto(Net_Crypto *c) 3021void do_net_crypto(Net_Crypto *c, void *userdata)
2689{ 3022{
2690 unix_time_update(); 3023 unix_time_update();
2691 kill_timedout(c); 3024 kill_timedout(c, userdata);
2692 do_tcp(c); 3025 do_tcp(c, userdata);
2693 send_crypto_packets(c); 3026 send_crypto_packets(c);
2694} 3027}
2695 3028
@@ -2706,10 +3039,10 @@ void kill_net_crypto(Net_Crypto *c)
2706 3039
2707 kill_tcp_connections(c->tcp_c); 3040 kill_tcp_connections(c->tcp_c);
2708 bs_list_free(&c->ip_port_list); 3041 bs_list_free(&c->ip_port_list);
2709 networking_registerhandler(c->dht->net, NET_PACKET_COOKIE_REQUEST, NULL, NULL); 3042 networking_registerhandler(dht_get_net(c->dht), NET_PACKET_COOKIE_REQUEST, nullptr, nullptr);
2710 networking_registerhandler(c->dht->net, NET_PACKET_COOKIE_RESPONSE, NULL, NULL); 3043 networking_registerhandler(dht_get_net(c->dht), NET_PACKET_COOKIE_RESPONSE, nullptr, nullptr);
2711 networking_registerhandler(c->dht->net, NET_PACKET_CRYPTO_HS, NULL, NULL); 3044 networking_registerhandler(dht_get_net(c->dht), NET_PACKET_CRYPTO_HS, nullptr, nullptr);
2712 networking_registerhandler(c->dht->net, NET_PACKET_CRYPTO_DATA, NULL, NULL); 3045 networking_registerhandler(dht_get_net(c->dht), NET_PACKET_CRYPTO_DATA, nullptr, nullptr);
2713 sodium_memzero(c, sizeof(Net_Crypto)); 3046 crypto_memzero(c, sizeof(Net_Crypto));
2714 free(c); 3047 free(c);
2715} 3048}
diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h
index c9554bfc..ec55bf6f 100644
--- a/toxcore/net_crypto.h
+++ b/toxcore/net_crypto.h
@@ -1,32 +1,34 @@
1/* net_crypto.h 1/*
2 *
3 * Functions for the core network crypto. 2 * Functions for the core network crypto.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2013 Tox project.
4 * 8 *
5 * Copyright (C) 2013 Tox project All Rights Reserved. 9 * This file is part of Tox, the free peer to peer instant messenger.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23
24#ifndef NET_CRYPTO_H 24#ifndef NET_CRYPTO_H
25#define NET_CRYPTO_H 25#define NET_CRYPTO_H
26 26
27#include "DHT.h" 27#include "DHT.h"
28#include "LAN_discovery.h" 28#include "LAN_discovery.h"
29#include "TCP_connection.h" 29#include "TCP_connection.h"
30#include "logger.h"
31
30#include <pthread.h> 32#include <pthread.h>
31 33
32#define CRYPTO_CONN_NO_CONNECTION 0 34#define CRYPTO_CONN_NO_CONNECTION 0
@@ -47,7 +49,7 @@
47/* Maximum total size of packets that net_crypto sends. */ 49/* Maximum total size of packets that net_crypto sends. */
48#define MAX_CRYPTO_PACKET_SIZE 1400 50#define MAX_CRYPTO_PACKET_SIZE 1400
49 51
50#define CRYPTO_DATA_PACKET_MIN_SIZE (1 + sizeof(uint16_t) + (sizeof(uint32_t) + sizeof(uint32_t)) + crypto_box_MACBYTES) 52#define CRYPTO_DATA_PACKET_MIN_SIZE (1 + sizeof(uint16_t) + (sizeof(uint32_t) + sizeof(uint32_t)) + CRYPTO_MAC_SIZE)
51 53
52/* Max size of data in packets */ 54/* Max size of data in packets */
53#define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - CRYPTO_DATA_PACKET_MIN_SIZE) 55#define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - CRYPTO_DATA_PACKET_MIN_SIZE)
@@ -60,7 +62,7 @@
60#define MAX_NUM_SENDPACKET_TRIES 8 62#define MAX_NUM_SENDPACKET_TRIES 8
61 63
62/* The timeout of no received UDP packets before the direct UDP connection is considered dead. */ 64/* The timeout of no received UDP packets before the direct UDP connection is considered dead. */
63#define UDP_DIRECT_TIMEOUT ((MAX_NUM_SENDPACKET_TRIES * CRYPTO_SEND_PACKET_INTERVAL) / 1000) 65#define UDP_DIRECT_TIMEOUT 8
64 66
65#define PACKET_ID_PADDING 0 /* Denotes padding */ 67#define PACKET_ID_PADDING 0 /* Denotes padding */
66#define PACKET_ID_REQUEST 1 /* Used to request unreceived packets */ 68#define PACKET_ID_REQUEST 1 /* Used to request unreceived packets */
@@ -87,136 +89,23 @@
87#define DEFAULT_PING_CONNECTION 1000 89#define DEFAULT_PING_CONNECTION 1000
88#define DEFAULT_TCP_PING_CONNECTION 500 90#define DEFAULT_TCP_PING_CONNECTION 500
89 91
90typedef struct { 92typedef struct Net_Crypto Net_Crypto;
91 uint64_t sent_time; 93
92 uint16_t length; 94const uint8_t *nc_get_self_public_key(const Net_Crypto *c);
93 uint8_t data[MAX_CRYPTO_DATA_SIZE]; 95const uint8_t *nc_get_self_secret_key(const Net_Crypto *c);
94} Packet_Data; 96TCP_Connections *nc_get_tcp_c(const Net_Crypto *c);
95 97DHT *nc_get_dht(const Net_Crypto *c);
96typedef struct { 98
97 Packet_Data *buffer[CRYPTO_PACKET_BUFFER_SIZE]; 99typedef struct New_Connection {
98 uint32_t buffer_start;
99 uint32_t buffer_end; /* packet numbers in array: {buffer_start, buffer_end) */
100} Packets_Array;
101
102typedef struct {
103 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */
104 uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */
105 uint8_t sent_nonce[crypto_box_NONCEBYTES]; /* Nonce of sent packets. */
106 uint8_t sessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* Our public key for this session. */
107 uint8_t sessionsecret_key[crypto_box_SECRETKEYBYTES]; /* Our private key for this session. */
108 uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */
109 uint8_t shared_key[crypto_box_BEFORENMBYTES]; /* The precomputed shared key from encrypt_precompute. */
110 uint8_t status; /* 0 if no connection, 1 we are sending cookie request packets,
111 * 2 if we are sending handshake packets
112 * 3 if connection is not confirmed yet (we have received a handshake but no data packets yet),
113 * 4 if the connection is established.
114 */
115 uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */
116 uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; /* The dht public key of the peer */
117
118 uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */
119 uint16_t temp_packet_length;
120 uint64_t temp_packet_sent_time; /* The time at which the last temp_packet was sent in ms. */
121 uint32_t temp_packet_num_sent;
122
123 IP_Port ip_portv4; /* The ip and port to contact this guy directly.*/
124 IP_Port ip_portv6;
125 uint64_t direct_lastrecv_timev4; /* The Time at which we last received a direct packet in ms. */
126 uint64_t direct_lastrecv_timev6;
127
128 uint64_t last_tcp_sent; /* Time the last TCP packet was sent. */
129
130 Packets_Array send_array;
131 Packets_Array recv_array;
132
133 int (*connection_status_callback)(void *object, int id, uint8_t status);
134 void *connection_status_callback_object;
135 int connection_status_callback_id;
136
137 int (*connection_data_callback)(void *object, int id, uint8_t *data, uint16_t length);
138 void *connection_data_callback_object;
139 int connection_data_callback_id;
140
141 int (*connection_lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length);
142 void *connection_lossy_data_callback_object;
143 int connection_lossy_data_callback_id;
144
145 uint64_t last_request_packet_sent;
146 uint64_t direct_send_attempt_time;
147
148 uint32_t packet_counter;
149 double packet_recv_rate;
150 uint64_t packet_counter_set;
151
152 double packet_send_rate;
153 uint32_t packets_left;
154 uint64_t last_packets_left_set;
155 double last_packets_left_rem;
156
157 double packet_send_rate_requested;
158 uint32_t packets_left_requested;
159 uint64_t last_packets_left_requested_set;
160 double last_packets_left_requested_rem;
161
162 uint32_t last_sendqueue_size[CONGESTION_QUEUE_ARRAY_SIZE], last_sendqueue_counter;
163 long signed int last_num_packets_sent[CONGESTION_LAST_SENT_ARRAY_SIZE],
164 last_num_packets_resent[CONGESTION_LAST_SENT_ARRAY_SIZE];
165 uint32_t packets_sent, packets_resent;
166 uint64_t last_congestion_event;
167 uint64_t rtt_time;
168
169 /* TCP_connection connection_number */
170 unsigned int connection_number_tcp;
171
172 uint8_t maximum_speed_reached;
173
174 pthread_mutex_t mutex;
175
176 void (*dht_pk_callback)(void *data, int32_t number, const uint8_t *dht_public_key);
177 void *dht_pk_callback_object;
178 uint32_t dht_pk_callback_number;
179} Crypto_Connection;
180
181typedef struct {
182 IP_Port source; 100 IP_Port source;
183 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */ 101 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The real public key of the peer. */
184 uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; /* The dht public key of the peer. */ 102 uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The dht public key of the peer. */
185 uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */ 103 uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of received packets. */
186 uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */ 104 uint8_t peersessionpublic_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The public key of the peer. */
187 uint8_t *cookie; 105 uint8_t *cookie;
188 uint8_t cookie_length; 106 uint8_t cookie_length;
189} New_Connection; 107} New_Connection;
190 108
191typedef struct {
192 DHT *dht;
193 TCP_Connections *tcp_c;
194
195 Crypto_Connection *crypto_connections;
196 pthread_mutex_t tcp_mutex;
197
198 pthread_mutex_t connections_mutex;
199 unsigned int connection_use_counter;
200
201 uint32_t crypto_connections_length; /* Length of connections array. */
202
203 /* Our public and secret keys. */
204 uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
205 uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
206
207 /* The secret key used for cookies */
208 uint8_t secret_symmetric_key[crypto_box_KEYBYTES];
209
210 int (*new_connection_callback)(void *object, New_Connection *n_c);
211 void *new_connection_callback_object;
212
213 /* The current optimal sleep time */
214 uint32_t current_sleep_time;
215
216 BS_LIST ip_port_list;
217} Net_Crypto;
218
219
220/* Set function to be called when someone requests a new connection to us. 109/* Set function to be called when someone requests a new connection to us.
221 * 110 *
222 * The set function should return -1 on failure and 0 on success. 111 * The set function should return -1 on failure and 0 on success.
@@ -248,7 +137,7 @@ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const u
248 * return -1 on failure. 137 * return -1 on failure.
249 * return 0 on success. 138 * return 0 on success.
250 */ 139 */
251int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, _Bool connected); 140int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, bool connected);
252 141
253/* Set function to be called when connection with crypt_connection_id goes connects/disconnects. 142/* Set function to be called when connection with crypt_connection_id goes connects/disconnects.
254 * 143 *
@@ -261,7 +150,7 @@ int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port,
261 * return 0 on success. 150 * return 0 on success.
262 */ 151 */
263int connection_status_handler(const Net_Crypto *c, int crypt_connection_id, 152int connection_status_handler(const Net_Crypto *c, int crypt_connection_id,
264 int (*connection_status_callback)(void *object, int id, uint8_t status), void *object, int id); 153 int (*connection_status_callback)(void *object, int id, uint8_t status, void *userdata), void *object, int id);
265 154
266/* Set function to be called when connection with crypt_connection_id receives a lossless data packet of length. 155/* Set function to be called when connection with crypt_connection_id receives a lossless data packet of length.
267 * 156 *
@@ -272,7 +161,7 @@ int connection_status_handler(const Net_Crypto *c, int crypt_connection_id,
272 * return 0 on success. 161 * return 0 on success.
273 */ 162 */
274int connection_data_handler(const Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object, 163int connection_data_handler(const Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object,
275 int id, uint8_t *data, uint16_t length), void *object, int id); 164 int id, const uint8_t *data, uint16_t length, void *userdata), void *object, int id);
276 165
277 166
278/* Set function to be called when connection with crypt_connection_id receives a lossy data packet of length. 167/* Set function to be called when connection with crypt_connection_id receives a lossy data packet of length.
@@ -284,7 +173,8 @@ int connection_data_handler(const Net_Crypto *c, int crypt_connection_id, int (*
284 * return 0 on success. 173 * return 0 on success.
285 */ 174 */
286int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id, 175int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id,
287 int (*connection_lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length), void *object, 176 int (*connection_lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata),
177 void *object,
288 int id); 178 int id);
289 179
290/* Set the function for this friend that will be callbacked with object and number if 180/* Set the function for this friend that will be callbacked with object and number if
@@ -298,7 +188,7 @@ int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id,
298 * return 0 on success. 188 * return 0 on success.
299 */ 189 */
300int nc_dht_pk_callback(Net_Crypto *c, int crypt_connection_id, void (*function)(void *data, int32_t number, 190int nc_dht_pk_callback(Net_Crypto *c, int crypt_connection_id, void (*function)(void *data, int32_t number,
301 const uint8_t *dht_public_key), void *object, uint32_t number); 191 const uint8_t *dht_public_key, void *userdata), void *object, uint32_t number);
302 192
303/* returns the number of packet slots left in the sendbuffer. 193/* returns the number of packet slots left in the sendbuffer.
304 * return 0 if failure. 194 * return 0 if failure.
@@ -308,7 +198,7 @@ uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connecti
308/* Return 1 if max speed was reached for this connection (no more data can be physically through the pipe). 198/* Return 1 if max speed was reached for this connection (no more data can be physically through the pipe).
309 * Return 0 if it wasn't reached. 199 * Return 0 if it wasn't reached.
310 */ 200 */
311_Bool max_speed_reached(Net_Crypto *c, int crypt_connection_id); 201bool max_speed_reached(Net_Crypto *c, int crypt_connection_id);
312 202
313/* Sends a lossless cryptopacket. 203/* Sends a lossless cryptopacket.
314 * 204 *
@@ -364,7 +254,7 @@ int get_random_tcp_con_number(Net_Crypto *c);
364 * return 0 on success. 254 * return 0 on success.
365 * return -1 on failure. 255 * return -1 on failure.
366 */ 256 */
367int send_tcp_onion_request(Net_Crypto *c, unsigned int TCP_conn_number, const uint8_t *data, uint16_t length); 257int send_tcp_onion_request(Net_Crypto *c, unsigned int tcp_connections_number, const uint8_t *data, uint16_t length);
368 258
369/* Copy a maximum of num TCP relays we are connected to to tcp_relays. 259/* Copy a maximum of num TCP relays we are connected to to tcp_relays.
370 * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6. 260 * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6.
@@ -386,7 +276,7 @@ int crypto_kill(Net_Crypto *c, int crypt_connection_id);
386 * sets direct_connected to 1 if connection connects directly to other, 0 if it isn't. 276 * sets direct_connected to 1 if connection connects directly to other, 0 if it isn't.
387 * sets online_tcp_relays to the number of connected tcp relays this connection has. 277 * sets online_tcp_relays to the number of connected tcp relays this connection has.
388 */ 278 */
389unsigned int crypto_connection_status(const Net_Crypto *c, int crypt_connection_id, _Bool *direct_connected, 279unsigned int crypto_connection_status(const Net_Crypto *c, int crypt_connection_id, bool *direct_connected,
390 unsigned int *online_tcp_relays); 280 unsigned int *online_tcp_relays);
391 281
392/* Generate our public and private keys. 282/* Generate our public and private keys.
@@ -395,26 +285,26 @@ unsigned int crypto_connection_status(const Net_Crypto *c, int crypt_connection_
395void new_keys(Net_Crypto *c); 285void new_keys(Net_Crypto *c);
396 286
397/* Save the public and private keys to the keys array. 287/* Save the public and private keys to the keys array.
398 * Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES. 288 * Length must be CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE.
399 */ 289 */
400void save_keys(const Net_Crypto *c, uint8_t *keys); 290void save_keys(const Net_Crypto *c, uint8_t *keys);
401 291
402/* Load the secret key. 292/* Load the secret key.
403 * Length must be crypto_box_SECRETKEYBYTES. 293 * Length must be CRYPTO_SECRET_KEY_SIZE.
404 */ 294 */
405void load_secret_key(Net_Crypto *c, const uint8_t *sk); 295void load_secret_key(Net_Crypto *c, const uint8_t *sk);
406 296
407/* Create new instance of Net_Crypto. 297/* Create new instance of Net_Crypto.
408 * Sets all the global connection variables to their default values. 298 * Sets all the global connection variables to their default values.
409 */ 299 */
410Net_Crypto *new_net_crypto(DHT *dht, TCP_Proxy_Info *proxy_info); 300Net_Crypto *new_net_crypto(Logger *log, DHT *dht, TCP_Proxy_Info *proxy_info);
411 301
412/* return the optimal interval in ms for running do_net_crypto. 302/* return the optimal interval in ms for running do_net_crypto.
413 */ 303 */
414uint32_t crypto_run_interval(const Net_Crypto *c); 304uint32_t crypto_run_interval(const Net_Crypto *c);
415 305
416/* Main loop. */ 306/* Main loop. */
417void do_net_crypto(Net_Crypto *c); 307void do_net_crypto(Net_Crypto *c, void *userdata);
418 308
419void kill_net_crypto(Net_Crypto *c); 309void kill_net_crypto(Net_Crypto *c);
420 310
diff --git a/toxcore/network.c b/toxcore/network.c
index c6cf6ed4..44ca2dee 100644
--- a/toxcore/network.c
+++ b/toxcore/network.c
@@ -1,63 +1,113 @@
1/* network.c 1/*
2 *
3 * Functions for the core networking. 2 * Functions for the core networking.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2013 Tox project.
4 * 8 *
5 * Copyright (C) 2013 Tox project All Rights Reserved. 9 * This file is part of Tox, the free peer to peer instant messenger.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
28#ifdef __APPLE__
29#define _DARWIN_C_SOURCE
30#endif
23 31
24#if (_WIN32_WINNT >= _WIN32_WINNT_WINXP) 32#ifndef _XOPEN_SOURCE
33#define _XOPEN_SOURCE 600
34#endif
35
36#if defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_WINXP
37#undef _WIN32_WINNT
25#define _WIN32_WINNT 0x501 38#define _WIN32_WINNT 0x501
26#endif 39#endif
27 40
28#ifdef HAVE_CONFIG_H 41#if !defined(OS_WIN32) && (defined(_WIN32) || defined(__WIN32__) || defined(WIN32))
29#include "config.h" 42#define OS_WIN32
30#endif 43#endif
31 44
32#include "logger.h" 45#ifdef OS_WIN32
46#ifndef WINVER
47//Windows XP
48#define WINVER 0x0501
49#endif
50#endif
33 51
34#if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32) 52#ifdef PLAN9
35#include <errno.h> 53#include <u.h> // Plan 9 requires this is imported first
54// Comment line here to avoid reordering by source code formatters.
55#include <libc.h>
56#endif
57
58#ifdef OS_WIN32 /* Put win32 includes here */
59// The mingw32/64 Windows library warns about including winsock2.h after
60// windows.h even though with the above it's a valid thing to do. So, to make
61// mingw32 headers happy, we include winsock2.h first.
62#include <winsock2.h>
63// Comment line here to avoid reordering by source code formatters.
64#include <windows.h>
65#include <ws2tcpip.h>
36#endif 66#endif
37 67
68#include "network.h"
69
38#ifdef __APPLE__ 70#ifdef __APPLE__
39#include <mach/clock.h> 71#include <mach/clock.h>
40#include <mach/mach.h> 72#include <mach/mach.h>
41#endif 73#endif
42 74
43#include "network.h" 75#if !defined(OS_WIN32)
44#include "util.h" 76
77#include <arpa/inet.h>
78#include <errno.h>
79#include <fcntl.h>
80#include <netdb.h>
81#include <netinet/in.h>
82#include <sys/ioctl.h>
83#include <sys/socket.h>
84#include <sys/time.h>
85#include <sys/types.h>
86#include <unistd.h>
87
88#define TOX_EWOULDBLOCK EWOULDBLOCK
89
90#else
91#ifndef IPV6_V6ONLY
92#define IPV6_V6ONLY 27
93#endif
45 94
46#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) 95#define TOX_EWOULDBLOCK WSAEWOULDBLOCK
47 96
48static const char *inet_ntop(sa_family_t family, void *addr, char *buf, size_t bufsize) 97static const char *inet_ntop(int family, const void *addr, char *buf, size_t bufsize)
49{ 98{
50 if (family == AF_INET) { 99 if (family == AF_INET) {
51 struct sockaddr_in saddr; 100 struct sockaddr_in saddr;
52 memset(&saddr, 0, sizeof(saddr)); 101 memset(&saddr, 0, sizeof(saddr));
53 102
54 saddr.sin_family = AF_INET; 103 saddr.sin_family = AF_INET;
55 saddr.sin_addr = *(struct in_addr *)addr; 104 saddr.sin_addr = *(const struct in_addr *)addr;
56 105
57 DWORD len = bufsize; 106 DWORD len = bufsize;
58 107
59 if (WSAAddressToString((LPSOCKADDR)&saddr, sizeof(saddr), NULL, buf, &len)) 108 if (WSAAddressToString((LPSOCKADDR)&saddr, sizeof(saddr), nullptr, buf, &len)) {
60 return NULL; 109 return nullptr;
110 }
61 111
62 return buf; 112 return buf;
63 } else if (family == AF_INET6) { 113 } else if (family == AF_INET6) {
@@ -65,20 +115,21 @@ static const char *inet_ntop(sa_family_t family, void *addr, char *buf, size_t b
65 memset(&saddr, 0, sizeof(saddr)); 115 memset(&saddr, 0, sizeof(saddr));
66 116
67 saddr.sin6_family = AF_INET6; 117 saddr.sin6_family = AF_INET6;
68 saddr.sin6_addr = *(struct in6_addr *)addr; 118 saddr.sin6_addr = *(const struct in6_addr *)addr;
69 119
70 DWORD len = bufsize; 120 DWORD len = bufsize;
71 121
72 if (WSAAddressToString((LPSOCKADDR)&saddr, sizeof(saddr), NULL, buf, &len)) 122 if (WSAAddressToString((LPSOCKADDR)&saddr, sizeof(saddr), nullptr, buf, &len)) {
73 return NULL; 123 return nullptr;
124 }
74 125
75 return buf; 126 return buf;
76 } 127 }
77 128
78 return NULL; 129 return nullptr;
79} 130}
80 131
81static int inet_pton(sa_family_t family, const char *addrString, void *addrbuf) 132static int inet_pton(int family, const char *addrString, void *addrbuf)
82{ 133{
83 if (family == AF_INET) { 134 if (family == AF_INET) {
84 struct sockaddr_in saddr; 135 struct sockaddr_in saddr;
@@ -86,8 +137,9 @@ static int inet_pton(sa_family_t family, const char *addrString, void *addrbuf)
86 137
87 INT len = sizeof(saddr); 138 INT len = sizeof(saddr);
88 139
89 if (WSAStringToAddress((LPTSTR)addrString, AF_INET, NULL, (LPSOCKADDR)&saddr, &len)) 140 if (WSAStringToAddress((LPTSTR)addrString, AF_INET, nullptr, (LPSOCKADDR)&saddr, &len)) {
90 return 0; 141 return 0;
142 }
91 143
92 *(struct in_addr *)addrbuf = saddr.sin_addr; 144 *(struct in_addr *)addrbuf = saddr.sin_addr;
93 145
@@ -98,8 +150,9 @@ static int inet_pton(sa_family_t family, const char *addrString, void *addrbuf)
98 150
99 INT len = sizeof(saddr); 151 INT len = sizeof(saddr);
100 152
101 if (WSAStringToAddress((LPTSTR)addrString, AF_INET6, NULL, (LPSOCKADDR)&saddr, &len)) 153 if (WSAStringToAddress((LPTSTR)addrString, AF_INET6, nullptr, (LPSOCKADDR)&saddr, &len)) {
102 return 0; 154 return 0;
155 }
103 156
104 *(struct in6_addr *)addrbuf = saddr.sin6_addr; 157 *(struct in6_addr *)addrbuf = saddr.sin6_addr;
105 158
@@ -111,34 +164,196 @@ static int inet_pton(sa_family_t family, const char *addrString, void *addrbuf)
111 164
112#endif 165#endif
113 166
167#include <assert.h>
168#include <stdio.h>
169#include <stdlib.h>
170#include <string.h>
171
172#include "logger.h"
173#include "util.h"
174
175// Disable MSG_NOSIGNAL on systems not supporting it, e.g. Windows, FreeBSD
176#if !defined(MSG_NOSIGNAL)
177#define MSG_NOSIGNAL 0
178#endif
179
180#ifndef IPV6_ADD_MEMBERSHIP
181#ifdef IPV6_JOIN_GROUP
182#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
183#endif
184#endif
185
186#if TOX_INET6_ADDRSTRLEN < INET6_ADDRSTRLEN
187#error TOX_INET6_ADDRSTRLEN should be greater or equal to INET6_ADDRSTRLEN (#INET6_ADDRSTRLEN)
188#endif
189
190#if TOX_INET_ADDRSTRLEN < INET_ADDRSTRLEN
191#error TOX_INET_ADDRSTRLEN should be greater or equal to INET_ADDRSTRLEN (#INET_ADDRSTRLEN)
192#endif
193
194static int make_proto(int proto);
195static int make_socktype(int type);
196
197static int make_family(Family tox_family)
198{
199 switch (tox_family.value) {
200 case TOX_AF_INET:
201 return AF_INET;
202
203 case TOX_AF_INET6:
204 return AF_INET6;
205
206 case TOX_AF_UNSPEC:
207 return AF_UNSPEC;
208
209 default:
210 return tox_family.value;
211 }
212}
213
214static const Family *make_tox_family(int family)
215{
216 switch (family) {
217 case AF_INET:
218 return &net_family_ipv4;
219
220 case AF_INET6:
221 return &net_family_ipv6;
222
223 case AF_UNSPEC:
224 return &net_family_unspec;
225
226 default:
227 return nullptr;
228 }
229}
230
231static void get_ip4(IP4 *result, const struct in_addr *addr)
232{
233 result->uint32 = addr->s_addr;
234}
235
236static void get_ip6(IP6 *result, const struct in6_addr *addr)
237{
238 assert(sizeof(result->uint8) == sizeof(addr->s6_addr));
239 memcpy(result->uint8, addr->s6_addr, sizeof(result->uint8));
240}
241
242static void fill_addr4(IP4 ip, struct in_addr *addr)
243{
244 addr->s_addr = ip.uint32;
245}
246
247static void fill_addr6(IP6 ip, struct in6_addr *addr)
248{
249 assert(sizeof(ip.uint8) == sizeof(addr->s6_addr));
250 memcpy(addr->s6_addr, ip.uint8, sizeof(ip.uint8));
251}
252
253#if !defined(INADDR_LOOPBACK)
254#define INADDR_LOOPBACK 0x7f000001
255#endif
256
257const IP4 IP4_BROADCAST = { INADDR_BROADCAST };
258const IP6 IP6_BROADCAST = {
259 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
260};
261
262IP4 get_ip4_loopback(void)
263{
264 IP4 loopback;
265 loopback.uint32 = htonl(INADDR_LOOPBACK);
266 return loopback;
267}
268
269IP6 get_ip6_loopback(void)
270{
271 IP6 loopback;
272 get_ip6(&loopback, &in6addr_loopback);
273 return loopback;
274}
275
276const Socket net_invalid_socket = {
277#ifdef OS_WIN32
278 (int)INVALID_SOCKET,
279#else
280 -1,
281#endif
282};
283
284const Family net_family_unspec = {TOX_AF_UNSPEC};
285const Family net_family_ipv4 = {TOX_AF_INET};
286const Family net_family_ipv6 = {TOX_AF_INET6};
287const Family net_family_tcp_family = {TCP_FAMILY};
288const Family net_family_tcp_onion = {TCP_ONION_FAMILY};
289const Family net_family_tcp_ipv4 = {TCP_INET};
290const Family net_family_tcp_ipv6 = {TCP_INET6};
291const Family net_family_tox_tcp_ipv4 = {TOX_TCP_INET};
292const Family net_family_tox_tcp_ipv6 = {TOX_TCP_INET6};
293
294bool net_family_is_unspec(Family family)
295{
296 return family.value == net_family_unspec.value;
297}
298
299bool net_family_is_ipv4(Family family)
300{
301 return family.value == net_family_ipv4.value;
302}
303
304bool net_family_is_ipv6(Family family)
305{
306 return family.value == net_family_ipv6.value;
307}
308
309bool net_family_is_tcp_family(Family family)
310{
311 return family.value == net_family_tcp_family.value;
312}
313
314bool net_family_is_tcp_onion(Family family)
315{
316 return family.value == net_family_tcp_onion.value;
317}
318
319bool net_family_is_tcp_ipv4(Family family)
320{
321 return family.value == net_family_tcp_ipv4.value;
322}
323
324bool net_family_is_tcp_ipv6(Family family)
325{
326 return family.value == net_family_tcp_ipv6.value;
327}
328
329bool net_family_is_tox_tcp_ipv4(Family family)
330{
331 return family.value == net_family_tox_tcp_ipv4.value;
332}
333
334bool net_family_is_tox_tcp_ipv6(Family family)
335{
336 return family.value == net_family_tox_tcp_ipv6.value;
337}
338
114/* Check if socket is valid. 339/* Check if socket is valid.
115 * 340 *
116 * return 1 if valid 341 * return 1 if valid
117 * return 0 if not valid 342 * return 0 if not valid
118 */ 343 */
119int sock_valid(sock_t sock) 344int sock_valid(Socket sock)
120{ 345{
121#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) 346 return sock.socket != net_invalid_socket.socket;
122
123 if (sock == INVALID_SOCKET) {
124#else
125
126 if (sock < 0) {
127#endif
128 return 0;
129 }
130
131 return 1;
132} 347}
133 348
134/* Close the socket. 349/* Close the socket.
135 */ 350 */
136void kill_sock(sock_t sock) 351void kill_sock(Socket sock)
137{ 352{
138#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) 353#ifdef OS_WIN32
139 closesocket(sock); 354 closesocket(sock.socket);
140#else 355#else
141 close(sock); 356 close(sock.socket);
142#endif 357#endif
143} 358}
144 359
@@ -147,13 +362,13 @@ void kill_sock(sock_t sock)
147 * return 1 on success 362 * return 1 on success
148 * return 0 on failure 363 * return 0 on failure
149 */ 364 */
150int set_socket_nonblock(sock_t sock) 365int set_socket_nonblock(Socket sock)
151{ 366{
152#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) 367#ifdef OS_WIN32
153 u_long mode = 1; 368 u_long mode = 1;
154 return (ioctlsocket(sock, FIONBIO, &mode) == 0); 369 return (ioctlsocket(sock.socket, FIONBIO, &mode) == 0);
155#else 370#else
156 return (fcntl(sock, F_SETFL, O_NONBLOCK, 1) == 0); 371 return (fcntl(sock.socket, F_SETFL, O_NONBLOCK, 1) == 0);
157#endif 372#endif
158} 373}
159 374
@@ -162,11 +377,11 @@ int set_socket_nonblock(sock_t sock)
162 * return 1 on success 377 * return 1 on success
163 * return 0 on failure 378 * return 0 on failure
164 */ 379 */
165int set_socket_nosigpipe(sock_t sock) 380int set_socket_nosigpipe(Socket sock)
166{ 381{
167#if defined(__MACH__) 382#if defined(__APPLE__)
168 int set = 1; 383 int set = 1;
169 return (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)) == 0); 384 return setsockopt(sock.socket, SOL_SOCKET, SO_NOSIGPIPE, (const char *)&set, sizeof(int)) == 0;
170#else 385#else
171 return 1; 386 return 1;
172#endif 387#endif
@@ -177,10 +392,10 @@ int set_socket_nosigpipe(sock_t sock)
177 * return 1 on success 392 * return 1 on success
178 * return 0 on failure 393 * return 0 on failure
179 */ 394 */
180int set_socket_reuseaddr(sock_t sock) 395int set_socket_reuseaddr(Socket sock)
181{ 396{
182 int set = 1; 397 int set = 1;
183 return (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&set, sizeof(set)) == 0); 398 return setsockopt(sock.socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&set, sizeof(set)) == 0;
184} 399}
185 400
186/* Set socket to dual (IPv4 + IPv6 socket) 401/* Set socket to dual (IPv4 + IPv6 socket)
@@ -188,17 +403,18 @@ int set_socket_reuseaddr(sock_t sock)
188 * return 1 on success 403 * return 1 on success
189 * return 0 on failure 404 * return 0 on failure
190 */ 405 */
191int set_socket_dualstack(sock_t sock) 406int set_socket_dualstack(Socket sock)
192{ 407{
193 int ipv6only = 0; 408 int ipv6only = 0;
194 socklen_t optsize = sizeof(ipv6only); 409 socklen_t optsize = sizeof(ipv6only);
195 int res = getsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&ipv6only, &optsize); 410 int res = getsockopt(sock.socket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, &optsize);
196 411
197 if ((res == 0) && (ipv6only == 0)) 412 if ((res == 0) && (ipv6only == 0)) {
198 return 1; 413 return 1;
414 }
199 415
200 ipv6only = 0; 416 ipv6only = 0;
201 return (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&ipv6only, sizeof(ipv6only)) == 0); 417 return setsockopt(sock.socket, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&ipv6only, sizeof(ipv6only)) == 0;
202} 418}
203 419
204 420
@@ -206,7 +422,7 @@ int set_socket_dualstack(sock_t sock)
206static uint64_t current_time_actual(void) 422static uint64_t current_time_actual(void)
207{ 423{
208 uint64_t time; 424 uint64_t time;
209#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) 425#ifdef OS_WIN32
210 /* This probably works fine */ 426 /* This probably works fine */
211 FILETIME ft; 427 FILETIME ft;
212 GetSystemTimeAsFileTime(&ft); 428 GetSystemTimeAsFileTime(&ft);
@@ -217,14 +433,14 @@ static uint64_t current_time_actual(void)
217 return time / 10; 433 return time / 10;
218#else 434#else
219 struct timeval a; 435 struct timeval a;
220 gettimeofday(&a, NULL); 436 gettimeofday(&a, nullptr);
221 time = 1000000ULL * a.tv_sec + a.tv_usec; 437 time = 1000000ULL * a.tv_sec + a.tv_usec;
222 return time; 438 return time;
223#endif 439#endif
224} 440}
225 441
226 442
227#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) 443#ifdef OS_WIN32
228static uint64_t last_monotime; 444static uint64_t last_monotime;
229static uint64_t add_monotime; 445static uint64_t add_monotime;
230#endif 446#endif
@@ -233,12 +449,17 @@ static uint64_t add_monotime;
233uint64_t current_time_monotonic(void) 449uint64_t current_time_monotonic(void)
234{ 450{
235 uint64_t time; 451 uint64_t time;
236#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) 452#ifdef OS_WIN32
453 uint64_t old_add_monotime = add_monotime;
237 time = (uint64_t)GetTickCount() + add_monotime; 454 time = (uint64_t)GetTickCount() + add_monotime;
238 455
239 if (time < last_monotime) { /* Prevent time from ever decreasing because of 32 bit wrap. */ 456 /* Check if time has decreased because of 32 bit wrap from GetTickCount(), while avoiding false positives from race
457 * conditions when multiple threads call this function at once */
458 if (time + 0x10000 < last_monotime) {
240 uint32_t add = ~0; 459 uint32_t add = ~0;
241 add_monotime += add; 460 /* use old_add_monotime rather than simply incrementing add_monotime, to handle the case that many threads
461 * simultaneously detect an overflow */
462 add_monotime = old_add_monotime + add;
242 time += add; 463 time += add;
243 } 464 }
244 465
@@ -265,92 +486,127 @@ uint64_t current_time_monotonic(void)
265 return time; 486 return time;
266} 487}
267 488
268/* In case no logging */ 489static uint32_t data_0(uint16_t buflen, const uint8_t *buffer)
269#ifndef TOX_LOGGER 490{
270#define loglogdata(__message__, __buffer__, __buflen__, __ip_port__, __res__) 491 return buflen > 4 ? net_ntohl(*(const uint32_t *)&buffer[1]) : 0;
271#else 492}
272#define data_0(__buflen__, __buffer__) __buflen__ > 4 ? ntohl(*(uint32_t *)&__buffer__[1]) : 0 493static uint32_t data_1(uint16_t buflen, const uint8_t *buffer)
273#define data_1(__buflen__, __buffer__) __buflen__ > 7 ? ntohl(*(uint32_t *)&__buffer__[5]) : 0 494{
274 495 return buflen > 7 ? net_ntohl(*(const uint32_t *)&buffer[5]) : 0;
275#define loglogdata(__message__, __buffer__, __buflen__, __ip_port__, __res__) \ 496}
276 (__ip_port__) .ip; \ 497
277 if (__res__ < 0) /* Windows doesn't necessarily know %zu */ \ 498static void loglogdata(Logger *log, const char *message, const uint8_t *buffer,
278 LOGGER_TRACE("[%2u] %s %3hu%c %s:%hu (%u: %s) | %04x%04x", \ 499 uint16_t buflen, IP_Port ip_port, int res)
279 __buffer__[0], __message__, (__buflen__ < 999 ? (uint16_t)__buflen__ : 999), 'E', \ 500{
280 ip_ntoa(&((__ip_port__).ip)), ntohs((__ip_port__).port), errno, strerror(errno), data_0(__buflen__, __buffer__), data_1(__buflen__, __buffer__)); \ 501 char ip_str[IP_NTOA_LEN];
281 else if ((__res__ > 0) && ((size_t)__res__ <= __buflen__)) \ 502
282 LOGGER_TRACE("[%2u] %s %3zu%c %s:%hu (%u: %s) | %04x%04x", \ 503 if (res < 0) { /* Windows doesn't necessarily know %zu */
283 __buffer__[0], __message__, (__res__ < 999 ? (size_t)__res__ : 999), ((size_t)__res__ < __buflen__ ? '<' : '='), \ 504 int error = net_error();
284 ip_ntoa(&((__ip_port__).ip)), ntohs((__ip_port__).port), 0, "OK", data_0(__buflen__, __buffer__), data_1(__buflen__, __buffer__)); \ 505 const char *strerror = net_new_strerror(error);
285 else /* empty or overwrite */ \ 506 LOGGER_TRACE(log, "[%2u] %s %3u%c %s:%u (%u: %s) | %04x%04x",
286 LOGGER_TRACE("[%2u] %s %zu%c%zu %s:%hu (%u: %s) | %04x%04x", \ 507 buffer[0], message, (buflen < 999 ? buflen : 999), 'E',
287 __buffer__[0], __message__, (size_t)__res__, (!__res__ ? '!' : '>'), __buflen__, \ 508 ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port.port), error,
288 ip_ntoa(&((__ip_port__).ip)), ntohs((__ip_port__).port), 0, "OK", data_0(__buflen__, __buffer__), data_1(__buflen__, __buffer__)); 509 strerror, data_0(buflen, buffer), data_1(buflen, buffer));
289 510 net_kill_strerror(strerror);
290#endif /* TOX_LOGGER */ 511 } else if ((res > 0) && ((size_t)res <= buflen)) {
512 LOGGER_TRACE(log, "[%2u] %s %3u%c %s:%u (%u: %s) | %04x%04x",
513 buffer[0], message, (res < 999 ? res : 999), ((size_t)res < buflen ? '<' : '='),
514 ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port.port), 0, "OK",
515 data_0(buflen, buffer), data_1(buflen, buffer));
516 } else { /* empty or overwrite */
517 LOGGER_TRACE(log, "[%2u] %s %u%c%u %s:%u (%u: %s) | %04x%04x",
518 buffer[0], message, res, (!res ? '!' : '>'), buflen,
519 ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port.port), 0, "OK",
520 data_0(buflen, buffer), data_1(buflen, buffer));
521 }
522}
523
524typedef struct {
525 packet_handler_callback function;
526 void *object;
527} Packet_Handler;
528
529struct Networking_Core {
530 Logger *log;
531 Packet_Handler packethandlers[256];
532
533 Family family;
534 uint16_t port;
535 /* Our UDP socket. */
536 Socket sock;
537};
538
539Family net_family(const Networking_Core *net)
540{
541 return net->family;
542}
543
544uint16_t net_port(const Networking_Core *net)
545{
546 return net->port;
547}
291 548
292/* Basic network functions: 549/* Basic network functions:
293 * Function to send packet(data) of length length to ip_port. 550 * Function to send packet(data) of length length to ip_port.
294 */ 551 */
295int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint16_t length) 552int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint16_t length)
296{ 553{
297 if (net->family == 0) /* Socket not initialized */ 554 if (net_family_is_unspec(net->family)) { /* Socket not initialized */
555 LOGGER_ERROR(net->log, "attempted to send message of length %u on uninitialised socket", (unsigned)length);
298 return -1; 556 return -1;
557 }
299 558
300 /* socket AF_INET, but target IP NOT: can't send */ 559 /* socket TOX_AF_INET, but target IP NOT: can't send */
301 if ((net->family == AF_INET) && (ip_port.ip.family != AF_INET)) 560 if (net_family_is_ipv4(net->family) && !net_family_is_ipv4(ip_port.ip.family)) {
561 LOGGER_ERROR(net->log, "attempted to send message with network family %d (probably IPv6) on IPv4 socket",
562 ip_port.ip.family.value);
302 return -1; 563 return -1;
564 }
303 565
304 struct sockaddr_storage addr; 566 if (net_family_is_ipv4(ip_port.ip.family) && net_family_is_ipv6(net->family)) {
305 size_t addrsize = 0; 567 /* must convert to IPV4-in-IPV6 address */
568 IP6 ip6;
306 569
307 if (ip_port.ip.family == AF_INET) { 570 /* there should be a macro for this in a standards compliant
308 if (net->family == AF_INET6) { 571 * environment, not found */
309 /* must convert to IPV4-in-IPV6 address */ 572 ip6.uint32[0] = 0;
310 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; 573 ip6.uint32[1] = 0;
574 ip6.uint32[2] = net_htonl(0xFFFF);
575 ip6.uint32[3] = ip_port.ip.ip.v4.uint32;
311 576
312 addrsize = sizeof(struct sockaddr_in6); 577 ip_port.ip.family = net_family_ipv6;
313 addr6->sin6_family = AF_INET6; 578 ip_port.ip.ip.v6 = ip6;
314 addr6->sin6_port = ip_port.port; 579 }
315 580
316 /* there should be a macro for this in a standards compliant 581 struct sockaddr_storage addr;
317 * environment, not found */
318 IP6 ip6;
319 582
320 ip6.uint32[0] = 0; 583 size_t addrsize;
321 ip6.uint32[1] = 0;
322 ip6.uint32[2] = htonl(0xFFFF);
323 ip6.uint32[3] = ip_port.ip.ip4.uint32;
324 addr6->sin6_addr = ip6.in6_addr;
325 584
326 addr6->sin6_flowinfo = 0; 585 if (net_family_is_ipv4(ip_port.ip.family)) {
327 addr6->sin6_scope_id = 0; 586 struct sockaddr_in *const addr4 = (struct sockaddr_in *)&addr;
328 } else {
329 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
330 587
331 addrsize = sizeof(struct sockaddr_in); 588 addrsize = sizeof(struct sockaddr_in);
332 addr4->sin_family = AF_INET; 589 addr4->sin_family = AF_INET;
333 addr4->sin_addr = ip_port.ip.ip4.in_addr; 590 addr4->sin_port = ip_port.port;
334 addr4->sin_port = ip_port.port; 591 fill_addr4(ip_port.ip.ip.v4, &addr4->sin_addr);
335 } 592 } else if (net_family_is_ipv6(ip_port.ip.family)) {
336 } else if (ip_port.ip.family == AF_INET6) { 593 struct sockaddr_in6 *const addr6 = (struct sockaddr_in6 *)&addr;
337 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
338 594
339 addrsize = sizeof(struct sockaddr_in6); 595 addrsize = sizeof(struct sockaddr_in6);
340 addr6->sin6_family = AF_INET6; 596 addr6->sin6_family = AF_INET6;
341 addr6->sin6_port = ip_port.port; 597 addr6->sin6_port = ip_port.port;
342 addr6->sin6_addr = ip_port.ip.ip6.in6_addr; 598 fill_addr6(ip_port.ip.ip.v6, &addr6->sin6_addr);
343 599
344 addr6->sin6_flowinfo = 0; 600 addr6->sin6_flowinfo = 0;
345 addr6->sin6_scope_id = 0; 601 addr6->sin6_scope_id = 0;
346 } else { 602 } else {
347 /* unknown address type*/ 603 LOGGER_WARNING(net->log, "unknown address type: %d", ip_port.ip.family.value);
348 return -1; 604 return -1;
349 } 605 }
350 606
351 int res = sendto(net->sock, (char *) data, length, 0, (struct sockaddr *)&addr, addrsize); 607 const int res = sendto(net->sock.socket, (const char *) data, length, 0, (struct sockaddr *)&addr, addrsize);
352 608
353 loglogdata("O=>", data, length, ip_port, res); 609 loglogdata(net->log, "O=>", data, length, ip_port, res);
354 610
355 return res; 611 return res;
356} 612}
@@ -360,22 +616,26 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint1
360 * Packet data is put into data. 616 * Packet data is put into data.
361 * Packet length is put into length. 617 * Packet length is put into length.
362 */ 618 */
363static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t *length) 619static int receivepacket(Logger *log, Socket sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
364{ 620{
365 memset(ip_port, 0, sizeof(IP_Port)); 621 memset(ip_port, 0, sizeof(IP_Port));
366 struct sockaddr_storage addr; 622 struct sockaddr_storage addr;
367#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) 623#ifdef OS_WIN32
368 int addrlen = sizeof(addr); 624 int addrlen = sizeof(addr);
369#else 625#else
370 socklen_t addrlen = sizeof(addr); 626 socklen_t addrlen = sizeof(addr);
371#endif 627#endif
372 *length = 0; 628 *length = 0;
373 int fail_or_len = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen); 629 int fail_or_len = recvfrom(sock.socket, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen);
374 630
375 if (fail_or_len < 0) { 631 if (fail_or_len < 0) {
632 int error = net_error();
376 633
377 LOGGER_SCOPE( if ((fail_or_len < 0) && (errno != EWOULDBLOCK)) 634 if (fail_or_len < 0 && error != TOX_EWOULDBLOCK) {
378 LOGGER_ERROR("Unexpected error reading from socket: %u, %s\n", errno, strerror(errno)); ); 635 const char *strerror = net_new_strerror(error);
636 LOGGER_ERROR(log, "Unexpected error reading from socket: %u, %s", error, strerror);
637 net_kill_strerror(strerror);
638 }
379 639
380 return -1; /* Nothing received. */ 640 return -1; /* Nothing received. */
381 } 641 }
@@ -385,23 +645,38 @@ static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t
385 if (addr.ss_family == AF_INET) { 645 if (addr.ss_family == AF_INET) {
386 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr; 646 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
387 647
388 ip_port->ip.family = addr_in->sin_family; 648 const Family *const family = make_tox_family(addr_in->sin_family);
389 ip_port->ip.ip4.in_addr = addr_in->sin_addr; 649 assert(family != nullptr);
650
651 if (family == nullptr) {
652 return -1;
653 }
654
655 ip_port->ip.family = *family;
656 get_ip4(&ip_port->ip.ip.v4, &addr_in->sin_addr);
390 ip_port->port = addr_in->sin_port; 657 ip_port->port = addr_in->sin_port;
391 } else if (addr.ss_family == AF_INET6) { 658 } else if (addr.ss_family == AF_INET6) {
392 struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr; 659 struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr;
393 ip_port->ip.family = addr_in6->sin6_family; 660 const Family *const family = make_tox_family(addr_in6->sin6_family);
394 ip_port->ip.ip6.in6_addr = addr_in6->sin6_addr; 661 assert(family != nullptr);
662
663 if (family == nullptr) {
664 return -1;
665 }
666
667 ip_port->ip.family = *family;
668 get_ip6(&ip_port->ip.ip.v6, &addr_in6->sin6_addr);
395 ip_port->port = addr_in6->sin6_port; 669 ip_port->port = addr_in6->sin6_port;
396 670
397 if (IPV6_IPV4_IN_V6(ip_port->ip.ip6)) { 671 if (IPV6_IPV4_IN_V6(ip_port->ip.ip.v6)) {
398 ip_port->ip.family = AF_INET; 672 ip_port->ip.family = net_family_ipv4;
399 ip_port->ip.ip4.uint32 = ip_port->ip.ip6.uint32[3]; 673 ip_port->ip.ip.v4.uint32 = ip_port->ip.ip.v6.uint32[3];
400 } 674 }
401 } else 675 } else {
402 return -1; 676 return -1;
677 }
403 678
404 loglogdata("=>O", data, MAX_UDP_PACKET_SIZE, *ip_port, *length); 679 loglogdata(log, "=>O", data, MAX_UDP_PACKET_SIZE, *ip_port, *length);
405 680
406 return 0; 681 return 0;
407} 682}
@@ -412,10 +687,12 @@ void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handl
412 net->packethandlers[byte].object = object; 687 net->packethandlers[byte].object = object;
413} 688}
414 689
415void networking_poll(Networking_Core *net) 690void networking_poll(Networking_Core *net, void *userdata)
416{ 691{
417 if (net->family == 0) /* Socket not initialized */ 692 if (net_family_is_unspec(net->family)) {
693 /* Socket not initialized */
418 return; 694 return;
695 }
419 696
420 unix_time_update(); 697 unix_time_update();
421 698
@@ -423,15 +700,17 @@ void networking_poll(Networking_Core *net)
423 uint8_t data[MAX_UDP_PACKET_SIZE]; 700 uint8_t data[MAX_UDP_PACKET_SIZE];
424 uint32_t length; 701 uint32_t length;
425 702
426 while (receivepacket(net->sock, &ip_port, data, &length) != -1) { 703 while (receivepacket(net->log, net->sock, &ip_port, data, &length) != -1) {
427 if (length < 1) continue; 704 if (length < 1) {
705 continue;
706 }
428 707
429 if (!(net->packethandlers[data[0]].function)) { 708 if (!(net->packethandlers[data[0]].function)) {
430 LOGGER_WARNING("[%02u] -- Packet has no handler", data[0]); 709 LOGGER_WARNING(net->log, "[%02u] -- Packet has no handler", data[0]);
431 continue; 710 continue;
432 } 711 }
433 712
434 net->packethandlers[data[0]].function(net->packethandlers[data[0]].object, ip_port, data, length); 713 net->packethandlers[data[0]].function(net->packethandlers[data[0]].object, ip_port, data, length, userdata);
435 } 714 }
436} 715}
437 716
@@ -440,27 +719,33 @@ void networking_poll(Networking_Core *net)
440#include <sodium.h> 719#include <sodium.h>
441#endif 720#endif
442 721
443uint8_t at_startup_ran = 0; 722static uint8_t at_startup_ran = 0;
444int networking_at_startup(void) 723int networking_at_startup(void)
445{ 724{
446 if (at_startup_ran != 0) 725 if (at_startup_ran != 0) {
447 return 0; 726 return 0;
727 }
448 728
449#ifndef VANILLA_NACL 729#ifndef VANILLA_NACL
450 730
451#ifdef USE_RANDOMBYTES_STIR 731#ifdef USE_RANDOMBYTES_STIR
452 randombytes_stir(); 732 randombytes_stir();
453#else 733#else
454 sodium_init(); 734
735 if (sodium_init() == -1) {
736 return -1;
737 }
738
455#endif /*USE_RANDOMBYTES_STIR*/ 739#endif /*USE_RANDOMBYTES_STIR*/
456 740
457#endif/*VANILLA_NACL*/ 741#endif/*VANILLA_NACL*/
458 742
459#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) 743#ifdef OS_WIN32
460 WSADATA wsaData; 744 WSADATA wsaData;
461 745
462 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) 746 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) {
463 return -1; 747 return -1;
748 }
464 749
465#endif 750#endif
466 srand((uint32_t)current_time_actual()); 751 srand((uint32_t)current_time_actual());
@@ -468,21 +753,22 @@ int networking_at_startup(void)
468 return 0; 753 return 0;
469} 754}
470 755
471/* TODO: Put this somewhere 756/* TODO(irungentoo): Put this somewhere */
757#if 0
472static void at_shutdown(void) 758static void at_shutdown(void)
473{ 759{
474#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) 760#ifdef OS_WIN32
475 WSACleanup(); 761 WSACleanup();
476#endif 762#endif
477} 763}
478*/ 764#endif
479 765
480/* Initialize networking. 766/* Initialize networking.
481 * Added for reverse compatibility with old new_networking calls. 767 * Added for reverse compatibility with old new_networking calls.
482 */ 768 */
483Networking_Core *new_networking(IP ip, uint16_t port) 769Networking_Core *new_networking(Logger *log, IP ip, uint16_t port)
484{ 770{
485 return new_networking_ex(ip, port, port + (TOX_PORTRANGE_TO - TOX_PORTRANGE_FROM), 0); 771 return new_networking_ex(log, ip, port, port + (TOX_PORTRANGE_TO - TOX_PORTRANGE_FROM), nullptr);
486} 772}
487 773
488/* Initialize networking. 774/* Initialize networking.
@@ -495,7 +781,7 @@ Networking_Core *new_networking(IP ip, uint16_t port)
495 * 781 *
496 * If error is non NULL it is set to 0 if no issues, 1 if socket related error, 2 if other. 782 * If error is non NULL it is set to 0 if no issues, 1 if socket related error, 2 if other.
497 */ 783 */
498Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to, unsigned int *error) 784Networking_Core *new_networking_ex(Logger *log, IP ip, uint16_t port_from, uint16_t port_to, unsigned int *error)
499{ 785{
500 /* If both from and to are 0, use default port range 786 /* If both from and to are 0, use default port range
501 * If one is 0 and the other is non-0, use the non-0 value as only port 787 * If one is 0 and the other is non-0, use the non-0 value as only port
@@ -514,96 +800,104 @@ Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to,
514 port_to = temp; 800 port_to = temp;
515 } 801 }
516 802
517 if (error) 803 if (error) {
518 *error = 2; 804 *error = 2;
805 }
519 806
520 /* maybe check for invalid IPs like 224+.x.y.z? if there is any IP set ever */ 807 /* maybe check for invalid IPs like 224+.x.y.z? if there is any IP set ever */
521 if (ip.family != AF_INET && ip.family != AF_INET6) { 808 if (!net_family_is_ipv4(ip.family) && !net_family_is_ipv6(ip.family)) {
522#ifdef DEBUG 809 LOGGER_ERROR(log, "invalid address family: %u\n", ip.family.value);
523 fprintf(stderr, "Invalid address family: %u\n", ip.family); 810 return nullptr;
524#endif
525 return NULL;
526 } 811 }
527 812
528 if (networking_at_startup() != 0) 813 if (networking_at_startup() != 0) {
529 return NULL; 814 return nullptr;
815 }
530 816
531 Networking_Core *temp = calloc(1, sizeof(Networking_Core)); 817 Networking_Core *temp = (Networking_Core *)calloc(1, sizeof(Networking_Core));
532 818
533 if (temp == NULL) 819 if (temp == nullptr) {
534 return NULL; 820 return nullptr;
821 }
535 822
823 temp->log = log;
536 temp->family = ip.family; 824 temp->family = ip.family;
537 temp->port = 0; 825 temp->port = 0;
538 826
539 /* Initialize our socket. */ 827 /* Initialize our socket. */
540 /* add log message what we're creating */ 828 /* add log message what we're creating */
541 temp->sock = socket(temp->family, SOCK_DGRAM, IPPROTO_UDP); 829 temp->sock = net_socket(temp->family, TOX_SOCK_DGRAM, TOX_PROTO_UDP);
542 830
543 /* Check for socket error. */ 831 /* Check for socket error. */
544 if (!sock_valid(temp->sock)) { 832 if (!sock_valid(temp->sock)) {
545#ifdef DEBUG 833 int neterror = net_error();
546 fprintf(stderr, "Failed to get a socket?! %u, %s\n", errno, strerror(errno)); 834 const char *strerror = net_new_strerror(neterror);
547#endif 835 LOGGER_ERROR(log, "Failed to get a socket?! %d, %s", neterror, strerror);
836 net_kill_strerror(strerror);
548 free(temp); 837 free(temp);
549 838
550 if (error) 839 if (error) {
551 *error = 1; 840 *error = 1;
841 }
552 842
553 return NULL; 843 return nullptr;
554 } 844 }
555 845
556 /* Functions to increase the size of the send and receive UDP buffers. 846 /* Functions to increase the size of the send and receive UDP buffers.
557 */ 847 */
558 int n = 1024 * 1024 * 2; 848 int n = 1024 * 1024 * 2;
559 setsockopt(temp->sock, SOL_SOCKET, SO_RCVBUF, (char *)&n, sizeof(n)); 849 setsockopt(temp->sock.socket, SOL_SOCKET, SO_RCVBUF, (const char *)&n, sizeof(n));
560 setsockopt(temp->sock, SOL_SOCKET, SO_SNDBUF, (char *)&n, sizeof(n)); 850 setsockopt(temp->sock.socket, SOL_SOCKET, SO_SNDBUF, (const char *)&n, sizeof(n));
561 851
562 /* Enable broadcast on socket */ 852 /* Enable broadcast on socket */
563 int broadcast = 1; 853 int broadcast = 1;
564 setsockopt(temp->sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast)); 854 setsockopt(temp->sock.socket, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof(broadcast));
565 855
566 /* iOS UDP sockets are weird and apparently can SIGPIPE */ 856 /* iOS UDP sockets are weird and apparently can SIGPIPE */
567 if (!set_socket_nosigpipe(temp->sock)) { 857 if (!set_socket_nosigpipe(temp->sock)) {
568 kill_networking(temp); 858 kill_networking(temp);
569 859
570 if (error) 860 if (error) {
571 *error = 1; 861 *error = 1;
862 }
572 863
573 return NULL; 864 return nullptr;
574 } 865 }
575 866
576 /* Set socket nonblocking. */ 867 /* Set socket nonblocking. */
577 if (!set_socket_nonblock(temp->sock)) { 868 if (!set_socket_nonblock(temp->sock)) {
578 kill_networking(temp); 869 kill_networking(temp);
579 870
580 if (error) 871 if (error) {
581 *error = 1; 872 *error = 1;
873 }
582 874
583 return NULL; 875 return nullptr;
584 } 876 }
585 877
586 /* Bind our socket to port PORT and the given IP address (usually 0.0.0.0 or ::) */ 878 /* Bind our socket to port PORT and the given IP address (usually 0.0.0.0 or ::) */
587 uint16_t *portptr = NULL; 879 uint16_t *portptr = nullptr;
588 struct sockaddr_storage addr; 880 struct sockaddr_storage addr;
589 size_t addrsize; 881 size_t addrsize;
590 882
591 if (temp->family == AF_INET) { 883 memset(&addr, 0, sizeof(struct sockaddr_storage));
884
885 if (net_family_is_ipv4(temp->family)) {
592 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr; 886 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
593 887
594 addrsize = sizeof(struct sockaddr_in); 888 addrsize = sizeof(struct sockaddr_in);
595 addr4->sin_family = AF_INET; 889 addr4->sin_family = AF_INET;
596 addr4->sin_port = 0; 890 addr4->sin_port = 0;
597 addr4->sin_addr = ip.ip4.in_addr; 891 fill_addr4(ip.ip.v4, &addr4->sin_addr);
598 892
599 portptr = &addr4->sin_port; 893 portptr = &addr4->sin_port;
600 } else if (temp->family == AF_INET6) { 894 } else if (net_family_is_ipv6(temp->family)) {
601 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; 895 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
602 896
603 addrsize = sizeof(struct sockaddr_in6); 897 addrsize = sizeof(struct sockaddr_in6);
604 addr6->sin6_family = AF_INET6; 898 addr6->sin6_family = AF_INET6;
605 addr6->sin6_port = 0; 899 addr6->sin6_port = 0;
606 addr6->sin6_addr = ip.ip6.in6_addr; 900 fill_addr6(ip.ip.v6, &addr6->sin6_addr);
607 901
608 addr6->sin6_flowinfo = 0; 902 addr6->sin6_flowinfo = 0;
609 addr6->sin6_scope_id = 0; 903 addr6->sin6_scope_id = 0;
@@ -611,16 +905,13 @@ Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to,
611 portptr = &addr6->sin6_port; 905 portptr = &addr6->sin6_port;
612 } else { 906 } else {
613 free(temp); 907 free(temp);
614 return NULL; 908 return nullptr;
615 } 909 }
616 910
617 if (ip.family == AF_INET6) { 911 if (net_family_is_ipv6(ip.family)) {
618#ifdef TOX_LOGGER 912 const int is_dualstack = set_socket_dualstack(temp->sock);
619 int is_dualstack = 913 LOGGER_DEBUG(log, "Dual-stack socket: %s",
620#endif /* TOX_LOGGER */ 914 is_dualstack ? "enabled" : "Failed to enable, won't be able to receive from/send to IPv4 addresses");
621 set_socket_dualstack(temp->sock);
622 LOGGER_DEBUG( "Dual-stack socket: %s",
623 is_dualstack ? "enabled" : "Failed to enable, won't be able to receive from/send to IPv4 addresses" );
624 /* multicast local nodes */ 915 /* multicast local nodes */
625 struct ipv6_mreq mreq; 916 struct ipv6_mreq mreq;
626 memset(&mreq, 0, sizeof(mreq)); 917 memset(&mreq, 0, sizeof(mreq));
@@ -628,13 +919,13 @@ Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to,
628 mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02; 919 mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02;
629 mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01; 920 mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01;
630 mreq.ipv6mr_interface = 0; 921 mreq.ipv6mr_interface = 0;
631#ifdef TOX_LOGGER 922 const int res = setsockopt(temp->sock.socket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (const char *)&mreq, sizeof(mreq));
632 int res =
633#endif /* TOX_LOGGER */
634 setsockopt(temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq));
635 923
636 LOGGER_DEBUG(res < 0 ? "Failed to activate local multicast membership. (%u, %s)" : 924 int neterror = net_error();
637 "Local multicast group FF02::1 joined successfully", errno, strerror(errno) ); 925 const char *strerror = net_new_strerror(neterror);
926 LOGGER_DEBUG(log, res < 0 ? "Failed to activate local multicast membership. (%d, %s)" :
927 "Local multicast group FF02::1 joined successfully", neterror, strerror);
928 net_kill_strerror(strerror);
638 } 929 }
639 930
640 /* a hanging program or a different user might block the standard port; 931 /* a hanging program or a different user might block the standard port;
@@ -654,59 +945,84 @@ Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to,
654 * it worked ok (which it did previously without a successful bind) 945 * it worked ok (which it did previously without a successful bind)
655 */ 946 */
656 uint16_t port_to_try = port_from; 947 uint16_t port_to_try = port_from;
657 *portptr = htons(port_to_try); 948 *portptr = net_htons(port_to_try);
658 int tries; 949 int tries;
659 950
660 for (tries = port_from; tries <= port_to; tries++) { 951 for (tries = port_from; tries <= port_to; tries++) {
661 int res = bind(temp->sock, (struct sockaddr *)&addr, addrsize); 952 int res = bind(temp->sock.socket, (struct sockaddr *)&addr, addrsize);
662 953
663 if (!res) { 954 if (!res) {
664 temp->port = *portptr; 955 temp->port = *portptr;
665 956
666 LOGGER_DEBUG("Bound successfully to %s:%u", ip_ntoa(&ip), ntohs(temp->port)); 957 char ip_str[IP_NTOA_LEN];
958 LOGGER_DEBUG(log, "Bound successfully to %s:%u", ip_ntoa(&ip, ip_str, sizeof(ip_str)),
959 net_ntohs(temp->port));
667 960
668 /* errno isn't reset on success, only set on failure, the failed 961 /* errno isn't reset on success, only set on failure, the failed
669 * binds with parallel clients yield a -EPERM to the outside if 962 * binds with parallel clients yield a -EPERM to the outside if
670 * errno isn't cleared here */ 963 * errno isn't cleared here */
671 if (tries > 0) 964 if (tries > 0) {
672 errno = 0; 965 errno = 0;
966 }
673 967
674 if (error) 968 if (error) {
675 *error = 0; 969 *error = 0;
970 }
676 971
677 return temp; 972 return temp;
678 } 973 }
679 974
680 port_to_try++; 975 port_to_try++;
681 976
682 if (port_to_try > port_to) 977 if (port_to_try > port_to) {
683 port_to_try = port_from; 978 port_to_try = port_from;
979 }
684 980
685 *portptr = htons(port_to_try); 981 *portptr = net_htons(port_to_try);
686 } 982 }
687 983
688 LOGGER_ERROR("Failed to bind socket: %u, %s IP: %s port_from: %u port_to: %u", errno, strerror(errno), 984 char ip_str[IP_NTOA_LEN];
689 ip_ntoa(&ip), port_from, port_to); 985 int neterror = net_error();
690 986 const char *strerror = net_new_strerror(neterror);
987 LOGGER_ERROR(log, "Failed to bind socket: %d, %s IP: %s port_from: %u port_to: %u", neterror, strerror,
988 ip_ntoa(&ip, ip_str, sizeof(ip_str)), port_from, port_to);
989 net_kill_strerror(strerror);
691 kill_networking(temp); 990 kill_networking(temp);
692 991
693 if (error) 992 if (error) {
694 *error = 1; 993 *error = 1;
994 }
995
996 return nullptr;
997}
695 998
696 return NULL; 999Networking_Core *new_networking_no_udp(Logger *log)
1000{
1001 /* this is the easiest way to completely disable UDP without changing too much code. */
1002 Networking_Core *net = (Networking_Core *)calloc(1, sizeof(Networking_Core));
1003
1004 if (net == nullptr) {
1005 return nullptr;
1006 }
1007
1008 net->log = log;
1009
1010 return net;
697} 1011}
698 1012
699/* Function to cleanup networking stuff. */ 1013/* Function to cleanup networking stuff. */
700void kill_networking(Networking_Core *net) 1014void kill_networking(Networking_Core *net)
701{ 1015{
702 if (!net) 1016 if (!net) {
703 return; 1017 return;
1018 }
704 1019
705 if (net->family != 0) /* Socket not initialized */ 1020 if (!net_family_is_unspec(net->family)) {
1021 /* Socket is initialized, so we close it. */
706 kill_sock(net->sock); 1022 kill_sock(net->sock);
1023 }
707 1024
708 free(net); 1025 free(net);
709 return;
710} 1026}
711 1027
712 1028
@@ -718,26 +1034,41 @@ void kill_networking(Networking_Core *net)
718 */ 1034 */
719int ip_equal(const IP *a, const IP *b) 1035int ip_equal(const IP *a, const IP *b)
720{ 1036{
721 if (!a || !b) 1037 if (!a || !b) {
722 return 0; 1038 return 0;
1039 }
723 1040
724 /* same family */ 1041 /* same family */
725 if (a->family == b->family) { 1042 if (a->family.value == b->family.value) {
726 if (a->family == AF_INET) 1043 if (net_family_is_ipv4(a->family) || net_family_is_tcp_ipv4(a->family)) {
727 return (a->ip4.in_addr.s_addr == b->ip4.in_addr.s_addr); 1044 struct in_addr addr_a;
728 else if (a->family == AF_INET6) 1045 struct in_addr addr_b;
729 return a->ip6.uint64[0] == b->ip6.uint64[0] && a->ip6.uint64[1] == b->ip6.uint64[1]; 1046 fill_addr4(a->ip.v4, &addr_a);
730 else 1047 fill_addr4(b->ip.v4, &addr_b);
731 return 0; 1048 return addr_a.s_addr == addr_b.s_addr;
1049 }
1050
1051 if (net_family_is_ipv6(a->family) || net_family_is_tcp_ipv6(a->family)) {
1052 return a->ip.v6.uint64[0] == b->ip.v6.uint64[0] &&
1053 a->ip.v6.uint64[1] == b->ip.v6.uint64[1];
1054 }
1055
1056 return 0;
732 } 1057 }
733 1058
734 /* different family: check on the IPv6 one if it is the IPv4 one embedded */ 1059 /* different family: check on the IPv6 one if it is the IPv4 one embedded */
735 if ((a->family == AF_INET) && (b->family == AF_INET6)) { 1060 if (net_family_is_ipv4(a->family) && net_family_is_ipv6(b->family)) {
736 if (IPV6_IPV4_IN_V6(b->ip6)) 1061 if (IPV6_IPV4_IN_V6(b->ip.v6)) {
737 return (a->ip4.in_addr.s_addr == b->ip6.uint32[3]); 1062 struct in_addr addr_a;
738 } else if ((a->family == AF_INET6) && (b->family == AF_INET)) { 1063 fill_addr4(a->ip.v4, &addr_a);
739 if (IPV6_IPV4_IN_V6(a->ip6)) 1064 return addr_a.s_addr == b->ip.v6.uint32[3];
740 return (a->ip6.uint32[3] == b->ip4.in_addr.s_addr); 1065 }
1066 } else if (net_family_is_ipv6(a->family) && net_family_is_ipv4(b->family)) {
1067 if (IPV6_IPV4_IN_V6(a->ip.v6)) {
1068 struct in_addr addr_b;
1069 fill_addr4(b->ip.v4, &addr_b);
1070 return a->ip.v6.uint32[3] == addr_b.s_addr;
1071 }
741 } 1072 }
742 1073
743 return 0; 1074 return 0;
@@ -751,11 +1082,13 @@ int ip_equal(const IP *a, const IP *b)
751 */ 1082 */
752int ipport_equal(const IP_Port *a, const IP_Port *b) 1083int ipport_equal(const IP_Port *a, const IP_Port *b)
753{ 1084{
754 if (!a || !b) 1085 if (!a || !b) {
755 return 0; 1086 return 0;
1087 }
756 1088
757 if (!a->port || (a->port != b->port)) 1089 if (!a->port || (a->port != b->port)) {
758 return 0; 1090 return 0;
1091 }
759 1092
760 return ip_equal(&a->ip, &b->ip); 1093 return ip_equal(&a->ip, &b->ip);
761} 1094}
@@ -763,39 +1096,44 @@ int ipport_equal(const IP_Port *a, const IP_Port *b)
763/* nulls out ip */ 1096/* nulls out ip */
764void ip_reset(IP *ip) 1097void ip_reset(IP *ip)
765{ 1098{
766 if (!ip) 1099 if (!ip) {
767 return; 1100 return;
1101 }
768 1102
769 memset(ip, 0, sizeof(IP)); 1103 memset(ip, 0, sizeof(IP));
770} 1104}
771 1105
772/* nulls out ip, sets family according to flag */ 1106/* nulls out ip, sets family according to flag */
773void ip_init(IP *ip, uint8_t ipv6enabled) 1107void ip_init(IP *ip, bool ipv6enabled)
774{ 1108{
775 if (!ip) 1109 if (!ip) {
776 return; 1110 return;
1111 }
777 1112
778 memset(ip, 0, sizeof(IP)); 1113 memset(ip, 0, sizeof(IP));
779 ip->family = ipv6enabled ? AF_INET6 : AF_INET; 1114 ip->family = ipv6enabled ? net_family_ipv6 : net_family_ipv4;
780} 1115}
781 1116
782/* checks if ip is valid */ 1117/* checks if ip is valid */
783int ip_isset(const IP *ip) 1118bool ip_isset(const IP *ip)
784{ 1119{
785 if (!ip) 1120 if (!ip) {
786 return 0; 1121 return false;
1122 }
787 1123
788 return (ip->family != 0); 1124 return !net_family_is_unspec(ip->family);
789} 1125}
790 1126
791/* checks if ip is valid */ 1127/* checks if ip is valid */
792int ipport_isset(const IP_Port *ipport) 1128bool ipport_isset(const IP_Port *ipport)
793{ 1129{
794 if (!ipport) 1130 if (!ipport) {
795 return 0; 1131 return false;
1132 }
796 1133
797 if (!ipport->port) 1134 if (!ipport->port) {
798 return 0; 1135 return false;
1136 }
799 1137
800 return ip_isset(&ipport->ip); 1138 return ip_isset(&ipport->ip);
801} 1139}
@@ -803,8 +1141,9 @@ int ipport_isset(const IP_Port *ipport)
803/* copies an ip structure (careful about direction!) */ 1141/* copies an ip structure (careful about direction!) */
804void ip_copy(IP *target, const IP *source) 1142void ip_copy(IP *target, const IP *source)
805{ 1143{
806 if (!source || !target) 1144 if (!source || !target) {
807 return; 1145 return;
1146 }
808 1147
809 memcpy(target, source, sizeof(IP)); 1148 memcpy(target, source, sizeof(IP));
810} 1149}
@@ -812,47 +1151,59 @@ void ip_copy(IP *target, const IP *source)
812/* copies an ip_port structure (careful about direction!) */ 1151/* copies an ip_port structure (careful about direction!) */
813void ipport_copy(IP_Port *target, const IP_Port *source) 1152void ipport_copy(IP_Port *target, const IP_Port *source)
814{ 1153{
815 if (!source || !target) 1154 if (!source || !target) {
816 return; 1155 return;
1156 }
817 1157
818 memcpy(target, source, sizeof(IP_Port)); 1158 memcpy(target, source, sizeof(IP_Port));
819} 1159}
820 1160
821/* ip_ntoa 1161/* ip_ntoa
822 * converts ip into a string 1162 * converts ip into a string
823 * uses a static buffer, so mustn't used multiple times in the same output 1163 * ip_str must be of length at least IP_NTOA_LEN
824 * 1164 *
825 * IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]" 1165 * IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]"
826 * writes error message into the buffer on error 1166 * writes error message into the buffer on error
1167 *
1168 * returns ip_str
827 */ 1169 */
828/* there would be INET6_ADDRSTRLEN, but it might be too short for the error message */ 1170const char *ip_ntoa(const IP *ip, char *ip_str, size_t length)
829static char addresstext[96]; // FIXME magic number. Why not INET6_ADDRSTRLEN ?
830const char *ip_ntoa(const IP *ip)
831{ 1171{
1172 if (length < IP_NTOA_LEN) {
1173 snprintf(ip_str, length, "Bad buf length");
1174 return ip_str;
1175 }
1176
832 if (ip) { 1177 if (ip) {
833 if (ip->family == AF_INET) { 1178 const int family = make_family(ip->family);
1179
1180 if (net_family_is_ipv4(ip->family)) {
834 /* returns standard quad-dotted notation */ 1181 /* returns standard quad-dotted notation */
835 struct in_addr *addr = (struct in_addr *)&ip->ip4; 1182 struct in_addr addr;
1183 fill_addr4(ip->ip.v4, &addr);
836 1184
837 addresstext[0] = 0; 1185 ip_str[0] = 0;
838 inet_ntop(ip->family, addr, addresstext, sizeof(addresstext)); 1186 inet_ntop(family, &addr, ip_str, length);
839 } else if (ip->family == AF_INET6) { 1187 } else if (net_family_is_ipv6(ip->family)) {
840 /* returns hex-groups enclosed into square brackets */ 1188 /* returns hex-groups enclosed into square brackets */
841 struct in6_addr *addr = (struct in6_addr *)&ip->ip6; 1189 struct in6_addr addr;
842 1190 fill_addr6(ip->ip.v6, &addr);
843 addresstext[0] = '['; 1191
844 inet_ntop(ip->family, addr, &addresstext[1], sizeof(addresstext) - 3); 1192 ip_str[0] = '[';
845 size_t len = strlen(addresstext); 1193 inet_ntop(family, &addr, &ip_str[1], length - 3);
846 addresstext[len] = ']'; 1194 size_t len = strlen(ip_str);
847 addresstext[len + 1] = 0; 1195 ip_str[len] = ']';
848 } else 1196 ip_str[len + 1] = 0;
849 snprintf(addresstext, sizeof(addresstext), "(IP invalid, family %u)", ip->family); 1197 } else {
850 } else 1198 snprintf(ip_str, length, "(IP invalid, family %u)", ip->family.value);
851 snprintf(addresstext, sizeof(addresstext), "(IP invalid: NULL)"); 1199 }
1200 } else {
1201 snprintf(ip_str, length, "(IP invalid: NULL)");
1202 }
852 1203
853 /* brute force protection against lacking termination */ 1204 /* brute force protection against lacking termination */
854 addresstext[sizeof(addresstext) - 1] = 0; 1205 ip_str[length - 1] = 0;
855 return addresstext; 1206 return ip_str;
856} 1207}
857 1208
858/* 1209/*
@@ -860,10 +1211,10 @@ const char *ip_ntoa(const IP *ip)
860 * parses IP structure into an address string 1211 * parses IP structure into an address string
861 * 1212 *
862 * input 1213 * input
863 * ip: ip of AF_INET or AF_INET6 families 1214 * ip: ip of TOX_AF_INET or TOX_AF_INET6 families
864 * length: length of the address buffer 1215 * length: length of the address buffer
865 * Must be at least INET_ADDRSTRLEN for AF_INET 1216 * Must be at least INET_ADDRSTRLEN for TOX_AF_INET
866 * and INET6_ADDRSTRLEN for AF_INET6 1217 * and INET6_ADDRSTRLEN for TOX_AF_INET6
867 * 1218 *
868 * output 1219 * output
869 * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6) 1220 * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6)
@@ -876,12 +1227,14 @@ int ip_parse_addr(const IP *ip, char *address, size_t length)
876 return 0; 1227 return 0;
877 } 1228 }
878 1229
879 if (ip->family == AF_INET) { 1230 if (net_family_is_ipv4(ip->family)) {
880 struct in_addr *addr = (struct in_addr *)&ip->ip4; 1231 const struct in_addr *addr = (const struct in_addr *)&ip->ip.v4;
881 return inet_ntop(ip->family, addr, address, length) != NULL; 1232 return inet_ntop(make_family(ip->family), addr, address, length) != nullptr;
882 } else if (ip->family == AF_INET6) { 1233 }
883 struct in6_addr *addr = (struct in6_addr *)&ip->ip6; 1234
884 return inet_ntop(ip->family, addr, address, length) != NULL; 1235 if (net_family_is_ipv6(ip->family)) {
1236 const struct in6_addr *addr = (const struct in6_addr *)&ip->ip.v6;
1237 return inet_ntop(make_family(ip->family), addr, address, length) != nullptr;
885 } 1238 }
886 1239
887 return 0; 1240 return 0;
@@ -902,22 +1255,23 @@ int ip_parse_addr(const IP *ip, char *address, size_t length)
902 */ 1255 */
903int addr_parse_ip(const char *address, IP *to) 1256int addr_parse_ip(const char *address, IP *to)
904{ 1257{
905 if (!address || !to) 1258 if (!address || !to) {
906 return 0; 1259 return 0;
1260 }
907 1261
908 struct in_addr addr4; 1262 struct in_addr addr4;
909 1263
910 if (1 == inet_pton(AF_INET, address, &addr4)) { 1264 if (inet_pton(AF_INET, address, &addr4) == 1) {
911 to->family = AF_INET; 1265 to->family = net_family_ipv4;
912 to->ip4.in_addr = addr4; 1266 get_ip4(&to->ip.v4, &addr4);
913 return 1; 1267 return 1;
914 } 1268 }
915 1269
916 struct in6_addr addr6; 1270 struct in6_addr addr6;
917 1271
918 if (1 == inet_pton(AF_INET6, address, &addr6)) { 1272 if (inet_pton(AF_INET6, address, &addr6) == 1) {
919 to->family = AF_INET6; 1273 to->family = net_family_ipv6;
920 to->ip6.in6_addr = addr6; 1274 get_ip6(&to->ip.v6, &addr6);
921 return 1; 1275 return 1;
922 } 1276 }
923 1277
@@ -932,24 +1286,26 @@ int addr_parse_ip(const char *address, IP *to)
932 * input 1286 * input
933 * address: a hostname (or something parseable to an IP address) 1287 * address: a hostname (or something parseable to an IP address)
934 * to: to.family MUST be initialized, either set to a specific IP version 1288 * to: to.family MUST be initialized, either set to a specific IP version
935 * (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both 1289 * (TOX_AF_INET/TOX_AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both
936 * IP versions are acceptable 1290 * IP versions are acceptable
937 * extra can be NULL and is only set in special circumstances, see returns 1291 * extra can be NULL and is only set in special circumstances, see returns
938 * 1292 *
939 * returns in *to a valid IPAny (v4/v6), 1293 * returns in *to a valid IPAny (v4/v6),
940 * prefers v6 if ip.family was AF_UNSPEC and both available 1294 * prefers v6 if ip.family was AF_UNSPEC and both available
941 * returns in *extra an IPv4 address, if family was AF_UNSPEC and *to is AF_INET6 1295 * returns in *extra an IPv4 address, if family was AF_UNSPEC and *to is TOX_AF_INET6
942 * returns 0 on failure, TOX_ADDR_RESOLVE_* on success. 1296 * returns 0 on failure, TOX_ADDR_RESOLVE_* on success.
943 */ 1297 */
944int addr_resolve(const char *address, IP *to, IP *extra) 1298int addr_resolve(const char *address, IP *to, IP *extra)
945{ 1299{
946 if (!address || !to) 1300 if (!address || !to) {
947 return 0; 1301 return 0;
1302 }
948 1303
949 sa_family_t family = to->family; 1304 Family tox_family = to->family;
1305 int family = make_family(tox_family);
950 1306
951 struct addrinfo *server = NULL; 1307 struct addrinfo *server = nullptr;
952 struct addrinfo *walker = NULL; 1308 struct addrinfo *walker = nullptr;
953 struct addrinfo hints; 1309 struct addrinfo hints;
954 int rc; 1310 int rc;
955 int result = 0; 1311 int result = 0;
@@ -959,10 +1315,11 @@ int addr_resolve(const char *address, IP *to, IP *extra)
959 hints.ai_family = family; 1315 hints.ai_family = family;
960 hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses. 1316 hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
961 1317
962 if (networking_at_startup() != 0) 1318 if (networking_at_startup() != 0) {
963 return 0; 1319 return 0;
1320 }
964 1321
965 rc = getaddrinfo(address, NULL, &hints, &server); 1322 rc = getaddrinfo(address, nullptr, &hints, &server);
966 1323
967 // Lookup failed. 1324 // Lookup failed.
968 if (rc != 0) { 1325 if (rc != 0) {
@@ -974,17 +1331,17 @@ int addr_resolve(const char *address, IP *to, IP *extra)
974 IP ip6; 1331 IP ip6;
975 ip_init(&ip6, 1); // ipv6enabled = 1 1332 ip_init(&ip6, 1); // ipv6enabled = 1
976 1333
977 for (walker = server; (walker != NULL) && !done; walker = walker->ai_next) { 1334 for (walker = server; (walker != nullptr) && !done; walker = walker->ai_next) {
978 switch (walker->ai_family) { 1335 switch (walker->ai_family) {
979 case AF_INET: 1336 case AF_INET:
980 if (walker->ai_family == family) { /* AF_INET requested, done */ 1337 if (walker->ai_family == family) { /* AF_INET requested, done */
981 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr; 1338 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
982 to->ip4.in_addr = addr->sin_addr; 1339 get_ip4(&to->ip.v4, &addr->sin_addr);
983 result = TOX_ADDR_RESOLVE_INET; 1340 result = TOX_ADDR_RESOLVE_INET;
984 done = 1; 1341 done = 1;
985 } else if (!(result & TOX_ADDR_RESOLVE_INET)) { /* AF_UNSPEC requested, store away */ 1342 } else if (!(result & TOX_ADDR_RESOLVE_INET)) { /* AF_UNSPEC requested, store away */
986 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr; 1343 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
987 ip4.ip4.in_addr = addr->sin_addr; 1344 get_ip4(&ip4.ip.v4, &addr->sin_addr);
988 result |= TOX_ADDR_RESOLVE_INET; 1345 result |= TOX_ADDR_RESOLVE_INET;
989 } 1346 }
990 1347
@@ -994,14 +1351,14 @@ int addr_resolve(const char *address, IP *to, IP *extra)
994 if (walker->ai_family == family) { /* AF_INET6 requested, done */ 1351 if (walker->ai_family == family) { /* AF_INET6 requested, done */
995 if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) { 1352 if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
996 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr; 1353 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr;
997 to->ip6.in6_addr = addr->sin6_addr; 1354 get_ip6(&to->ip.v6, &addr->sin6_addr);
998 result = TOX_ADDR_RESOLVE_INET6; 1355 result = TOX_ADDR_RESOLVE_INET6;
999 done = 1; 1356 done = 1;
1000 } 1357 }
1001 } else if (!(result & TOX_ADDR_RESOLVE_INET6)) { /* AF_UNSPEC requested, store away */ 1358 } else if (!(result & TOX_ADDR_RESOLVE_INET6)) { /* AF_UNSPEC requested, store away */
1002 if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) { 1359 if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
1003 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr; 1360 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr;
1004 ip6.ip6.in6_addr = addr->sin6_addr; 1361 get_ip6(&ip6.ip.v6, &addr->sin6_addr);
1005 result |= TOX_ADDR_RESOLVE_INET6; 1362 result |= TOX_ADDR_RESOLVE_INET6;
1006 } 1363 }
1007 } 1364 }
@@ -1014,7 +1371,7 @@ int addr_resolve(const char *address, IP *to, IP *extra)
1014 if (result & TOX_ADDR_RESOLVE_INET6) { 1371 if (result & TOX_ADDR_RESOLVE_INET6) {
1015 ip_copy(to, &ip6); 1372 ip_copy(to, &ip6);
1016 1373
1017 if ((result & TOX_ADDR_RESOLVE_INET) && (extra != NULL)) { 1374 if ((result & TOX_ADDR_RESOLVE_INET) && (extra != nullptr)) {
1018 ip_copy(extra, &ip4); 1375 ip_copy(extra, &ip4);
1019 } 1376 }
1020 } else if (result & TOX_ADDR_RESOLVE_INET) { 1377 } else if (result & TOX_ADDR_RESOLVE_INET) {
@@ -1034,7 +1391,7 @@ int addr_resolve(const char *address, IP *to, IP *extra)
1034 * 1391 *
1035 * address: a hostname (or something parseable to an IP address) 1392 * address: a hostname (or something parseable to an IP address)
1036 * to: to.family MUST be initialized, either set to a specific IP version 1393 * to: to.family MUST be initialized, either set to a specific IP version
1037 * (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both 1394 * (TOX_AF_INET/TOX_AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both
1038 * IP versions are acceptable 1395 * IP versions are acceptable
1039 * extra can be NULL and is only set in special circumstances, see returns 1396 * extra can be NULL and is only set in special circumstances, see returns
1040 * 1397 *
@@ -1045,9 +1402,323 @@ int addr_resolve(const char *address, IP *to, IP *extra)
1045 */ 1402 */
1046int addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra) 1403int addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra)
1047{ 1404{
1048 if (!addr_resolve(address, to, extra)) 1405 if (!addr_resolve(address, to, extra)) {
1049 if (!addr_parse_ip(address, to)) 1406 if (!addr_parse_ip(address, to)) {
1050 return 0; 1407 return 0;
1408 }
1409 }
1051 1410
1052 return 1; 1411 return 1;
1053} 1412}
1413
1414int net_connect(Socket sock, IP_Port ip_port)
1415{
1416 struct sockaddr_storage addr = {0};
1417 size_t addrsize;
1418
1419 if (net_family_is_ipv4(ip_port.ip.family)) {
1420 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
1421
1422 addrsize = sizeof(struct sockaddr_in);
1423 addr4->sin_family = AF_INET;
1424 fill_addr4(ip_port.ip.ip.v4, &addr4->sin_addr);
1425 addr4->sin_port = ip_port.port;
1426 } else if (net_family_is_ipv6(ip_port.ip.family)) {
1427 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
1428
1429 addrsize = sizeof(struct sockaddr_in6);
1430 addr6->sin6_family = AF_INET6;
1431 fill_addr6(ip_port.ip.ip.v6, &addr6->sin6_addr);
1432 addr6->sin6_port = ip_port.port;
1433 } else {
1434 return 0;
1435 }
1436
1437 return connect(sock.socket, (struct sockaddr *)&addr, addrsize);
1438}
1439
1440int32_t net_getipport(const char *node, IP_Port **res, int tox_type)
1441{
1442 struct addrinfo *infos;
1443 int ret = getaddrinfo(node, nullptr, nullptr, &infos);
1444 *res = nullptr;
1445
1446 if (ret != 0) {
1447 return -1;
1448 }
1449
1450 // Used to avoid malloc parameter overflow
1451 const size_t MAX_COUNT = MIN(SIZE_MAX, INT32_MAX) / sizeof(IP_Port);
1452 int type = make_socktype(tox_type);
1453 struct addrinfo *cur;
1454 size_t count = 0;
1455
1456 for (cur = infos; count < MAX_COUNT && cur != nullptr; cur = cur->ai_next) {
1457 if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {
1458 continue;
1459 }
1460
1461 if (cur->ai_family != AF_INET && cur->ai_family != AF_INET6) {
1462 continue;
1463 }
1464
1465 count++;
1466 }
1467
1468 assert(count <= MAX_COUNT);
1469
1470 if (count == 0) {
1471 freeaddrinfo(infos);
1472 return 0;
1473 }
1474
1475 *res = (IP_Port *)malloc(sizeof(IP_Port) * count);
1476
1477 if (*res == nullptr) {
1478 freeaddrinfo(infos);
1479 return -1;
1480 }
1481
1482 IP_Port *ip_port = *res;
1483
1484 for (cur = infos; cur != nullptr; cur = cur->ai_next) {
1485 if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {
1486 continue;
1487 }
1488
1489 if (cur->ai_family == AF_INET) {
1490 struct sockaddr_in *addr = (struct sockaddr_in *)cur->ai_addr;
1491 memcpy(&ip_port->ip.ip.v4, &addr->sin_addr, sizeof(IP4));
1492 } else if (cur->ai_family == AF_INET6) {
1493 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)cur->ai_addr;
1494 memcpy(&ip_port->ip.ip.v6, &addr->sin6_addr, sizeof(IP6));
1495 } else {
1496 continue;
1497 }
1498
1499 const Family *const family = make_tox_family(cur->ai_family);
1500 assert(family != nullptr);
1501
1502 if (family == nullptr) {
1503 freeaddrinfo(infos);
1504 return -1;
1505 }
1506
1507 ip_port->ip.family = *family;
1508
1509 ip_port++;
1510 }
1511
1512 freeaddrinfo(infos);
1513
1514 return count;
1515}
1516
1517void net_freeipport(IP_Port *ip_ports)
1518{
1519 free(ip_ports);
1520}
1521
1522/* return 1 on success
1523 * return 0 on failure
1524 */
1525int bind_to_port(Socket sock, Family family, uint16_t port)
1526{
1527 struct sockaddr_storage addr = {0};
1528 size_t addrsize;
1529
1530 if (net_family_is_ipv4(family)) {
1531 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
1532
1533 addrsize = sizeof(struct sockaddr_in);
1534 addr4->sin_family = AF_INET;
1535 addr4->sin_port = net_htons(port);
1536 } else if (net_family_is_ipv6(family)) {
1537 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
1538
1539 addrsize = sizeof(struct sockaddr_in6);
1540 addr6->sin6_family = AF_INET6;
1541 addr6->sin6_port = net_htons(port);
1542 } else {
1543 return 0;
1544 }
1545
1546 return bind(sock.socket, (struct sockaddr *)&addr, addrsize) == 0;
1547}
1548
1549static int make_socktype(int type)
1550{
1551 switch (type) {
1552 case TOX_SOCK_STREAM:
1553 return SOCK_STREAM;
1554
1555 case TOX_SOCK_DGRAM:
1556 return SOCK_DGRAM;
1557
1558 default:
1559 return type;
1560 }
1561}
1562
1563static int make_proto(int proto)
1564{
1565 switch (proto) {
1566 case TOX_PROTO_TCP:
1567 return IPPROTO_TCP;
1568
1569 case TOX_PROTO_UDP:
1570 return IPPROTO_UDP;
1571
1572 default:
1573 return proto;
1574 }
1575}
1576
1577Socket net_socket(Family domain, int type, int protocol)
1578{
1579 const int platform_domain = make_family(domain);
1580 const int platform_type = make_socktype(type);
1581 const int platform_prot = make_proto(protocol);
1582 const Socket sock = {(int)socket(platform_domain, platform_type, platform_prot)};
1583 return sock;
1584}
1585
1586int net_send(Socket sock, const void *buf, size_t len)
1587{
1588 return send(sock.socket, (const char *)buf, len, MSG_NOSIGNAL);
1589}
1590
1591int net_recv(Socket sock, void *buf, size_t len)
1592{
1593 return recv(sock.socket, (char *)buf, len, MSG_NOSIGNAL);
1594}
1595
1596int net_listen(Socket sock, int backlog)
1597{
1598 return listen(sock.socket, backlog);
1599}
1600
1601Socket net_accept(Socket sock)
1602{
1603 const Socket newsock = {accept(sock.socket, nullptr, nullptr)};
1604 return newsock;
1605}
1606
1607size_t net_socket_data_recv_buffer(Socket sock)
1608{
1609#ifdef OS_WIN32
1610 unsigned long count = 0;
1611 ioctlsocket(sock.socket, FIONREAD, &count);
1612#else
1613 int count = 0;
1614 ioctl(sock.socket, FIONREAD, &count);
1615#endif
1616
1617 return count;
1618}
1619
1620uint32_t net_htonl(uint32_t hostlong)
1621{
1622 return htonl(hostlong);
1623}
1624
1625uint16_t net_htons(uint16_t hostshort)
1626{
1627 return htons(hostshort);
1628}
1629
1630uint32_t net_ntohl(uint32_t hostlong)
1631{
1632 return ntohl(hostlong);
1633}
1634
1635uint16_t net_ntohs(uint16_t hostshort)
1636{
1637 return ntohs(hostshort);
1638}
1639
1640size_t net_pack_u16(uint8_t *bytes, uint16_t v)
1641{
1642 bytes[0] = (v >> 8) & 0xff;
1643 bytes[1] = v & 0xff;
1644 return sizeof(v);
1645}
1646
1647size_t net_pack_u32(uint8_t *bytes, uint32_t v)
1648{
1649 uint8_t *p = bytes;
1650 p += net_pack_u16(p, (v >> 16) & 0xffff);
1651 p += net_pack_u16(p, v & 0xffff);
1652 return p - bytes;
1653}
1654
1655size_t net_pack_u64(uint8_t *bytes, uint64_t v)
1656{
1657 uint8_t *p = bytes;
1658 p += net_pack_u32(p, (v >> 32) & 0xffffffff);
1659 p += net_pack_u32(p, v & 0xffffffff);
1660 return p - bytes;
1661}
1662
1663size_t net_unpack_u16(const uint8_t *bytes, uint16_t *v)
1664{
1665 uint8_t hi = bytes[0];
1666 uint8_t lo = bytes[1];
1667 *v = ((uint16_t)hi << 8) | lo;
1668 return sizeof(*v);
1669}
1670
1671size_t net_unpack_u32(const uint8_t *bytes, uint32_t *v)
1672{
1673 const uint8_t *p = bytes;
1674 uint16_t lo, hi;
1675 p += net_unpack_u16(p, &hi);
1676 p += net_unpack_u16(p, &lo);
1677 *v = ((uint32_t)hi << 16) | lo;
1678 return p - bytes;
1679}
1680
1681size_t net_unpack_u64(const uint8_t *bytes, uint64_t *v)
1682{
1683 const uint8_t *p = bytes;
1684 uint32_t lo, hi;
1685 p += net_unpack_u32(p, &hi);
1686 p += net_unpack_u32(p, &lo);
1687 *v = ((uint64_t)hi << 32) | lo;
1688 return p - bytes;
1689}
1690
1691int net_error(void)
1692{
1693#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
1694 return WSAGetLastError();
1695#else
1696 return errno;
1697#endif
1698}
1699
1700const char *net_new_strerror(int error)
1701{
1702#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
1703 char *str = nullptr;
1704 // Windows API is weird. The 5th function arg is of char* type, but we
1705 // have to pass char** so that it could assign new memory block to our
1706 // pointer, so we have to cast our char** to char* for the compilation
1707 // not to fail (otherwise it would fail to find a variant of this function
1708 // accepting char** as the 5th arg) and Windows inside casts it back
1709 // to char** to do the assignment. So no, this cast you see here, although
1710 // it looks weird, is not a mistake.
1711 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr,
1712 error, 0, (char *)&str, 0, nullptr);
1713 return str;
1714#else
1715 return strerror(error);
1716#endif
1717}
1718
1719void net_kill_strerror(const char *strerror)
1720{
1721#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
1722 LocalFree((char *)strerror);
1723#endif
1724}
diff --git a/toxcore/network.h b/toxcore/network.h
index 8d2ccfce..8071375b 100644
--- a/toxcore/network.h
+++ b/toxcore/network.h
@@ -1,172 +1,209 @@
1/* network.h 1/*
2 *
3 * Datatypes, functions and includes for the core networking. 2 * Datatypes, functions and includes for the core networking.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2013 Tox project.
4 * 8 *
5 * Copyright (C) 2013 Tox project All Rights Reserved. 9 * This file is part of Tox, the free peer to peer instant messenger.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23
24#ifndef NETWORK_H 24#ifndef NETWORK_H
25#define NETWORK_H 25#define NETWORK_H
26 26
27#ifdef PLAN9 27#include "logger.h"
28#include <u.h> //Plan 9 requires this is imported first
29#include <libc.h>
30#endif
31
32#include <stdlib.h>
33#include <stdio.h>
34#include <stdint.h>
35#include <string.h>
36#include <time.h>
37 28
38#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) /* Put win32 includes here */ 29#include <stdbool.h> // bool
39#ifndef WINVER 30#include <stddef.h> // size_t
40//Windows XP 31#include <stdint.h> // uint*_t
41#define WINVER 0x0501
42#endif
43#include <winsock2.h>
44#include <windows.h>
45#include <ws2tcpip.h>
46 32
47#ifndef IPV6_V6ONLY 33#ifdef __cplusplus
48#define IPV6_V6ONLY 27 34extern "C" {
49#endif 35#endif
50 36
51typedef unsigned int sock_t; 37typedef struct Family {
52/* sa_family_t is the sockaddr_in / sockaddr_in6 family field */ 38 uint8_t value;
53typedef short sa_family_t; 39} Family;
54 40
55#ifndef EWOULDBLOCK 41bool net_family_is_unspec(Family family);
56#define EWOULDBLOCK WSAEWOULDBLOCK 42bool net_family_is_ipv4(Family family);
57#endif 43bool net_family_is_ipv6(Family family);
58 44bool net_family_is_tcp_family(Family family);
59#else // Linux includes 45bool net_family_is_tcp_onion(Family family);
60 46bool net_family_is_tcp_ipv4(Family family);
61#include <fcntl.h> 47bool net_family_is_tcp_ipv6(Family family);
62#include <sys/socket.h> 48bool net_family_is_tox_tcp_ipv4(Family family);
63#include <netinet/in.h> 49bool net_family_is_tox_tcp_ipv6(Family family);
64#include <arpa/inet.h> 50
65#include <errno.h> 51extern const Family net_family_unspec;
66#include <sys/time.h> 52extern const Family net_family_ipv4;
67#include <sys/types.h> 53extern const Family net_family_ipv6;
68#include <netdb.h> 54extern const Family net_family_tcp_family;
69#include <unistd.h> 55extern const Family net_family_tcp_onion;
56extern const Family net_family_tcp_ipv4;
57extern const Family net_family_tcp_ipv6;
58extern const Family net_family_tox_tcp_ipv4;
59extern const Family net_family_tox_tcp_ipv6;
60
61typedef struct Socket {
62 int socket;
63} Socket;
64
65Socket net_socket(Family domain, int type, int protocol);
70 66
71typedef int sock_t; 67/* Check if socket is valid.
72 68 *
73#endif 69 * return 1 if valid
70 * return 0 if not valid
71 */
72int sock_valid(Socket sock);
74 73
75#if defined(__AIX__) 74extern const Socket net_invalid_socket;
76# define _XOPEN_SOURCE 1
77#endif
78 75
79#if defined(__sun__) 76/**
80#define __EXTENSIONS__ 1 // SunOS! 77 * Calls send(sockfd, buf, len, MSG_NOSIGNAL).
81#if defined(__SunOS5_6__) || defined(__SunOS5_7__) || defined(__SunOS5_8__) || defined(__SunOS5_9__) || defined(__SunOS5_10__) 78 */
82//Nothing needed 79int net_send(Socket sockfd, const void *buf, size_t len);
83#else 80/**
84#define __MAKECONTEXT_V2_SOURCE 1 81 * Calls recv(sockfd, buf, len, MSG_NOSIGNAL).
85#endif 82 */
86#endif 83int net_recv(Socket sockfd, void *buf, size_t len);
84/**
85 * Calls listen(sockfd, backlog).
86 */
87int net_listen(Socket sockfd, int backlog);
88/**
89 * Calls accept(sockfd, nullptr, nullptr).
90 */
91Socket net_accept(Socket sockfd);
87 92
88#ifndef IPV6_ADD_MEMBERSHIP 93/**
89#ifdef IPV6_JOIN_GROUP 94 * return the amount of data in the tcp recv buffer.
90#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP 95 * return 0 on failure.
91#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP 96 */
92#endif 97size_t net_socket_data_recv_buffer(Socket sock);
93#endif
94 98
95#define MAX_UDP_PACKET_SIZE 2048 99#define MAX_UDP_PACKET_SIZE 2048
96 100
97#define NET_PACKET_PING_REQUEST 0 /* Ping request packet ID. */ 101typedef enum NET_PACKET_TYPE {
98#define NET_PACKET_PING_RESPONSE 1 /* Ping response packet ID. */ 102 NET_PACKET_PING_REQUEST = 0x00, /* Ping request packet ID. */
99#define NET_PACKET_GET_NODES 2 /* Get nodes request packet ID. */ 103 NET_PACKET_PING_RESPONSE = 0x01, /* Ping response packet ID. */
100#define NET_PACKET_SEND_NODES_IPV6 4 /* Send nodes response packet ID for other addresses. */ 104 NET_PACKET_GET_NODES = 0x02, /* Get nodes request packet ID. */
101#define NET_PACKET_COOKIE_REQUEST 24 /* Cookie request packet */ 105 NET_PACKET_SEND_NODES_IPV6 = 0x04, /* Send nodes response packet ID for other addresses. */
102#define NET_PACKET_COOKIE_RESPONSE 25 /* Cookie response packet */ 106 NET_PACKET_COOKIE_REQUEST = 0x18, /* Cookie request packet */
103#define NET_PACKET_CRYPTO_HS 26 /* Crypto handshake packet */ 107 NET_PACKET_COOKIE_RESPONSE = 0x19, /* Cookie response packet */
104#define NET_PACKET_CRYPTO_DATA 27 /* Crypto data packet */ 108 NET_PACKET_CRYPTO_HS = 0x1a, /* Crypto handshake packet */
105#define NET_PACKET_CRYPTO 32 /* Encrypted data packet ID. */ 109 NET_PACKET_CRYPTO_DATA = 0x1b, /* Crypto data packet */
106#define NET_PACKET_LAN_DISCOVERY 33 /* LAN discovery packet ID. */ 110 NET_PACKET_CRYPTO = 0x20, /* Encrypted data packet ID. */
111 NET_PACKET_LAN_DISCOVERY = 0x21, /* LAN discovery packet ID. */
112
113 /* See: docs/Prevent_Tracking.txt and onion.{c,h} */
114 NET_PACKET_ONION_SEND_INITIAL = 0x80,
115 NET_PACKET_ONION_SEND_1 = 0x81,
116 NET_PACKET_ONION_SEND_2 = 0x82,
107 117
108/* See: docs/Prevent_Tracking.txt and onion.{c, h} */ 118 NET_PACKET_ANNOUNCE_REQUEST = 0x83,
109#define NET_PACKET_ONION_SEND_INITIAL 128 119 NET_PACKET_ANNOUNCE_RESPONSE = 0x84,
110#define NET_PACKET_ONION_SEND_1 129 120 NET_PACKET_ONION_DATA_REQUEST = 0x85,
111#define NET_PACKET_ONION_SEND_2 130 121 NET_PACKET_ONION_DATA_RESPONSE = 0x86,
112 122
113#define NET_PACKET_ANNOUNCE_REQUEST 131 123 NET_PACKET_ONION_RECV_3 = 0x8c,
114#define NET_PACKET_ANNOUNCE_RESPONSE 132 124 NET_PACKET_ONION_RECV_2 = 0x8d,
115#define NET_PACKET_ONION_DATA_REQUEST 133 125 NET_PACKET_ONION_RECV_1 = 0x8e,
116#define NET_PACKET_ONION_DATA_RESPONSE 134
117 126
118#define NET_PACKET_ONION_RECV_3 140 127 BOOTSTRAP_INFO_PACKET_ID = 0xf0, /* Only used for bootstrap nodes */
119#define NET_PACKET_ONION_RECV_2 141
120#define NET_PACKET_ONION_RECV_1 142
121 128
122/* Only used for bootstrap nodes */ 129 NET_PACKET_MAX = 0xff, /* This type must remain within a single uint8. */
123#define BOOTSTRAP_INFO_PACKET_ID 240 130} NET_PACKET_TYPE;
124 131
125 132
126#define TOX_PORTRANGE_FROM 33445 133#define TOX_PORTRANGE_FROM 33445
127#define TOX_PORTRANGE_TO 33545 134#define TOX_PORTRANGE_TO 33545
128#define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM 135#define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM
129 136
137/* Redefinitions of variables for safe transfer over wire. */
138#define TOX_AF_UNSPEC 0
139#define TOX_AF_INET 2
140#define TOX_AF_INET6 10
141#define TOX_TCP_INET 130
142#define TOX_TCP_INET6 138
143
144#define TOX_SOCK_STREAM 1
145#define TOX_SOCK_DGRAM 2
146
147#define TOX_PROTO_TCP 1
148#define TOX_PROTO_UDP 2
149
130/* TCP related */ 150/* TCP related */
131#define TCP_ONION_FAMILY (AF_INET6 + 1) 151#define TCP_ONION_FAMILY (TOX_AF_INET6 + 1)
132#define TCP_INET (AF_INET6 + 2) 152#define TCP_INET (TOX_AF_INET6 + 2)
133#define TCP_INET6 (AF_INET6 + 3) 153#define TCP_INET6 (TOX_AF_INET6 + 3)
134#define TCP_FAMILY (AF_INET6 + 4) 154#define TCP_FAMILY (TOX_AF_INET6 + 4)
135 155
136typedef union { 156typedef union IP4 {
137 uint8_t uint8[4];
138 uint16_t uint16[2];
139 uint32_t uint32; 157 uint32_t uint32;
140 struct in_addr in_addr; 158 uint16_t uint16[2];
141} 159 uint8_t uint8[4];
142IP4; 160} IP4;
161
162IP4 get_ip4_loopback(void);
163extern const IP4 IP4_BROADCAST;
143 164
144typedef union { 165typedef union IP6 {
145 uint8_t uint8[16]; 166 uint8_t uint8[16];
146 uint16_t uint16[8]; 167 uint16_t uint16[8];
147 uint32_t uint32[4]; 168 uint32_t uint32[4];
148 uint64_t uint64[2]; 169 uint64_t uint64[2];
149 struct in6_addr in6_addr; 170} IP6;
150} 171
151IP6; 172IP6 get_ip6_loopback(void);
173extern const IP6 IP6_BROADCAST;
152 174
153typedef struct { 175#define IP_DEFINED
154 uint8_t family; 176typedef struct IP {
177 Family family;
155 union { 178 union {
156 IP4 ip4; 179 IP4 v4;
157 IP6 ip6; 180 IP6 v6;
158 }; 181 } ip;
159} 182} IP;
160IP;
161 183
162typedef struct { 184#define IP_PORT_DEFINED
185typedef struct IP_Port {
163 IP ip; 186 IP ip;
164 uint16_t port; 187 uint16_t port;
165} 188} IP_Port;
166IP_Port; 189
190/* Convert values between host and network byte order.
191 */
192uint32_t net_htonl(uint32_t hostlong);
193uint16_t net_htons(uint16_t hostshort);
194uint32_t net_ntohl(uint32_t hostlong);
195uint16_t net_ntohs(uint16_t hostshort);
196
197size_t net_pack_u16(uint8_t *bytes, uint16_t v);
198size_t net_pack_u32(uint8_t *bytes, uint32_t v);
199size_t net_pack_u64(uint8_t *bytes, uint64_t v);
200
201size_t net_unpack_u16(const uint8_t *bytes, uint16_t *v);
202size_t net_unpack_u32(const uint8_t *bytes, uint32_t *v);
203size_t net_unpack_u64(const uint8_t *bytes, uint64_t *v);
167 204
168/* Does the IP6 struct a contain an IPv4 address in an IPv6 one? */ 205/* Does the IP6 struct a contain an IPv4 address in an IPv6 one? */
169#define IPV6_IPV4_IN_V6(a) ((a.uint64[0] == 0) && (a.uint32[2] == htonl (0xffff))) 206#define IPV6_IPV4_IN_V6(a) ((a.uint64[0] == 0) && (a.uint32[2] == net_htonl (0xffff)))
170 207
171#define SIZE_IP4 4 208#define SIZE_IP4 4
172#define SIZE_IP6 16 209#define SIZE_IP6 16
@@ -174,30 +211,37 @@ IP_Port;
174#define SIZE_PORT 2 211#define SIZE_PORT 2
175#define SIZE_IPPORT (SIZE_IP + SIZE_PORT) 212#define SIZE_IPPORT (SIZE_IP + SIZE_PORT)
176 213
177#define TOX_ENABLE_IPV6_DEFAULT 1 214#define TOX_ENABLE_IPV6_DEFAULT true
178 215
179/* addr_resolve return values */ 216/* addr_resolve return values */
180#define TOX_ADDR_RESOLVE_INET 1 217#define TOX_ADDR_RESOLVE_INET 1
181#define TOX_ADDR_RESOLVE_INET6 2 218#define TOX_ADDR_RESOLVE_INET6 2
182 219
220#define TOX_INET6_ADDRSTRLEN 66
221#define TOX_INET_ADDRSTRLEN 22
222
183/* ip_ntoa 223/* ip_ntoa
184 * converts ip into a string 224 * converts ip into a string
185 * uses a static buffer, so mustn't used multiple times in the same output 225 * ip_str must be of length at least IP_NTOA_LEN
186 * 226 *
187 * IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]" 227 * IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]"
188 * writes error message into the buffer on error 228 * writes error message into the buffer on error
229 *
230 * returns ip_str
189 */ 231 */
190const char *ip_ntoa(const IP *ip); 232/* this would be TOX_INET6_ADDRSTRLEN, but it might be too short for the error message */
233#define IP_NTOA_LEN 96 // TODO(irungentoo): magic number. Why not INET6_ADDRSTRLEN ?
234const char *ip_ntoa(const IP *ip, char *ip_str, size_t length);
191 235
192/* 236/*
193 * ip_parse_addr 237 * ip_parse_addr
194 * parses IP structure into an address string 238 * parses IP structure into an address string
195 * 239 *
196 * input 240 * input
197 * ip: ip of AF_INET or AF_INET6 families 241 * ip: ip of TOX_AF_INET or TOX_AF_INET6 families
198 * length: length of the address buffer 242 * length: length of the address buffer
199 * Must be at least INET_ADDRSTRLEN for AF_INET 243 * Must be at least TOX_INET_ADDRSTRLEN for TOX_AF_INET
200 * and INET6_ADDRSTRLEN for AF_INET6 244 * and TOX_INET6_ADDRSTRLEN for TOX_AF_INET6
201 * 245 *
202 * output 246 * output
203 * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6) 247 * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6)
@@ -240,11 +284,11 @@ int ipport_equal(const IP_Port *a, const IP_Port *b);
240/* nulls out ip */ 284/* nulls out ip */
241void ip_reset(IP *ip); 285void ip_reset(IP *ip);
242/* nulls out ip, sets family according to flag */ 286/* nulls out ip, sets family according to flag */
243void ip_init(IP *ip, uint8_t ipv6enabled); 287void ip_init(IP *ip, bool ipv6enabled);
244/* checks if ip is valid */ 288/* checks if ip is valid */
245int ip_isset(const IP *ip); 289bool ip_isset(const IP *ip);
246/* checks if ip is valid */ 290/* checks if ip is valid */
247int ipport_isset(const IP_Port *ipport); 291bool ipport_isset(const IP_Port *ipport);
248/* copies an ip structure */ 292/* copies an ip structure */
249void ip_copy(IP *target, const IP *source); 293void ip_copy(IP *target, const IP *source);
250/* copies an ip_port structure */ 294/* copies an ip_port structure */
@@ -258,13 +302,13 @@ void ipport_copy(IP_Port *target, const IP_Port *source);
258 * input 302 * input
259 * address: a hostname (or something parseable to an IP address) 303 * address: a hostname (or something parseable to an IP address)
260 * to: to.family MUST be initialized, either set to a specific IP version 304 * to: to.family MUST be initialized, either set to a specific IP version
261 * (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both 305 * (TOX_AF_INET/TOX_AF_INET6) or to the unspecified TOX_AF_UNSPEC (= 0), if both
262 * IP versions are acceptable 306 * IP versions are acceptable
263 * extra can be NULL and is only set in special circumstances, see returns 307 * extra can be NULL and is only set in special circumstances, see returns
264 * 308 *
265 * returns in *to a valid IPAny (v4/v6), 309 * returns in *to a valid IPAny (v4/v6),
266 * prefers v6 if ip.family was AF_UNSPEC and both available 310 * prefers v6 if ip.family was TOX_AF_UNSPEC and both available
267 * returns in *extra an IPv4 address, if family was AF_UNSPEC and *to is AF_INET6 311 * returns in *extra an IPv4 address, if family was TOX_AF_UNSPEC and *to is TOX_AF_INET6
268 * returns 0 on failure 312 * returns 0 on failure
269 */ 313 */
270int addr_resolve(const char *address, IP *to, IP *extra); 314int addr_resolve(const char *address, IP *to, IP *extra);
@@ -275,12 +319,12 @@ int addr_resolve(const char *address, IP *to, IP *extra);
275 * 319 *
276 * address: a hostname (or something parseable to an IP address) 320 * address: a hostname (or something parseable to an IP address)
277 * to: to.family MUST be initialized, either set to a specific IP version 321 * to: to.family MUST be initialized, either set to a specific IP version
278 * (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both 322 * (TOX_AF_INET/TOX_AF_INET6) or to the unspecified TOX_AF_UNSPEC (= 0), if both
279 * IP versions are acceptable 323 * IP versions are acceptable
280 * extra can be NULL and is only set in special circumstances, see returns 324 * extra can be NULL and is only set in special circumstances, see returns
281 * 325 *
282 * returns in *tro a matching address (IPv6 or IPv4) 326 * returns in *tro a matching address (IPv6 or IPv4)
283 * returns in *extra, if not NULL, an IPv4 address, if to->family was AF_UNSPEC 327 * returns in *extra, if not NULL, an IPv4 address, if to->family was TOX_AF_UNSPEC
284 * returns 1 on success 328 * returns 1 on success
285 * returns 0 on failure 329 * returns 0 on failure
286 */ 330 */
@@ -290,21 +334,13 @@ int addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra);
290 * Packet data is put into data. 334 * Packet data is put into data.
291 * Packet length is put into length. 335 * Packet length is put into length.
292 */ 336 */
293typedef int (*packet_handler_callback)(void *object, IP_Port ip_port, const uint8_t *data, uint16_t len); 337typedef int (*packet_handler_callback)(void *object, IP_Port ip_port, const uint8_t *data, uint16_t len,
294 338 void *userdata);
295typedef struct {
296 packet_handler_callback function;
297 void *object;
298} Packet_Handles;
299 339
300typedef struct { 340typedef struct Networking_Core Networking_Core;
301 Packet_Handles packethandlers[256];
302 341
303 sa_family_t family; 342Family net_family(const Networking_Core *net);
304 uint16_t port; 343uint16_t net_port(const Networking_Core *net);
305 /* Our UDP socket. */
306 sock_t sock;
307} Networking_Core;
308 344
309/* Run this before creating sockets. 345/* Run this before creating sockets.
310 * 346 *
@@ -313,44 +349,37 @@ typedef struct {
313 */ 349 */
314int networking_at_startup(void); 350int networking_at_startup(void);
315 351
316/* Check if socket is valid.
317 *
318 * return 1 if valid
319 * return 0 if not valid
320 */
321int sock_valid(sock_t sock);
322
323/* Close the socket. 352/* Close the socket.
324 */ 353 */
325void kill_sock(sock_t sock); 354void kill_sock(Socket sock);
326 355
327/* Set socket as nonblocking 356/* Set socket as nonblocking
328 * 357 *
329 * return 1 on success 358 * return 1 on success
330 * return 0 on failure 359 * return 0 on failure
331 */ 360 */
332int set_socket_nonblock(sock_t sock); 361int set_socket_nonblock(Socket sock);
333 362
334/* Set socket to not emit SIGPIPE 363/* Set socket to not emit SIGPIPE
335 * 364 *
336 * return 1 on success 365 * return 1 on success
337 * return 0 on failure 366 * return 0 on failure
338 */ 367 */
339int set_socket_nosigpipe(sock_t sock); 368int set_socket_nosigpipe(Socket sock);
340 369
341/* Enable SO_REUSEADDR on socket. 370/* Enable SO_REUSEADDR on socket.
342 * 371 *
343 * return 1 on success 372 * return 1 on success
344 * return 0 on failure 373 * return 0 on failure
345 */ 374 */
346int set_socket_reuseaddr(sock_t sock); 375int set_socket_reuseaddr(Socket sock);
347 376
348/* Set socket to dual (IPv4 + IPv6 socket) 377/* Set socket to dual (IPv4 + IPv6 socket)
349 * 378 *
350 * return 1 on success 379 * return 1 on success
351 * return 0 on failure 380 * return 0 on failure
352 */ 381 */
353int set_socket_dualstack(sock_t sock); 382int set_socket_dualstack(Socket sock);
354 383
355/* return current monotonic time in milliseconds (ms). */ 384/* return current monotonic time in milliseconds (ms). */
356uint64_t current_time_monotonic(void); 385uint64_t current_time_monotonic(void);
@@ -364,7 +393,60 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint1
364void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object); 393void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object);
365 394
366/* Call this several times a second. */ 395/* Call this several times a second. */
367void networking_poll(Networking_Core *net); 396void networking_poll(Networking_Core *net, void *userdata);
397
398/* Connect a socket to the address specified by the ip_port. */
399int net_connect(Socket sock, IP_Port ip_port);
400
401/* High-level getaddrinfo implementation.
402 * Given node, which identifies an Internet host, net_getipport() fills an array
403 * with one or more IP_Port structures, each of which contains an Internet
404 * address that can be specified by calling net_connect(), the port is ignored.
405 *
406 * Skip all addresses with socktype != type (use type = -1 to get all addresses)
407 * To correctly deallocate array memory use net_freeipport()
408 *
409 * return number of elements in res array
410 * and -1 on error.
411 */
412int32_t net_getipport(const char *node, IP_Port **res, int tox_type);
413
414/* Deallocates memory allocated by net_getipport
415 */
416void net_freeipport(IP_Port *ip_ports);
417
418/* return 1 on success
419 * return 0 on failure
420 */
421int bind_to_port(Socket sock, Family family, uint16_t port);
422
423/* Get the last networking error code.
424 *
425 * Similar to Unix's errno, but cross-platform, as not all platforms use errno
426 * to indicate networking errors.
427 *
428 * Note that different platforms may return different codes for the same error,
429 * so you likely shouldn't be checking the value returned by this function
430 * unless you know what you are doing, you likely just want to use it in
431 * combination with net_new_strerror() to print the error.
432 *
433 * return platform-dependent network error code, if any.
434 */
435int net_error(void);
436
437/* Get a text explanation for the error code from net_error().
438 *
439 * return NULL on failure.
440 * return pointer to a NULL-terminated string describing the error code on
441 * success. The returned string must be freed using net_kill_strerror().
442 */
443const char *net_new_strerror(int error);
444
445/* Frees the string returned by net_new_strerror().
446 * It's valid to pass NULL as the argument, the function does nothing in this
447 * case.
448 */
449void net_kill_strerror(const char *strerror);
368 450
369/* Initialize networking. 451/* Initialize networking.
370 * bind to ip and port. 452 * bind to ip and port.
@@ -376,10 +458,15 @@ void networking_poll(Networking_Core *net);
376 * 458 *
377 * If error is non NULL it is set to 0 if no issues, 1 if socket related error, 2 if other. 459 * If error is non NULL it is set to 0 if no issues, 1 if socket related error, 2 if other.
378 */ 460 */
379Networking_Core *new_networking(IP ip, uint16_t port); 461Networking_Core *new_networking(Logger *log, IP ip, uint16_t port);
380Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to, unsigned int *error); 462Networking_Core *new_networking_ex(Logger *log, IP ip, uint16_t port_from, uint16_t port_to, unsigned int *error);
463Networking_Core *new_networking_no_udp(Logger *log);
381 464
382/* Function to cleanup networking stuff (doesn't do much right now). */ 465/* Function to cleanup networking stuff (doesn't do much right now). */
383void kill_networking(Networking_Core *net); 466void kill_networking(Networking_Core *net);
384 467
468#ifdef __cplusplus
469} // extern "C"
470#endif
471
385#endif 472#endif
diff --git a/toxcore/onion.c b/toxcore/onion.c
index 2bed5821..5bbc7f75 100644
--- a/toxcore/onion.c
+++ b/toxcore/onion.c
@@ -1,29 +1,35 @@
1/* 1/*
2* onion.c -- Implementation of the onion part of docs/Prevent_Tracking.txt 2 * Implementation of the onion part of docs/Prevent_Tracking.txt
3* 3 */
4* Copyright (C) 2013 Tox project All Rights Reserved. 4
5* 5/*
6* This file is part of Tox. 6 * Copyright © 2016-2018 The TokTok team.
7* 7 * Copyright © 2013 Tox project.
8* Tox is free software: you can redistribute it and/or modify 8 *
9* it under the terms of the GNU General Public License as published by 9 * This file is part of Tox, the free peer to peer instant messenger.
10* the Free Software Foundation, either version 3 of the License, or 10 *
11* (at your option) any later version. 11 * Tox is free software: you can redistribute it and/or modify
12* 12 * it under the terms of the GNU General Public License as published by
13* Tox is distributed in the hope that it will be useful, 13 * the Free Software Foundation, either version 3 of the License, or
14* but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * (at your option) any later version.
15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 *
16* GNU General Public License for more details. 16 * Tox is distributed in the hope that it will be useful,
17* 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18* You should have received a copy of the GNU General Public License 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19* along with Tox. If not, see <http://www.gnu.org/licenses/>. 19 * GNU General Public License for more details.
20* 20 *
21*/ 21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
23 */
22#ifdef HAVE_CONFIG_H 24#ifdef HAVE_CONFIG_H
23#include "config.h" 25#include "config.h"
24#endif 26#endif
25 27
26#include "onion.h" 28#include "onion.h"
29
30#include <stdlib.h>
31#include <string.h>
32
27#include "util.h" 33#include "util.h"
28 34
29#define RETURN_1 ONION_RETURN_1 35#define RETURN_1 ONION_RETURN_1
@@ -48,38 +54,37 @@ static void change_symmetric_key(Onion *onion)
48/* packing and unpacking functions */ 54/* packing and unpacking functions */
49static void ip_pack(uint8_t *data, IP source) 55static void ip_pack(uint8_t *data, IP source)
50{ 56{
51 to_net_family(&source); 57 data[0] = source.family.value;
52
53 data[0] = source.family;
54 58
55 if (source.family == TOX_AF_INET || source.family == TOX_TCP_INET) { 59 if (net_family_is_ipv4(source.family) || net_family_is_tox_tcp_ipv4(source.family)) {
56 memset(data + 1, 0, SIZE_IP6); 60 memset(data + 1, 0, SIZE_IP6);
57 memcpy(data + 1, source.ip4.uint8, SIZE_IP4); 61 memcpy(data + 1, source.ip.v4.uint8, SIZE_IP4);
58 } else { 62 } else {
59 memcpy(data + 1, source.ip6.uint8, SIZE_IP6); 63 memcpy(data + 1, source.ip.v6.uint8, SIZE_IP6);
60 } 64 }
61} 65}
62 66
63/* return 0 on success, -1 on failure. */ 67/* return 0 on success, -1 on failure. */
64static int ip_unpack(IP *target, const uint8_t *data, unsigned int data_size, _Bool disable_family_check) 68static int ip_unpack(IP *target, const uint8_t *data, unsigned int data_size, bool disable_family_check)
65{ 69{
66 if (data_size < (1 + SIZE_IP6)) 70 if (data_size < (1 + SIZE_IP6)) {
67 return -1; 71 return -1;
72 }
68 73
69 target->family = data[0]; 74 // TODO(iphydf): Validate input.
75 target->family.value = data[0];
70 76
71 if (target->family == TOX_AF_INET || target->family == TOX_TCP_INET) { 77 if (net_family_is_ipv4(target->family) || net_family_is_tox_tcp_ipv4(target->family)) {
72 memcpy(target->ip4.uint8, data + 1, SIZE_IP4); 78 memcpy(target->ip.v4.uint8, data + 1, SIZE_IP4);
73 } else { 79 } else {
74 memcpy(target->ip6.uint8, data + 1, SIZE_IP6); 80 memcpy(target->ip.v6.uint8, data + 1, SIZE_IP6);
75 } 81 }
76 82
77 if (!disable_family_check) { 83 bool valid = disable_family_check ||
78 return to_host_family(target); 84 net_family_is_ipv4(target->family) ||
79 } else { 85 net_family_is_ipv6(target->family);
80 to_host_family(target); 86
81 return 0; 87 return valid ? 0 : -1;
82 }
83} 88}
84 89
85static void ipport_pack(uint8_t *data, const IP_Port *source) 90static void ipport_pack(uint8_t *data, const IP_Port *source)
@@ -89,13 +94,15 @@ static void ipport_pack(uint8_t *data, const IP_Port *source)
89} 94}
90 95
91/* return 0 on success, -1 on failure. */ 96/* return 0 on success, -1 on failure. */
92static int ipport_unpack(IP_Port *target, const uint8_t *data, unsigned int data_size, _Bool disable_family_check) 97static int ipport_unpack(IP_Port *target, const uint8_t *data, unsigned int data_size, bool disable_family_check)
93{ 98{
94 if (data_size < (SIZE_IP + SIZE_PORT)) 99 if (data_size < (SIZE_IP + SIZE_PORT)) {
95 return -1; 100 return -1;
101 }
96 102
97 if (ip_unpack(&target->ip, data, data_size, disable_family_check) == -1) 103 if (ip_unpack(&target->ip, data, data_size, disable_family_check) == -1) {
98 return -1; 104 return -1;
105 }
99 106
100 memcpy(&target->port, data + SIZE_IP, SIZE_PORT); 107 memcpy(&target->port, data + SIZE_IP, SIZE_PORT);
101 return 0; 108 return 0;
@@ -113,30 +120,31 @@ static int ipport_unpack(IP_Port *target, const uint8_t *data, unsigned int data
113 */ 120 */
114int create_onion_path(const DHT *dht, Onion_Path *new_path, const Node_format *nodes) 121int create_onion_path(const DHT *dht, Onion_Path *new_path, const Node_format *nodes)
115{ 122{
116 if (!new_path || !nodes) 123 if (!new_path || !nodes) {
117 return -1; 124 return -1;
125 }
118 126
119 encrypt_precompute(nodes[0].public_key, dht->self_secret_key, new_path->shared_key1); 127 encrypt_precompute(nodes[0].public_key, dht_get_self_secret_key(dht), new_path->shared_key1);
120 memcpy(new_path->public_key1, dht->self_public_key, crypto_box_PUBLICKEYBYTES); 128 memcpy(new_path->public_key1, dht_get_self_public_key(dht), CRYPTO_PUBLIC_KEY_SIZE);
121 129
122 uint8_t random_public_key[crypto_box_PUBLICKEYBYTES]; 130 uint8_t random_public_key[CRYPTO_PUBLIC_KEY_SIZE];
123 uint8_t random_secret_key[crypto_box_SECRETKEYBYTES]; 131 uint8_t random_secret_key[CRYPTO_SECRET_KEY_SIZE];
124 132
125 crypto_box_keypair(random_public_key, random_secret_key); 133 crypto_new_keypair(random_public_key, random_secret_key);
126 encrypt_precompute(nodes[1].public_key, random_secret_key, new_path->shared_key2); 134 encrypt_precompute(nodes[1].public_key, random_secret_key, new_path->shared_key2);
127 memcpy(new_path->public_key2, random_public_key, crypto_box_PUBLICKEYBYTES); 135 memcpy(new_path->public_key2, random_public_key, CRYPTO_PUBLIC_KEY_SIZE);
128 136
129 crypto_box_keypair(random_public_key, random_secret_key); 137 crypto_new_keypair(random_public_key, random_secret_key);
130 encrypt_precompute(nodes[2].public_key, random_secret_key, new_path->shared_key3); 138 encrypt_precompute(nodes[2].public_key, random_secret_key, new_path->shared_key3);
131 memcpy(new_path->public_key3, random_public_key, crypto_box_PUBLICKEYBYTES); 139 memcpy(new_path->public_key3, random_public_key, CRYPTO_PUBLIC_KEY_SIZE);
132 140
133 new_path->ip_port1 = nodes[0].ip_port; 141 new_path->ip_port1 = nodes[0].ip_port;
134 new_path->ip_port2 = nodes[1].ip_port; 142 new_path->ip_port2 = nodes[1].ip_port;
135 new_path->ip_port3 = nodes[2].ip_port; 143 new_path->ip_port3 = nodes[2].ip_port;
136 144
137 memcpy(new_path->node_public_key1, nodes[0].public_key, crypto_box_PUBLICKEYBYTES); 145 memcpy(new_path->node_public_key1, nodes[0].public_key, CRYPTO_PUBLIC_KEY_SIZE);
138 memcpy(new_path->node_public_key2, nodes[1].public_key, crypto_box_PUBLICKEYBYTES); 146 memcpy(new_path->node_public_key2, nodes[1].public_key, CRYPTO_PUBLIC_KEY_SIZE);
139 memcpy(new_path->node_public_key3, nodes[2].public_key, crypto_box_PUBLICKEYBYTES); 147 memcpy(new_path->node_public_key3, nodes[2].public_key, CRYPTO_PUBLIC_KEY_SIZE);
140 148
141 return 0; 149 return 0;
142} 150}
@@ -148,16 +156,17 @@ int create_onion_path(const DHT *dht, Onion_Path *new_path, const Node_format *n
148 */ 156 */
149int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_Path *path) 157int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_Path *path)
150{ 158{
151 if (num_nodes < ONION_PATH_LENGTH) 159 if (num_nodes < ONION_PATH_LENGTH) {
152 return -1; 160 return -1;
161 }
153 162
154 nodes[0].ip_port = path->ip_port1; 163 nodes[0].ip_port = path->ip_port1;
155 nodes[1].ip_port = path->ip_port2; 164 nodes[1].ip_port = path->ip_port2;
156 nodes[2].ip_port = path->ip_port3; 165 nodes[2].ip_port = path->ip_port3;
157 166
158 memcpy(nodes[0].public_key, path->node_public_key1, crypto_box_PUBLICKEYBYTES); 167 memcpy(nodes[0].public_key, path->node_public_key1, CRYPTO_PUBLIC_KEY_SIZE);
159 memcpy(nodes[1].public_key, path->node_public_key2, crypto_box_PUBLICKEYBYTES); 168 memcpy(nodes[1].public_key, path->node_public_key2, CRYPTO_PUBLIC_KEY_SIZE);
160 memcpy(nodes[2].public_key, path->node_public_key3, crypto_box_PUBLICKEYBYTES); 169 memcpy(nodes[2].public_key, path->node_public_key3, CRYPTO_PUBLIC_KEY_SIZE);
161 return 0; 170 return 0;
162} 171}
163 172
@@ -173,47 +182,51 @@ int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_
173int create_onion_packet(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, IP_Port dest, 182int create_onion_packet(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, IP_Port dest,
174 const uint8_t *data, uint16_t length) 183 const uint8_t *data, uint16_t length)
175{ 184{
176 if (1 + length + SEND_1 > max_packet_length || length == 0) 185 if (1 + length + SEND_1 > max_packet_length || length == 0) {
177 return -1; 186 return -1;
187 }
178 188
179 uint8_t step1[SIZE_IPPORT + length]; 189 VLA(uint8_t, step1, SIZE_IPPORT + length);
180 190
181 ipport_pack(step1, &dest); 191 ipport_pack(step1, &dest);
182 memcpy(step1 + SIZE_IPPORT, data, length); 192 memcpy(step1 + SIZE_IPPORT, data, length);
183 193
184 uint8_t nonce[crypto_box_NONCEBYTES]; 194 uint8_t nonce[CRYPTO_NONCE_SIZE];
185 random_nonce(nonce); 195 random_nonce(nonce);
186 196
187 uint8_t step2[SIZE_IPPORT + SEND_BASE + length]; 197 VLA(uint8_t, step2, SIZE_IPPORT + SEND_BASE + length);
188 ipport_pack(step2, &path->ip_port3); 198 ipport_pack(step2, &path->ip_port3);
189 memcpy(step2 + SIZE_IPPORT, path->public_key3, crypto_box_PUBLICKEYBYTES); 199 memcpy(step2 + SIZE_IPPORT, path->public_key3, CRYPTO_PUBLIC_KEY_SIZE);
190 200
191 int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, sizeof(step1), 201 int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, SIZEOF_VLA(step1),
192 step2 + SIZE_IPPORT + crypto_box_PUBLICKEYBYTES); 202 step2 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
193 203
194 if (len != SIZE_IPPORT + length + crypto_box_MACBYTES) 204 if (len != SIZE_IPPORT + length + CRYPTO_MAC_SIZE) {
195 return -1; 205 return -1;
206 }
196 207
197 uint8_t step3[SIZE_IPPORT + SEND_BASE * 2 + length]; 208 VLA(uint8_t, step3, SIZE_IPPORT + SEND_BASE * 2 + length);
198 ipport_pack(step3, &path->ip_port2); 209 ipport_pack(step3, &path->ip_port2);
199 memcpy(step3 + SIZE_IPPORT, path->public_key2, crypto_box_PUBLICKEYBYTES); 210 memcpy(step3 + SIZE_IPPORT, path->public_key2, CRYPTO_PUBLIC_KEY_SIZE);
200 len = encrypt_data_symmetric(path->shared_key2, nonce, step2, sizeof(step2), 211 len = encrypt_data_symmetric(path->shared_key2, nonce, step2, SIZEOF_VLA(step2),
201 step3 + SIZE_IPPORT + crypto_box_PUBLICKEYBYTES); 212 step3 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
202 213
203 if (len != SIZE_IPPORT + SEND_BASE + length + crypto_box_MACBYTES) 214 if (len != SIZE_IPPORT + SEND_BASE + length + CRYPTO_MAC_SIZE) {
204 return -1; 215 return -1;
216 }
205 217
206 packet[0] = NET_PACKET_ONION_SEND_INITIAL; 218 packet[0] = NET_PACKET_ONION_SEND_INITIAL;
207 memcpy(packet + 1, nonce, crypto_box_NONCEBYTES); 219 memcpy(packet + 1, nonce, CRYPTO_NONCE_SIZE);
208 memcpy(packet + 1 + crypto_box_NONCEBYTES, path->public_key1, crypto_box_PUBLICKEYBYTES); 220 memcpy(packet + 1 + CRYPTO_NONCE_SIZE, path->public_key1, CRYPTO_PUBLIC_KEY_SIZE);
209 221
210 len = encrypt_data_symmetric(path->shared_key1, nonce, step3, sizeof(step3), 222 len = encrypt_data_symmetric(path->shared_key1, nonce, step3, SIZEOF_VLA(step3),
211 packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); 223 packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);
212 224
213 if (len != SIZE_IPPORT + SEND_BASE * 2 + length + crypto_box_MACBYTES) 225 if (len != SIZE_IPPORT + SEND_BASE * 2 + length + CRYPTO_MAC_SIZE) {
214 return -1; 226 return -1;
227 }
215 228
216 return 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + len; 229 return 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + len;
217} 230}
218 231
219/* Create a onion packet to be sent over tcp. 232/* Create a onion packet to be sent over tcp.
@@ -228,38 +241,41 @@ int create_onion_packet(uint8_t *packet, uint16_t max_packet_length, const Onion
228int create_onion_packet_tcp(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, IP_Port dest, 241int create_onion_packet_tcp(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, IP_Port dest,
229 const uint8_t *data, uint16_t length) 242 const uint8_t *data, uint16_t length)
230{ 243{
231 if (crypto_box_NONCEBYTES + SIZE_IPPORT + SEND_BASE * 2 + length > max_packet_length || length == 0) 244 if (CRYPTO_NONCE_SIZE + SIZE_IPPORT + SEND_BASE * 2 + length > max_packet_length || length == 0) {
232 return -1; 245 return -1;
246 }
233 247
234 uint8_t step1[SIZE_IPPORT + length]; 248 VLA(uint8_t, step1, SIZE_IPPORT + length);
235 249
236 ipport_pack(step1, &dest); 250 ipport_pack(step1, &dest);
237 memcpy(step1 + SIZE_IPPORT, data, length); 251 memcpy(step1 + SIZE_IPPORT, data, length);
238 252
239 uint8_t nonce[crypto_box_NONCEBYTES]; 253 uint8_t nonce[CRYPTO_NONCE_SIZE];
240 random_nonce(nonce); 254 random_nonce(nonce);
241 255
242 uint8_t step2[SIZE_IPPORT + SEND_BASE + length]; 256 VLA(uint8_t, step2, SIZE_IPPORT + SEND_BASE + length);
243 ipport_pack(step2, &path->ip_port3); 257 ipport_pack(step2, &path->ip_port3);
244 memcpy(step2 + SIZE_IPPORT, path->public_key3, crypto_box_PUBLICKEYBYTES); 258 memcpy(step2 + SIZE_IPPORT, path->public_key3, CRYPTO_PUBLIC_KEY_SIZE);
245 259
246 int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, sizeof(step1), 260 int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, SIZEOF_VLA(step1),
247 step2 + SIZE_IPPORT + crypto_box_PUBLICKEYBYTES); 261 step2 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
248 262
249 if (len != SIZE_IPPORT + length + crypto_box_MACBYTES) 263 if (len != SIZE_IPPORT + length + CRYPTO_MAC_SIZE) {
250 return -1; 264 return -1;
265 }
251 266
252 ipport_pack(packet + crypto_box_NONCEBYTES, &path->ip_port2); 267 ipport_pack(packet + CRYPTO_NONCE_SIZE, &path->ip_port2);
253 memcpy(packet + crypto_box_NONCEBYTES + SIZE_IPPORT, path->public_key2, crypto_box_PUBLICKEYBYTES); 268 memcpy(packet + CRYPTO_NONCE_SIZE + SIZE_IPPORT, path->public_key2, CRYPTO_PUBLIC_KEY_SIZE);
254 len = encrypt_data_symmetric(path->shared_key2, nonce, step2, sizeof(step2), 269 len = encrypt_data_symmetric(path->shared_key2, nonce, step2, SIZEOF_VLA(step2),
255 packet + crypto_box_NONCEBYTES + SIZE_IPPORT + crypto_box_PUBLICKEYBYTES); 270 packet + CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
256 271
257 if (len != SIZE_IPPORT + SEND_BASE + length + crypto_box_MACBYTES) 272 if (len != SIZE_IPPORT + SEND_BASE + length + CRYPTO_MAC_SIZE) {
258 return -1; 273 return -1;
274 }
259 275
260 memcpy(packet, nonce, crypto_box_NONCEBYTES); 276 memcpy(packet, nonce, CRYPTO_NONCE_SIZE);
261 277
262 return crypto_box_NONCEBYTES + SIZE_IPPORT + crypto_box_PUBLICKEYBYTES + len; 278 return CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE + len;
263} 279}
264 280
265/* Create and send a onion packet. 281/* Create and send a onion packet.
@@ -275,11 +291,13 @@ int send_onion_packet(Networking_Core *net, const Onion_Path *path, IP_Port dest
275 uint8_t packet[ONION_MAX_PACKET_SIZE]; 291 uint8_t packet[ONION_MAX_PACKET_SIZE];
276 int len = create_onion_packet(packet, sizeof(packet), path, dest, data, length); 292 int len = create_onion_packet(packet, sizeof(packet), path, dest, data, length);
277 293
278 if (len == -1) 294 if (len == -1) {
279 return -1; 295 return -1;
296 }
280 297
281 if (sendpacket(net, path->ip_port1, packet, len) != len) 298 if (sendpacket(net, path->ip_port1, packet, len) != len) {
282 return -1; 299 return -1;
300 }
283 301
284 return 0; 302 return 0;
285} 303}
@@ -292,151 +310,170 @@ int send_onion_packet(Networking_Core *net, const Onion_Path *path, IP_Port dest
292 */ 310 */
293int send_onion_response(Networking_Core *net, IP_Port dest, const uint8_t *data, uint16_t length, const uint8_t *ret) 311int send_onion_response(Networking_Core *net, IP_Port dest, const uint8_t *data, uint16_t length, const uint8_t *ret)
294{ 312{
295 if (length > ONION_RESPONSE_MAX_DATA_SIZE || length == 0) 313 if (length > ONION_RESPONSE_MAX_DATA_SIZE || length == 0) {
296 return -1; 314 return -1;
315 }
297 316
298 uint8_t packet[1 + RETURN_3 + length]; 317 VLA(uint8_t, packet, 1 + RETURN_3 + length);
299 packet[0] = NET_PACKET_ONION_RECV_3; 318 packet[0] = NET_PACKET_ONION_RECV_3;
300 memcpy(packet + 1, ret, RETURN_3); 319 memcpy(packet + 1, ret, RETURN_3);
301 memcpy(packet + 1 + RETURN_3, data, length); 320 memcpy(packet + 1 + RETURN_3, data, length);
302 321
303 if ((uint32_t)sendpacket(net, dest, packet, sizeof(packet)) != sizeof(packet)) 322 if ((uint32_t)sendpacket(net, dest, packet, SIZEOF_VLA(packet)) != SIZEOF_VLA(packet)) {
304 return -1; 323 return -1;
324 }
305 325
306 return 0; 326 return 0;
307} 327}
308 328
309static int handle_send_initial(void *object, IP_Port source, const uint8_t *packet, uint16_t length) 329static int handle_send_initial(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
310{ 330{
311 Onion *onion = object; 331 Onion *onion = (Onion *)object;
312 332
313 if (length > ONION_MAX_PACKET_SIZE) 333 if (length > ONION_MAX_PACKET_SIZE) {
314 return 1; 334 return 1;
335 }
315 336
316 if (length <= 1 + SEND_1) 337 if (length <= 1 + SEND_1) {
317 return 1; 338 return 1;
339 }
318 340
319 change_symmetric_key(onion); 341 change_symmetric_key(onion);
320 342
321 uint8_t plain[ONION_MAX_PACKET_SIZE]; 343 uint8_t plain[ONION_MAX_PACKET_SIZE];
322 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 344 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
323 get_shared_key(&onion->shared_keys_1, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); 345 get_shared_key(&onion->shared_keys_1, shared_key, dht_get_self_secret_key(onion->dht), packet + 1 + CRYPTO_NONCE_SIZE);
324 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, 346 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
325 length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), plain); 347 length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE), plain);
326 348
327 if (len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)) 349 if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE)) {
328 return 1; 350 return 1;
351 }
329 352
330 return onion_send_1(onion, plain, len, source, packet + 1); 353 return onion_send_1(onion, plain, len, source, packet + 1);
331} 354}
332 355
333int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, IP_Port source, const uint8_t *nonce) 356int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, IP_Port source, const uint8_t *nonce)
334{ 357{
335 if (len > ONION_MAX_PACKET_SIZE + SIZE_IPPORT - (1 + crypto_box_NONCEBYTES + ONION_RETURN_1)) 358 if (len > ONION_MAX_PACKET_SIZE + SIZE_IPPORT - (1 + CRYPTO_NONCE_SIZE + ONION_RETURN_1)) {
336 return 1; 359 return 1;
360 }
337 361
338 if (len <= SIZE_IPPORT + SEND_BASE * 2) 362 if (len <= SIZE_IPPORT + SEND_BASE * 2) {
339 return 1; 363 return 1;
364 }
340 365
341 IP_Port send_to; 366 IP_Port send_to;
342 367
343 if (ipport_unpack(&send_to, plain, len, 0) == -1) 368 if (ipport_unpack(&send_to, plain, len, 0) == -1) {
344 return 1; 369 return 1;
370 }
345 371
346 uint8_t ip_port[SIZE_IPPORT]; 372 uint8_t ip_port[SIZE_IPPORT];
347 ipport_pack(ip_port, &source); 373 ipport_pack(ip_port, &source);
348 374
349 uint8_t data[ONION_MAX_PACKET_SIZE]; 375 uint8_t data[ONION_MAX_PACKET_SIZE];
350 data[0] = NET_PACKET_ONION_SEND_1; 376 data[0] = NET_PACKET_ONION_SEND_1;
351 memcpy(data + 1, nonce, crypto_box_NONCEBYTES); 377 memcpy(data + 1, nonce, CRYPTO_NONCE_SIZE);
352 memcpy(data + 1 + crypto_box_NONCEBYTES, plain + SIZE_IPPORT, len - SIZE_IPPORT); 378 memcpy(data + 1 + CRYPTO_NONCE_SIZE, plain + SIZE_IPPORT, len - SIZE_IPPORT);
353 uint16_t data_len = 1 + crypto_box_NONCEBYTES + (len - SIZE_IPPORT); 379 uint16_t data_len = 1 + CRYPTO_NONCE_SIZE + (len - SIZE_IPPORT);
354 uint8_t *ret_part = data + data_len; 380 uint8_t *ret_part = data + data_len;
355 new_nonce(ret_part); 381 random_nonce(ret_part);
356 len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ip_port, SIZE_IPPORT, 382 len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ip_port, SIZE_IPPORT,
357 ret_part + crypto_box_NONCEBYTES); 383 ret_part + CRYPTO_NONCE_SIZE);
358 384
359 if (len != SIZE_IPPORT + crypto_box_MACBYTES) 385 if (len != SIZE_IPPORT + CRYPTO_MAC_SIZE) {
360 return 1; 386 return 1;
387 }
361 388
362 data_len += crypto_box_NONCEBYTES + len; 389 data_len += CRYPTO_NONCE_SIZE + len;
363 390
364 if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) 391 if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) {
365 return 1; 392 return 1;
393 }
366 394
367 return 0; 395 return 0;
368} 396}
369 397
370static int handle_send_1(void *object, IP_Port source, const uint8_t *packet, uint16_t length) 398static int handle_send_1(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
371{ 399{
372 Onion *onion = object; 400 Onion *onion = (Onion *)object;
373 401
374 if (length > ONION_MAX_PACKET_SIZE) 402 if (length > ONION_MAX_PACKET_SIZE) {
375 return 1; 403 return 1;
404 }
376 405
377 if (length <= 1 + SEND_2) 406 if (length <= 1 + SEND_2) {
378 return 1; 407 return 1;
408 }
379 409
380 change_symmetric_key(onion); 410 change_symmetric_key(onion);
381 411
382 uint8_t plain[ONION_MAX_PACKET_SIZE]; 412 uint8_t plain[ONION_MAX_PACKET_SIZE];
383 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 413 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
384 get_shared_key(&onion->shared_keys_2, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); 414 get_shared_key(&onion->shared_keys_2, shared_key, dht_get_self_secret_key(onion->dht), packet + 1 + CRYPTO_NONCE_SIZE);
385 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, 415 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
386 length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1), plain); 416 length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1), plain);
387 417
388 if (len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1 + crypto_box_MACBYTES)) 418 if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1 + CRYPTO_MAC_SIZE)) {
389 return 1; 419 return 1;
420 }
390 421
391 IP_Port send_to; 422 IP_Port send_to;
392 423
393 if (ipport_unpack(&send_to, plain, len, 0) == -1) 424 if (ipport_unpack(&send_to, plain, len, 0) == -1) {
394 return 1; 425 return 1;
426 }
395 427
396 uint8_t data[ONION_MAX_PACKET_SIZE]; 428 uint8_t data[ONION_MAX_PACKET_SIZE];
397 data[0] = NET_PACKET_ONION_SEND_2; 429 data[0] = NET_PACKET_ONION_SEND_2;
398 memcpy(data + 1, packet + 1, crypto_box_NONCEBYTES); 430 memcpy(data + 1, packet + 1, CRYPTO_NONCE_SIZE);
399 memcpy(data + 1 + crypto_box_NONCEBYTES, plain + SIZE_IPPORT, len - SIZE_IPPORT); 431 memcpy(data + 1 + CRYPTO_NONCE_SIZE, plain + SIZE_IPPORT, len - SIZE_IPPORT);
400 uint16_t data_len = 1 + crypto_box_NONCEBYTES + (len - SIZE_IPPORT); 432 uint16_t data_len = 1 + CRYPTO_NONCE_SIZE + (len - SIZE_IPPORT);
401 uint8_t *ret_part = data + data_len; 433 uint8_t *ret_part = data + data_len;
402 new_nonce(ret_part); 434 random_nonce(ret_part);
403 uint8_t ret_data[RETURN_1 + SIZE_IPPORT]; 435 uint8_t ret_data[RETURN_1 + SIZE_IPPORT];
404 ipport_pack(ret_data, &source); 436 ipport_pack(ret_data, &source);
405 memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_1), RETURN_1); 437 memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_1), RETURN_1);
406 len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data), 438 len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),
407 ret_part + crypto_box_NONCEBYTES); 439 ret_part + CRYPTO_NONCE_SIZE);
408 440
409 if (len != RETURN_2 - crypto_box_NONCEBYTES) 441 if (len != RETURN_2 - CRYPTO_NONCE_SIZE) {
410 return 1; 442 return 1;
443 }
411 444
412 data_len += crypto_box_NONCEBYTES + len; 445 data_len += CRYPTO_NONCE_SIZE + len;
413 446
414 if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) 447 if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) {
415 return 1; 448 return 1;
449 }
416 450
417 return 0; 451 return 0;
418} 452}
419 453
420static int handle_send_2(void *object, IP_Port source, const uint8_t *packet, uint16_t length) 454static int handle_send_2(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
421{ 455{
422 Onion *onion = object; 456 Onion *onion = (Onion *)object;
423 457
424 if (length > ONION_MAX_PACKET_SIZE) 458 if (length > ONION_MAX_PACKET_SIZE) {
425 return 1; 459 return 1;
460 }
426 461
427 if (length <= 1 + SEND_3) 462 if (length <= 1 + SEND_3) {
428 return 1; 463 return 1;
464 }
429 465
430 change_symmetric_key(onion); 466 change_symmetric_key(onion);
431 467
432 uint8_t plain[ONION_MAX_PACKET_SIZE]; 468 uint8_t plain[ONION_MAX_PACKET_SIZE];
433 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 469 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
434 get_shared_key(&onion->shared_keys_3, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); 470 get_shared_key(&onion->shared_keys_3, shared_key, dht_get_self_secret_key(onion->dht), packet + 1 + CRYPTO_NONCE_SIZE);
435 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, 471 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
436 length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2), plain); 472 length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2), plain);
437 473
438 if (len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2 + crypto_box_MACBYTES)) 474 if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2 + CRYPTO_MAC_SIZE)) {
439 return 1; 475 return 1;
476 }
440 477
441 if (len <= SIZE_IPPORT) { 478 if (len <= SIZE_IPPORT) {
442 return 1; 479 return 1;
@@ -449,41 +486,46 @@ static int handle_send_2(void *object, IP_Port source, const uint8_t *packet, ui
449 486
450 IP_Port send_to; 487 IP_Port send_to;
451 488
452 if (ipport_unpack(&send_to, plain, len, 0) == -1) 489 if (ipport_unpack(&send_to, plain, len, 0) == -1) {
453 return 1; 490 return 1;
491 }
454 492
455 uint8_t data[ONION_MAX_PACKET_SIZE]; 493 uint8_t data[ONION_MAX_PACKET_SIZE];
456 memcpy(data, plain + SIZE_IPPORT, len - SIZE_IPPORT); 494 memcpy(data, plain + SIZE_IPPORT, len - SIZE_IPPORT);
457 uint16_t data_len = (len - SIZE_IPPORT); 495 uint16_t data_len = (len - SIZE_IPPORT);
458 uint8_t *ret_part = data + (len - SIZE_IPPORT); 496 uint8_t *ret_part = data + (len - SIZE_IPPORT);
459 new_nonce(ret_part); 497 random_nonce(ret_part);
460 uint8_t ret_data[RETURN_2 + SIZE_IPPORT]; 498 uint8_t ret_data[RETURN_2 + SIZE_IPPORT];
461 ipport_pack(ret_data, &source); 499 ipport_pack(ret_data, &source);
462 memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_2), RETURN_2); 500 memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_2), RETURN_2);
463 len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data), 501 len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),
464 ret_part + crypto_box_NONCEBYTES); 502 ret_part + CRYPTO_NONCE_SIZE);
465 503
466 if (len != RETURN_3 - crypto_box_NONCEBYTES) 504 if (len != RETURN_3 - CRYPTO_NONCE_SIZE) {
467 return 1; 505 return 1;
506 }
468 507
469 data_len += RETURN_3; 508 data_len += RETURN_3;
470 509
471 if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) 510 if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) {
472 return 1; 511 return 1;
512 }
473 513
474 return 0; 514 return 0;
475} 515}
476 516
477 517
478static int handle_recv_3(void *object, IP_Port source, const uint8_t *packet, uint16_t length) 518static int handle_recv_3(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
479{ 519{
480 Onion *onion = object; 520 Onion *onion = (Onion *)object;
481 521
482 if (length > ONION_MAX_PACKET_SIZE) 522 if (length > ONION_MAX_PACKET_SIZE) {
483 return 1; 523 return 1;
524 }
484 525
485 if (length <= 1 + RETURN_3) 526 if (length <= 1 + RETURN_3) {
486 return 1; 527 return 1;
528 }
487 529
488 if (packet[1 + RETURN_3] != NET_PACKET_ANNOUNCE_RESPONSE && 530 if (packet[1 + RETURN_3] != NET_PACKET_ANNOUNCE_RESPONSE &&
489 packet[1 + RETURN_3] != NET_PACKET_ONION_DATA_RESPONSE) { 531 packet[1 + RETURN_3] != NET_PACKET_ONION_DATA_RESPONSE) {
@@ -493,16 +535,18 @@ static int handle_recv_3(void *object, IP_Port source, const uint8_t *packet, ui
493 change_symmetric_key(onion); 535 change_symmetric_key(onion);
494 536
495 uint8_t plain[SIZE_IPPORT + RETURN_2]; 537 uint8_t plain[SIZE_IPPORT + RETURN_2];
496 int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES, 538 int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
497 SIZE_IPPORT + RETURN_2 + crypto_box_MACBYTES, plain); 539 SIZE_IPPORT + RETURN_2 + CRYPTO_MAC_SIZE, plain);
498 540
499 if ((uint32_t)len != sizeof(plain)) 541 if ((uint32_t)len != sizeof(plain)) {
500 return 1; 542 return 1;
543 }
501 544
502 IP_Port send_to; 545 IP_Port send_to;
503 546
504 if (ipport_unpack(&send_to, plain, len, 0) == -1) 547 if (ipport_unpack(&send_to, plain, len, 0) == -1) {
505 return 1; 548 return 1;
549 }
506 550
507 uint8_t data[ONION_MAX_PACKET_SIZE]; 551 uint8_t data[ONION_MAX_PACKET_SIZE];
508 data[0] = NET_PACKET_ONION_RECV_2; 552 data[0] = NET_PACKET_ONION_RECV_2;
@@ -510,21 +554,24 @@ static int handle_recv_3(void *object, IP_Port source, const uint8_t *packet, ui
510 memcpy(data + 1 + RETURN_2, packet + 1 + RETURN_3, length - (1 + RETURN_3)); 554 memcpy(data + 1 + RETURN_2, packet + 1 + RETURN_3, length - (1 + RETURN_3));
511 uint16_t data_len = 1 + RETURN_2 + (length - (1 + RETURN_3)); 555 uint16_t data_len = 1 + RETURN_2 + (length - (1 + RETURN_3));
512 556
513 if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) 557 if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) {
514 return 1; 558 return 1;
559 }
515 560
516 return 0; 561 return 0;
517} 562}
518 563
519static int handle_recv_2(void *object, IP_Port source, const uint8_t *packet, uint16_t length) 564static int handle_recv_2(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
520{ 565{
521 Onion *onion = object; 566 Onion *onion = (Onion *)object;
522 567
523 if (length > ONION_MAX_PACKET_SIZE) 568 if (length > ONION_MAX_PACKET_SIZE) {
524 return 1; 569 return 1;
570 }
525 571
526 if (length <= 1 + RETURN_2) 572 if (length <= 1 + RETURN_2) {
527 return 1; 573 return 1;
574 }
528 575
529 if (packet[1 + RETURN_2] != NET_PACKET_ANNOUNCE_RESPONSE && 576 if (packet[1 + RETURN_2] != NET_PACKET_ANNOUNCE_RESPONSE &&
530 packet[1 + RETURN_2] != NET_PACKET_ONION_DATA_RESPONSE) { 577 packet[1 + RETURN_2] != NET_PACKET_ONION_DATA_RESPONSE) {
@@ -534,16 +581,18 @@ static int handle_recv_2(void *object, IP_Port source, const uint8_t *packet, ui
534 change_symmetric_key(onion); 581 change_symmetric_key(onion);
535 582
536 uint8_t plain[SIZE_IPPORT + RETURN_1]; 583 uint8_t plain[SIZE_IPPORT + RETURN_1];
537 int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES, 584 int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
538 SIZE_IPPORT + RETURN_1 + crypto_box_MACBYTES, plain); 585 SIZE_IPPORT + RETURN_1 + CRYPTO_MAC_SIZE, plain);
539 586
540 if ((uint32_t)len != sizeof(plain)) 587 if ((uint32_t)len != sizeof(plain)) {
541 return 1; 588 return 1;
589 }
542 590
543 IP_Port send_to; 591 IP_Port send_to;
544 592
545 if (ipport_unpack(&send_to, plain, len, 0) == -1) 593 if (ipport_unpack(&send_to, plain, len, 0) == -1) {
546 return 1; 594 return 1;
595 }
547 596
548 uint8_t data[ONION_MAX_PACKET_SIZE]; 597 uint8_t data[ONION_MAX_PACKET_SIZE];
549 data[0] = NET_PACKET_ONION_RECV_1; 598 data[0] = NET_PACKET_ONION_RECV_1;
@@ -551,21 +600,24 @@ static int handle_recv_2(void *object, IP_Port source, const uint8_t *packet, ui
551 memcpy(data + 1 + RETURN_1, packet + 1 + RETURN_2, length - (1 + RETURN_2)); 600 memcpy(data + 1 + RETURN_1, packet + 1 + RETURN_2, length - (1 + RETURN_2));
552 uint16_t data_len = 1 + RETURN_1 + (length - (1 + RETURN_2)); 601 uint16_t data_len = 1 + RETURN_1 + (length - (1 + RETURN_2));
553 602
554 if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) 603 if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) {
555 return 1; 604 return 1;
605 }
556 606
557 return 0; 607 return 0;
558} 608}
559 609
560static int handle_recv_1(void *object, IP_Port source, const uint8_t *packet, uint16_t length) 610static int handle_recv_1(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
561{ 611{
562 Onion *onion = object; 612 Onion *onion = (Onion *)object;
563 613
564 if (length > ONION_MAX_PACKET_SIZE) 614 if (length > ONION_MAX_PACKET_SIZE) {
565 return 1; 615 return 1;
616 }
566 617
567 if (length <= 1 + RETURN_1) 618 if (length <= 1 + RETURN_1) {
568 return 1; 619 return 1;
620 }
569 621
570 if (packet[1 + RETURN_1] != NET_PACKET_ANNOUNCE_RESPONSE && 622 if (packet[1 + RETURN_1] != NET_PACKET_ANNOUNCE_RESPONSE &&
571 packet[1 + RETURN_1] != NET_PACKET_ONION_DATA_RESPONSE) { 623 packet[1 + RETURN_1] != NET_PACKET_ONION_DATA_RESPONSE) {
@@ -575,24 +627,30 @@ static int handle_recv_1(void *object, IP_Port source, const uint8_t *packet, ui
575 change_symmetric_key(onion); 627 change_symmetric_key(onion);
576 628
577 uint8_t plain[SIZE_IPPORT]; 629 uint8_t plain[SIZE_IPPORT];
578 int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES, 630 int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
579 SIZE_IPPORT + crypto_box_MACBYTES, plain); 631 SIZE_IPPORT + CRYPTO_MAC_SIZE, plain);
580 632
581 if ((uint32_t)len != SIZE_IPPORT) 633 if ((uint32_t)len != SIZE_IPPORT) {
582 return 1; 634 return 1;
635 }
583 636
584 IP_Port send_to; 637 IP_Port send_to;
585 638
586 if (ipport_unpack(&send_to, plain, len, 1) == -1) 639 if (ipport_unpack(&send_to, plain, len, 1) == -1) {
587 return 1; 640 return 1;
641 }
588 642
589 uint16_t data_len = length - (1 + RETURN_1); 643 uint16_t data_len = length - (1 + RETURN_1);
590 644
591 if (onion->recv_1_function && send_to.ip.family != AF_INET && send_to.ip.family != AF_INET6) 645 if (onion->recv_1_function &&
646 !net_family_is_ipv4(send_to.ip.family) &&
647 !net_family_is_ipv6(send_to.ip.family)) {
592 return onion->recv_1_function(onion->callback_object, send_to, packet + (1 + RETURN_1), data_len); 648 return onion->recv_1_function(onion->callback_object, send_to, packet + (1 + RETURN_1), data_len);
649 }
593 650
594 if ((uint32_t)sendpacket(onion->net, send_to, packet + (1 + RETURN_1), data_len) != data_len) 651 if ((uint32_t)sendpacket(onion->net, send_to, packet + (1 + RETURN_1), data_len) != data_len) {
595 return 1; 652 return 1;
653 }
596 654
597 return 0; 655 return 0;
598} 656}
@@ -605,16 +663,18 @@ void set_callback_handle_recv_1(Onion *onion, int (*function)(void *, IP_Port, c
605 663
606Onion *new_onion(DHT *dht) 664Onion *new_onion(DHT *dht)
607{ 665{
608 if (dht == NULL) 666 if (dht == nullptr) {
609 return NULL; 667 return nullptr;
668 }
610 669
611 Onion *onion = calloc(1, sizeof(Onion)); 670 Onion *onion = (Onion *)calloc(1, sizeof(Onion));
612 671
613 if (onion == NULL) 672 if (onion == nullptr) {
614 return NULL; 673 return nullptr;
674 }
615 675
616 onion->dht = dht; 676 onion->dht = dht;
617 onion->net = dht->net; 677 onion->net = dht_get_net(dht);
618 new_symmetric_key(onion->secret_symmetric_key); 678 new_symmetric_key(onion->secret_symmetric_key);
619 onion->timestamp = unix_time(); 679 onion->timestamp = unix_time();
620 680
@@ -631,16 +691,17 @@ Onion *new_onion(DHT *dht)
631 691
632void kill_onion(Onion *onion) 692void kill_onion(Onion *onion)
633{ 693{
634 if (onion == NULL) 694 if (onion == nullptr) {
635 return; 695 return;
696 }
636 697
637 networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_INITIAL, NULL, NULL); 698 networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_INITIAL, nullptr, nullptr);
638 networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, NULL, NULL); 699 networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, nullptr, nullptr);
639 networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_2, NULL, NULL); 700 networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_2, nullptr, nullptr);
640 701
641 networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_3, NULL, NULL); 702 networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_3, nullptr, nullptr);
642 networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_2, NULL, NULL); 703 networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_2, nullptr, nullptr);
643 networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_1, NULL, NULL); 704 networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_1, nullptr, nullptr);
644 705
645 free(onion); 706 free(onion);
646} 707}
diff --git a/toxcore/onion.h b/toxcore/onion.h
index 2b270ea9..e81b3a52 100644
--- a/toxcore/onion.h
+++ b/toxcore/onion.h
@@ -1,25 +1,26 @@
1/* 1/*
2* onion.h -- Implementation of the onion part of docs/Prevent_Tracking.txt 2 * Implementation of the onion part of docs/Prevent_Tracking.txt
3* 3 */
4* Copyright (C) 2013 Tox project All Rights Reserved.
5*
6* This file is part of Tox.
7*
8* Tox is free software: you can redistribute it and/or modify
9* it under the terms of the GNU General Public License as published by
10* the Free Software Foundation, either version 3 of the License, or
11* (at your option) any later version.
12*
13* Tox is distributed in the hope that it will be useful,
14* but WITHOUT ANY WARRANTY; without even the implied warranty of
15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16* GNU General Public License for more details.
17*
18* You should have received a copy of the GNU General Public License
19* along with Tox. If not, see <http://www.gnu.org/licenses/>.
20*
21*/
22 4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2013 Tox project.
8 *
9 * This file is part of Tox, the free peer to peer instant messenger.
10 *
11 * Tox is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * Tox is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
23 */
23#ifndef ONION_H 24#ifndef ONION_H
24#define ONION_H 25#define ONION_H
25 26
@@ -28,7 +29,7 @@
28typedef struct { 29typedef struct {
29 DHT *dht; 30 DHT *dht;
30 Networking_Core *net; 31 Networking_Core *net;
31 uint8_t secret_symmetric_key[crypto_box_KEYBYTES]; 32 uint8_t secret_symmetric_key[CRYPTO_SYMMETRIC_KEY_SIZE];
32 uint64_t timestamp; 33 uint64_t timestamp;
33 34
34 Shared_Keys shared_keys_1; 35 Shared_Keys shared_keys_1;
@@ -41,14 +42,14 @@ typedef struct {
41 42
42#define ONION_MAX_PACKET_SIZE 1400 43#define ONION_MAX_PACKET_SIZE 1400
43 44
44#define ONION_RETURN_1 (crypto_box_NONCEBYTES + SIZE_IPPORT + crypto_box_MACBYTES) 45#define ONION_RETURN_1 (CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_MAC_SIZE)
45#define ONION_RETURN_2 (crypto_box_NONCEBYTES + SIZE_IPPORT + crypto_box_MACBYTES + ONION_RETURN_1) 46#define ONION_RETURN_2 (CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_MAC_SIZE + ONION_RETURN_1)
46#define ONION_RETURN_3 (crypto_box_NONCEBYTES + SIZE_IPPORT + crypto_box_MACBYTES + ONION_RETURN_2) 47#define ONION_RETURN_3 (CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_MAC_SIZE + ONION_RETURN_2)
47 48
48#define ONION_SEND_BASE (crypto_box_PUBLICKEYBYTES + SIZE_IPPORT + crypto_box_MACBYTES) 49#define ONION_SEND_BASE (CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT + CRYPTO_MAC_SIZE)
49#define ONION_SEND_3 (crypto_box_NONCEBYTES + ONION_SEND_BASE + ONION_RETURN_2) 50#define ONION_SEND_3 (CRYPTO_NONCE_SIZE + ONION_SEND_BASE + ONION_RETURN_2)
50#define ONION_SEND_2 (crypto_box_NONCEBYTES + ONION_SEND_BASE*2 + ONION_RETURN_1) 51#define ONION_SEND_2 (CRYPTO_NONCE_SIZE + ONION_SEND_BASE*2 + ONION_RETURN_1)
51#define ONION_SEND_1 (crypto_box_NONCEBYTES + ONION_SEND_BASE*3) 52#define ONION_SEND_1 (CRYPTO_NONCE_SIZE + ONION_SEND_BASE*3)
52 53
53#define ONION_MAX_DATA_SIZE (ONION_MAX_PACKET_SIZE - (ONION_SEND_1 + 1)) 54#define ONION_MAX_DATA_SIZE (ONION_MAX_PACKET_SIZE - (ONION_SEND_1 + 1))
54#define ONION_RESPONSE_MAX_DATA_SIZE (ONION_MAX_PACKET_SIZE - (1 + ONION_RETURN_3)) 55#define ONION_RESPONSE_MAX_DATA_SIZE (ONION_MAX_PACKET_SIZE - (1 + ONION_RETURN_3))
@@ -56,22 +57,22 @@ typedef struct {
56#define ONION_PATH_LENGTH 3 57#define ONION_PATH_LENGTH 3
57 58
58typedef struct { 59typedef struct {
59 uint8_t shared_key1[crypto_box_BEFORENMBYTES]; 60 uint8_t shared_key1[CRYPTO_SHARED_KEY_SIZE];
60 uint8_t shared_key2[crypto_box_BEFORENMBYTES]; 61 uint8_t shared_key2[CRYPTO_SHARED_KEY_SIZE];
61 uint8_t shared_key3[crypto_box_BEFORENMBYTES]; 62 uint8_t shared_key3[CRYPTO_SHARED_KEY_SIZE];
62 63
63 uint8_t public_key1[crypto_box_PUBLICKEYBYTES]; 64 uint8_t public_key1[CRYPTO_PUBLIC_KEY_SIZE];
64 uint8_t public_key2[crypto_box_PUBLICKEYBYTES]; 65 uint8_t public_key2[CRYPTO_PUBLIC_KEY_SIZE];
65 uint8_t public_key3[crypto_box_PUBLICKEYBYTES]; 66 uint8_t public_key3[CRYPTO_PUBLIC_KEY_SIZE];
66 67
67 IP_Port ip_port1; 68 IP_Port ip_port1;
68 uint8_t node_public_key1[crypto_box_PUBLICKEYBYTES]; 69 uint8_t node_public_key1[CRYPTO_PUBLIC_KEY_SIZE];
69 70
70 IP_Port ip_port2; 71 IP_Port ip_port2;
71 uint8_t node_public_key2[crypto_box_PUBLICKEYBYTES]; 72 uint8_t node_public_key2[CRYPTO_PUBLIC_KEY_SIZE];
72 73
73 IP_Port ip_port3; 74 IP_Port ip_port3;
74 uint8_t node_public_key3[crypto_box_PUBLICKEYBYTES]; 75 uint8_t node_public_key3[CRYPTO_PUBLIC_KEY_SIZE];
75 76
76 uint32_t path_num; 77 uint32_t path_num;
77} Onion_Path; 78} Onion_Path;
@@ -144,12 +145,12 @@ int send_onion_response(Networking_Core *net, IP_Port dest, const uint8_t *data,
144 * 145 *
145 * Used to handle these packets that are received in a non traditional way (by TCP for example). 146 * Used to handle these packets that are received in a non traditional way (by TCP for example).
146 * 147 *
147 * Source family must be set to something else than AF_INET6 or AF_INET so that the callback gets called 148 * Source family must be set to something else than TOX_AF_INET6 or TOX_AF_INET so that the callback gets called
148 * when the response is received. 149 * when the response is received.
149 */ 150 */
150int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, IP_Port source, const uint8_t *nonce); 151int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, IP_Port source, const uint8_t *nonce);
151 152
152/* Set the callback to be called when the dest ip_port doesn't have AF_INET6 or AF_INET as the family. 153/* Set the callback to be called when the dest ip_port doesn't have TOX_AF_INET6 or TOX_AF_INET as the family.
153 * 154 *
154 * Format: function(void *object, IP_Port dest, uint8_t *data, uint16_t length) 155 * Format: function(void *object, IP_Port dest, uint8_t *data, uint16_t length)
155 */ 156 */
diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c
index 676b38da..6c9e8659 100644
--- a/toxcore/onion_announce.c
+++ b/toxcore/onion_announce.c
@@ -1,39 +1,73 @@
1/* 1/*
2* onion_announce.c -- Implementation of the announce part of docs/Prevent_Tracking.txt 2 * Implementation of the announce part of docs/Prevent_Tracking.txt
3* 3 */
4* Copyright (C) 2013 Tox project All Rights Reserved. 4
5* 5/*
6* This file is part of Tox. 6 * Copyright © 2016-2017 The TokTok team.
7* 7 * Copyright © 2013 Tox project.
8* Tox is free software: you can redistribute it and/or modify 8 *
9* it under the terms of the GNU General Public License as published by 9 * This file is part of Tox, the free peer to peer instant messenger.
10* the Free Software Foundation, either version 3 of the License, or 10 *
11* (at your option) any later version. 11 * Tox is free software: you can redistribute it and/or modify
12* 12 * it under the terms of the GNU General Public License as published by
13* Tox is distributed in the hope that it will be useful, 13 * the Free Software Foundation, either version 3 of the License, or
14* but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * (at your option) any later version.
15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 *
16* GNU General Public License for more details. 16 * Tox is distributed in the hope that it will be useful,
17* 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18* You should have received a copy of the GNU General Public License 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19* along with Tox. If not, see <http://www.gnu.org/licenses/>. 19 * GNU General Public License for more details.
20* 20 *
21*/ 21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
23 */
22#ifdef HAVE_CONFIG_H 24#ifdef HAVE_CONFIG_H
23#include "config.h" 25#include "config.h"
24#endif 26#endif
25 27
26#include "onion_announce.h" 28#include "onion_announce.h"
29
30#include <stdlib.h>
31#include <string.h>
32
27#include "LAN_discovery.h" 33#include "LAN_discovery.h"
28#include "util.h" 34#include "util.h"
29 35
30#define PING_ID_TIMEOUT 20 36#define PING_ID_TIMEOUT ONION_ANNOUNCE_TIMEOUT
31 37
32#define ANNOUNCE_REQUEST_SIZE_RECV (ONION_ANNOUNCE_REQUEST_SIZE + ONION_RETURN_3) 38#define ANNOUNCE_REQUEST_SIZE_RECV (ONION_ANNOUNCE_REQUEST_SIZE + ONION_RETURN_3)
33 39
34#define DATA_REQUEST_MIN_SIZE ONION_DATA_REQUEST_MIN_SIZE 40#define DATA_REQUEST_MIN_SIZE ONION_DATA_REQUEST_MIN_SIZE
35#define DATA_REQUEST_MIN_SIZE_RECV (DATA_REQUEST_MIN_SIZE + ONION_RETURN_3) 41#define DATA_REQUEST_MIN_SIZE_RECV (DATA_REQUEST_MIN_SIZE + ONION_RETURN_3)
36 42
43typedef struct {
44 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
45 IP_Port ret_ip_port;
46 uint8_t ret[ONION_RETURN_3];
47 uint8_t data_public_key[CRYPTO_PUBLIC_KEY_SIZE];
48 uint64_t time;
49} Onion_Announce_Entry;
50
51struct Onion_Announce {
52 DHT *dht;
53 Networking_Core *net;
54 Onion_Announce_Entry entries[ONION_ANNOUNCE_MAX_ENTRIES];
55 /* This is CRYPTO_SYMMETRIC_KEY_SIZE long just so we can use new_symmetric_key() to fill it */
56 uint8_t secret_bytes[CRYPTO_SYMMETRIC_KEY_SIZE];
57
58 Shared_Keys shared_keys_recv;
59};
60
61uint8_t *onion_announce_entry_public_key(Onion_Announce *onion_a, uint32_t entry)
62{
63 return onion_a->entries[entry].public_key;
64}
65
66void onion_announce_entry_set_time(Onion_Announce *onion_a, uint32_t entry, uint64_t time)
67{
68 onion_a->entries[entry].time = time;
69}
70
37/* Create an onion announce request packet in packet of max_packet_length (recommended size ONION_ANNOUNCE_REQUEST_SIZE). 71/* Create an onion announce request packet in packet of max_packet_length (recommended size ONION_ANNOUNCE_REQUEST_SIZE).
38 * 72 *
39 * dest_client_id is the public key of the node the packet will be sent to. 73 * dest_client_id is the public key of the node the packet will be sent to.
@@ -51,27 +85,29 @@ int create_announce_request(uint8_t *packet, uint16_t max_packet_length, const u
51 const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id, 85 const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id,
52 const uint8_t *data_public_key, uint64_t sendback_data) 86 const uint8_t *data_public_key, uint64_t sendback_data)
53{ 87{
54 if (max_packet_length < ONION_ANNOUNCE_REQUEST_SIZE) 88 if (max_packet_length < ONION_ANNOUNCE_REQUEST_SIZE) {
55 return -1; 89 return -1;
90 }
56 91
57 uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + 92 uint8_t plain[ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE +
58 ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; 93 ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
59 memcpy(plain, ping_id, ONION_PING_ID_SIZE); 94 memcpy(plain, ping_id, ONION_PING_ID_SIZE);
60 memcpy(plain + ONION_PING_ID_SIZE, client_id, crypto_box_PUBLICKEYBYTES); 95 memcpy(plain + ONION_PING_ID_SIZE, client_id, CRYPTO_PUBLIC_KEY_SIZE);
61 memcpy(plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES, data_public_key, crypto_box_PUBLICKEYBYTES); 96 memcpy(plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE, data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
62 memcpy(plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES, &sendback_data, 97 memcpy(plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE, &sendback_data,
63 sizeof(sendback_data)); 98 sizeof(sendback_data));
64 99
65 packet[0] = NET_PACKET_ANNOUNCE_REQUEST; 100 packet[0] = NET_PACKET_ANNOUNCE_REQUEST;
66 random_nonce(packet + 1); 101 random_nonce(packet + 1);
67 102
68 int len = encrypt_data(dest_client_id, secret_key, packet + 1, plain, sizeof(plain), 103 int len = encrypt_data(dest_client_id, secret_key, packet + 1, plain, sizeof(plain),
69 packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); 104 packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);
70 105
71 if ((uint32_t)len + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES != ONION_ANNOUNCE_REQUEST_SIZE) 106 if ((uint32_t)len + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE != ONION_ANNOUNCE_REQUEST_SIZE) {
72 return -1; 107 return -1;
108 }
73 109
74 memcpy(packet + 1 + crypto_box_NONCEBYTES, public_key, crypto_box_PUBLICKEYBYTES); 110 memcpy(packet + 1 + CRYPTO_NONCE_SIZE, public_key, CRYPTO_PUBLIC_KEY_SIZE);
75 111
76 return ONION_ANNOUNCE_REQUEST_SIZE; 112 return ONION_ANNOUNCE_REQUEST_SIZE;
77} 113}
@@ -89,28 +125,31 @@ int create_announce_request(uint8_t *packet, uint16_t max_packet_length, const u
89int create_data_request(uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key, 125int create_data_request(uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key,
90 const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length) 126 const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length)
91{ 127{
92 if (DATA_REQUEST_MIN_SIZE + length > max_packet_length) 128 if (DATA_REQUEST_MIN_SIZE + length > max_packet_length) {
93 return -1; 129 return -1;
130 }
94 131
95 if ((unsigned int)DATA_REQUEST_MIN_SIZE + length > ONION_MAX_DATA_SIZE) 132 if (DATA_REQUEST_MIN_SIZE + length > ONION_MAX_DATA_SIZE) {
96 return -1; 133 return -1;
134 }
97 135
98 packet[0] = NET_PACKET_ONION_DATA_REQUEST; 136 packet[0] = NET_PACKET_ONION_DATA_REQUEST;
99 memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); 137 memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);
100 memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); 138 memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
101 139
102 uint8_t random_public_key[crypto_box_PUBLICKEYBYTES]; 140 uint8_t random_public_key[CRYPTO_PUBLIC_KEY_SIZE];
103 uint8_t random_secret_key[crypto_box_SECRETKEYBYTES]; 141 uint8_t random_secret_key[CRYPTO_SECRET_KEY_SIZE];
104 crypto_box_keypair(random_public_key, random_secret_key); 142 crypto_new_keypair(random_public_key, random_secret_key);
105 143
106 memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, random_public_key, crypto_box_PUBLICKEYBYTES); 144 memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, random_public_key, CRYPTO_PUBLIC_KEY_SIZE);
107 145
108 int len = encrypt_data(encrypt_public_key, random_secret_key, packet + 1 + crypto_box_PUBLICKEYBYTES, data, length, 146 int len = encrypt_data(encrypt_public_key, random_secret_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length,
109 packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); 147 packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);
110 148
111 if (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + len != DATA_REQUEST_MIN_SIZE + 149 if (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + len != DATA_REQUEST_MIN_SIZE +
112 length) 150 length) {
113 return -1; 151 return -1;
152 }
114 153
115 return DATA_REQUEST_MIN_SIZE + length; 154 return DATA_REQUEST_MIN_SIZE + length;
116} 155}
@@ -137,17 +176,20 @@ int send_announce_request(Networking_Core *net, const Onion_Path *path, Node_for
137 int len = create_announce_request(request, sizeof(request), dest.public_key, public_key, secret_key, ping_id, client_id, 176 int len = create_announce_request(request, sizeof(request), dest.public_key, public_key, secret_key, ping_id, client_id,
138 data_public_key, sendback_data); 177 data_public_key, sendback_data);
139 178
140 if (len != sizeof(request)) 179 if (len != sizeof(request)) {
141 return -1; 180 return -1;
181 }
142 182
143 uint8_t packet[ONION_MAX_PACKET_SIZE]; 183 uint8_t packet[ONION_MAX_PACKET_SIZE];
144 len = create_onion_packet(packet, sizeof(packet), path, dest.ip_port, request, sizeof(request)); 184 len = create_onion_packet(packet, sizeof(packet), path, dest.ip_port, request, sizeof(request));
145 185
146 if (len == -1) 186 if (len == -1) {
147 return -1; 187 return -1;
188 }
148 189
149 if (sendpacket(net, path->ip_port1, packet, len) != len) 190 if (sendpacket(net, path->ip_port1, packet, len) != len) {
150 return -1; 191 return -1;
192 }
151 193
152 return 0; 194 return 0;
153} 195}
@@ -172,17 +214,20 @@ int send_data_request(Networking_Core *net, const Onion_Path *path, IP_Port dest
172 uint8_t request[ONION_MAX_DATA_SIZE]; 214 uint8_t request[ONION_MAX_DATA_SIZE];
173 int len = create_data_request(request, sizeof(request), public_key, encrypt_public_key, nonce, data, length); 215 int len = create_data_request(request, sizeof(request), public_key, encrypt_public_key, nonce, data, length);
174 216
175 if (len == -1) 217 if (len == -1) {
176 return -1; 218 return -1;
219 }
177 220
178 uint8_t packet[ONION_MAX_PACKET_SIZE]; 221 uint8_t packet[ONION_MAX_PACKET_SIZE];
179 len = create_onion_packet(packet, sizeof(packet), path, dest, request, len); 222 len = create_onion_packet(packet, sizeof(packet), path, dest, request, len);
180 223
181 if (len == -1) 224 if (len == -1) {
182 return -1; 225 return -1;
226 }
183 227
184 if (sendpacket(net, path->ip_port1, packet, len) != len) 228 if (sendpacket(net, path->ip_port1, packet, len) != len) {
185 return -1; 229 return -1;
230 }
186 231
187 return 0; 232 return 0;
188} 233}
@@ -192,12 +237,12 @@ static void generate_ping_id(const Onion_Announce *onion_a, uint64_t time, const
192 IP_Port ret_ip_port, uint8_t *ping_id) 237 IP_Port ret_ip_port, uint8_t *ping_id)
193{ 238{
194 time /= PING_ID_TIMEOUT; 239 time /= PING_ID_TIMEOUT;
195 uint8_t data[crypto_box_KEYBYTES + sizeof(time) + crypto_box_PUBLICKEYBYTES + sizeof(ret_ip_port)]; 240 uint8_t data[CRYPTO_SYMMETRIC_KEY_SIZE + sizeof(time) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(ret_ip_port)];
196 memcpy(data, onion_a->secret_bytes, crypto_box_KEYBYTES); 241 memcpy(data, onion_a->secret_bytes, CRYPTO_SYMMETRIC_KEY_SIZE);
197 memcpy(data + crypto_box_KEYBYTES, &time, sizeof(time)); 242 memcpy(data + CRYPTO_SYMMETRIC_KEY_SIZE, &time, sizeof(time));
198 memcpy(data + crypto_box_KEYBYTES + sizeof(time), public_key, crypto_box_PUBLICKEYBYTES); 243 memcpy(data + CRYPTO_SYMMETRIC_KEY_SIZE + sizeof(time), public_key, CRYPTO_PUBLIC_KEY_SIZE);
199 memcpy(data + crypto_box_KEYBYTES + sizeof(time) + crypto_box_PUBLICKEYBYTES, &ret_ip_port, sizeof(ret_ip_port)); 244 memcpy(data + CRYPTO_SYMMETRIC_KEY_SIZE + sizeof(time) + CRYPTO_PUBLIC_KEY_SIZE, &ret_ip_port, sizeof(ret_ip_port));
200 crypto_hash_sha256(ping_id, data, sizeof(data)); 245 crypto_sha256(ping_id, data, sizeof(data));
201} 246}
202 247
203/* check if public key is in entries list 248/* check if public key is in entries list
@@ -211,42 +256,74 @@ static int in_entries(const Onion_Announce *onion_a, const uint8_t *public_key)
211 256
212 for (i = 0; i < ONION_ANNOUNCE_MAX_ENTRIES; ++i) { 257 for (i = 0; i < ONION_ANNOUNCE_MAX_ENTRIES; ++i) {
213 if (!is_timeout(onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT) 258 if (!is_timeout(onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT)
214 && public_key_cmp(onion_a->entries[i].public_key, public_key) == 0) 259 && public_key_cmp(onion_a->entries[i].public_key, public_key) == 0) {
215 return i; 260 return i;
261 }
216 } 262 }
217 263
218 return -1; 264 return -1;
219} 265}
220 266
221static uint8_t cmp_public_key[crypto_box_PUBLICKEYBYTES]; 267typedef struct {
268 const uint8_t *base_public_key;
269 Onion_Announce_Entry entry;
270} Cmp_data;
271
222static int cmp_entry(const void *a, const void *b) 272static int cmp_entry(const void *a, const void *b)
223{ 273{
224 Onion_Announce_Entry entry1, entry2; 274 Cmp_data cmp1, cmp2;
225 memcpy(&entry1, a, sizeof(Onion_Announce_Entry)); 275 memcpy(&cmp1, a, sizeof(Cmp_data));
226 memcpy(&entry2, b, sizeof(Onion_Announce_Entry)); 276 memcpy(&cmp2, b, sizeof(Cmp_data));
277 Onion_Announce_Entry entry1 = cmp1.entry;
278 Onion_Announce_Entry entry2 = cmp2.entry;
279 const uint8_t *cmp_public_key = cmp1.base_public_key;
280
227 int t1 = is_timeout(entry1.time, ONION_ANNOUNCE_TIMEOUT); 281 int t1 = is_timeout(entry1.time, ONION_ANNOUNCE_TIMEOUT);
228 int t2 = is_timeout(entry2.time, ONION_ANNOUNCE_TIMEOUT); 282 int t2 = is_timeout(entry2.time, ONION_ANNOUNCE_TIMEOUT);
229 283
230 if (t1 && t2) 284 if (t1 && t2) {
231 return 0; 285 return 0;
286 }
232 287
233 if (t1) 288 if (t1) {
234 return -1; 289 return -1;
290 }
235 291
236 if (t2) 292 if (t2) {
237 return 1; 293 return 1;
294 }
238 295
239 int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key); 296 int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key);
240 297
241 if (close == 1) 298 if (close == 1) {
242 return 1; 299 return 1;
300 }
243 301
244 if (close == 2) 302 if (close == 2) {
245 return -1; 303 return -1;
304 }
246 305
247 return 0; 306 return 0;
248} 307}
249 308
309static void sort_onion_announce_list(Onion_Announce_Entry *list, unsigned int length, const uint8_t *comp_public_key)
310{
311 // Pass comp_public_key to qsort with each Client_data entry, so the
312 // comparison function can use it as the base of comparison.
313 VLA(Cmp_data, cmp_list, length);
314
315 for (uint32_t i = 0; i < length; i++) {
316 cmp_list[i].base_public_key = comp_public_key;
317 cmp_list[i].entry = list[i];
318 }
319
320 qsort(cmp_list, length, sizeof(Cmp_data), cmp_entry);
321
322 for (uint32_t i = 0; i < length; i++) {
323 list[i] = cmp_list[i].entry;
324 }
325}
326
250/* add entry to entries list 327/* add entry to entries list
251 * 328 *
252 * return -1 if failure 329 * return -1 if failure
@@ -258,53 +335,55 @@ static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, const ui
258 335
259 int pos = in_entries(onion_a, public_key); 336 int pos = in_entries(onion_a, public_key);
260 337
261 unsigned int i;
262
263 if (pos == -1) { 338 if (pos == -1) {
264 for (i = 0; i < ONION_ANNOUNCE_MAX_ENTRIES; ++i) { 339 for (unsigned i = 0; i < ONION_ANNOUNCE_MAX_ENTRIES; ++i) {
265 if (is_timeout(onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT)) 340 if (is_timeout(onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT)) {
266 pos = i; 341 pos = i;
342 }
267 } 343 }
268 } 344 }
269 345
270 if (pos == -1) { 346 if (pos == -1) {
271 if (id_closest(onion_a->dht->self_public_key, public_key, onion_a->entries[0].public_key) == 1) 347 if (id_closest(dht_get_self_public_key(onion_a->dht), public_key, onion_a->entries[0].public_key) == 1) {
272 pos = 0; 348 pos = 0;
349 }
273 } 350 }
274 351
275 if (pos == -1) 352 if (pos == -1) {
276 return -1; 353 return -1;
354 }
277 355
278 memcpy(onion_a->entries[pos].public_key, public_key, crypto_box_PUBLICKEYBYTES); 356 memcpy(onion_a->entries[pos].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
279 onion_a->entries[pos].ret_ip_port = ret_ip_port; 357 onion_a->entries[pos].ret_ip_port = ret_ip_port;
280 memcpy(onion_a->entries[pos].ret, ret, ONION_RETURN_3); 358 memcpy(onion_a->entries[pos].ret, ret, ONION_RETURN_3);
281 memcpy(onion_a->entries[pos].data_public_key, data_public_key, crypto_box_PUBLICKEYBYTES); 359 memcpy(onion_a->entries[pos].data_public_key, data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
282 onion_a->entries[pos].time = unix_time(); 360 onion_a->entries[pos].time = unix_time();
283 361
284 memcpy(cmp_public_key, onion_a->dht->self_public_key, crypto_box_PUBLICKEYBYTES); 362 sort_onion_announce_list(onion_a->entries, ONION_ANNOUNCE_MAX_ENTRIES, dht_get_self_public_key(onion_a->dht));
285 qsort(onion_a->entries, ONION_ANNOUNCE_MAX_ENTRIES, sizeof(Onion_Announce_Entry), cmp_entry);
286 return in_entries(onion_a, public_key); 363 return in_entries(onion_a, public_key);
287} 364}
288 365
289static int handle_announce_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length) 366static int handle_announce_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
290{ 367{
291 Onion_Announce *onion_a = object; 368 Onion_Announce *onion_a = (Onion_Announce *)object;
292 369
293 if (length != ANNOUNCE_REQUEST_SIZE_RECV) 370 if (length != ANNOUNCE_REQUEST_SIZE_RECV) {
294 return 1; 371 return 1;
372 }
295 373
296 const uint8_t *packet_public_key = packet + 1 + crypto_box_NONCEBYTES; 374 const uint8_t *packet_public_key = packet + 1 + CRYPTO_NONCE_SIZE;
297 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 375 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
298 get_shared_key(&onion_a->shared_keys_recv, shared_key, onion_a->dht->self_secret_key, packet_public_key); 376 get_shared_key(&onion_a->shared_keys_recv, shared_key, dht_get_self_secret_key(onion_a->dht), packet_public_key);
299 377
300 uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + 378 uint8_t plain[ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE +
301 ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; 379 ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
302 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, 380 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
303 ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + 381 ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH +
304 crypto_box_MACBYTES, plain); 382 CRYPTO_MAC_SIZE, plain);
305 383
306 if ((uint32_t)len != sizeof(plain)) 384 if ((uint32_t)len != sizeof(plain)) {
307 return 1; 385 return 1;
386 }
308 387
309 uint8_t ping_id1[ONION_PING_ID_SIZE]; 388 uint8_t ping_id1[ONION_PING_ID_SIZE];
310 generate_ping_id(onion_a, unix_time(), packet_public_key, source, ping_id1); 389 generate_ping_id(onion_a, unix_time(), packet_public_key, source, ping_id1);
@@ -312,12 +391,12 @@ static int handle_announce_request(void *object, IP_Port source, const uint8_t *
312 uint8_t ping_id2[ONION_PING_ID_SIZE]; 391 uint8_t ping_id2[ONION_PING_ID_SIZE];
313 generate_ping_id(onion_a, unix_time() + PING_ID_TIMEOUT, packet_public_key, source, ping_id2); 392 generate_ping_id(onion_a, unix_time() + PING_ID_TIMEOUT, packet_public_key, source, ping_id2);
314 393
315 int index = -1; 394 int index;
316 395
317 uint8_t *data_public_key = plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES; 396 uint8_t *data_public_key = plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE;
318 397
319 if (sodium_memcmp(ping_id1, plain, ONION_PING_ID_SIZE) == 0 398 if (crypto_memcmp(ping_id1, plain, ONION_PING_ID_SIZE) == 0
320 || sodium_memcmp(ping_id2, plain, ONION_PING_ID_SIZE) == 0) { 399 || crypto_memcmp(ping_id2, plain, ONION_PING_ID_SIZE) == 0) {
321 index = add_to_entries(onion_a, source, packet_public_key, data_public_key, 400 index = add_to_entries(onion_a, source, packet_public_key, data_public_key,
322 packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3)); 401 packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3));
323 } else { 402 } else {
@@ -326,9 +405,9 @@ static int handle_announce_request(void *object, IP_Port source, const uint8_t *
326 405
327 /*Respond with a announce response packet*/ 406 /*Respond with a announce response packet*/
328 Node_format nodes_list[MAX_SENT_NODES]; 407 Node_format nodes_list[MAX_SENT_NODES];
329 unsigned int num_nodes = get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, 0, 408 unsigned int num_nodes = get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, net_family_unspec,
330 LAN_ip(source.ip) == 0, 1); 409 ip_is_lan(source.ip) == 0, 1);
331 uint8_t nonce[crypto_box_NONCEBYTES]; 410 uint8_t nonce[CRYPTO_NONCE_SIZE];
332 random_nonce(nonce); 411 random_nonce(nonce);
333 412
334 uint8_t pl[1 + ONION_PING_ID_SIZE + sizeof(nodes_list)]; 413 uint8_t pl[1 + ONION_PING_ID_SIZE + sizeof(nodes_list)];
@@ -347,7 +426,7 @@ static int handle_announce_request(void *object, IP_Port source, const uint8_t *
347 } 426 }
348 } else { 427 } else {
349 pl[0] = 1; 428 pl[0] = 1;
350 memcpy(pl + 1, onion_a->entries[index].data_public_key, crypto_box_PUBLICKEYBYTES); 429 memcpy(pl + 1, onion_a->entries[index].data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
351 } 430 }
352 } 431 }
353 432
@@ -356,68 +435,77 @@ static int handle_announce_request(void *object, IP_Port source, const uint8_t *
356 if (num_nodes != 0) { 435 if (num_nodes != 0) {
357 nodes_length = pack_nodes(pl + 1 + ONION_PING_ID_SIZE, sizeof(nodes_list), nodes_list, num_nodes); 436 nodes_length = pack_nodes(pl + 1 + ONION_PING_ID_SIZE, sizeof(nodes_list), nodes_list, num_nodes);
358 437
359 if (nodes_length <= 0) 438 if (nodes_length <= 0) {
360 return 1; 439 return 1;
440 }
361 } 441 }
362 442
363 uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE]; 443 uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE];
364 len = encrypt_data_symmetric(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + nodes_length, 444 len = encrypt_data_symmetric(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + nodes_length,
365 data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES); 445 data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE);
366 446
367 if (len != 1 + ONION_PING_ID_SIZE + nodes_length + crypto_box_MACBYTES) 447 if (len != 1 + ONION_PING_ID_SIZE + nodes_length + CRYPTO_MAC_SIZE) {
368 return 1; 448 return 1;
449 }
369 450
370 data[0] = NET_PACKET_ANNOUNCE_RESPONSE; 451 data[0] = NET_PACKET_ANNOUNCE_RESPONSE;
371 memcpy(data + 1, plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES, 452 memcpy(data + 1, plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
372 ONION_ANNOUNCE_SENDBACK_DATA_LENGTH); 453 ONION_ANNOUNCE_SENDBACK_DATA_LENGTH);
373 memcpy(data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, nonce, crypto_box_NONCEBYTES); 454 memcpy(data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, nonce, CRYPTO_NONCE_SIZE);
374 455
375 if (send_onion_response(onion_a->net, source, data, 456 if (send_onion_response(onion_a->net, source, data,
376 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES + len, 457 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE + len,
377 packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3)) == -1) 458 packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3)) == -1) {
378 return 1; 459 return 1;
460 }
379 461
380 return 0; 462 return 0;
381} 463}
382 464
383static int handle_data_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length) 465static int handle_data_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
384{ 466{
385 Onion_Announce *onion_a = object; 467 Onion_Announce *onion_a = (Onion_Announce *)object;
386 468
387 if (length <= DATA_REQUEST_MIN_SIZE_RECV) 469 if (length <= DATA_REQUEST_MIN_SIZE_RECV) {
388 return 1; 470 return 1;
471 }
389 472
390 if (length > ONION_MAX_PACKET_SIZE) 473 if (length > ONION_MAX_PACKET_SIZE) {
391 return 1; 474 return 1;
475 }
392 476
393 int index = in_entries(onion_a, packet + 1); 477 int index = in_entries(onion_a, packet + 1);
394 478
395 if (index == -1) 479 if (index == -1) {
396 return 1; 480 return 1;
481 }
397 482
398 uint8_t data[length - (crypto_box_PUBLICKEYBYTES + ONION_RETURN_3)]; 483 VLA(uint8_t, data, length - (CRYPTO_PUBLIC_KEY_SIZE + ONION_RETURN_3));
399 data[0] = NET_PACKET_ONION_DATA_RESPONSE; 484 data[0] = NET_PACKET_ONION_DATA_RESPONSE;
400 memcpy(data + 1, packet + 1 + crypto_box_PUBLICKEYBYTES, length - (1 + crypto_box_PUBLICKEYBYTES + ONION_RETURN_3)); 485 memcpy(data + 1, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, length - (1 + CRYPTO_PUBLIC_KEY_SIZE + ONION_RETURN_3));
401 486
402 if (send_onion_response(onion_a->net, onion_a->entries[index].ret_ip_port, data, sizeof(data), 487 if (send_onion_response(onion_a->net, onion_a->entries[index].ret_ip_port, data, SIZEOF_VLA(data),
403 onion_a->entries[index].ret) == -1) 488 onion_a->entries[index].ret) == -1) {
404 return 1; 489 return 1;
490 }
405 491
406 return 0; 492 return 0;
407} 493}
408 494
409Onion_Announce *new_onion_announce(DHT *dht) 495Onion_Announce *new_onion_announce(DHT *dht)
410{ 496{
411 if (dht == NULL) 497 if (dht == nullptr) {
412 return NULL; 498 return nullptr;
499 }
413 500
414 Onion_Announce *onion_a = calloc(1, sizeof(Onion_Announce)); 501 Onion_Announce *onion_a = (Onion_Announce *)calloc(1, sizeof(Onion_Announce));
415 502
416 if (onion_a == NULL) 503 if (onion_a == nullptr) {
417 return NULL; 504 return nullptr;
505 }
418 506
419 onion_a->dht = dht; 507 onion_a->dht = dht;
420 onion_a->net = dht->net; 508 onion_a->net = dht_get_net(dht);
421 new_symmetric_key(onion_a->secret_bytes); 509 new_symmetric_key(onion_a->secret_bytes);
422 510
423 networking_registerhandler(onion_a->net, NET_PACKET_ANNOUNCE_REQUEST, &handle_announce_request, onion_a); 511 networking_registerhandler(onion_a->net, NET_PACKET_ANNOUNCE_REQUEST, &handle_announce_request, onion_a);
@@ -428,10 +516,11 @@ Onion_Announce *new_onion_announce(DHT *dht)
428 516
429void kill_onion_announce(Onion_Announce *onion_a) 517void kill_onion_announce(Onion_Announce *onion_a)
430{ 518{
431 if (onion_a == NULL) 519 if (onion_a == nullptr) {
432 return; 520 return;
521 }
433 522
434 networking_registerhandler(onion_a->net, NET_PACKET_ANNOUNCE_REQUEST, NULL, NULL); 523 networking_registerhandler(onion_a->net, NET_PACKET_ANNOUNCE_REQUEST, nullptr, nullptr);
435 networking_registerhandler(onion_a->net, NET_PACKET_ONION_DATA_REQUEST, NULL, NULL); 524 networking_registerhandler(onion_a->net, NET_PACKET_ONION_DATA_REQUEST, nullptr, nullptr);
436 free(onion_a); 525 free(onion_a);
437} 526}
diff --git a/toxcore/onion_announce.h b/toxcore/onion_announce.h
index a9128be8..36484ff2 100644
--- a/toxcore/onion_announce.h
+++ b/toxcore/onion_announce.h
@@ -1,25 +1,26 @@
1/* 1/*
2* onion_announce.h -- Implementation of the announce part of docs/Prevent_Tracking.txt 2 * Implementation of the announce part of docs/Prevent_Tracking.txt
3* 3 */
4* Copyright (C) 2013 Tox project All Rights Reserved.
5*
6* This file is part of Tox.
7*
8* Tox is free software: you can redistribute it and/or modify
9* it under the terms of the GNU General Public License as published by
10* the Free Software Foundation, either version 3 of the License, or
11* (at your option) any later version.
12*
13* Tox is distributed in the hope that it will be useful,
14* but WITHOUT ANY WARRANTY; without even the implied warranty of
15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16* GNU General Public License for more details.
17*
18* You should have received a copy of the GNU General Public License
19* along with Tox. If not, see <http://www.gnu.org/licenses/>.
20*
21*/
22 4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2013 Tox project.
8 *
9 * This file is part of Tox, the free peer to peer instant messenger.
10 *
11 * Tox is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * Tox is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
23 */
23#ifndef ONION_ANNOUNCE_H 24#ifndef ONION_ANNOUNCE_H
24#define ONION_ANNOUNCE_H 25#define ONION_ANNOUNCE_H
25 26
@@ -27,41 +28,29 @@
27 28
28#define ONION_ANNOUNCE_MAX_ENTRIES 160 29#define ONION_ANNOUNCE_MAX_ENTRIES 160
29#define ONION_ANNOUNCE_TIMEOUT 300 30#define ONION_ANNOUNCE_TIMEOUT 300
30#define ONION_PING_ID_SIZE crypto_hash_sha256_BYTES 31#define ONION_PING_ID_SIZE CRYPTO_SHA256_SIZE
31 32
32#define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (sizeof(uint64_t)) 33#define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (sizeof(uint64_t))
33 34
34#define ONION_ANNOUNCE_REQUEST_SIZE (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_MACBYTES) 35#define ONION_ANNOUNCE_REQUEST_SIZE (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_MAC_SIZE)
35 36
36#define ONION_ANNOUNCE_RESPONSE_MIN_SIZE (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES + 1 + ONION_PING_ID_SIZE + crypto_box_MACBYTES) 37#define ONION_ANNOUNCE_RESPONSE_MIN_SIZE (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE + 1 + ONION_PING_ID_SIZE + CRYPTO_MAC_SIZE)
37#define ONION_ANNOUNCE_RESPONSE_MAX_SIZE (ONION_ANNOUNCE_RESPONSE_MIN_SIZE + sizeof(Node_format)*MAX_SENT_NODES) 38#define ONION_ANNOUNCE_RESPONSE_MAX_SIZE (ONION_ANNOUNCE_RESPONSE_MIN_SIZE + sizeof(Node_format)*MAX_SENT_NODES)
38 39
39#define ONION_DATA_RESPONSE_MIN_SIZE (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) 40#define ONION_DATA_RESPONSE_MIN_SIZE (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE)
40 41
41#if ONION_PING_ID_SIZE != crypto_box_PUBLICKEYBYTES 42#if ONION_PING_ID_SIZE != CRYPTO_PUBLIC_KEY_SIZE
42#error announce response packets assume that ONION_PING_ID_SIZE is equal to crypto_box_PUBLICKEYBYTES 43#error announce response packets assume that ONION_PING_ID_SIZE is equal to CRYPTO_PUBLIC_KEY_SIZE
43#endif 44#endif
44 45
45#define ONION_DATA_REQUEST_MIN_SIZE (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) 46#define ONION_DATA_REQUEST_MIN_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE)
46#define MAX_DATA_REQUEST_SIZE (ONION_MAX_DATA_SIZE - ONION_DATA_REQUEST_MIN_SIZE) 47#define MAX_DATA_REQUEST_SIZE (ONION_MAX_DATA_SIZE - ONION_DATA_REQUEST_MIN_SIZE)
47 48
48typedef struct { 49typedef struct Onion_Announce Onion_Announce;
49 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 50
50 IP_Port ret_ip_port; 51/* These two are not public; they are for tests only! */
51 uint8_t ret[ONION_RETURN_3]; 52uint8_t *onion_announce_entry_public_key(Onion_Announce *onion_a, uint32_t entry);
52 uint8_t data_public_key[crypto_box_PUBLICKEYBYTES]; 53void onion_announce_entry_set_time(Onion_Announce *onion_a, uint32_t entry, uint64_t time);
53 uint64_t time;
54} Onion_Announce_Entry;
55
56typedef struct {
57 DHT *dht;
58 Networking_Core *net;
59 Onion_Announce_Entry entries[ONION_ANNOUNCE_MAX_ENTRIES];
60 /* This is crypto_box_KEYBYTES long just so we can use new_symmetric_key() to fill it */
61 uint8_t secret_bytes[crypto_box_KEYBYTES];
62
63 Shared_Keys shared_keys_recv;
64} Onion_Announce;
65 54
66/* Create an onion announce request packet in packet of max_packet_length (recommended size ONION_ANNOUNCE_REQUEST_SIZE). 55/* Create an onion announce request packet in packet of max_packet_length (recommended size ONION_ANNOUNCE_REQUEST_SIZE).
67 * 56 *
diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c
index b879f393..fa6c08c9 100644
--- a/toxcore/onion_client.c
+++ b/toxcore/onion_client.c
@@ -1,38 +1,161 @@
1/* 1/*
2* onion_client.c -- Implementation of the client part of docs/Prevent_Tracking.txt 2 * Implementation of the client part of docs/Prevent_Tracking.txt (The part that
3* (The part that uses the onion stuff to connect to the friend) 3 * uses the onion stuff to connect to the friend)
4* 4 */
5* Copyright (C) 2013 Tox project All Rights Reserved. 5
6* 6/*
7* This file is part of Tox. 7 * Copyright © 2016-2017 The TokTok team.
8* 8 * Copyright © 2013 Tox project.
9* Tox is free software: you can redistribute it and/or modify 9 *
10* it under the terms of the GNU General Public License as published by 10 * This file is part of Tox, the free peer to peer instant messenger.
11* the Free Software Foundation, either version 3 of the License, or 11 *
12* (at your option) any later version. 12 * Tox is free software: you can redistribute it and/or modify
13* 13 * it under the terms of the GNU General Public License as published by
14* Tox is distributed in the hope that it will be useful, 14 * the Free Software Foundation, either version 3 of the License, or
15* but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * (at your option) any later version.
16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 *
17* GNU General Public License for more details. 17 * Tox is distributed in the hope that it will be useful,
18* 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19* You should have received a copy of the GNU General Public License 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20* along with Tox. If not, see <http://www.gnu.org/licenses/>. 20 * GNU General Public License for more details.
21* 21 *
22*/ 22 * You should have received a copy of the GNU General Public License
23 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
24 */
23#ifdef HAVE_CONFIG_H 25#ifdef HAVE_CONFIG_H
24#include "config.h" 26#include "config.h"
25#endif 27#endif
26 28
27#include "onion_client.h" 29#include "onion_client.h"
28#include "util.h" 30
31#include <stdlib.h>
32#include <string.h>
33
29#include "LAN_discovery.h" 34#include "LAN_discovery.h"
35#include "util.h"
30 36
31/* defines for the array size and 37/* defines for the array size and
32 timeout for onion announce packets. */ 38 timeout for onion announce packets. */
33#define ANNOUNCE_ARRAY_SIZE 256 39#define ANNOUNCE_ARRAY_SIZE 256
34#define ANNOUNCE_TIMEOUT 10 40#define ANNOUNCE_TIMEOUT 10
35 41
42typedef struct {
43 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
44 IP_Port ip_port;
45 uint8_t ping_id[ONION_PING_ID_SIZE];
46 uint8_t data_public_key[CRYPTO_PUBLIC_KEY_SIZE];
47 uint8_t is_stored;
48
49 uint64_t added_time;
50
51 uint64_t timestamp;
52
53 uint64_t last_pinged;
54
55 uint8_t unsuccessful_pings;
56
57 uint32_t path_used;
58} Onion_Node;
59
60typedef struct {
61 Onion_Path paths[NUMBER_ONION_PATHS];
62 uint64_t last_path_success[NUMBER_ONION_PATHS];
63 uint64_t last_path_used[NUMBER_ONION_PATHS];
64 uint64_t path_creation_time[NUMBER_ONION_PATHS];
65 /* number of times used without success. */
66 unsigned int last_path_used_times[NUMBER_ONION_PATHS];
67} Onion_Client_Paths;
68
69typedef struct {
70 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
71 uint64_t timestamp;
72} Last_Pinged;
73
74typedef struct {
75 uint8_t status; /* 0 if friend is not valid, 1 if friend is valid.*/
76 uint8_t is_online; /* Set by the onion_set_friend_status function. */
77
78 uint8_t know_dht_public_key; /* 0 if we don't know the dht public key of the other, 1 if we do. */
79 uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];
80 uint8_t real_public_key[CRYPTO_PUBLIC_KEY_SIZE];
81
82 Onion_Node clients_list[MAX_ONION_CLIENTS];
83 uint8_t temp_public_key[CRYPTO_PUBLIC_KEY_SIZE];
84 uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE];
85
86 uint64_t last_reported_announced;
87
88 uint64_t last_dht_pk_onion_sent;
89 uint64_t last_dht_pk_dht_sent;
90
91 uint64_t last_noreplay;
92
93 uint64_t last_seen;
94
95 Last_Pinged last_pinged[MAX_STORED_PINGED_NODES];
96 uint8_t last_pinged_index;
97
98 int (*tcp_relay_node_callback)(void *object, uint32_t number, IP_Port ip_port, const uint8_t *public_key);
99 void *tcp_relay_node_callback_object;
100 uint32_t tcp_relay_node_callback_number;
101
102 void (*dht_pk_callback)(void *data, int32_t number, const uint8_t *dht_public_key, void *userdata);
103 void *dht_pk_callback_object;
104 uint32_t dht_pk_callback_number;
105
106 uint32_t run_count;
107} Onion_Friend;
108
109struct Onion_Client {
110 DHT *dht;
111 Net_Crypto *c;
112 Networking_Core *net;
113 Onion_Friend *friends_list;
114 uint16_t num_friends;
115
116 Onion_Node clients_announce_list[MAX_ONION_CLIENTS_ANNOUNCE];
117 uint64_t last_announce;
118
119 Onion_Client_Paths onion_paths_self;
120 Onion_Client_Paths onion_paths_friends;
121
122 uint8_t secret_symmetric_key[CRYPTO_SYMMETRIC_KEY_SIZE];
123 uint64_t last_run, first_run;
124
125 uint8_t temp_public_key[CRYPTO_PUBLIC_KEY_SIZE];
126 uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE];
127
128 Last_Pinged last_pinged[MAX_STORED_PINGED_NODES];
129
130 Node_format path_nodes[MAX_PATH_NODES];
131 uint16_t path_nodes_index;
132
133 Node_format path_nodes_bs[MAX_PATH_NODES];
134 uint16_t path_nodes_index_bs;
135
136 Ping_Array *announce_ping_array;
137 uint8_t last_pinged_index;
138 struct {
139 oniondata_handler_callback function;
140 void *object;
141 } Onion_Data_Handlers[256];
142
143 uint64_t last_packet_recv;
144
145 unsigned int onion_connected;
146 bool UDP_connected;
147};
148
149DHT *onion_get_dht(const Onion_Client *onion_c)
150{
151 return onion_c->dht;
152}
153
154Net_Crypto *onion_get_net_crypto(const Onion_Client *onion_c)
155{
156 return onion_c->c;
157}
158
36/* Add a node to the path_nodes bootstrap array. 159/* Add a node to the path_nodes bootstrap array.
37 * 160 *
38 * return -1 on failure 161 * return -1 on failure
@@ -40,25 +163,28 @@
40 */ 163 */
41int onion_add_bs_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *public_key) 164int onion_add_bs_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *public_key)
42{ 165{
43 if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6) 166 if (!net_family_is_ipv4(ip_port.ip.family) && !net_family_is_ipv6(ip_port.ip.family)) {
44 return -1; 167 return -1;
168 }
45 169
46 unsigned int i; 170 unsigned int i;
47 171
48 for (i = 0; i < MAX_PATH_NODES; ++i) { 172 for (i = 0; i < MAX_PATH_NODES; ++i) {
49 if (public_key_cmp(public_key, onion_c->path_nodes_bs[i].public_key) == 0) 173 if (public_key_cmp(public_key, onion_c->path_nodes_bs[i].public_key) == 0) {
50 return -1; 174 return -1;
175 }
51 } 176 }
52 177
53 onion_c->path_nodes_bs[onion_c->path_nodes_index_bs % MAX_PATH_NODES].ip_port = ip_port; 178 onion_c->path_nodes_bs[onion_c->path_nodes_index_bs % MAX_PATH_NODES].ip_port = ip_port;
54 memcpy(onion_c->path_nodes_bs[onion_c->path_nodes_index_bs % MAX_PATH_NODES].public_key, public_key, 179 memcpy(onion_c->path_nodes_bs[onion_c->path_nodes_index_bs % MAX_PATH_NODES].public_key, public_key,
55 crypto_box_PUBLICKEYBYTES); 180 CRYPTO_PUBLIC_KEY_SIZE);
56 181
57 uint16_t last = onion_c->path_nodes_index_bs; 182 uint16_t last = onion_c->path_nodes_index_bs;
58 ++onion_c->path_nodes_index_bs; 183 ++onion_c->path_nodes_index_bs;
59 184
60 if (onion_c->path_nodes_index_bs < last) 185 if (onion_c->path_nodes_index_bs < last) {
61 onion_c->path_nodes_index_bs = MAX_PATH_NODES + 1; 186 onion_c->path_nodes_index_bs = MAX_PATH_NODES + 1;
187 }
62 188
63 return 0; 189 return 0;
64} 190}
@@ -70,25 +196,28 @@ int onion_add_bs_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t
70 */ 196 */
71static int onion_add_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *public_key) 197static int onion_add_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *public_key)
72{ 198{
73 if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6) 199 if (!net_family_is_ipv4(ip_port.ip.family) && !net_family_is_ipv6(ip_port.ip.family)) {
74 return -1; 200 return -1;
201 }
75 202
76 unsigned int i; 203 unsigned int i;
77 204
78 for (i = 0; i < MAX_PATH_NODES; ++i) { 205 for (i = 0; i < MAX_PATH_NODES; ++i) {
79 if (public_key_cmp(public_key, onion_c->path_nodes[i].public_key) == 0) 206 if (public_key_cmp(public_key, onion_c->path_nodes[i].public_key) == 0) {
80 return -1; 207 return -1;
208 }
81 } 209 }
82 210
83 onion_c->path_nodes[onion_c->path_nodes_index % MAX_PATH_NODES].ip_port = ip_port; 211 onion_c->path_nodes[onion_c->path_nodes_index % MAX_PATH_NODES].ip_port = ip_port;
84 memcpy(onion_c->path_nodes[onion_c->path_nodes_index % MAX_PATH_NODES].public_key, public_key, 212 memcpy(onion_c->path_nodes[onion_c->path_nodes_index % MAX_PATH_NODES].public_key, public_key,
85 crypto_box_PUBLICKEYBYTES); 213 CRYPTO_PUBLIC_KEY_SIZE);
86 214
87 uint16_t last = onion_c->path_nodes_index; 215 uint16_t last = onion_c->path_nodes_index;
88 ++onion_c->path_nodes_index; 216 ++onion_c->path_nodes_index;
89 217
90 if (onion_c->path_nodes_index < last) 218 if (onion_c->path_nodes_index < last) {
91 onion_c->path_nodes_index = MAX_PATH_NODES + 1; 219 onion_c->path_nodes_index = MAX_PATH_NODES + 1;
220 }
92 221
93 return 0; 222 return 0;
94} 223}
@@ -101,16 +230,19 @@ uint16_t onion_backup_nodes(const Onion_Client *onion_c, Node_format *nodes, uin
101{ 230{
102 unsigned int i; 231 unsigned int i;
103 232
104 if (!max_num) 233 if (!max_num) {
105 return 0; 234 return 0;
235 }
106 236
107 unsigned int num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES; 237 unsigned int num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES;
108 238
109 if (num_nodes == 0) 239 if (num_nodes == 0) {
110 return 0; 240 return 0;
241 }
111 242
112 if (num_nodes < max_num) 243 if (num_nodes < max_num) {
113 max_num = num_nodes; 244 max_num = num_nodes;
245 }
114 246
115 for (i = 0; i < max_num; ++i) { 247 for (i = 0; i < max_num; ++i) {
116 nodes[i] = onion_c->path_nodes[(onion_c->path_nodes_index - (1 + i)) % num_nodes]; 248 nodes[i] = onion_c->path_nodes[(onion_c->path_nodes_index - (1 + i)) % num_nodes];
@@ -127,15 +259,17 @@ static uint16_t random_nodes_path_onion(const Onion_Client *onion_c, Node_format
127{ 259{
128 unsigned int i; 260 unsigned int i;
129 261
130 if (!max_num) 262 if (!max_num) {
131 return 0; 263 return 0;
264 }
132 265
133 unsigned int num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES; 266 unsigned int num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES;
134 267
135 //if (DHT_non_lan_connected(onion_c->dht)) { 268 //if (DHT_non_lan_connected(onion_c->dht)) {
136 if (DHT_isconnected(onion_c->dht)) { 269 if (DHT_isconnected(onion_c->dht)) {
137 if (num_nodes == 0) 270 if (num_nodes == 0) {
138 return 0; 271 return 0;
272 }
139 273
140 for (i = 0; i < max_num; ++i) { 274 for (i = 0; i < max_num; ++i) {
141 nodes[i] = onion_c->path_nodes[rand() % num_nodes]; 275 nodes[i] = onion_c->path_nodes[rand() % num_nodes];
@@ -148,8 +282,8 @@ static uint16_t random_nodes_path_onion(const Onion_Client *onion_c, Node_format
148 } 282 }
149 283
150 if (num_nodes >= 2) { 284 if (num_nodes >= 2) {
151 nodes[0].ip_port.ip.family = TCP_FAMILY; 285 nodes[0].ip_port.ip.family = net_family_tcp_family;
152 nodes[0].ip_port.ip.ip4.uint32 = random_tcp; 286 nodes[0].ip_port.ip.ip.v4.uint32 = random_tcp;
153 287
154 for (i = 1; i < max_num; ++i) { 288 for (i = 1; i < max_num; ++i) {
155 nodes[i] = onion_c->path_nodes[rand() % num_nodes]; 289 nodes[i] = onion_c->path_nodes[rand() % num_nodes];
@@ -158,11 +292,12 @@ static uint16_t random_nodes_path_onion(const Onion_Client *onion_c, Node_format
158 unsigned int num_nodes_bs = (onion_c->path_nodes_index_bs < MAX_PATH_NODES) ? onion_c->path_nodes_index_bs : 292 unsigned int num_nodes_bs = (onion_c->path_nodes_index_bs < MAX_PATH_NODES) ? onion_c->path_nodes_index_bs :
159 MAX_PATH_NODES; 293 MAX_PATH_NODES;
160 294
161 if (num_nodes_bs == 0) 295 if (num_nodes_bs == 0) {
162 return 0; 296 return 0;
297 }
163 298
164 nodes[0].ip_port.ip.family = TCP_FAMILY; 299 nodes[0].ip_port.ip.family = net_family_tcp_family;
165 nodes[0].ip_port.ip.ip4.uint32 = random_tcp; 300 nodes[0].ip_port.ip.ip.v4.uint32 = random_tcp;
166 301
167 for (i = 1; i < max_num; ++i) { 302 for (i = 1; i < max_num; ++i) {
168 nodes[i] = onion_c->path_nodes_bs[rand() % num_nodes_bs]; 303 nodes[i] = onion_c->path_nodes_bs[rand() % num_nodes_bs];
@@ -190,7 +325,7 @@ static int is_path_used(const Onion_Client_Paths *onion_paths, const Node_format
190 continue; 325 continue;
191 } 326 }
192 327
193 // TODO: do we really have to check it with the last node? 328 // TODO(irungentoo): do we really have to check it with the last node?
194 if (ipport_equal(&onion_paths->paths[i].ip_port1, &nodes[ONION_PATH_LENGTH - 1].ip_port)) { 329 if (ipport_equal(&onion_paths->paths[i].ip_port1, &nodes[ONION_PATH_LENGTH - 1].ip_port)) {
195 return i; 330 return i;
196 } 331 }
@@ -200,23 +335,34 @@ static int is_path_used(const Onion_Client_Paths *onion_paths, const Node_format
200} 335}
201 336
202/* is path timed out */ 337/* is path timed out */
203static _Bool path_timed_out(Onion_Client_Paths *onion_paths, uint32_t pathnum) 338static bool path_timed_out(Onion_Client_Paths *onion_paths, uint32_t pathnum)
204{ 339{
205 pathnum = pathnum % NUMBER_ONION_PATHS; 340 pathnum = pathnum % NUMBER_ONION_PATHS;
206 341
207 return ((onion_paths->last_path_success[pathnum] + ONION_PATH_TIMEOUT < onion_paths->last_path_used[pathnum] 342 bool is_new = onion_paths->last_path_success[pathnum] == onion_paths->path_creation_time[pathnum];
208 && onion_paths->last_path_used_times[pathnum] >= ONION_PATH_MAX_NO_RESPONSE_USES) 343 uint64_t timeout = is_new ? ONION_PATH_FIRST_TIMEOUT : ONION_PATH_TIMEOUT;
344
345 return ((onion_paths->last_path_used_times[pathnum] >= ONION_PATH_MAX_NO_RESPONSE_USES
346 && is_timeout(onion_paths->last_path_used[pathnum], timeout))
209 || is_timeout(onion_paths->path_creation_time[pathnum], ONION_PATH_MAX_LIFETIME)); 347 || is_timeout(onion_paths->path_creation_time[pathnum], ONION_PATH_MAX_LIFETIME));
210} 348}
211 349
350/* should node be considered to have timed out */
351static bool onion_node_timed_out(const Onion_Node *node)
352{
353 return (node->timestamp == 0
354 || (node->unsuccessful_pings >= ONION_NODE_MAX_PINGS
355 && is_timeout(node->last_pinged, ONION_NODE_TIMEOUT)));
356}
357
212/* Create a new path or use an old suitable one (if pathnum is valid) 358/* Create a new path or use an old suitable one (if pathnum is valid)
213 * or a random one from onion_paths. 359 * or a random one from onion_paths.
214 * 360 *
215 * return -1 on failure 361 * return -1 on failure
216 * return 0 on success 362 * return 0 on success
217 * 363 *
218 * TODO: Make this function better, it currently probably is vulnerable to some attacks that 364 * TODO(irungentoo): Make this function better, it currently probably is
219 * could de anonimize us. 365 * vulnerable to some attacks that could deanonimize us.
220 */ 366 */
221static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_paths, uint32_t pathnum, Onion_Path *path) 367static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_paths, uint32_t pathnum, Onion_Path *path)
222{ 368{
@@ -229,17 +375,19 @@ static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_pa
229 if (path_timed_out(onion_paths, pathnum)) { 375 if (path_timed_out(onion_paths, pathnum)) {
230 Node_format nodes[ONION_PATH_LENGTH]; 376 Node_format nodes[ONION_PATH_LENGTH];
231 377
232 if (random_nodes_path_onion(onion_c, nodes, ONION_PATH_LENGTH) != ONION_PATH_LENGTH) 378 if (random_nodes_path_onion(onion_c, nodes, ONION_PATH_LENGTH) != ONION_PATH_LENGTH) {
233 return -1; 379 return -1;
380 }
234 381
235 int n = is_path_used(onion_paths, nodes); 382 int n = is_path_used(onion_paths, nodes);
236 383
237 if (n == -1) { 384 if (n == -1) {
238 if (create_onion_path(onion_c->dht, &onion_paths->paths[pathnum], nodes) == -1) 385 if (create_onion_path(onion_c->dht, &onion_paths->paths[pathnum], nodes) == -1) {
239 return -1; 386 return -1;
387 }
240 388
241 onion_paths->last_path_success[pathnum] = unix_time() + ONION_PATH_FIRST_TIMEOUT - ONION_PATH_TIMEOUT;
242 onion_paths->path_creation_time[pathnum] = unix_time(); 389 onion_paths->path_creation_time[pathnum] = unix_time();
390 onion_paths->last_path_success[pathnum] = onion_paths->path_creation_time[pathnum];
243 onion_paths->last_path_used_times[pathnum] = ONION_PATH_MAX_NO_RESPONSE_USES / 2; 391 onion_paths->last_path_used_times[pathnum] = ONION_PATH_MAX_NO_RESPONSE_USES / 2;
244 392
245 uint32_t path_num = rand(); 393 uint32_t path_num = rand();
@@ -253,17 +401,21 @@ static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_pa
253 } 401 }
254 } 402 }
255 403
404 if (onion_paths->last_path_used_times[pathnum] < ONION_PATH_MAX_NO_RESPONSE_USES) {
405 onion_paths->last_path_used[pathnum] = unix_time();
406 }
407
256 ++onion_paths->last_path_used_times[pathnum]; 408 ++onion_paths->last_path_used_times[pathnum];
257 onion_paths->last_path_used[pathnum] = unix_time();
258 memcpy(path, &onion_paths->paths[pathnum], sizeof(Onion_Path)); 409 memcpy(path, &onion_paths->paths[pathnum], sizeof(Onion_Path));
259 return 0; 410 return 0;
260} 411}
261 412
262/* Does path with path_num exist. */ 413/* Does path with path_num exist. */
263static _Bool path_exists(Onion_Client_Paths *onion_paths, uint32_t path_num) 414static bool path_exists(Onion_Client_Paths *onion_paths, uint32_t path_num)
264{ 415{
265 if (path_timed_out(onion_paths, path_num)) 416 if (path_timed_out(onion_paths, path_num)) {
266 return 0; 417 return 0;
418 }
267 419
268 return onion_paths->paths[path_num % NUMBER_ONION_PATHS].path_num == path_num; 420 return onion_paths->paths[path_num % NUMBER_ONION_PATHS].path_num == path_num;
269} 421}
@@ -273,8 +425,9 @@ static _Bool path_exists(Onion_Client_Paths *onion_paths, uint32_t path_num)
273 */ 425 */
274static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, uint32_t path_num) 426static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, uint32_t path_num)
275{ 427{
276 if (num > onion_c->num_friends) 428 if (num > onion_c->num_friends) {
277 return -1; 429 return -1;
430 }
278 431
279 Onion_Client_Paths *onion_paths; 432 Onion_Client_Paths *onion_paths;
280 433
@@ -312,28 +465,33 @@ static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, uint32_t
312static int send_onion_packet_tcp_udp(const Onion_Client *onion_c, const Onion_Path *path, IP_Port dest, 465static int send_onion_packet_tcp_udp(const Onion_Client *onion_c, const Onion_Path *path, IP_Port dest,
313 const uint8_t *data, uint16_t length) 466 const uint8_t *data, uint16_t length)
314{ 467{
315 if (path->ip_port1.ip.family == AF_INET || path->ip_port1.ip.family == AF_INET6) { 468 if (net_family_is_ipv4(path->ip_port1.ip.family) || net_family_is_ipv6(path->ip_port1.ip.family)) {
316 uint8_t packet[ONION_MAX_PACKET_SIZE]; 469 uint8_t packet[ONION_MAX_PACKET_SIZE];
317 int len = create_onion_packet(packet, sizeof(packet), path, dest, data, length); 470 int len = create_onion_packet(packet, sizeof(packet), path, dest, data, length);
318 471
319 if (len == -1) 472 if (len == -1) {
320 return -1; 473 return -1;
474 }
321 475
322 if (sendpacket(onion_c->net, path->ip_port1, packet, len) != len) 476 if (sendpacket(onion_c->net, path->ip_port1, packet, len) != len) {
323 return -1; 477 return -1;
478 }
324 479
325 return 0; 480 return 0;
326 } else if (path->ip_port1.ip.family == TCP_FAMILY) { 481 }
482
483 if (net_family_is_tcp_family(path->ip_port1.ip.family)) {
327 uint8_t packet[ONION_MAX_PACKET_SIZE]; 484 uint8_t packet[ONION_MAX_PACKET_SIZE];
328 int len = create_onion_packet_tcp(packet, sizeof(packet), path, dest, data, length); 485 int len = create_onion_packet_tcp(packet, sizeof(packet), path, dest, data, length);
329 486
330 if (len == -1) 487 if (len == -1) {
331 return -1; 488 return -1;
489 }
332 490
333 return send_tcp_onion_request(onion_c->c, path->ip_port1.ip.ip4.uint32, packet, len); 491 return send_tcp_onion_request(onion_c->c, path->ip_port1.ip.ip.v4.uint32, packet, len);
334 } else {
335 return -1;
336 } 492 }
493
494 return -1;
337} 495}
338 496
339/* Creates a sendback for use in an announce request. 497/* Creates a sendback for use in an announce request.
@@ -354,15 +512,16 @@ static int send_onion_packet_tcp_udp(const Onion_Client *onion_c, const Onion_Pa
354static int new_sendback(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, IP_Port ip_port, 512static int new_sendback(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, IP_Port ip_port,
355 uint32_t path_num, uint64_t *sendback) 513 uint32_t path_num, uint64_t *sendback)
356{ 514{
357 uint8_t data[sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port) + sizeof(uint32_t)]; 515 uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)];
358 memcpy(data, &num, sizeof(uint32_t)); 516 memcpy(data, &num, sizeof(uint32_t));
359 memcpy(data + sizeof(uint32_t), public_key, crypto_box_PUBLICKEYBYTES); 517 memcpy(data + sizeof(uint32_t), public_key, CRYPTO_PUBLIC_KEY_SIZE);
360 memcpy(data + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES, &ip_port, sizeof(IP_Port)); 518 memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, &ip_port, sizeof(IP_Port));
361 memcpy(data + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port), &path_num, sizeof(uint32_t)); 519 memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), &path_num, sizeof(uint32_t));
362 *sendback = ping_array_add(&onion_c->announce_ping_array, data, sizeof(data)); 520 *sendback = ping_array_add(onion_c->announce_ping_array, data, sizeof(data));
363 521
364 if (*sendback == 0) 522 if (*sendback == 0) {
365 return -1; 523 return -1;
524 }
366 525
367 return 0; 526 return 0;
368} 527}
@@ -371,7 +530,7 @@ static int new_sendback(Onion_Client *onion_c, uint32_t num, const uint8_t *publ
371 * ip contained in it in ret_ip_port 530 * ip contained in it in ret_ip_port
372 * 531 *
373 * sendback is the sendback ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big 532 * sendback is the sendback ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big
374 * ret_pubkey must be at least crypto_box_PUBLICKEYBYTES big 533 * ret_pubkey must be at least CRYPTO_PUBLIC_KEY_SIZE big
375 * ret_ip_port must be at least 1 big 534 * ret_ip_port must be at least 1 big
376 * 535 *
377 * return ~0 on failure 536 * return ~0 on failure
@@ -382,14 +541,15 @@ static uint32_t check_sendback(Onion_Client *onion_c, const uint8_t *sendback, u
382{ 541{
383 uint64_t sback; 542 uint64_t sback;
384 memcpy(&sback, sendback, sizeof(uint64_t)); 543 memcpy(&sback, sendback, sizeof(uint64_t));
385 uint8_t data[sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port) + sizeof(uint32_t)]; 544 uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)];
386 545
387 if (ping_array_check(data, sizeof(data), &onion_c->announce_ping_array, sback) != sizeof(data)) 546 if (ping_array_check(onion_c->announce_ping_array, data, sizeof(data), sback) != sizeof(data)) {
388 return ~0; 547 return ~0;
548 }
389 549
390 memcpy(ret_pubkey, data + sizeof(uint32_t), crypto_box_PUBLICKEYBYTES); 550 memcpy(ret_pubkey, data + sizeof(uint32_t), CRYPTO_PUBLIC_KEY_SIZE);
391 memcpy(ret_ip_port, data + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES, sizeof(IP_Port)); 551 memcpy(ret_ip_port, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, sizeof(IP_Port));
392 memcpy(path_num, data + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port), sizeof(uint32_t)); 552 memcpy(path_num, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), sizeof(uint32_t));
393 553
394 uint32_t num; 554 uint32_t num;
395 memcpy(&num, data, sizeof(uint32_t)); 555 memcpy(&num, data, sizeof(uint32_t));
@@ -399,39 +559,44 @@ static uint32_t check_sendback(Onion_Client *onion_c, const uint8_t *sendback, u
399static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, const uint8_t *dest_pubkey, 559static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, const uint8_t *dest_pubkey,
400 const uint8_t *ping_id, uint32_t pathnum) 560 const uint8_t *ping_id, uint32_t pathnum)
401{ 561{
402 if (num > onion_c->num_friends) 562 if (num > onion_c->num_friends) {
403 return -1; 563 return -1;
564 }
404 565
405 uint64_t sendback; 566 uint64_t sendback;
406 Onion_Path path; 567 Onion_Path path;
407 568
408 if (num == 0) { 569 if (num == 0) {
409 if (random_path(onion_c, &onion_c->onion_paths_self, pathnum, &path) == -1) 570 if (random_path(onion_c, &onion_c->onion_paths_self, pathnum, &path) == -1) {
410 return -1; 571 return -1;
572 }
411 } else { 573 } else {
412 if (random_path(onion_c, &onion_c->onion_paths_friends, pathnum, &path) == -1) 574 if (random_path(onion_c, &onion_c->onion_paths_friends, pathnum, &path) == -1) {
413 return -1; 575 return -1;
576 }
414 } 577 }
415 578
416 if (new_sendback(onion_c, num, dest_pubkey, dest, path.path_num, &sendback) == -1) 579 if (new_sendback(onion_c, num, dest_pubkey, dest, path.path_num, &sendback) == -1) {
417 return -1; 580 return -1;
581 }
418 582
419 uint8_t zero_ping_id[ONION_PING_ID_SIZE] = {0}; 583 uint8_t zero_ping_id[ONION_PING_ID_SIZE] = {0};
420 584
421 if (ping_id == NULL) 585 if (ping_id == nullptr) {
422 ping_id = zero_ping_id; 586 ping_id = zero_ping_id;
587 }
423 588
424 uint8_t request[ONION_ANNOUNCE_REQUEST_SIZE]; 589 uint8_t request[ONION_ANNOUNCE_REQUEST_SIZE];
425 int len; 590 int len;
426 591
427 if (num == 0) { 592 if (num == 0) {
428 len = create_announce_request(request, sizeof(request), dest_pubkey, onion_c->c->self_public_key, 593 len = create_announce_request(request, sizeof(request), dest_pubkey, nc_get_self_public_key(onion_c->c),
429 onion_c->c->self_secret_key, ping_id, onion_c->c->self_public_key, onion_c->temp_public_key, sendback); 594 nc_get_self_secret_key(onion_c->c), ping_id, nc_get_self_public_key(onion_c->c),
430 595 onion_c->temp_public_key, sendback);
431 } else { 596 } else {
432 len = create_announce_request(request, sizeof(request), dest_pubkey, onion_c->friends_list[num - 1].temp_public_key, 597 len = create_announce_request(request, sizeof(request), dest_pubkey, onion_c->friends_list[num - 1].temp_public_key,
433 onion_c->friends_list[num - 1].temp_secret_key, ping_id, onion_c->friends_list[num - 1].real_public_key, zero_ping_id, 598 onion_c->friends_list[num - 1].temp_secret_key, ping_id,
434 sendback); 599 onion_c->friends_list[num - 1].real_public_key, zero_ping_id, sendback);
435 } 600 }
436 601
437 if (len == -1) { 602 if (len == -1) {
@@ -441,70 +606,105 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_
441 return send_onion_packet_tcp_udp(onion_c, &path, dest, request, len); 606 return send_onion_packet_tcp_udp(onion_c, &path, dest, request, len);
442} 607}
443 608
444static uint8_t cmp_public_key[crypto_box_PUBLICKEYBYTES]; 609typedef struct {
445static int cmp_entry(const void *a, const void *b) 610 const uint8_t *base_public_key;
611 Onion_Node entry;
612} Onion_Client_Cmp_data;
613
614static int onion_client_cmp_entry(const void *a, const void *b)
446{ 615{
447 Onion_Node entry1, entry2; 616 Onion_Client_Cmp_data cmp1, cmp2;
448 memcpy(&entry1, a, sizeof(Onion_Node)); 617 memcpy(&cmp1, a, sizeof(Onion_Client_Cmp_data));
449 memcpy(&entry2, b, sizeof(Onion_Node)); 618 memcpy(&cmp2, b, sizeof(Onion_Client_Cmp_data));
450 int t1 = is_timeout(entry1.timestamp, ONION_NODE_TIMEOUT); 619 Onion_Node entry1 = cmp1.entry;
451 int t2 = is_timeout(entry2.timestamp, ONION_NODE_TIMEOUT); 620 Onion_Node entry2 = cmp2.entry;
621 const uint8_t *cmp_public_key = cmp1.base_public_key;
622
623 int t1 = onion_node_timed_out(&entry1);
624 int t2 = onion_node_timed_out(&entry2);
452 625
453 if (t1 && t2) 626 if (t1 && t2) {
454 return 0; 627 return 0;
628 }
455 629
456 if (t1) 630 if (t1) {
457 return -1; 631 return -1;
632 }
458 633
459 if (t2) 634 if (t2) {
460 return 1; 635 return 1;
636 }
461 637
462 int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key); 638 int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key);
463 639
464 if (close == 1) 640 if (close == 1) {
465 return 1; 641 return 1;
642 }
466 643
467 if (close == 2) 644 if (close == 2) {
468 return -1; 645 return -1;
646 }
469 647
470 return 0; 648 return 0;
471} 649}
472 650
651static void sort_onion_node_list(Onion_Node *list, unsigned int length, const uint8_t *comp_public_key)
652{
653 // Pass comp_public_key to qsort with each Client_data entry, so the
654 // comparison function can use it as the base of comparison.
655 VLA(Onion_Client_Cmp_data, cmp_list, length);
656
657 for (uint32_t i = 0; i < length; i++) {
658 cmp_list[i].base_public_key = comp_public_key;
659 cmp_list[i].entry = list[i];
660 }
661
662 qsort(cmp_list, length, sizeof(Onion_Client_Cmp_data), onion_client_cmp_entry);
663
664 for (uint32_t i = 0; i < length; i++) {
665 list[i] = cmp_list[i].entry;
666 }
667}
668
473static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, IP_Port ip_port, 669static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, IP_Port ip_port,
474 uint8_t is_stored, const uint8_t *pingid_or_key, uint32_t path_num) 670 uint8_t is_stored, const uint8_t *pingid_or_key, uint32_t path_used)
475{ 671{
476 if (num > onion_c->num_friends) 672 if (num > onion_c->num_friends) {
477 return -1; 673 return -1;
674 }
478 675
479 Onion_Node *list_nodes = NULL; 676 Onion_Node *list_nodes = nullptr;
480 uint8_t *reference_id = NULL; 677 const uint8_t *reference_id = nullptr;
481 unsigned int list_length; 678 unsigned int list_length;
482 679
483 if (num == 0) { 680 if (num == 0) {
484 list_nodes = onion_c->clients_announce_list; 681 list_nodes = onion_c->clients_announce_list;
485 reference_id = onion_c->c->self_public_key; 682 reference_id = nc_get_self_public_key(onion_c->c);
486 list_length = MAX_ONION_CLIENTS_ANNOUNCE; 683 list_length = MAX_ONION_CLIENTS_ANNOUNCE;
487 684
488 if (is_stored == 1 && public_key_cmp(pingid_or_key, onion_c->temp_public_key) != 0) { 685 if (is_stored == 1 && public_key_cmp(pingid_or_key, onion_c->temp_public_key) != 0) {
489 is_stored = 0; 686 is_stored = 0;
490 } 687 }
491
492 } else { 688 } else {
493 if (is_stored >= 2) 689 if (is_stored >= 2) {
494 return -1; 690 return -1;
691 }
692
693 if (is_stored == 1) {
694 onion_c->friends_list[num - 1].last_reported_announced = unix_time();
695 }
495 696
496 list_nodes = onion_c->friends_list[num - 1].clients_list; 697 list_nodes = onion_c->friends_list[num - 1].clients_list;
497 reference_id = onion_c->friends_list[num - 1].real_public_key; 698 reference_id = onion_c->friends_list[num - 1].real_public_key;
498 list_length = MAX_ONION_CLIENTS; 699 list_length = MAX_ONION_CLIENTS;
499 } 700 }
500 701
501 memcpy(cmp_public_key, reference_id, crypto_box_PUBLICKEYBYTES); 702 sort_onion_node_list(list_nodes, list_length, reference_id);
502 qsort(list_nodes, list_length, sizeof(Onion_Node), cmp_entry);
503 703
504 int index = -1, stored = 0; 704 int index = -1, stored = 0;
505 unsigned int i; 705 unsigned int i;
506 706
507 if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT) 707 if (onion_node_timed_out(&list_nodes[0])
508 || id_closest(reference_id, list_nodes[0].public_key, public_key) == 2) { 708 || id_closest(reference_id, list_nodes[0].public_key, public_key) == 2) {
509 index = 0; 709 index = 0;
510 } 710 }
@@ -517,28 +717,32 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t
517 } 717 }
518 } 718 }
519 719
520 if (index == -1) 720 if (index == -1) {
521 return 0; 721 return 0;
722 }
522 723
523 memcpy(list_nodes[index].public_key, public_key, crypto_box_PUBLICKEYBYTES); 724 memcpy(list_nodes[index].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
524 list_nodes[index].ip_port = ip_port; 725 list_nodes[index].ip_port = ip_port;
525 726
526 //TODO: remove this and find a better source of nodes to use for paths. 727 // TODO(irungentoo): remove this and find a better source of nodes to use for paths.
527 onion_add_path_node(onion_c, ip_port, public_key); 728 onion_add_path_node(onion_c, ip_port, public_key);
528 729
529 if (is_stored == 1) { 730 if (is_stored == 1) {
530 memcpy(list_nodes[index].data_public_key, pingid_or_key, crypto_box_PUBLICKEYBYTES); 731 memcpy(list_nodes[index].data_public_key, pingid_or_key, CRYPTO_PUBLIC_KEY_SIZE);
531 } else { 732 } else {
532 memcpy(list_nodes[index].ping_id, pingid_or_key, ONION_PING_ID_SIZE); 733 memcpy(list_nodes[index].ping_id, pingid_or_key, ONION_PING_ID_SIZE);
533 } 734 }
534 735
535 list_nodes[index].is_stored = is_stored; 736 list_nodes[index].is_stored = is_stored;
536 list_nodes[index].timestamp = unix_time(); 737 list_nodes[index].timestamp = unix_time();
738 list_nodes[index].unsuccessful_pings = 0;
537 739
538 if (!stored) 740 if (!stored) {
539 list_nodes[index].last_pinged = 0; 741 list_nodes[index].last_pinged = 0;
742 list_nodes[index].added_time = unix_time();
743 }
540 744
541 list_nodes[index].path_used = set_path_timeouts(onion_c, num, path_num); 745 list_nodes[index].path_used = path_used;
542 return 0; 746 return 0;
543} 747}
544 748
@@ -547,12 +751,14 @@ static int good_to_ping(Last_Pinged *last_pinged, uint8_t *last_pinged_index, co
547 unsigned int i; 751 unsigned int i;
548 752
549 for (i = 0; i < MAX_STORED_PINGED_NODES; ++i) { 753 for (i = 0; i < MAX_STORED_PINGED_NODES; ++i) {
550 if (!is_timeout(last_pinged[i].timestamp, MIN_NODE_PING_TIME)) 754 if (!is_timeout(last_pinged[i].timestamp, MIN_NODE_PING_TIME)) {
551 if (public_key_cmp(last_pinged[i].public_key, public_key) == 0) 755 if (public_key_cmp(last_pinged[i].public_key, public_key) == 0) {
552 return 0; 756 return 0;
757 }
758 }
553 } 759 }
554 760
555 memcpy(last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].public_key, public_key, crypto_box_PUBLICKEYBYTES); 761 memcpy(last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
556 last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].timestamp = unix_time(); 762 last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].timestamp = unix_time();
557 ++*last_pinged_index; 763 ++*last_pinged_index;
558 return 1; 764 return 1;
@@ -561,22 +767,24 @@ static int good_to_ping(Last_Pinged *last_pinged, uint8_t *last_pinged_index, co
561static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_format *nodes, uint16_t num_nodes, 767static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_format *nodes, uint16_t num_nodes,
562 IP_Port source) 768 IP_Port source)
563{ 769{
564 if (num > onion_c->num_friends) 770 if (num > onion_c->num_friends) {
565 return -1; 771 return -1;
772 }
566 773
567 if (num_nodes == 0) 774 if (num_nodes == 0) {
568 return 0; 775 return 0;
776 }
569 777
570 Onion_Node *list_nodes = NULL; 778 Onion_Node *list_nodes = nullptr;
571 uint8_t *reference_id = NULL; 779 const uint8_t *reference_id = nullptr;
572 unsigned int list_length; 780 unsigned int list_length;
573 781
574 Last_Pinged *last_pinged = NULL; 782 Last_Pinged *last_pinged = nullptr;
575 uint8_t *last_pinged_index = NULL; 783 uint8_t *last_pinged_index = nullptr;
576 784
577 if (num == 0) { 785 if (num == 0) {
578 list_nodes = onion_c->clients_announce_list; 786 list_nodes = onion_c->clients_announce_list;
579 reference_id = onion_c->c->self_public_key; 787 reference_id = nc_get_self_public_key(onion_c->c);
580 list_length = MAX_ONION_CLIENTS_ANNOUNCE; 788 list_length = MAX_ONION_CLIENTS_ANNOUNCE;
581 last_pinged = onion_c->last_pinged; 789 last_pinged = onion_c->last_pinged;
582 last_pinged_index = &onion_c->last_pinged_index; 790 last_pinged_index = &onion_c->last_pinged_index;
@@ -589,18 +797,20 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_for
589 } 797 }
590 798
591 unsigned int i, j; 799 unsigned int i, j;
592 int lan_ips_accepted = (LAN_ip(source.ip) == 0); 800 int lan_ips_accepted = (ip_is_lan(source.ip) == 0);
593 801
594 for (i = 0; i < num_nodes; ++i) { 802 for (i = 0; i < num_nodes; ++i) {
595 803
596 if (!lan_ips_accepted) 804 if (!lan_ips_accepted) {
597 if (LAN_ip(nodes[i].ip_port.ip) == 0) 805 if (ip_is_lan(nodes[i].ip_port.ip) == 0) {
598 continue; 806 continue;
807 }
808 }
599 809
600 if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT) 810 if (onion_node_timed_out(&list_nodes[0])
601 || id_closest(reference_id, list_nodes[0].public_key, nodes[i].public_key) == 2 811 || id_closest(reference_id, list_nodes[0].public_key, nodes[i].public_key) == 2
602 || is_timeout(list_nodes[1].timestamp, ONION_NODE_TIMEOUT) 812 || onion_node_timed_out(&list_nodes[1])
603 || id_closest(reference_id, list_nodes[1].public_key, nodes[i].public_key) == 2 ) { 813 || id_closest(reference_id, list_nodes[1].public_key, nodes[i].public_key) == 2) {
604 /* check if node is already in list. */ 814 /* check if node is already in list. */
605 for (j = 0; j < list_length; ++j) { 815 for (j = 0; j < list_length; ++j) {
606 if (public_key_cmp(list_nodes[j].public_key, nodes[i].public_key) == 0) { 816 if (public_key_cmp(list_nodes[j].public_key, nodes[i].public_key) == 0) {
@@ -609,7 +819,7 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_for
609 } 819 }
610 820
611 if (j == list_length && good_to_ping(last_pinged, last_pinged_index, nodes[i].public_key)) { 821 if (j == list_length && good_to_ping(last_pinged, last_pinged_index, nodes[i].public_key)) {
612 client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].public_key, NULL, ~0); 822 client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].public_key, nullptr, ~0);
613 } 823 }
614 } 824 }
615 } 825 }
@@ -617,125 +827,148 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_for
617 return 0; 827 return 0;
618} 828}
619 829
620static int handle_announce_response(void *object, IP_Port source, const uint8_t *packet, uint16_t length) 830static int handle_announce_response(void *object, IP_Port source, const uint8_t *packet, uint16_t length,
831 void *userdata)
621{ 832{
622 Onion_Client *onion_c = object; 833 Onion_Client *onion_c = (Onion_Client *)object;
623 834
624 if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) 835 if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) {
625 return 1; 836 return 1;
837 }
626 838
627 uint16_t len_nodes = length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE; 839 uint16_t len_nodes = length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE;
628 840
629 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 841 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
630 IP_Port ip_port; 842 IP_Port ip_port;
631 uint32_t path_num; 843 uint32_t path_num;
632 uint32_t num = check_sendback(onion_c, packet + 1, public_key, &ip_port, &path_num); 844 uint32_t num = check_sendback(onion_c, packet + 1, public_key, &ip_port, &path_num);
633 845
634 if (num > onion_c->num_friends) 846 if (num > onion_c->num_friends) {
635 return 1; 847 return 1;
848 }
636 849
637 uint8_t plain[1 + ONION_PING_ID_SIZE + len_nodes]; 850 VLA(uint8_t, plain, 1 + ONION_PING_ID_SIZE + len_nodes);
638 int len = -1; 851 int len;
639 852
640 if (num == 0) { 853 if (num == 0) {
641 len = decrypt_data(public_key, onion_c->c->self_secret_key, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, 854 len = decrypt_data(public_key, nc_get_self_secret_key(onion_c->c),
642 packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES, 855 packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
643 length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES), plain); 856 packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE,
857 length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE), plain);
644 } else { 858 } else {
645 if (onion_c->friends_list[num - 1].status == 0) 859 if (onion_c->friends_list[num - 1].status == 0) {
646 return 1; 860 return 1;
861 }
647 862
648 len = decrypt_data(public_key, onion_c->friends_list[num - 1].temp_secret_key, 863 len = decrypt_data(public_key, onion_c->friends_list[num - 1].temp_secret_key,
649 packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, 864 packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
650 packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES, 865 packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE,
651 length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES), plain); 866 length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE), plain);
652 } 867 }
653 868
654 if ((uint32_t)len != sizeof(plain)) 869 if ((uint32_t)len != SIZEOF_VLA(plain)) {
655 return 1; 870 return 1;
871 }
656 872
657 if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, path_num) == -1) 873 uint32_t path_used = set_path_timeouts(onion_c, num, path_num);
874
875 if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, path_used) == -1) {
658 return 1; 876 return 1;
877 }
659 878
660 if (len_nodes != 0) { 879 if (len_nodes != 0) {
661 Node_format nodes[MAX_SENT_NODES]; 880 Node_format nodes[MAX_SENT_NODES];
662 int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, plain + 1 + ONION_PING_ID_SIZE, len_nodes, 0); 881 int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, nullptr, plain + 1 + ONION_PING_ID_SIZE, len_nodes, 0);
663 882
664 if (num_nodes <= 0) 883 if (num_nodes <= 0) {
665 return 1; 884 return 1;
885 }
666 886
667 if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1) 887 if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1) {
668 return 1; 888 return 1;
889 }
669 } 890 }
670 891
671 //TODO: LAN vs non LAN ips?, if we are connected only to LAN, are we offline? 892 // TODO(irungentoo): LAN vs non LAN ips?, if we are connected only to LAN, are we offline?
672 onion_c->last_packet_recv = unix_time(); 893 onion_c->last_packet_recv = unix_time();
673 return 0; 894 return 0;
674} 895}
675 896
676#define DATA_IN_RESPONSE_MIN_SIZE ONION_DATA_IN_RESPONSE_MIN_SIZE 897#define DATA_IN_RESPONSE_MIN_SIZE ONION_DATA_IN_RESPONSE_MIN_SIZE
677 898
678static int handle_data_response(void *object, IP_Port source, const uint8_t *packet, uint16_t length) 899static int handle_data_response(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
679{ 900{
680 Onion_Client *onion_c = object; 901 Onion_Client *onion_c = (Onion_Client *)object;
681 902
682 if (length <= (ONION_DATA_RESPONSE_MIN_SIZE + DATA_IN_RESPONSE_MIN_SIZE)) 903 if (length <= (ONION_DATA_RESPONSE_MIN_SIZE + DATA_IN_RESPONSE_MIN_SIZE)) {
683 return 1; 904 return 1;
905 }
684 906
685 if (length > MAX_DATA_REQUEST_SIZE) 907 if (length > MAX_DATA_REQUEST_SIZE) {
686 return 1; 908 return 1;
909 }
687 910
688 uint8_t temp_plain[length - ONION_DATA_RESPONSE_MIN_SIZE]; 911 VLA(uint8_t, temp_plain, length - ONION_DATA_RESPONSE_MIN_SIZE);
689 int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_c->temp_secret_key, packet + 1, 912 int len = decrypt_data(packet + 1 + CRYPTO_NONCE_SIZE, onion_c->temp_secret_key, packet + 1,
690 packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, 913 packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
691 length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), temp_plain); 914 length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE), temp_plain);
692 915
693 if ((uint32_t)len != sizeof(temp_plain)) 916 if ((uint32_t)len != SIZEOF_VLA(temp_plain)) {
694 return 1; 917 return 1;
918 }
695 919
696 uint8_t plain[sizeof(temp_plain) - DATA_IN_RESPONSE_MIN_SIZE]; 920 VLA(uint8_t, plain, SIZEOF_VLA(temp_plain) - DATA_IN_RESPONSE_MIN_SIZE);
697 len = decrypt_data(temp_plain, onion_c->c->self_secret_key, packet + 1, temp_plain + crypto_box_PUBLICKEYBYTES, 921 len = decrypt_data(temp_plain, nc_get_self_secret_key(onion_c->c),
698 sizeof(temp_plain) - crypto_box_PUBLICKEYBYTES, plain); 922 packet + 1, temp_plain + CRYPTO_PUBLIC_KEY_SIZE,
923 SIZEOF_VLA(temp_plain) - CRYPTO_PUBLIC_KEY_SIZE, plain);
699 924
700 if ((uint32_t)len != sizeof(plain)) 925 if ((uint32_t)len != SIZEOF_VLA(plain)) {
701 return 1; 926 return 1;
927 }
702 928
703 if (!onion_c->Onion_Data_Handlers[plain[0]].function) 929 if (!onion_c->Onion_Data_Handlers[plain[0]].function) {
704 return 1; 930 return 1;
931 }
705 932
706 return onion_c->Onion_Data_Handlers[plain[0]].function(onion_c->Onion_Data_Handlers[plain[0]].object, temp_plain, plain, 933 return onion_c->Onion_Data_Handlers[plain[0]].function(onion_c->Onion_Data_Handlers[plain[0]].object, temp_plain, plain,
707 sizeof(plain)); 934 SIZEOF_VLA(plain), userdata);
708} 935}
709 936
710#define DHTPK_DATA_MIN_LENGTH (1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES) 937#define DHTPK_DATA_MIN_LENGTH (1 + sizeof(uint64_t) + CRYPTO_PUBLIC_KEY_SIZE)
711#define DHTPK_DATA_MAX_LENGTH (DHTPK_DATA_MIN_LENGTH + sizeof(Node_format)*MAX_SENT_NODES) 938#define DHTPK_DATA_MAX_LENGTH (DHTPK_DATA_MIN_LENGTH + sizeof(Node_format)*MAX_SENT_NODES)
712static int handle_dhtpk_announce(void *object, const uint8_t *source_pubkey, const uint8_t *data, uint16_t length) 939static int handle_dhtpk_announce(void *object, const uint8_t *source_pubkey, const uint8_t *data, uint16_t length,
940 void *userdata)
713{ 941{
714 Onion_Client *onion_c = object; 942 Onion_Client *onion_c = (Onion_Client *)object;
715 943
716 if (length < DHTPK_DATA_MIN_LENGTH) 944 if (length < DHTPK_DATA_MIN_LENGTH) {
717 return 1; 945 return 1;
946 }
718 947
719 if (length > DHTPK_DATA_MAX_LENGTH) 948 if (length > DHTPK_DATA_MAX_LENGTH) {
720 return 1; 949 return 1;
950 }
721 951
722 int friend_num = onion_friend_num(onion_c, source_pubkey); 952 int friend_num = onion_friend_num(onion_c, source_pubkey);
723 953
724 if (friend_num == -1) 954 if (friend_num == -1) {
725 return 1; 955 return 1;
956 }
726 957
727 uint64_t no_replay; 958 uint64_t no_replay;
728 memcpy(&no_replay, data + 1, sizeof(uint64_t)); 959 memcpy(&no_replay, data + 1, sizeof(uint64_t));
729 net_to_host((uint8_t *) &no_replay, sizeof(no_replay)); 960 net_to_host((uint8_t *) &no_replay, sizeof(no_replay));
730 961
731 if (no_replay <= onion_c->friends_list[friend_num].last_noreplay) 962 if (no_replay <= onion_c->friends_list[friend_num].last_noreplay) {
732 return 1; 963 return 1;
964 }
733 965
734 onion_c->friends_list[friend_num].last_noreplay = no_replay; 966 onion_c->friends_list[friend_num].last_noreplay = no_replay;
735 967
736 if (onion_c->friends_list[friend_num].dht_pk_callback) 968 if (onion_c->friends_list[friend_num].dht_pk_callback) {
737 onion_c->friends_list[friend_num].dht_pk_callback(onion_c->friends_list[friend_num].dht_pk_callback_object, 969 onion_c->friends_list[friend_num].dht_pk_callback(onion_c->friends_list[friend_num].dht_pk_callback_object,
738 onion_c->friends_list[friend_num].dht_pk_callback_number, data + 1 + sizeof(uint64_t)); 970 onion_c->friends_list[friend_num].dht_pk_callback_number, data + 1 + sizeof(uint64_t), userdata);
971 }
739 972
740 onion_set_friend_DHT_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t)); 973 onion_set_friend_DHT_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t));
741 onion_c->friends_list[friend_num].last_seen = unix_time(); 974 onion_c->friends_list[friend_num].last_seen = unix_time();
@@ -744,20 +977,21 @@ static int handle_dhtpk_announce(void *object, const uint8_t *source_pubkey, con
744 977
745 if (len_nodes != 0) { 978 if (len_nodes != 0) {
746 Node_format nodes[MAX_SENT_NODES]; 979 Node_format nodes[MAX_SENT_NODES];
747 int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, 980 int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, nullptr, data + 1 + sizeof(uint64_t) + CRYPTO_PUBLIC_KEY_SIZE,
748 len_nodes, 1); 981 len_nodes, 1);
749 982
750 if (num_nodes <= 0) 983 if (num_nodes <= 0) {
751 return 1; 984 return 1;
985 }
752 986
753 int i; 987 int i;
754 988
755 for (i = 0; i < num_nodes; ++i) { 989 for (i = 0; i < num_nodes; ++i) {
756 uint8_t family = nodes[i].ip_port.ip.family; 990 const Family family = nodes[i].ip_port.ip.family;
757 991
758 if (family == AF_INET || family == AF_INET6) { 992 if (net_family_is_ipv4(family) || net_family_is_ipv6(family)) {
759 DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].public_key, onion_c->friends_list[friend_num].dht_public_key); 993 DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].public_key, onion_c->friends_list[friend_num].dht_public_key);
760 } else if (family == TCP_INET || family == TCP_INET6) { 994 } else if (net_family_is_tcp_ipv4(family) || net_family_is_tcp_ipv6(family)) {
761 if (onion_c->friends_list[friend_num].tcp_relay_node_callback) { 995 if (onion_c->friends_list[friend_num].tcp_relay_node_callback) {
762 void *obj = onion_c->friends_list[friend_num].tcp_relay_node_callback_object; 996 void *obj = onion_c->friends_list[friend_num].tcp_relay_node_callback_object;
763 uint32_t number = onion_c->friends_list[friend_num].tcp_relay_node_callback_number; 997 uint32_t number = onion_c->friends_list[friend_num].tcp_relay_node_callback_number;
@@ -770,18 +1004,21 @@ static int handle_dhtpk_announce(void *object, const uint8_t *source_pubkey, con
770 return 0; 1004 return 0;
771} 1005}
772 1006
773static int handle_tcp_onion(void *object, const uint8_t *data, uint16_t length) 1007static int handle_tcp_onion(void *object, const uint8_t *data, uint16_t length, void *userdata)
774{ 1008{
775 if (length == 0) 1009 if (length == 0) {
776 return 1; 1010 return 1;
1011 }
777 1012
778 IP_Port ip_port = {0}; 1013 IP_Port ip_port = {{{0}}};
779 ip_port.ip.family = TCP_FAMILY; 1014 ip_port.ip.family = net_family_tcp_family;
780 1015
781 if (data[0] == NET_PACKET_ANNOUNCE_RESPONSE) { 1016 if (data[0] == NET_PACKET_ANNOUNCE_RESPONSE) {
782 return handle_announce_response(object, ip_port, data, length); 1017 return handle_announce_response(object, ip_port, data, length, userdata);
783 } else if (data[0] == NET_PACKET_ONION_DATA_RESPONSE) { 1018 }
784 return handle_data_response(object, ip_port, data, length); 1019
1020 if (data[0] == NET_PACKET_ONION_DATA_RESPONSE) {
1021 return handle_data_response(object, ip_port, data, length, userdata);
785 } 1022 }
786 1023
787 return 1; 1024 return 1;
@@ -797,21 +1034,25 @@ static int handle_tcp_onion(void *object, const uint8_t *data, uint16_t length)
797 */ 1034 */
798int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length) 1035int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length)
799{ 1036{
800 if ((uint32_t)friend_num >= onion_c->num_friends) 1037 if ((uint32_t)friend_num >= onion_c->num_friends) {
801 return -1; 1038 return -1;
1039 }
802 1040
803 if (length + DATA_IN_RESPONSE_MIN_SIZE > MAX_DATA_REQUEST_SIZE) 1041 if (length + DATA_IN_RESPONSE_MIN_SIZE > MAX_DATA_REQUEST_SIZE) {
804 return -1; 1042 return -1;
1043 }
805 1044
806 if (length == 0) 1045 if (length == 0) {
807 return -1; 1046 return -1;
1047 }
808 1048
809 unsigned int i, good_nodes[MAX_ONION_CLIENTS], num_good = 0, num_nodes = 0; 1049 unsigned int i, good_nodes[MAX_ONION_CLIENTS], num_good = 0, num_nodes = 0;
810 Onion_Node *list_nodes = onion_c->friends_list[friend_num].clients_list; 1050 Onion_Node *list_nodes = onion_c->friends_list[friend_num].clients_list;
811 1051
812 for (i = 0; i < MAX_ONION_CLIENTS; ++i) { 1052 for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
813 if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT)) 1053 if (onion_node_timed_out(&list_nodes[i])) {
814 continue; 1054 continue;
1055 }
815 1056
816 ++num_nodes; 1057 ++num_nodes;
817 1058
@@ -821,37 +1062,43 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data,
821 } 1062 }
822 } 1063 }
823 1064
824 if (num_good < (num_nodes / 4) + 1) 1065 if (num_good < (num_nodes - 1) / 4 + 1) {
825 return -1; 1066 return -1;
1067 }
826 1068
827 uint8_t nonce[crypto_box_NONCEBYTES]; 1069 uint8_t nonce[CRYPTO_NONCE_SIZE];
828 random_nonce(nonce); 1070 random_nonce(nonce);
829 1071
830 uint8_t packet[DATA_IN_RESPONSE_MIN_SIZE + length]; 1072 VLA(uint8_t, packet, DATA_IN_RESPONSE_MIN_SIZE + length);
831 memcpy(packet, onion_c->c->self_public_key, crypto_box_PUBLICKEYBYTES); 1073 memcpy(packet, nc_get_self_public_key(onion_c->c), CRYPTO_PUBLIC_KEY_SIZE);
832 int len = encrypt_data(onion_c->friends_list[friend_num].real_public_key, onion_c->c->self_secret_key, nonce, data, 1074 int len = encrypt_data(onion_c->friends_list[friend_num].real_public_key,
833 length, packet + crypto_box_PUBLICKEYBYTES); 1075 nc_get_self_secret_key(onion_c->c), nonce, data,
1076 length, packet + CRYPTO_PUBLIC_KEY_SIZE);
834 1077
835 if ((uint32_t)len + crypto_box_PUBLICKEYBYTES != sizeof(packet)) 1078 if ((uint32_t)len + CRYPTO_PUBLIC_KEY_SIZE != SIZEOF_VLA(packet)) {
836 return -1; 1079 return -1;
1080 }
837 1081
838 unsigned int good = 0; 1082 unsigned int good = 0;
839 1083
840 for (i = 0; i < num_good; ++i) { 1084 for (i = 0; i < num_good; ++i) {
841 Onion_Path path; 1085 Onion_Path path;
842 1086
843 if (random_path(onion_c, &onion_c->onion_paths_friends, ~0, &path) == -1) 1087 if (random_path(onion_c, &onion_c->onion_paths_friends, ~0, &path) == -1) {
844 continue; 1088 continue;
1089 }
845 1090
846 uint8_t o_packet[ONION_MAX_PACKET_SIZE]; 1091 uint8_t o_packet[ONION_MAX_PACKET_SIZE];
847 len = create_data_request(o_packet, sizeof(o_packet), onion_c->friends_list[friend_num].real_public_key, 1092 len = create_data_request(o_packet, sizeof(o_packet), onion_c->friends_list[friend_num].real_public_key,
848 list_nodes[good_nodes[i]].data_public_key, nonce, packet, sizeof(packet)); 1093 list_nodes[good_nodes[i]].data_public_key, nonce, packet, SIZEOF_VLA(packet));
849 1094
850 if (len == -1) 1095 if (len == -1) {
851 continue; 1096 continue;
1097 }
852 1098
853 if (send_onion_packet_tcp_udp(onion_c, &path, list_nodes[good_nodes[i]].ip_port, o_packet, len) == 0) 1099 if (send_onion_packet_tcp_udp(onion_c, &path, list_nodes[good_nodes[i]].ip_port, o_packet, len) == 0) {
854 ++good; 1100 ++good;
1101 }
855 } 1102 }
856 1103
857 return good; 1104 return good;
@@ -866,57 +1113,67 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data,
866 */ 1113 */
867static int send_dht_dhtpk(const Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length) 1114static int send_dht_dhtpk(const Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length)
868{ 1115{
869 if ((uint32_t)friend_num >= onion_c->num_friends) 1116 if ((uint32_t)friend_num >= onion_c->num_friends) {
870 return -1; 1117 return -1;
1118 }
871 1119
872 if (!onion_c->friends_list[friend_num].know_dht_public_key) 1120 if (!onion_c->friends_list[friend_num].know_dht_public_key) {
873 return -1; 1121 return -1;
1122 }
874 1123
875 uint8_t nonce[crypto_box_NONCEBYTES]; 1124 uint8_t nonce[CRYPTO_NONCE_SIZE];
876 new_nonce(nonce); 1125 random_nonce(nonce);
877 1126
878 uint8_t temp[DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES + length]; 1127 VLA(uint8_t, temp, DATA_IN_RESPONSE_MIN_SIZE + CRYPTO_NONCE_SIZE + length);
879 memcpy(temp, onion_c->c->self_public_key, crypto_box_PUBLICKEYBYTES); 1128 memcpy(temp, nc_get_self_public_key(onion_c->c), CRYPTO_PUBLIC_KEY_SIZE);
880 memcpy(temp + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); 1129 memcpy(temp + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
881 int len = encrypt_data(onion_c->friends_list[friend_num].real_public_key, onion_c->c->self_secret_key, nonce, data, 1130 int len = encrypt_data(onion_c->friends_list[friend_num].real_public_key,
882 length, temp + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); 1131 nc_get_self_secret_key(onion_c->c), nonce, data,
1132 length, temp + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
883 1133
884 if ((uint32_t)len + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES != sizeof(temp)) 1134 if ((uint32_t)len + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE != SIZEOF_VLA(temp)) {
885 return -1; 1135 return -1;
1136 }
886 1137
887 uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; 1138 uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
888 len = create_request(onion_c->dht->self_public_key, onion_c->dht->self_secret_key, packet, 1139 len = create_request(dht_get_self_public_key(onion_c->dht), dht_get_self_secret_key(onion_c->dht), packet,
889 onion_c->friends_list[friend_num].dht_public_key, temp, sizeof(temp), CRYPTO_PACKET_DHTPK); 1140 onion_c->friends_list[friend_num].dht_public_key, temp, SIZEOF_VLA(temp), CRYPTO_PACKET_DHTPK);
890 1141
891 if (len == -1) 1142 if (len == -1) {
892 return -1; 1143 return -1;
1144 }
893 1145
894 return route_tofriend(onion_c->dht, onion_c->friends_list[friend_num].dht_public_key, packet, len); 1146 return route_tofriend(onion_c->dht, onion_c->friends_list[friend_num].dht_public_key, packet, len);
895} 1147}
896 1148
897static int handle_dht_dhtpk(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet, 1149static int handle_dht_dhtpk(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet,
898 uint16_t length) 1150 uint16_t length, void *userdata)
899{ 1151{
900 Onion_Client *onion_c = object; 1152 Onion_Client *onion_c = (Onion_Client *)object;
901 1153
902 if (length < DHTPK_DATA_MIN_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES) 1154 if (length < DHTPK_DATA_MIN_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + CRYPTO_NONCE_SIZE) {
903 return 1; 1155 return 1;
1156 }
904 1157
905 if (length > DHTPK_DATA_MAX_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES) 1158 if (length > DHTPK_DATA_MAX_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + CRYPTO_NONCE_SIZE) {
906 return 1; 1159 return 1;
1160 }
907 1161
908 uint8_t plain[DHTPK_DATA_MAX_LENGTH]; 1162 uint8_t plain[DHTPK_DATA_MAX_LENGTH];
909 int len = decrypt_data(packet, onion_c->c->self_secret_key, packet + crypto_box_PUBLICKEYBYTES, 1163 int len = decrypt_data(packet, nc_get_self_secret_key(onion_c->c),
910 packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, 1164 packet + CRYPTO_PUBLIC_KEY_SIZE,
911 length - (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES), plain); 1165 packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
1166 length - (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE), plain);
912 1167
913 if (len != length - (DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES)) 1168 if (len != length - (DATA_IN_RESPONSE_MIN_SIZE + CRYPTO_NONCE_SIZE)) {
914 return 1; 1169 return 1;
1170 }
915 1171
916 if (public_key_cmp(source_pubkey, plain + 1 + sizeof(uint64_t)) != 0) 1172 if (public_key_cmp(source_pubkey, plain + 1 + sizeof(uint64_t)) != 0) {
917 return 1; 1173 return 1;
1174 }
918 1175
919 return handle_dhtpk_announce(onion_c, packet, plain, len); 1176 return handle_dhtpk_announce(onion_c, packet, plain, len, userdata);
920} 1177}
921/* Send the packets to tell our friends what our DHT public key is. 1178/* Send the packets to tell our friends what our DHT public key is.
922 * 1179 *
@@ -929,15 +1186,16 @@ static int handle_dht_dhtpk(void *object, IP_Port source, const uint8_t *source_
929 */ 1186 */
930static int send_dhtpk_announce(Onion_Client *onion_c, uint16_t friend_num, uint8_t onion_dht_both) 1187static int send_dhtpk_announce(Onion_Client *onion_c, uint16_t friend_num, uint8_t onion_dht_both)
931{ 1188{
932 if (friend_num >= onion_c->num_friends) 1189 if (friend_num >= onion_c->num_friends) {
933 return -1; 1190 return -1;
1191 }
934 1192
935 uint8_t data[DHTPK_DATA_MAX_LENGTH]; 1193 uint8_t data[DHTPK_DATA_MAX_LENGTH];
936 data[0] = ONION_DATA_DHTPK; 1194 data[0] = ONION_DATA_DHTPK;
937 uint64_t no_replay = unix_time(); 1195 uint64_t no_replay = unix_time();
938 host_to_net((uint8_t *)&no_replay, sizeof(no_replay)); 1196 host_to_net((uint8_t *)&no_replay, sizeof(no_replay));
939 memcpy(data + 1, &no_replay, sizeof(no_replay)); 1197 memcpy(data + 1, &no_replay, sizeof(no_replay));
940 memcpy(data + 1 + sizeof(uint64_t), onion_c->dht->self_public_key, crypto_box_PUBLICKEYBYTES); 1198 memcpy(data + 1 + sizeof(uint64_t), dht_get_self_public_key(onion_c->dht), CRYPTO_PUBLIC_KEY_SIZE);
941 Node_format nodes[MAX_SENT_NODES]; 1199 Node_format nodes[MAX_SENT_NODES];
942 uint16_t num_relays = copy_connected_tcp_relays(onion_c->c, nodes, (MAX_SENT_NODES / 2)); 1200 uint16_t num_relays = copy_connected_tcp_relays(onion_c->c, nodes, (MAX_SENT_NODES / 2));
943 uint16_t num_nodes = closelist_nodes(onion_c->dht, &nodes[num_relays], MAX_SENT_NODES - num_relays); 1201 uint16_t num_nodes = closelist_nodes(onion_c->dht, &nodes[num_relays], MAX_SENT_NODES - num_relays);
@@ -948,23 +1206,28 @@ static int send_dhtpk_announce(Onion_Client *onion_c, uint16_t friend_num, uint8
948 nodes_len = pack_nodes(data + DHTPK_DATA_MIN_LENGTH, DHTPK_DATA_MAX_LENGTH - DHTPK_DATA_MIN_LENGTH, nodes, 1206 nodes_len = pack_nodes(data + DHTPK_DATA_MIN_LENGTH, DHTPK_DATA_MAX_LENGTH - DHTPK_DATA_MIN_LENGTH, nodes,
949 num_nodes); 1207 num_nodes);
950 1208
951 if (nodes_len <= 0) 1209 if (nodes_len <= 0) {
952 return -1; 1210 return -1;
1211 }
953 } 1212 }
954 1213
955 int num1 = -1, num2 = -1; 1214 int num1 = -1, num2 = -1;
956 1215
957 if (onion_dht_both != 1) 1216 if (onion_dht_both != 1) {
958 num1 = send_onion_data(onion_c, friend_num, data, DHTPK_DATA_MIN_LENGTH + nodes_len); 1217 num1 = send_onion_data(onion_c, friend_num, data, DHTPK_DATA_MIN_LENGTH + nodes_len);
1218 }
959 1219
960 if (onion_dht_both != 0) 1220 if (onion_dht_both != 0) {
961 num2 = send_dht_dhtpk(onion_c, friend_num, data, DHTPK_DATA_MIN_LENGTH + nodes_len); 1221 num2 = send_dht_dhtpk(onion_c, friend_num, data, DHTPK_DATA_MIN_LENGTH + nodes_len);
1222 }
962 1223
963 if (num1 == -1) 1224 if (num1 == -1) {
964 return num2; 1225 return num2;
1226 }
965 1227
966 if (num2 == -1) 1228 if (num2 == -1) {
967 return num1; 1229 return num1;
1230 }
968 1231
969 return num1 + num2; 1232 return num1 + num2;
970} 1233}
@@ -979,11 +1242,13 @@ int onion_friend_num(const Onion_Client *onion_c, const uint8_t *public_key)
979 unsigned int i; 1242 unsigned int i;
980 1243
981 for (i = 0; i < onion_c->num_friends; ++i) { 1244 for (i = 0; i < onion_c->num_friends; ++i) {
982 if (onion_c->friends_list[i].status == 0) 1245 if (onion_c->friends_list[i].status == 0) {
983 continue; 1246 continue;
1247 }
984 1248
985 if (public_key_cmp(public_key, onion_c->friends_list[i].real_public_key) == 0) 1249 if (public_key_cmp(public_key, onion_c->friends_list[i].real_public_key) == 0) {
986 return i; 1250 return i;
1251 }
987 } 1252 }
988 1253
989 return -1; 1254 return -1;
@@ -998,14 +1263,15 @@ static int realloc_onion_friends(Onion_Client *onion_c, uint32_t num)
998{ 1263{
999 if (num == 0) { 1264 if (num == 0) {
1000 free(onion_c->friends_list); 1265 free(onion_c->friends_list);
1001 onion_c->friends_list = NULL; 1266 onion_c->friends_list = nullptr;
1002 return 0; 1267 return 0;
1003 } 1268 }
1004 1269
1005 Onion_Friend *newonion_friends = realloc(onion_c->friends_list, num * sizeof(Onion_Friend)); 1270 Onion_Friend *newonion_friends = (Onion_Friend *)realloc(onion_c->friends_list, num * sizeof(Onion_Friend));
1006 1271
1007 if (newonion_friends == NULL) 1272 if (newonion_friends == nullptr) {
1008 return -1; 1273 return -1;
1274 }
1009 1275
1010 onion_c->friends_list = newonion_friends; 1276 onion_c->friends_list = newonion_friends;
1011 return 0; 1277 return 0;
@@ -1020,8 +1286,9 @@ int onion_addfriend(Onion_Client *onion_c, const uint8_t *public_key)
1020{ 1286{
1021 int num = onion_friend_num(onion_c, public_key); 1287 int num = onion_friend_num(onion_c, public_key);
1022 1288
1023 if (num != -1) 1289 if (num != -1) {
1024 return num; 1290 return num;
1291 }
1025 1292
1026 unsigned int i, index = ~0; 1293 unsigned int i, index = ~0;
1027 1294
@@ -1033,17 +1300,18 @@ int onion_addfriend(Onion_Client *onion_c, const uint8_t *public_key)
1033 } 1300 }
1034 1301
1035 if (index == (uint32_t)~0) { 1302 if (index == (uint32_t)~0) {
1036 if (realloc_onion_friends(onion_c, onion_c->num_friends + 1) == -1) 1303 if (realloc_onion_friends(onion_c, onion_c->num_friends + 1) == -1) {
1037 return -1; 1304 return -1;
1305 }
1038 1306
1039 index = onion_c->num_friends; 1307 index = onion_c->num_friends;
1040 memset(&(onion_c->friends_list[onion_c->num_friends]), 0, sizeof(Onion_Friend)); 1308 memset(&onion_c->friends_list[onion_c->num_friends], 0, sizeof(Onion_Friend));
1041 ++onion_c->num_friends; 1309 ++onion_c->num_friends;
1042 } 1310 }
1043 1311
1044 onion_c->friends_list[index].status = 1; 1312 onion_c->friends_list[index].status = 1;
1045 memcpy(onion_c->friends_list[index].real_public_key, public_key, crypto_box_PUBLICKEYBYTES); 1313 memcpy(onion_c->friends_list[index].real_public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
1046 crypto_box_keypair(onion_c->friends_list[index].temp_public_key, onion_c->friends_list[index].temp_secret_key); 1314 crypto_new_keypair(onion_c->friends_list[index].temp_public_key, onion_c->friends_list[index].temp_secret_key);
1047 return index; 1315 return index;
1048} 1316}
1049 1317
@@ -1054,18 +1322,20 @@ int onion_addfriend(Onion_Client *onion_c, const uint8_t *public_key)
1054 */ 1322 */
1055int onion_delfriend(Onion_Client *onion_c, int friend_num) 1323int onion_delfriend(Onion_Client *onion_c, int friend_num)
1056{ 1324{
1057 if ((uint32_t)friend_num >= onion_c->num_friends) 1325 if ((uint32_t)friend_num >= onion_c->num_friends) {
1058 return -1; 1326 return -1;
1327 }
1059 1328
1060 //if (onion_c->friends_list[friend_num].know_dht_public_key) 1329 //if (onion_c->friends_list[friend_num].know_dht_public_key)
1061 // DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].dht_public_key, 0); 1330 // DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].dht_public_key, 0);
1062 1331
1063 sodium_memzero(&(onion_c->friends_list[friend_num]), sizeof(Onion_Friend)); 1332 crypto_memzero(&onion_c->friends_list[friend_num], sizeof(Onion_Friend));
1064 unsigned int i; 1333 unsigned int i;
1065 1334
1066 for (i = onion_c->num_friends; i != 0; --i) { 1335 for (i = onion_c->num_friends; i != 0; --i) {
1067 if (onion_c->friends_list[i - 1].status != 0) 1336 if (onion_c->friends_list[i - 1].status != 0) {
1068 break; 1337 break;
1338 }
1069 } 1339 }
1070 1340
1071 if (onion_c->num_friends != i) { 1341 if (onion_c->num_friends != i) {
@@ -1084,13 +1354,14 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num)
1084 * return -1 on failure. 1354 * return -1 on failure.
1085 * return 0 on success. 1355 * return 0 on success.
1086 */ 1356 */
1087int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num, int (*tcp_relay_node_callback)(void *object, 1357int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num, int (*callback)(void *object,
1088 uint32_t number, IP_Port ip_port, const uint8_t *public_key), void *object, uint32_t number) 1358 uint32_t number, IP_Port ip_port, const uint8_t *public_key), void *object, uint32_t number)
1089{ 1359{
1090 if ((uint32_t)friend_num >= onion_c->num_friends) 1360 if ((uint32_t)friend_num >= onion_c->num_friends) {
1091 return -1; 1361 return -1;
1362 }
1092 1363
1093 onion_c->friends_list[friend_num].tcp_relay_node_callback = tcp_relay_node_callback; 1364 onion_c->friends_list[friend_num].tcp_relay_node_callback = callback;
1094 onion_c->friends_list[friend_num].tcp_relay_node_callback_object = object; 1365 onion_c->friends_list[friend_num].tcp_relay_node_callback_object = object;
1095 onion_c->friends_list[friend_num].tcp_relay_node_callback_number = number; 1366 onion_c->friends_list[friend_num].tcp_relay_node_callback_number = number;
1096 return 0; 1367 return 0;
@@ -1105,10 +1376,11 @@ int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num, int (*tcp_rela
1105 * return 0 on success. 1376 * return 0 on success.
1106 */ 1377 */
1107int onion_dht_pk_callback(Onion_Client *onion_c, int friend_num, void (*function)(void *data, int32_t number, 1378int onion_dht_pk_callback(Onion_Client *onion_c, int friend_num, void (*function)(void *data, int32_t number,
1108 const uint8_t *dht_public_key), void *object, uint32_t number) 1379 const uint8_t *dht_public_key, void *userdata), void *object, uint32_t number)
1109{ 1380{
1110 if ((uint32_t)friend_num >= onion_c->num_friends) 1381 if ((uint32_t)friend_num >= onion_c->num_friends) {
1111 return -1; 1382 return -1;
1383 }
1112 1384
1113 onion_c->friends_list[friend_num].dht_pk_callback = function; 1385 onion_c->friends_list[friend_num].dht_pk_callback = function;
1114 onion_c->friends_list[friend_num].dht_pk_callback_object = object; 1386 onion_c->friends_list[friend_num].dht_pk_callback_object = object;
@@ -1123,11 +1395,13 @@ int onion_dht_pk_callback(Onion_Client *onion_c, int friend_num, void (*function
1123 */ 1395 */
1124int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uint8_t *dht_key) 1396int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uint8_t *dht_key)
1125{ 1397{
1126 if ((uint32_t)friend_num >= onion_c->num_friends) 1398 if ((uint32_t)friend_num >= onion_c->num_friends) {
1127 return -1; 1399 return -1;
1400 }
1128 1401
1129 if (onion_c->friends_list[friend_num].status == 0) 1402 if (onion_c->friends_list[friend_num].status == 0) {
1130 return -1; 1403 return -1;
1404 }
1131 1405
1132 if (onion_c->friends_list[friend_num].know_dht_public_key) { 1406 if (onion_c->friends_list[friend_num].know_dht_public_key) {
1133 if (public_key_cmp(dht_key, onion_c->friends_list[friend_num].dht_public_key) == 0) { 1407 if (public_key_cmp(dht_key, onion_c->friends_list[friend_num].dht_public_key) == 0) {
@@ -1139,7 +1413,7 @@ int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uin
1139 1413
1140 onion_c->friends_list[friend_num].last_seen = unix_time(); 1414 onion_c->friends_list[friend_num].last_seen = unix_time();
1141 onion_c->friends_list[friend_num].know_dht_public_key = 1; 1415 onion_c->friends_list[friend_num].know_dht_public_key = 1;
1142 memcpy(onion_c->friends_list[friend_num].dht_public_key, dht_key, crypto_box_PUBLICKEYBYTES); 1416 memcpy(onion_c->friends_list[friend_num].dht_public_key, dht_key, CRYPTO_PUBLIC_KEY_SIZE);
1143 1417
1144 return 0; 1418 return 0;
1145} 1419}
@@ -1151,16 +1425,19 @@ int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uin
1151 */ 1425 */
1152unsigned int onion_getfriend_DHT_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key) 1426unsigned int onion_getfriend_DHT_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key)
1153{ 1427{
1154 if ((uint32_t)friend_num >= onion_c->num_friends) 1428 if ((uint32_t)friend_num >= onion_c->num_friends) {
1155 return 0; 1429 return 0;
1430 }
1156 1431
1157 if (onion_c->friends_list[friend_num].status == 0) 1432 if (onion_c->friends_list[friend_num].status == 0) {
1158 return 0; 1433 return 0;
1434 }
1159 1435
1160 if (!onion_c->friends_list[friend_num].know_dht_public_key) 1436 if (!onion_c->friends_list[friend_num].know_dht_public_key) {
1161 return 0; 1437 return 0;
1438 }
1162 1439
1163 memcpy(dht_key, onion_c->friends_list[friend_num].dht_public_key, crypto_box_PUBLICKEYBYTES); 1440 memcpy(dht_key, onion_c->friends_list[friend_num].dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);
1164 return 1; 1441 return 1;
1165} 1442}
1166 1443
@@ -1173,10 +1450,11 @@ unsigned int onion_getfriend_DHT_pubkey(const Onion_Client *onion_c, int friend_
1173 */ 1450 */
1174int onion_getfriendip(const Onion_Client *onion_c, int friend_num, IP_Port *ip_port) 1451int onion_getfriendip(const Onion_Client *onion_c, int friend_num, IP_Port *ip_port)
1175{ 1452{
1176 uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; 1453 uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];
1177 1454
1178 if (onion_getfriend_DHT_pubkey(onion_c, friend_num, dht_public_key) == 0) 1455 if (onion_getfriend_DHT_pubkey(onion_c, friend_num, dht_public_key) == 0) {
1179 return -1; 1456 return -1;
1457 }
1180 1458
1181 return DHT_getfriendip(onion_c->dht, dht_public_key, ip_port); 1459 return DHT_getfriendip(onion_c->dht, dht_public_key, ip_port);
1182} 1460}
@@ -1193,11 +1471,13 @@ int onion_getfriendip(const Onion_Client *onion_c, int friend_num, IP_Port *ip_p
1193 */ 1471 */
1194int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_online) 1472int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_online)
1195{ 1473{
1196 if ((uint32_t)friend_num >= onion_c->num_friends) 1474 if ((uint32_t)friend_num >= onion_c->num_friends) {
1197 return -1; 1475 return -1;
1476 }
1198 1477
1199 if (is_online == 0 && onion_c->friends_list[friend_num].is_online == 1) 1478 if (is_online == 0 && onion_c->friends_list[friend_num].is_online == 1) {
1200 onion_c->friends_list[friend_num].last_seen = unix_time(); 1479 onion_c->friends_list[friend_num].last_seen = unix_time();
1480 }
1201 1481
1202 onion_c->friends_list[friend_num].is_online = is_online; 1482 onion_c->friends_list[friend_num].is_online = is_online;
1203 1483
@@ -1237,30 +1517,63 @@ static void populate_path_nodes_tcp(Onion_Client *onion_c)
1237 1517
1238#define ANNOUNCE_FRIEND (ONION_NODE_PING_INTERVAL * 6) 1518#define ANNOUNCE_FRIEND (ONION_NODE_PING_INTERVAL * 6)
1239#define ANNOUNCE_FRIEND_BEGINNING 3 1519#define ANNOUNCE_FRIEND_BEGINNING 3
1240#define FRIEND_ONION_NODE_TIMEOUT (ONION_NODE_TIMEOUT * 6)
1241 1520
1242#define RUN_COUNT_FRIEND_ANNOUNCE_BEGINNING 17 1521#define RUN_COUNT_FRIEND_ANNOUNCE_BEGINNING 17
1243 1522
1523#define ONION_FRIEND_BACKOFF_FACTOR 4
1524#define ONION_FRIEND_MAX_PING_INTERVAL (5*60*MAX_ONION_CLIENTS)
1525
1244static void do_friend(Onion_Client *onion_c, uint16_t friendnum) 1526static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
1245{ 1527{
1246 if (friendnum >= onion_c->num_friends) 1528 if (friendnum >= onion_c->num_friends) {
1247 return; 1529 return;
1530 }
1248 1531
1249 if (onion_c->friends_list[friendnum].status == 0) 1532 if (onion_c->friends_list[friendnum].status == 0) {
1250 return; 1533 return;
1534 }
1251 1535
1252 unsigned int interval = ANNOUNCE_FRIEND; 1536 unsigned int interval = ANNOUNCE_FRIEND;
1253 1537
1254 if (onion_c->friends_list[friendnum].run_count < RUN_COUNT_FRIEND_ANNOUNCE_BEGINNING) 1538 if (onion_c->friends_list[friendnum].run_count < RUN_COUNT_FRIEND_ANNOUNCE_BEGINNING) {
1255 interval = ANNOUNCE_FRIEND_BEGINNING; 1539 interval = ANNOUNCE_FRIEND_BEGINNING;
1540 } else {
1541 if (onion_c->friends_list[friendnum].last_reported_announced == 0) {
1542 onion_c->friends_list[friendnum].last_reported_announced = unix_time();
1543 }
1256 1544
1257 unsigned int i, count = 0; 1545 uint64_t backoff_interval = (unix_time() - onion_c->friends_list[friendnum].last_reported_announced)
1258 Onion_Node *list_nodes = onion_c->friends_list[friendnum].clients_list; 1546 / ONION_FRIEND_BACKOFF_FACTOR;
1547
1548 if (backoff_interval > ONION_FRIEND_MAX_PING_INTERVAL) {
1549 backoff_interval = ONION_FRIEND_MAX_PING_INTERVAL;
1550 }
1551
1552 if (interval < backoff_interval) {
1553 interval = backoff_interval;
1554 }
1555 }
1259 1556
1260 if (!onion_c->friends_list[friendnum].is_online) { 1557 if (!onion_c->friends_list[friendnum].is_online) {
1261 for (i = 0; i < MAX_ONION_CLIENTS; ++i) { 1558 unsigned int count = 0;
1262 if (is_timeout(list_nodes[i].timestamp, FRIEND_ONION_NODE_TIMEOUT)) 1559 Onion_Node *list_nodes = onion_c->friends_list[friendnum].clients_list;
1560
1561 // ensure we get a response from some node roughly once per
1562 // (interval / MAX_ONION_CLIENTS)
1563 bool ping_random = true;
1564
1565 for (unsigned i = 0; i < MAX_ONION_CLIENTS; ++i) {
1566 if (!(is_timeout(list_nodes[i].timestamp, interval / MAX_ONION_CLIENTS)
1567 && is_timeout(list_nodes[i].last_pinged, ONION_NODE_PING_INTERVAL))) {
1568 ping_random = false;
1569 break;
1570 }
1571 }
1572
1573 for (unsigned i = 0; i < MAX_ONION_CLIENTS; ++i) {
1574 if (onion_node_timed_out(&list_nodes[i])) {
1263 continue; 1575 continue;
1576 }
1264 1577
1265 ++count; 1578 ++count;
1266 1579
@@ -1270,9 +1583,17 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
1270 continue; 1583 continue;
1271 } 1584 }
1272 1585
1273 if (is_timeout(list_nodes[i].last_pinged, interval)) { 1586 if (list_nodes[i].unsuccessful_pings >= ONION_NODE_MAX_PINGS) {
1274 if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].public_key, 0, ~0) == 0) { 1587 continue;
1588 }
1589
1590 if (is_timeout(list_nodes[i].last_pinged, interval)
1591 || (ping_random && rand() % (MAX_ONION_CLIENTS - i) == 0)) {
1592 if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port,
1593 list_nodes[i].public_key, nullptr, ~0) == 0) {
1275 list_nodes[i].last_pinged = unix_time(); 1594 list_nodes[i].last_pinged = unix_time();
1595 ++list_nodes[i].unsuccessful_pings;
1596 ping_random = false;
1276 } 1597 }
1277 } 1598 }
1278 } 1599 }
@@ -1282,33 +1603,39 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
1282 1603
1283 unsigned int n = num_nodes; 1604 unsigned int n = num_nodes;
1284 1605
1285 if (num_nodes > (MAX_ONION_CLIENTS / 2)) 1606 if (num_nodes > (MAX_ONION_CLIENTS / 2)) {
1286 n = (MAX_ONION_CLIENTS / 2); 1607 n = (MAX_ONION_CLIENTS / 2);
1608 }
1287 1609
1288 if (num_nodes != 0) { 1610 if (count <= (uint32_t)rand() % MAX_ONION_CLIENTS) {
1289 unsigned int j; 1611 if (num_nodes != 0) {
1612 unsigned int j;
1290 1613
1291 for (j = 0; j < n; ++j) { 1614 for (j = 0; j < n; ++j) {
1292 unsigned int num = rand() % num_nodes; 1615 unsigned int num = rand() % num_nodes;
1293 client_send_announce_request(onion_c, friendnum + 1, onion_c->path_nodes[num].ip_port, 1616 client_send_announce_request(onion_c, friendnum + 1, onion_c->path_nodes[num].ip_port,
1294 onion_c->path_nodes[num].public_key, 0, ~0); 1617 onion_c->path_nodes[num].public_key, nullptr, ~0);
1295 } 1618 }
1296 1619
1297 ++onion_c->friends_list[friendnum].run_count; 1620 ++onion_c->friends_list[friendnum].run_count;
1621 }
1298 } 1622 }
1299 } else { 1623 } else {
1300 ++onion_c->friends_list[friendnum].run_count; 1624 ++onion_c->friends_list[friendnum].run_count;
1301 } 1625 }
1302 1626
1303 /* send packets to friend telling them our DHT public key. */ 1627 /* send packets to friend telling them our DHT public key. */
1304 if (is_timeout(onion_c->friends_list[friendnum].last_dht_pk_onion_sent, ONION_DHTPK_SEND_INTERVAL)) 1628 if (is_timeout(onion_c->friends_list[friendnum].last_dht_pk_onion_sent, ONION_DHTPK_SEND_INTERVAL)) {
1305 if (send_dhtpk_announce(onion_c, friendnum, 0) >= 1) 1629 if (send_dhtpk_announce(onion_c, friendnum, 0) >= 1) {
1306 onion_c->friends_list[friendnum].last_dht_pk_onion_sent = unix_time(); 1630 onion_c->friends_list[friendnum].last_dht_pk_onion_sent = unix_time();
1631 }
1632 }
1307 1633
1308 if (is_timeout(onion_c->friends_list[friendnum].last_dht_pk_dht_sent, DHT_DHTPK_SEND_INTERVAL)) 1634 if (is_timeout(onion_c->friends_list[friendnum].last_dht_pk_dht_sent, DHT_DHTPK_SEND_INTERVAL)) {
1309 if (send_dhtpk_announce(onion_c, friendnum, 1) >= 1) 1635 if (send_dhtpk_announce(onion_c, friendnum, 1) >= 1) {
1310 onion_c->friends_list[friendnum].last_dht_pk_dht_sent = unix_time(); 1636 onion_c->friends_list[friendnum].last_dht_pk_dht_sent = unix_time();
1311 1637 }
1638 }
1312 } 1639 }
1313} 1640}
1314 1641
@@ -1323,14 +1650,18 @@ void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_ha
1323#define ANNOUNCE_INTERVAL_NOT_ANNOUNCED 3 1650#define ANNOUNCE_INTERVAL_NOT_ANNOUNCED 3
1324#define ANNOUNCE_INTERVAL_ANNOUNCED ONION_NODE_PING_INTERVAL 1651#define ANNOUNCE_INTERVAL_ANNOUNCED ONION_NODE_PING_INTERVAL
1325 1652
1653#define TIME_TO_STABLE (ONION_NODE_PING_INTERVAL * 6)
1654#define ANNOUNCE_INTERVAL_STABLE (ONION_NODE_PING_INTERVAL * 8)
1655
1326static void do_announce(Onion_Client *onion_c) 1656static void do_announce(Onion_Client *onion_c)
1327{ 1657{
1328 unsigned int i, count = 0; 1658 unsigned int i, count = 0;
1329 Onion_Node *list_nodes = onion_c->clients_announce_list; 1659 Onion_Node *list_nodes = onion_c->clients_announce_list;
1330 1660
1331 for (i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE; ++i) { 1661 for (i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE; ++i) {
1332 if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT)) 1662 if (onion_node_timed_out(&list_nodes[i])) {
1333 continue; 1663 continue;
1664 }
1334 1665
1335 ++count; 1666 ++count;
1336 1667
@@ -1340,16 +1671,48 @@ static void do_announce(Onion_Client *onion_c)
1340 continue; 1671 continue;
1341 } 1672 }
1342 1673
1674 if (list_nodes[i].unsuccessful_pings >= ONION_NODE_MAX_PINGS) {
1675 continue;
1676 }
1677
1678
1343 unsigned int interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED; 1679 unsigned int interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED;
1344 1680
1345 if (list_nodes[i].is_stored && path_exists(&onion_c->onion_paths_self, list_nodes[i].path_used)) { 1681 if (list_nodes[i].is_stored && path_exists(&onion_c->onion_paths_self, list_nodes[i].path_used)) {
1346 interval = ANNOUNCE_INTERVAL_ANNOUNCED; 1682 interval = ANNOUNCE_INTERVAL_ANNOUNCED;
1683
1684 uint32_t pathnum = list_nodes[i].path_used % NUMBER_ONION_PATHS;
1685
1686 /* A node/path is considered 'stable', and can be pinged less
1687 * aggressively, if it has survived for at least TIME_TO_STABLE
1688 * and the latest packets sent to it are not timing out.
1689 */
1690 if (is_timeout(list_nodes[i].added_time, TIME_TO_STABLE)
1691 && !(list_nodes[i].unsuccessful_pings > 0
1692 && is_timeout(list_nodes[i].last_pinged, ONION_NODE_TIMEOUT))
1693 && is_timeout(onion_c->onion_paths_self.path_creation_time[pathnum], TIME_TO_STABLE)
1694 && !(onion_c->onion_paths_self.last_path_used_times[pathnum] > 0
1695 && is_timeout(onion_c->onion_paths_self.last_path_used[pathnum], ONION_PATH_TIMEOUT))) {
1696 interval = ANNOUNCE_INTERVAL_STABLE;
1697 }
1347 } 1698 }
1348 1699
1349 if (is_timeout(list_nodes[i].last_pinged, interval)) { 1700 if (is_timeout(list_nodes[i].last_pinged, interval)
1701 || (is_timeout(onion_c->last_announce, ONION_NODE_PING_INTERVAL)
1702 && rand() % (MAX_ONION_CLIENTS_ANNOUNCE - i) == 0)) {
1703 uint32_t path_to_use = list_nodes[i].path_used;
1704
1705 if (list_nodes[i].unsuccessful_pings == ONION_NODE_MAX_PINGS - 1
1706 && is_timeout(list_nodes[i].added_time, TIME_TO_STABLE)) {
1707 /* Last chance for a long-lived node - try a random path */
1708 path_to_use = ~0;
1709 }
1710
1350 if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].public_key, 1711 if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].public_key,
1351 list_nodes[i].ping_id, list_nodes[i].path_used) == 0) { 1712 list_nodes[i].ping_id, path_to_use) == 0) {
1352 list_nodes[i].last_pinged = unix_time(); 1713 list_nodes[i].last_pinged = unix_time();
1714 ++list_nodes[i].unsuccessful_pings;
1715 onion_c->last_announce = unix_time();
1353 } 1716 }
1354 } 1717 }
1355 } 1718 }
@@ -1366,11 +1729,11 @@ static void do_announce(Onion_Client *onion_c)
1366 path_nodes = onion_c->path_nodes; 1729 path_nodes = onion_c->path_nodes;
1367 } 1730 }
1368 1731
1369 if (count < (uint32_t)rand() % MAX_ONION_CLIENTS_ANNOUNCE) { 1732 if (count <= (uint32_t)rand() % MAX_ONION_CLIENTS_ANNOUNCE) {
1370 if (num_nodes != 0) { 1733 if (num_nodes != 0) {
1371 for (i = 0; i < (MAX_ONION_CLIENTS_ANNOUNCE / 2); ++i) { 1734 for (i = 0; i < (MAX_ONION_CLIENTS_ANNOUNCE / 2); ++i) {
1372 unsigned int num = rand() % num_nodes; 1735 unsigned int num = rand() % num_nodes;
1373 client_send_announce_request(onion_c, 0, path_nodes[num].ip_port, path_nodes[num].public_key, 0, ~0); 1736 client_send_announce_request(onion_c, 0, path_nodes[num].ip_port, path_nodes[num].public_key, nullptr, ~0);
1374 } 1737 }
1375 } 1738 }
1376 } 1739 }
@@ -1384,14 +1747,16 @@ static int onion_isconnected(const Onion_Client *onion_c)
1384{ 1747{
1385 unsigned int i, num = 0, announced = 0; 1748 unsigned int i, num = 0, announced = 0;
1386 1749
1387 if (is_timeout(onion_c->last_packet_recv, ONION_OFFLINE_TIMEOUT)) 1750 if (is_timeout(onion_c->last_packet_recv, ONION_OFFLINE_TIMEOUT)) {
1388 return 0; 1751 return 0;
1752 }
1389 1753
1390 if (onion_c->path_nodes_index == 0) 1754 if (onion_c->path_nodes_index == 0) {
1391 return 0; 1755 return 0;
1756 }
1392 1757
1393 for (i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE; ++i) { 1758 for (i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE; ++i) {
1394 if (!is_timeout(onion_c->clients_announce_list[i].timestamp, ONION_NODE_TIMEOUT)) { 1759 if (!onion_node_timed_out(&onion_c->clients_announce_list[i])) {
1395 ++num; 1760 ++num;
1396 1761
1397 if (onion_c->clients_announce_list[i].is_stored) { 1762 if (onion_c->clients_announce_list[i].is_stored) {
@@ -1407,10 +1772,11 @@ static int onion_isconnected(const Onion_Client *onion_c)
1407 } 1772 }
1408 1773
1409 /* Consider ourselves online if we are announced to half or more nodes 1774 /* Consider ourselves online if we are announced to half or more nodes
1410 we are connected to */ 1775 we are connected to */
1411 if (num && announced) { 1776 if (num && announced) {
1412 if ((num / 2) <= announced && (pnodes / 2) <= num) 1777 if ((num / 2) <= announced && (pnodes / 2) <= num) {
1413 return 1; 1778 return 1;
1779 }
1414 } 1780 }
1415 1781
1416 return 0; 1782 return 0;
@@ -1427,9 +1793,9 @@ unsigned int onion_connection_status(const Onion_Client *onion_c)
1427 if (onion_c->onion_connected >= ONION_CONNECTION_SECONDS) { 1793 if (onion_c->onion_connected >= ONION_CONNECTION_SECONDS) {
1428 if (onion_c->UDP_connected) { 1794 if (onion_c->UDP_connected) {
1429 return 2; 1795 return 2;
1430 } else {
1431 return 1;
1432 } 1796 }
1797
1798 return 1;
1433 } 1799 }
1434 1800
1435 return 0; 1801 return 0;
@@ -1437,10 +1803,9 @@ unsigned int onion_connection_status(const Onion_Client *onion_c)
1437 1803
1438void do_onion_client(Onion_Client *onion_c) 1804void do_onion_client(Onion_Client *onion_c)
1439{ 1805{
1440 unsigned int i; 1806 if (onion_c->last_run == unix_time()) {
1441
1442 if (onion_c->last_run == unix_time())
1443 return; 1807 return;
1808 }
1444 1809
1445 if (is_timeout(onion_c->first_run, ONION_CONNECTION_SECONDS)) { 1810 if (is_timeout(onion_c->first_run, ONION_CONNECTION_SECONDS)) {
1446 populate_path_nodes(onion_c); 1811 populate_path_nodes(onion_c);
@@ -1451,7 +1816,6 @@ void do_onion_client(Onion_Client *onion_c)
1451 if (onion_c->onion_connected < ONION_CONNECTION_SECONDS * 2) { 1816 if (onion_c->onion_connected < ONION_CONNECTION_SECONDS * 2) {
1452 ++onion_c->onion_connected; 1817 ++onion_c->onion_connected;
1453 } 1818 }
1454
1455 } else { 1819 } else {
1456 populate_path_nodes_tcp(onion_c); 1820 populate_path_nodes_tcp(onion_c);
1457 1821
@@ -1460,17 +1824,17 @@ void do_onion_client(Onion_Client *onion_c)
1460 } 1824 }
1461 } 1825 }
1462 1826
1463 _Bool UDP_connected = DHT_non_lan_connected(onion_c->dht); 1827 bool UDP_connected = DHT_non_lan_connected(onion_c->dht);
1464 1828
1465 if (is_timeout(onion_c->first_run, ONION_CONNECTION_SECONDS * 2)) { 1829 if (is_timeout(onion_c->first_run, ONION_CONNECTION_SECONDS * 2)) {
1466 set_tcp_onion_status(onion_c->c->tcp_c, !UDP_connected); 1830 set_tcp_onion_status(nc_get_tcp_c(onion_c->c), !UDP_connected);
1467 } 1831 }
1468 1832
1469 onion_c->UDP_connected = UDP_connected 1833 onion_c->UDP_connected = UDP_connected
1470 || get_random_tcp_onion_conn_number(onion_c->c->tcp_c) == -1; /* Check if connected to any TCP relays. */ 1834 || get_random_tcp_onion_conn_number(nc_get_tcp_c(onion_c->c)) == -1; /* Check if connected to any TCP relays. */
1471 1835
1472 if (onion_connection_status(onion_c)) { 1836 if (onion_connection_status(onion_c)) {
1473 for (i = 0; i < onion_c->num_friends; ++i) { 1837 for (unsigned i = 0; i < onion_c->num_friends; ++i) {
1474 do_friend(onion_c, i); 1838 do_friend(onion_c, i);
1475 } 1839 }
1476 } 1840 }
@@ -1484,46 +1848,50 @@ void do_onion_client(Onion_Client *onion_c)
1484 1848
1485Onion_Client *new_onion_client(Net_Crypto *c) 1849Onion_Client *new_onion_client(Net_Crypto *c)
1486{ 1850{
1487 if (c == NULL) 1851 if (c == nullptr) {
1488 return NULL; 1852 return nullptr;
1853 }
1489 1854
1490 Onion_Client *onion_c = calloc(1, sizeof(Onion_Client)); 1855 Onion_Client *onion_c = (Onion_Client *)calloc(1, sizeof(Onion_Client));
1491 1856
1492 if (onion_c == NULL) 1857 if (onion_c == nullptr) {
1493 return NULL; 1858 return nullptr;
1859 }
1494 1860
1495 if (ping_array_init(&onion_c->announce_ping_array, ANNOUNCE_ARRAY_SIZE, ANNOUNCE_TIMEOUT) != 0) { 1861 onion_c->announce_ping_array = ping_array_new(ANNOUNCE_ARRAY_SIZE, ANNOUNCE_TIMEOUT);
1862
1863 if (onion_c->announce_ping_array == nullptr) {
1496 free(onion_c); 1864 free(onion_c);
1497 return NULL; 1865 return nullptr;
1498 } 1866 }
1499 1867
1500 onion_c->dht = c->dht; 1868 onion_c->dht = nc_get_dht(c);
1501 onion_c->net = c->dht->net; 1869 onion_c->net = dht_get_net(onion_c->dht);
1502 onion_c->c = c; 1870 onion_c->c = c;
1503 new_symmetric_key(onion_c->secret_symmetric_key); 1871 new_symmetric_key(onion_c->secret_symmetric_key);
1504 crypto_box_keypair(onion_c->temp_public_key, onion_c->temp_secret_key); 1872 crypto_new_keypair(onion_c->temp_public_key, onion_c->temp_secret_key);
1505 networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_announce_response, onion_c); 1873 networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_announce_response, onion_c);
1506 networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_data_response, onion_c); 1874 networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_data_response, onion_c);
1507 oniondata_registerhandler(onion_c, ONION_DATA_DHTPK, &handle_dhtpk_announce, onion_c); 1875 oniondata_registerhandler(onion_c, ONION_DATA_DHTPK, &handle_dhtpk_announce, onion_c);
1508 cryptopacket_registerhandler(onion_c->dht, CRYPTO_PACKET_DHTPK, &handle_dht_dhtpk, onion_c); 1876 cryptopacket_registerhandler(onion_c->dht, CRYPTO_PACKET_DHTPK, &handle_dht_dhtpk, onion_c);
1509 set_onion_packet_tcp_connection_callback(onion_c->c->tcp_c, &handle_tcp_onion, onion_c); 1877 set_onion_packet_tcp_connection_callback(nc_get_tcp_c(onion_c->c), &handle_tcp_onion, onion_c);
1510 1878
1511 return onion_c; 1879 return onion_c;
1512} 1880}
1513 1881
1514void kill_onion_client(Onion_Client *onion_c) 1882void kill_onion_client(Onion_Client *onion_c)
1515{ 1883{
1516 if (onion_c == NULL) 1884 if (onion_c == nullptr) {
1517 return; 1885 return;
1886 }
1518 1887
1519 ping_array_free_all(&onion_c->announce_ping_array); 1888 ping_array_kill(onion_c->announce_ping_array);
1520 realloc_onion_friends(onion_c, 0); 1889 realloc_onion_friends(onion_c, 0);
1521 networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, NULL, NULL); 1890 networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, nullptr, nullptr);
1522 networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, NULL, NULL); 1891 networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, nullptr, nullptr);
1523 oniondata_registerhandler(onion_c, ONION_DATA_DHTPK, NULL, NULL); 1892 oniondata_registerhandler(onion_c, ONION_DATA_DHTPK, nullptr, nullptr);
1524 cryptopacket_registerhandler(onion_c->dht, CRYPTO_PACKET_DHTPK, NULL, NULL); 1893 cryptopacket_registerhandler(onion_c->dht, CRYPTO_PACKET_DHTPK, nullptr, nullptr);
1525 set_onion_packet_tcp_connection_callback(onion_c->c->tcp_c, NULL, NULL); 1894 set_onion_packet_tcp_connection_callback(nc_get_tcp_c(onion_c->c), nullptr, nullptr);
1526 sodium_memzero(onion_c, sizeof(Onion_Client)); 1895 crypto_memzero(onion_c, sizeof(Onion_Client));
1527 free(onion_c); 1896 free(onion_c);
1528} 1897}
1529
diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h
index 91056a09..327d4923 100644
--- a/toxcore/onion_client.h
+++ b/toxcore/onion_client.h
@@ -1,37 +1,38 @@
1/* 1/*
2* onion_client.h -- Implementation of the client part of docs/Prevent_Tracking.txt 2 * Implementation of the client part of docs/Prevent_Tracking.txt (The part that
3* (The part that uses the onion stuff to connect to the friend) 3 * uses the onion stuff to connect to the friend)
4* 4 */
5* Copyright (C) 2013 Tox project All Rights Reserved.
6*
7* This file is part of Tox.
8*
9* Tox is free software: you can redistribute it and/or modify
10* it under the terms of the GNU General Public License as published by
11* the Free Software Foundation, either version 3 of the License, or
12* (at your option) any later version.
13*
14* Tox is distributed in the hope that it will be useful,
15* but WITHOUT ANY WARRANTY; without even the implied warranty of
16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17* GNU General Public License for more details.
18*
19* You should have received a copy of the GNU General Public License
20* along with Tox. If not, see <http://www.gnu.org/licenses/>.
21*
22*/
23 5
6/*
7 * Copyright © 2016-2017 The TokTok team.
8 * Copyright © 2013 Tox project.
9 *
10 * This file is part of Tox, the free peer to peer instant messenger.
11 *
12 * Tox is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * Tox is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
24 */
24#ifndef ONION_CLIENT_H 25#ifndef ONION_CLIENT_H
25#define ONION_CLIENT_H 26#define ONION_CLIENT_H
26 27
27#include "onion_announce.h"
28#include "net_crypto.h" 28#include "net_crypto.h"
29#include "onion_announce.h"
29#include "ping_array.h" 30#include "ping_array.h"
30 31
31#define MAX_ONION_CLIENTS 8 32#define MAX_ONION_CLIENTS 8
32#define MAX_ONION_CLIENTS_ANNOUNCE 12 /* Number of nodes to announce ourselves to. */ 33#define MAX_ONION_CLIENTS_ANNOUNCE 12 /* Number of nodes to announce ourselves to. */
33#define ONION_NODE_PING_INTERVAL 15 34#define ONION_NODE_PING_INTERVAL 15
34#define ONION_NODE_TIMEOUT (ONION_NODE_PING_INTERVAL * 3) 35#define ONION_NODE_TIMEOUT ONION_NODE_PING_INTERVAL
35 36
36/* The interval in seconds at which to tell our friends where we are */ 37/* The interval in seconds at which to tell our friends where we are */
37#define ONION_DHTPK_SEND_INTERVAL 30 38#define ONION_DHTPK_SEND_INTERVAL 30
@@ -49,120 +50,25 @@
49#define MAX_STORED_PINGED_NODES 9 50#define MAX_STORED_PINGED_NODES 9
50#define MIN_NODE_PING_TIME 10 51#define MIN_NODE_PING_TIME 10
51 52
53#define ONION_NODE_MAX_PINGS 3
54
52#define MAX_PATH_NODES 32 55#define MAX_PATH_NODES 32
53 56
54/* If no packets are received within that interval tox will 57/* If no announce response packets are received within this interval tox will
55 * be considered offline. 58 * be considered offline. We give time for a node to be pinged often enough
59 * that it times out, which leads to the network being thoroughly tested as it
60 * is replaced.
56 */ 61 */
57#define ONION_OFFLINE_TIMEOUT (ONION_NODE_PING_INTERVAL * 1.25) 62#define ONION_OFFLINE_TIMEOUT (ONION_NODE_PING_INTERVAL * (ONION_NODE_MAX_PINGS+2))
58 63
59/* Onion data packet ids. */ 64/* Onion data packet ids. */
60#define ONION_DATA_FRIEND_REQ CRYPTO_PACKET_FRIEND_REQ 65#define ONION_DATA_FRIEND_REQ CRYPTO_PACKET_FRIEND_REQ
61#define ONION_DATA_DHTPK CRYPTO_PACKET_DHTPK 66#define ONION_DATA_DHTPK CRYPTO_PACKET_DHTPK
62 67
63typedef struct { 68typedef struct Onion_Client Onion_Client;
64 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
65 IP_Port ip_port;
66 uint8_t ping_id[ONION_PING_ID_SIZE];
67 uint8_t data_public_key[crypto_box_PUBLICKEYBYTES];
68 uint8_t is_stored;
69
70 uint64_t timestamp;
71
72 uint64_t last_pinged;
73
74 uint32_t path_used;
75} Onion_Node;
76
77typedef struct {
78 Onion_Path paths[NUMBER_ONION_PATHS];
79 uint64_t last_path_success[NUMBER_ONION_PATHS];
80 uint64_t last_path_used[NUMBER_ONION_PATHS];
81 uint64_t path_creation_time[NUMBER_ONION_PATHS];
82 /* number of times used without success. */
83 unsigned int last_path_used_times[NUMBER_ONION_PATHS];
84} Onion_Client_Paths;
85
86typedef struct {
87 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
88 uint64_t timestamp;
89} Last_Pinged;
90
91typedef struct {
92 uint8_t status; /* 0 if friend is not valid, 1 if friend is valid.*/
93 uint8_t is_online; /* Set by the onion_set_friend_status function. */
94
95 uint8_t know_dht_public_key; /* 0 if we don't know the dht public key of the other, 1 if we do. */
96 uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES];
97 uint8_t real_public_key[crypto_box_PUBLICKEYBYTES];
98
99 Onion_Node clients_list[MAX_ONION_CLIENTS];
100 uint8_t temp_public_key[crypto_box_PUBLICKEYBYTES];
101 uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES];
102
103 uint64_t last_dht_pk_onion_sent;
104 uint64_t last_dht_pk_dht_sent;
105
106 uint64_t last_noreplay;
107
108 uint64_t last_seen;
109
110 Last_Pinged last_pinged[MAX_STORED_PINGED_NODES];
111 uint8_t last_pinged_index;
112
113 int (*tcp_relay_node_callback)(void *object, uint32_t number, IP_Port ip_port, const uint8_t *public_key);
114 void *tcp_relay_node_callback_object;
115 uint32_t tcp_relay_node_callback_number;
116
117 void (*dht_pk_callback)(void *data, int32_t number, const uint8_t *dht_public_key);
118 void *dht_pk_callback_object;
119 uint32_t dht_pk_callback_number;
120
121 uint32_t run_count;
122} Onion_Friend;
123
124typedef int (*oniondata_handler_callback)(void *object, const uint8_t *source_pubkey, const uint8_t *data,
125 uint16_t len);
126
127typedef struct {
128 DHT *dht;
129 Net_Crypto *c;
130 Networking_Core *net;
131 Onion_Friend *friends_list;
132 uint16_t num_friends;
133
134 Onion_Node clients_announce_list[MAX_ONION_CLIENTS_ANNOUNCE];
135
136 Onion_Client_Paths onion_paths_self;
137 Onion_Client_Paths onion_paths_friends;
138
139 uint8_t secret_symmetric_key[crypto_box_KEYBYTES];
140 uint64_t last_run, first_run;
141
142 uint8_t temp_public_key[crypto_box_PUBLICKEYBYTES];
143 uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES];
144
145 Last_Pinged last_pinged[MAX_STORED_PINGED_NODES];
146
147 Node_format path_nodes[MAX_PATH_NODES];
148 uint16_t path_nodes_index;
149
150 Node_format path_nodes_bs[MAX_PATH_NODES];
151 uint16_t path_nodes_index_bs;
152
153 Ping_Array announce_ping_array;
154 uint8_t last_pinged_index;
155 struct {
156 oniondata_handler_callback function;
157 void *object;
158 } Onion_Data_Handlers[256];
159
160 uint64_t last_packet_recv;
161
162 unsigned int onion_connected;
163 _Bool UDP_connected;
164} Onion_Client;
165 69
70DHT *onion_get_dht(const Onion_Client *onion_c);
71Net_Crypto *onion_get_net_crypto(const Onion_Client *onion_c);
166 72
167/* Add a node to the path_nodes bootstrap array. 73/* Add a node to the path_nodes bootstrap array.
168 * 74 *
@@ -239,7 +145,7 @@ int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num, int (*tcp_rela
239 * return 0 on success. 145 * return 0 on success.
240 */ 146 */
241int onion_dht_pk_callback(Onion_Client *onion_c, int friend_num, void (*function)(void *data, int32_t number, 147int onion_dht_pk_callback(Onion_Client *onion_c, int friend_num, void (*function)(void *data, int32_t number,
242 const uint8_t *dht_public_key), void *object, uint32_t number); 148 const uint8_t *dht_public_key, void *userdata), void *object, uint32_t number);
243 149
244/* Set a friends DHT public key. 150/* Set a friends DHT public key.
245 * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to 151 * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to
@@ -257,7 +163,7 @@ int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uin
257 */ 163 */
258unsigned int onion_getfriend_DHT_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key); 164unsigned int onion_getfriend_DHT_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key);
259 165
260#define ONION_DATA_IN_RESPONSE_MIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) 166#define ONION_DATA_IN_RESPONSE_MIN_SIZE (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE)
261#define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE) 167#define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE)
262 168
263/* Send data of length length to friendnum. 169/* Send data of length length to friendnum.
@@ -271,6 +177,9 @@ unsigned int onion_getfriend_DHT_pubkey(const Onion_Client *onion_c, int friend_
271 */ 177 */
272int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length); 178int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length);
273 179
180typedef int (*oniondata_handler_callback)(void *object, const uint8_t *source_pubkey, const uint8_t *data,
181 uint16_t len, void *userdata);
182
274/* Function to call when onion data packet with contents beginning with byte is received. */ 183/* Function to call when onion data packet with contents beginning with byte is received. */
275void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object); 184void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object);
276 185
diff --git a/toxcore/ping.api.h b/toxcore/ping.api.h
new file mode 100644
index 00000000..edc04723
--- /dev/null
+++ b/toxcore/ping.api.h
@@ -0,0 +1,65 @@
1%{
2/*
3 * Buffered pinging using cyclic arrays.
4 */
5
6/*
7 * Copyright © 2016-2017 The TokTok team.
8 * Copyright © 2013 Tox project.
9 * Copyright © 2013 plutooo
10 *
11 * This file is part of Tox, the free peer to peer instant messenger.
12 * This file is donated to the Tox Project.
13 *
14 * Tox is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * Tox is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
26 */
27#ifndef PING_H
28#define PING_H
29
30#include "DHT.h"
31#include "network.h"
32
33#include <stdint.h>
34%}
35
36class iP_Port { struct this; }
37class dHT { struct this; }
38
39class ping {
40
41struct this;
42
43static this new(dHT::this *dht);
44void kill();
45
46/** Add nodes to the to_ping list.
47 * All nodes in this list are pinged every TIME_TOPING seconds
48 * and are then removed from the list.
49 * If the list is full the nodes farthest from our public_key are replaced.
50 * The purpose of this list is to enable quick integration of new nodes into the
51 * network while preventing amplification attacks.
52 *
53 * return 0 if node was added.
54 * return -1 if node was not added.
55 */
56int32_t add(const uint8_t *public_key, iP_Port::this ip_port);
57void iterate();
58
59int32_t send_request(iP_Port::this ipp, const uint8_t *public_key);
60
61}
62
63%{
64#endif /* PING_H */
65%}
diff --git a/toxcore/ping.c b/toxcore/ping.c
index f81766cb..3daeff86 100644
--- a/toxcore/ping.c
+++ b/toxcore/ping.c
@@ -1,40 +1,41 @@
1/* 1/*
2 * ping.c -- Buffered pinging using cyclic arrays. 2 * Buffered pinging using cyclic arrays.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2013 Tox project.
8 * Copyright © 2013 plutooo
3 * 9 *
10 * This file is part of Tox, the free peer to peer instant messenger.
4 * This file is donated to the Tox Project. 11 * This file is donated to the Tox Project.
5 * Copyright 2013 plutooo
6 *
7 * Copyright (C) 2013 Tox project All Rights Reserved.
8 *
9 * This file is part of Tox.
10 *
11 * Tox is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 * 12 *
16 * Tox is distributed in the hope that it will be useful, 13 * Tox is free software: you can redistribute it and/or modify
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * it under the terms of the GNU General Public License as published by
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * the Free Software Foundation, either version 3 of the License, or
19 * GNU General Public License for more details. 16 * (at your option) any later version.
20 * 17 *
21 * You should have received a copy of the GNU General Public License 18 * Tox is distributed in the hope that it will be useful,
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * 22 *
23 * You should have received a copy of the GNU General Public License
24 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
24 */ 25 */
25
26#ifdef HAVE_CONFIG_H 26#ifdef HAVE_CONFIG_H
27#include "config.h" 27#include "config.h"
28#endif 28#endif
29 29
30#include <stdint.h>
31
32#include "DHT.h"
33#include "ping.h" 30#include "ping.h"
34 31
32#include <stdlib.h>
33#include <string.h>
34
35#include "DHT.h"
35#include "network.h" 36#include "network.h"
36#include "util.h"
37#include "ping_array.h" 37#include "ping_array.h"
38#include "util.h"
38 39
39#define PING_NUM_MAX 512 40#define PING_NUM_MAX 512
40 41
@@ -45,143 +46,154 @@
45#define TIME_TO_PING 2 46#define TIME_TO_PING 2
46 47
47 48
48struct PING { 49struct Ping {
49 DHT *dht; 50 DHT *dht;
50 51
51 Ping_Array ping_array; 52 Ping_Array *ping_array;
52 Node_format to_ping[MAX_TO_PING]; 53 Node_format to_ping[MAX_TO_PING];
53 uint64_t last_to_ping; 54 uint64_t last_to_ping;
54}; 55};
55 56
56 57
57#define PING_PLAIN_SIZE (1 + sizeof(uint64_t)) 58#define PING_PLAIN_SIZE (1 + sizeof(uint64_t))
58#define DHT_PING_SIZE (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + PING_PLAIN_SIZE + crypto_box_MACBYTES) 59#define DHT_PING_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + PING_PLAIN_SIZE + CRYPTO_MAC_SIZE)
59#define PING_DATA_SIZE (crypto_box_PUBLICKEYBYTES + sizeof(IP_Port)) 60#define PING_DATA_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port))
60 61
61int send_ping_request(PING *ping, IP_Port ipp, const uint8_t *public_key) 62int32_t ping_send_request(Ping *ping, IP_Port ipp, const uint8_t *public_key)
62{ 63{
63 uint8_t pk[DHT_PING_SIZE]; 64 uint8_t pk[DHT_PING_SIZE];
64 int rc; 65 int rc;
65 uint64_t ping_id; 66 uint64_t ping_id;
66 67
67 if (id_equal(public_key, ping->dht->self_public_key)) 68 if (id_equal(public_key, dht_get_self_public_key(ping->dht))) {
68 return 1; 69 return 1;
70 }
69 71
70 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 72 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
71 73
72 // generate key to encrypt ping_id with recipient privkey 74 // generate key to encrypt ping_id with recipient privkey
73 DHT_get_shared_key_sent(ping->dht, shared_key, public_key); 75 DHT_get_shared_key_sent(ping->dht, shared_key, public_key);
74 // Generate random ping_id. 76 // Generate random ping_id.
75 uint8_t data[PING_DATA_SIZE]; 77 uint8_t data[PING_DATA_SIZE];
76 id_copy(data, public_key); 78 id_copy(data, public_key);
77 memcpy(data + crypto_box_PUBLICKEYBYTES, &ipp, sizeof(IP_Port)); 79 memcpy(data + CRYPTO_PUBLIC_KEY_SIZE, &ipp, sizeof(IP_Port));
78 ping_id = ping_array_add(&ping->ping_array, data, sizeof(data)); 80 ping_id = ping_array_add(ping->ping_array, data, sizeof(data));
79 81
80 if (ping_id == 0) 82 if (ping_id == 0) {
81 return 1; 83 return 1;
84 }
82 85
83 uint8_t ping_plain[PING_PLAIN_SIZE]; 86 uint8_t ping_plain[PING_PLAIN_SIZE];
84 ping_plain[0] = NET_PACKET_PING_REQUEST; 87 ping_plain[0] = NET_PACKET_PING_REQUEST;
85 memcpy(ping_plain + 1, &ping_id, sizeof(ping_id)); 88 memcpy(ping_plain + 1, &ping_id, sizeof(ping_id));
86 89
87 pk[0] = NET_PACKET_PING_REQUEST; 90 pk[0] = NET_PACKET_PING_REQUEST;
88 id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey 91 id_copy(pk + 1, dht_get_self_public_key(ping->dht)); // Our pubkey
89 new_nonce(pk + 1 + crypto_box_PUBLICKEYBYTES); // Generate new nonce 92 random_nonce(pk + 1 + CRYPTO_PUBLIC_KEY_SIZE); // Generate new nonce
90 93
91 94
92 rc = encrypt_data_symmetric(shared_key, 95 rc = encrypt_data_symmetric(shared_key,
93 pk + 1 + crypto_box_PUBLICKEYBYTES, 96 pk + 1 + CRYPTO_PUBLIC_KEY_SIZE,
94 ping_plain, sizeof(ping_plain), 97 ping_plain, sizeof(ping_plain),
95 pk + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); 98 pk + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
96 99
97 if (rc != PING_PLAIN_SIZE + crypto_box_MACBYTES) 100 if (rc != PING_PLAIN_SIZE + CRYPTO_MAC_SIZE) {
98 return 1; 101 return 1;
102 }
99 103
100 return sendpacket(ping->dht->net, ipp, pk, sizeof(pk)); 104 return sendpacket(dht_get_net(ping->dht), ipp, pk, sizeof(pk));
101} 105}
102 106
103static int send_ping_response(PING *ping, IP_Port ipp, const uint8_t *public_key, uint64_t ping_id, 107static int ping_send_response(Ping *ping, IP_Port ipp, const uint8_t *public_key, uint64_t ping_id,
104 uint8_t *shared_encryption_key) 108 uint8_t *shared_encryption_key)
105{ 109{
106 uint8_t pk[DHT_PING_SIZE]; 110 uint8_t pk[DHT_PING_SIZE];
107 int rc; 111 int rc;
108 112
109 if (id_equal(public_key, ping->dht->self_public_key)) 113 if (id_equal(public_key, dht_get_self_public_key(ping->dht))) {
110 return 1; 114 return 1;
115 }
111 116
112 uint8_t ping_plain[PING_PLAIN_SIZE]; 117 uint8_t ping_plain[PING_PLAIN_SIZE];
113 ping_plain[0] = NET_PACKET_PING_RESPONSE; 118 ping_plain[0] = NET_PACKET_PING_RESPONSE;
114 memcpy(ping_plain + 1, &ping_id, sizeof(ping_id)); 119 memcpy(ping_plain + 1, &ping_id, sizeof(ping_id));
115 120
116 pk[0] = NET_PACKET_PING_RESPONSE; 121 pk[0] = NET_PACKET_PING_RESPONSE;
117 id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey 122 id_copy(pk + 1, dht_get_self_public_key(ping->dht)); // Our pubkey
118 new_nonce(pk + 1 + crypto_box_PUBLICKEYBYTES); // Generate new nonce 123 random_nonce(pk + 1 + CRYPTO_PUBLIC_KEY_SIZE); // Generate new nonce
119 124
120 // Encrypt ping_id using recipient privkey 125 // Encrypt ping_id using recipient privkey
121 rc = encrypt_data_symmetric(shared_encryption_key, 126 rc = encrypt_data_symmetric(shared_encryption_key,
122 pk + 1 + crypto_box_PUBLICKEYBYTES, 127 pk + 1 + CRYPTO_PUBLIC_KEY_SIZE,
123 ping_plain, sizeof(ping_plain), 128 ping_plain, sizeof(ping_plain),
124 pk + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES ); 129 pk + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
125 130
126 if (rc != PING_PLAIN_SIZE + crypto_box_MACBYTES) 131 if (rc != PING_PLAIN_SIZE + CRYPTO_MAC_SIZE) {
127 return 1; 132 return 1;
133 }
128 134
129 return sendpacket(ping->dht->net, ipp, pk, sizeof(pk)); 135 return sendpacket(dht_get_net(ping->dht), ipp, pk, sizeof(pk));
130} 136}
131 137
132static int handle_ping_request(void *_dht, IP_Port source, const uint8_t *packet, uint16_t length) 138static int handle_ping_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
133{ 139{
134 DHT *dht = _dht; 140 DHT *dht = (DHT *)object;
135 int rc; 141 int rc;
136 142
137 if (length != DHT_PING_SIZE) 143 if (length != DHT_PING_SIZE) {
138 return 1; 144 return 1;
145 }
139 146
140 PING *ping = dht->ping; 147 Ping *ping = dht_get_ping(dht);
141 148
142 if (id_equal(packet + 1, ping->dht->self_public_key)) 149 if (id_equal(packet + 1, dht_get_self_public_key(ping->dht))) {
143 return 1; 150 return 1;
151 }
144 152
145 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 153 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
146 154
147 uint8_t ping_plain[PING_PLAIN_SIZE]; 155 uint8_t ping_plain[PING_PLAIN_SIZE];
148 // Decrypt ping_id 156 // Decrypt ping_id
149 DHT_get_shared_key_recv(dht, shared_key, packet + 1); 157 DHT_get_shared_key_recv(dht, shared_key, packet + 1);
150 rc = decrypt_data_symmetric(shared_key, 158 rc = decrypt_data_symmetric(shared_key,
151 packet + 1 + crypto_box_PUBLICKEYBYTES, 159 packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
152 packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, 160 packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
153 PING_PLAIN_SIZE + crypto_box_MACBYTES, 161 PING_PLAIN_SIZE + CRYPTO_MAC_SIZE,
154 ping_plain ); 162 ping_plain);
155 163
156 if (rc != sizeof(ping_plain)) 164 if (rc != sizeof(ping_plain)) {
157 return 1; 165 return 1;
166 }
158 167
159 if (ping_plain[0] != NET_PACKET_PING_REQUEST) 168 if (ping_plain[0] != NET_PACKET_PING_REQUEST) {
160 return 1; 169 return 1;
170 }
161 171
162 uint64_t ping_id; 172 uint64_t ping_id;
163 memcpy(&ping_id, ping_plain + 1, sizeof(ping_id)); 173 memcpy(&ping_id, ping_plain + 1, sizeof(ping_id));
164 // Send response 174 // Send response
165 send_ping_response(ping, source, packet + 1, ping_id, shared_key); 175 ping_send_response(ping, source, packet + 1, ping_id, shared_key);
166 add_to_ping(ping, packet + 1, source); 176 ping_add(ping, packet + 1, source);
167 177
168 return 0; 178 return 0;
169} 179}
170 180
171static int handle_ping_response(void *_dht, IP_Port source, const uint8_t *packet, uint16_t length) 181static int handle_ping_response(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
172{ 182{
173 DHT *dht = _dht; 183 DHT *dht = (DHT *)object;
174 int rc; 184 int rc;
175 185
176 if (length != DHT_PING_SIZE) 186 if (length != DHT_PING_SIZE) {
177 return 1; 187 return 1;
188 }
178 189
179 PING *ping = dht->ping; 190 Ping *ping = dht_get_ping(dht);
180 191
181 if (id_equal(packet + 1, ping->dht->self_public_key)) 192 if (id_equal(packet + 1, dht_get_self_public_key(ping->dht))) {
182 return 1; 193 return 1;
194 }
183 195
184 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 196 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
185 197
186 // generate key to encrypt ping_id with recipient privkey 198 // generate key to encrypt ping_id with recipient privkey
187 DHT_get_shared_key_sent(ping->dht, shared_key, packet + 1); 199 DHT_get_shared_key_sent(ping->dht, shared_key, packet + 1);
@@ -189,32 +201,37 @@ static int handle_ping_response(void *_dht, IP_Port source, const uint8_t *packe
189 uint8_t ping_plain[PING_PLAIN_SIZE]; 201 uint8_t ping_plain[PING_PLAIN_SIZE];
190 // Decrypt ping_id 202 // Decrypt ping_id
191 rc = decrypt_data_symmetric(shared_key, 203 rc = decrypt_data_symmetric(shared_key,
192 packet + 1 + crypto_box_PUBLICKEYBYTES, 204 packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
193 packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, 205 packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
194 PING_PLAIN_SIZE + crypto_box_MACBYTES, 206 PING_PLAIN_SIZE + CRYPTO_MAC_SIZE,
195 ping_plain); 207 ping_plain);
196 208
197 if (rc != sizeof(ping_plain)) 209 if (rc != sizeof(ping_plain)) {
198 return 1; 210 return 1;
211 }
199 212
200 if (ping_plain[0] != NET_PACKET_PING_RESPONSE) 213 if (ping_plain[0] != NET_PACKET_PING_RESPONSE) {
201 return 1; 214 return 1;
215 }
202 216
203 uint64_t ping_id; 217 uint64_t ping_id;
204 memcpy(&ping_id, ping_plain + 1, sizeof(ping_id)); 218 memcpy(&ping_id, ping_plain + 1, sizeof(ping_id));
205 uint8_t data[PING_DATA_SIZE]; 219 uint8_t data[PING_DATA_SIZE];
206 220
207 if (ping_array_check(data, sizeof(data), &ping->ping_array, ping_id) != sizeof(data)) 221 if (ping_array_check(ping->ping_array, data, sizeof(data), ping_id) != sizeof(data)) {
208 return 1; 222 return 1;
223 }
209 224
210 if (!id_equal(packet + 1, data)) 225 if (!id_equal(packet + 1, data)) {
211 return 1; 226 return 1;
227 }
212 228
213 IP_Port ipp; 229 IP_Port ipp;
214 memcpy(&ipp, data + crypto_box_PUBLICKEYBYTES, sizeof(IP_Port)); 230 memcpy(&ipp, data + CRYPTO_PUBLIC_KEY_SIZE, sizeof(IP_Port));
215 231
216 if (!ipport_equal(&ipp, &source)) 232 if (!ipport_equal(&ipp, &source)) {
217 return 1; 233 return 1;
234 }
218 235
219 addto_lists(dht, source, packet + 1); 236 addto_lists(dht, source, packet + 1);
220 return 0; 237 return 0;
@@ -233,14 +250,15 @@ static int in_list(const Client_data *list, uint16_t length, const uint8_t *publ
233 if (id_equal(list[i].public_key, public_key)) { 250 if (id_equal(list[i].public_key, public_key)) {
234 const IPPTsPng *ipptp; 251 const IPPTsPng *ipptp;
235 252
236 if (ip_port.ip.family == AF_INET) { 253 if (net_family_is_ipv4(ip_port.ip.family)) {
237 ipptp = &list[i].assoc4; 254 ipptp = &list[i].assoc4;
238 } else { 255 } else {
239 ipptp = &list[i].assoc6; 256 ipptp = &list[i].assoc6;
240 } 257 }
241 258
242 if (!is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT) && ipport_equal(&ipptp->ip_port, &ip_port)) 259 if (!is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT) && ipport_equal(&ipptp->ip_port, &ip_port)) {
243 return 1; 260 return 1;
261 }
244 } 262 }
245 } 263 }
246 264
@@ -257,21 +275,24 @@ static int in_list(const Client_data *list, uint16_t length, const uint8_t *publ
257 * return 0 if node was added. 275 * return 0 if node was added.
258 * return -1 if node was not added. 276 * return -1 if node was not added.
259 */ 277 */
260int add_to_ping(PING *ping, const uint8_t *public_key, IP_Port ip_port) 278int32_t ping_add(Ping *ping, const uint8_t *public_key, IP_Port ip_port)
261{ 279{
262 if (!ip_isset(&ip_port.ip)) 280 if (!ip_isset(&ip_port.ip)) {
263 return -1; 281 return -1;
282 }
264 283
265 if (!node_addable_to_close_list(ping->dht, public_key, ip_port)) 284 if (!node_addable_to_close_list(ping->dht, public_key, ip_port)) {
266 return -1; 285 return -1;
286 }
267 287
268 if (in_list(ping->dht->close_clientlist, LCLIENT_LIST, public_key, ip_port)) 288 if (in_list(dht_get_close_clientlist(ping->dht), LCLIENT_LIST, public_key, ip_port)) {
269 return -1; 289 return -1;
290 }
270 291
271 IP_Port temp; 292 IP_Port temp;
272 293
273 if (DHT_getfriendip(ping->dht, public_key, &temp) == 0) { 294 if (DHT_getfriendip(ping->dht, public_key, &temp) == 0) {
274 send_ping_request(ping, ip_port, public_key); 295 ping_send_request(ping, ip_port, public_key);
275 return -1; 296 return -1;
276 } 297 }
277 298
@@ -279,7 +300,7 @@ int add_to_ping(PING *ping, const uint8_t *public_key, IP_Port ip_port)
279 300
280 for (i = 0; i < MAX_TO_PING; ++i) { 301 for (i = 0; i < MAX_TO_PING; ++i) {
281 if (!ip_isset(&ping->to_ping[i].ip_port.ip)) { 302 if (!ip_isset(&ping->to_ping[i].ip_port.ip)) {
282 memcpy(ping->to_ping[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); 303 memcpy(ping->to_ping[i].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
283 ipport_copy(&ping->to_ping[i].ip_port, &ip_port); 304 ipport_copy(&ping->to_ping[i].ip_port, &ip_port);
284 return 0; 305 return 0;
285 } 306 }
@@ -289,8 +310,9 @@ int add_to_ping(PING *ping, const uint8_t *public_key, IP_Port ip_port)
289 } 310 }
290 } 311 }
291 312
292 if (add_to_list(ping->to_ping, MAX_TO_PING, public_key, ip_port, ping->dht->self_public_key)) 313 if (add_to_list(ping->to_ping, MAX_TO_PING, public_key, ip_port, dht_get_self_public_key(ping->dht))) {
293 return 0; 314 return 0;
315 }
294 316
295 return -1; 317 return -1;
296} 318}
@@ -299,56 +321,64 @@ int add_to_ping(PING *ping, const uint8_t *public_key, IP_Port ip_port)
299/* Ping all the valid nodes in the to_ping list every TIME_TO_PING seconds. 321/* Ping all the valid nodes in the to_ping list every TIME_TO_PING seconds.
300 * This function must be run at least once every TIME_TO_PING seconds. 322 * This function must be run at least once every TIME_TO_PING seconds.
301 */ 323 */
302void do_to_ping(PING *ping) 324void ping_iterate(Ping *ping)
303{ 325{
304 if (!is_timeout(ping->last_to_ping, TIME_TO_PING)) 326 if (!is_timeout(ping->last_to_ping, TIME_TO_PING)) {
305 return; 327 return;
328 }
306 329
307 if (!ip_isset(&ping->to_ping[0].ip_port.ip)) 330 if (!ip_isset(&ping->to_ping[0].ip_port.ip)) {
308 return; 331 return;
332 }
309 333
310 unsigned int i; 334 unsigned int i;
311 335
312 for (i = 0; i < MAX_TO_PING; ++i) { 336 for (i = 0; i < MAX_TO_PING; ++i) {
313 if (!ip_isset(&ping->to_ping[i].ip_port.ip)) 337 if (!ip_isset(&ping->to_ping[i].ip_port.ip)) {
314 break; 338 break;
339 }
315 340
316 if (!node_addable_to_close_list(ping->dht, ping->to_ping[i].public_key, ping->to_ping[i].ip_port)) 341 if (!node_addable_to_close_list(ping->dht, ping->to_ping[i].public_key, ping->to_ping[i].ip_port)) {
317 continue; 342 continue;
343 }
318 344
319 send_ping_request(ping, ping->to_ping[i].ip_port, ping->to_ping[i].public_key); 345 ping_send_request(ping, ping->to_ping[i].ip_port, ping->to_ping[i].public_key);
320 ip_reset(&ping->to_ping[i].ip_port.ip); 346 ip_reset(&ping->to_ping[i].ip_port.ip);
321 } 347 }
322 348
323 if (i != 0) 349 if (i != 0) {
324 ping->last_to_ping = unix_time(); 350 ping->last_to_ping = unix_time();
351 }
325} 352}
326 353
327 354
328PING *new_ping(DHT *dht) 355Ping *ping_new(DHT *dht)
329{ 356{
330 PING *ping = calloc(1, sizeof(PING)); 357 Ping *ping = (Ping *)calloc(1, sizeof(Ping));
358
359 if (ping == nullptr) {
360 return nullptr;
361 }
331 362
332 if (ping == NULL) 363 ping->ping_array = ping_array_new(PING_NUM_MAX, PING_TIMEOUT);
333 return NULL;
334 364
335 if (ping_array_init(&ping->ping_array, PING_NUM_MAX, PING_TIMEOUT) != 0) { 365 if (ping->ping_array == nullptr) {
336 free(ping); 366 free(ping);
337 return NULL; 367 return nullptr;
338 } 368 }
339 369
340 ping->dht = dht; 370 ping->dht = dht;
341 networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, &handle_ping_request, dht); 371 networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_REQUEST, &handle_ping_request, dht);
342 networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, dht); 372 networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_RESPONSE, &handle_ping_response, dht);
343 373
344 return ping; 374 return ping;
345} 375}
346 376
347void kill_ping(PING *ping) 377void ping_kill(Ping *ping)
348{ 378{
349 networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, NULL, NULL); 379 networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_REQUEST, nullptr, nullptr);
350 networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, NULL, NULL); 380 networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_RESPONSE, nullptr, nullptr);
351 ping_array_free_all(&ping->ping_array); 381 ping_array_kill(ping->ping_array);
352 382
353 free(ping); 383 free(ping);
354} 384}
diff --git a/toxcore/ping.h b/toxcore/ping.h
index 904ad844..61875a0b 100644
--- a/toxcore/ping.h
+++ b/toxcore/ping.h
@@ -1,32 +1,56 @@
1/* 1/*
2 * ping.h -- Buffered pinging using cyclic arrays. 2 * Buffered pinging using cyclic arrays.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2013 Tox project.
8 * Copyright © 2013 plutooo
3 * 9 *
10 * This file is part of Tox, the free peer to peer instant messenger.
4 * This file is donated to the Tox Project. 11 * This file is donated to the Tox Project.
5 * Copyright 2013 plutooo
6 * 12 *
7 * Copyright (C) 2013 Tox project All Rights Reserved. 13 * Tox is free software: you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation, either version 3 of the License, or
16 * (at your option) any later version.
8 * 17 *
9 * This file is part of Tox. 18 * Tox is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
10 * 22 *
11 * Tox is free software: you can redistribute it and/or modify 23 * You should have received a copy of the GNU General Public License
12 * it under the terms of the GNU General Public License as published by 24 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * Tox is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
23 */ 25 */
24#ifndef __PING_H__ 26#ifndef PING_H
25#define __PING_H__ 27#define PING_H
28
29#include "DHT.h"
30#include "network.h"
31
32#include <stdint.h>
33
34#ifndef IP_PORT_DEFINED
35#define IP_PORT_DEFINED
36typedef struct IP_Port IP_Port;
37#endif /* IP_PORT_DEFINED */
38
39#ifndef DHT_DEFINED
40#define DHT_DEFINED
41typedef struct DHT DHT;
42#endif /* DHT_DEFINED */
43
44#ifndef PING_DEFINED
45#define PING_DEFINED
46typedef struct Ping Ping;
47#endif /* PING_DEFINED */
48
49Ping *ping_new(DHT *dht);
26 50
27typedef struct PING PING; 51void ping_kill(Ping *ping);
28 52
29/* Add nodes to the to_ping list. 53/** Add nodes to the to_ping list.
30 * All nodes in this list are pinged every TIME_TOPING seconds 54 * All nodes in this list are pinged every TIME_TOPING seconds
31 * and are then removed from the list. 55 * and are then removed from the list.
32 * If the list is full the nodes farthest from our public_key are replaced. 56 * If the list is full the nodes farthest from our public_key are replaced.
@@ -36,12 +60,10 @@ typedef struct PING PING;
36 * return 0 if node was added. 60 * return 0 if node was added.
37 * return -1 if node was not added. 61 * return -1 if node was not added.
38 */ 62 */
39int add_to_ping(PING *ping, const uint8_t *public_key, IP_Port ip_port); 63int32_t ping_add(Ping *ping, const uint8_t *public_key, struct IP_Port ip_port);
40void do_to_ping(PING *ping);
41 64
42PING *new_ping(DHT *dht); 65void ping_iterate(Ping *ping);
43void kill_ping(PING *ping);
44 66
45int send_ping_request(PING *ping, IP_Port ipp, const uint8_t *public_key); 67int32_t ping_send_request(Ping *ping, struct IP_Port ipp, const uint8_t *public_key);
46 68
47#endif /* __PING_H__ */ 69#endif /* PING_H */
diff --git a/toxcore/ping_array.api.h b/toxcore/ping_array.api.h
new file mode 100644
index 00000000..55b80570
--- /dev/null
+++ b/toxcore/ping_array.api.h
@@ -0,0 +1,72 @@
1%{
2/*
3 * Implementation of an efficient array to store that we pinged something.
4 */
5
6/*
7 * Copyright © 2016-2017 The TokTok team.
8 * Copyright © 2013 Tox project.
9 *
10 * This file is part of Tox, the free peer to peer instant messenger.
11 *
12 * Tox is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * Tox is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
24 */
25#ifndef PING_ARRAY_H
26#define PING_ARRAY_H
27
28#include "network.h"
29%}
30
31class ping_Array {
32
33struct this;
34
35/**
36 * Initialize a Ping_Array.
37 * size represents the total size of the array and should be a power of 2.
38 * timeout represents the maximum timeout in seconds for the entry.
39 *
40 * return 0 on success.
41 * return -1 on failure.
42 */
43static this new(uint32_t size, uint32_t timeout);
44
45/**
46 * Free all the allocated memory in a Ping_Array.
47 */
48void kill();
49
50/**
51 * Add a data with length to the Ping_Array list and return a ping_id.
52 *
53 * return ping_id on success.
54 * return 0 on failure.
55 */
56uint64_t add(const uint8_t *data, uint32_t length);
57
58/**
59 * Check if ping_id is valid and not timed out.
60 *
61 * On success, copies the data into data of length,
62 *
63 * return length of data copied on success.
64 * return -1 on failure.
65 */
66int32_t check(uint8_t[length] data, uint64_t ping_id);
67
68}
69
70%{
71#endif
72%}
diff --git a/toxcore/ping_array.c b/toxcore/ping_array.c
index 93dade05..bcab9fe2 100644
--- a/toxcore/ping_array.c
+++ b/toxcore/ping_array.c
@@ -1,44 +1,110 @@
1/* ping_array.c 1/*
2 *
3 * Implementation of an efficient array to store that we pinged something. 2 * Implementation of an efficient array to store that we pinged something.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2014 Tox project.
4 * 8 *
9 * This file is part of Tox, the free peer to peer instant messenger.
5 * 10 *
6 * Copyright (C) 2014 Tox project All Rights Reserved. 11 * Tox is free software: you can redistribute it and/or modify
7 * 12 * it under the terms of the GNU General Public License as published by
8 * This file is part of Tox. 13 * the Free Software Foundation, either version 3 of the License, or
9 * 14 * (at your option) any later version.
10 * Tox is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * Tox is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 * 15 *
20 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
21 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
22 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
23 */ 23 */
24
25#ifdef HAVE_CONFIG_H 24#ifdef HAVE_CONFIG_H
26#include "config.h" 25#include "config.h"
27#endif 26#endif
28 27
29#include "ping_array.h" 28#include "ping_array.h"
29
30#include <stdlib.h>
31#include <string.h>
32
30#include "crypto_core.h" 33#include "crypto_core.h"
31#include "util.h" 34#include "util.h"
32 35
36
37typedef struct {
38 void *data;
39 uint32_t length;
40 uint64_t time;
41 uint64_t ping_id;
42} Ping_Array_Entry;
43
44struct Ping_Array {
45 Ping_Array_Entry *entries;
46
47 uint32_t last_deleted; /* number representing the next entry to be deleted. */
48 uint32_t last_added; /* number representing the last entry to be added. */
49 uint32_t total_size; /* The length of entries */
50 uint32_t timeout; /* The timeout after which entries are cleared. */
51};
52
53/* Initialize a Ping_Array.
54 * size represents the total size of the array and should be a power of 2.
55 * timeout represents the maximum timeout in seconds for the entry.
56 *
57 * return 0 on success.
58 * return -1 on failure.
59 */
60Ping_Array *ping_array_new(uint32_t size, uint32_t timeout)
61{
62 if (size == 0 || timeout == 0) {
63 return nullptr;
64 }
65
66 Ping_Array *empty_array = (Ping_Array *)calloc(1, sizeof(Ping_Array));
67
68 if (empty_array == nullptr) {
69 return nullptr;
70 }
71
72 empty_array->entries = (Ping_Array_Entry *)calloc(size, sizeof(Ping_Array_Entry));
73
74 if (empty_array->entries == nullptr) {
75 free(empty_array);
76 return nullptr;
77 }
78
79 empty_array->last_deleted = empty_array->last_added = 0;
80 empty_array->total_size = size;
81 empty_array->timeout = timeout;
82 return empty_array;
83}
84
33static void clear_entry(Ping_Array *array, uint32_t index) 85static void clear_entry(Ping_Array *array, uint32_t index)
34{ 86{
35 free(array->entries[index].data); 87 free(array->entries[index].data);
36 array->entries[index].data = NULL; 88 array->entries[index].data = nullptr;
37 array->entries[index].length = 89 array->entries[index].length =
38 array->entries[index].time = 90 array->entries[index].time =
39 array->entries[index].ping_id = 0; 91 array->entries[index].ping_id = 0;
40} 92}
41 93
94/* Free all the allocated memory in a Ping_Array.
95 */
96void ping_array_kill(Ping_Array *array)
97{
98 while (array->last_deleted != array->last_added) {
99 uint32_t index = array->last_deleted % array->total_size;
100 clear_entry(array, index);
101 ++array->last_deleted;
102 }
103
104 free(array->entries);
105 free(array);
106}
107
42/* Clear timed out entries. 108/* Clear timed out entries.
43 */ 109 */
44static void ping_array_clear_timedout(Ping_Array *array) 110static void ping_array_clear_timedout(Ping_Array *array)
@@ -46,8 +112,9 @@ static void ping_array_clear_timedout(Ping_Array *array)
46 while (array->last_deleted != array->last_added) { 112 while (array->last_deleted != array->last_added) {
47 uint32_t index = array->last_deleted % array->total_size; 113 uint32_t index = array->last_deleted % array->total_size;
48 114
49 if (!is_timeout(array->entries[index].time, array->timeout)) 115 if (!is_timeout(array->entries[index].time, array->timeout)) {
50 break; 116 break;
117 }
51 118
52 clear_entry(array, index); 119 clear_entry(array, index);
53 ++array->last_deleted; 120 ++array->last_deleted;
@@ -64,27 +131,29 @@ uint64_t ping_array_add(Ping_Array *array, const uint8_t *data, uint32_t length)
64 ping_array_clear_timedout(array); 131 ping_array_clear_timedout(array);
65 uint32_t index = array->last_added % array->total_size; 132 uint32_t index = array->last_added % array->total_size;
66 133
67 if (array->entries[index].data != NULL) { 134 if (array->entries[index].data != nullptr) {
68 array->last_deleted = array->last_added - array->total_size; 135 array->last_deleted = array->last_added - array->total_size;
69 clear_entry(array, index); 136 clear_entry(array, index);
70 } 137 }
71 138
72 array->entries[index].data = malloc(length); 139 array->entries[index].data = malloc(length);
73 140
74 if (array->entries[index].data == NULL) 141 if (array->entries[index].data == nullptr) {
75 return 0; 142 return 0;
143 }
76 144
77 memcpy(array->entries[index].data, data, length); 145 memcpy(array->entries[index].data, data, length);
78 array->entries[index].length = length; 146 array->entries[index].length = length;
79 array->entries[index].time = unix_time(); 147 array->entries[index].time = unix_time();
80 ++array->last_added; 148 ++array->last_added;
81 uint64_t ping_id = random_64b(); 149 uint64_t ping_id = random_u64();
82 ping_id /= array->total_size; 150 ping_id /= array->total_size;
83 ping_id *= array->total_size; 151 ping_id *= array->total_size;
84 ping_id += index; 152 ping_id += index;
85 153
86 if (ping_id == 0) 154 if (ping_id == 0) {
87 ping_id += array->total_size; 155 ping_id += array->total_size;
156 }
88 157
89 array->entries[index].ping_id = ping_id; 158 array->entries[index].ping_id = ping_id;
90 return ping_id; 159 return ping_id;
@@ -98,65 +167,32 @@ uint64_t ping_array_add(Ping_Array *array, const uint8_t *data, uint32_t length)
98 * return length of data copied on success. 167 * return length of data copied on success.
99 * return -1 on failure. 168 * return -1 on failure.
100 */ 169 */
101int ping_array_check(uint8_t *data, uint32_t length, Ping_Array *array, uint64_t ping_id) 170int32_t ping_array_check(Ping_Array *array, uint8_t *data, size_t length, uint64_t ping_id)
102{ 171{
103 if (ping_id == 0) 172 if (ping_id == 0) {
104 return -1; 173 return -1;
174 }
105 175
106 uint32_t index = ping_id % array->total_size; 176 uint32_t index = ping_id % array->total_size;
107 177
108 if (array->entries[index].ping_id != ping_id) 178 if (array->entries[index].ping_id != ping_id) {
109 return -1; 179 return -1;
180 }
110 181
111 if (is_timeout(array->entries[index].time, array->timeout)) 182 if (is_timeout(array->entries[index].time, array->timeout)) {
112 return -1; 183 return -1;
184 }
113 185
114 if (array->entries[index].length > length) 186 if (array->entries[index].length > length) {
115 return -1; 187 return -1;
188 }
116 189
117 if (array->entries[index].data == NULL) 190 if (array->entries[index].data == nullptr) {
118 return -1; 191 return -1;
192 }
119 193
120 memcpy(data, array->entries[index].data, array->entries[index].length); 194 memcpy(data, array->entries[index].data, array->entries[index].length);
121 uint32_t len = array->entries[index].length; 195 uint32_t len = array->entries[index].length;
122 clear_entry(array, index); 196 clear_entry(array, index);
123 return len; 197 return len;
124} 198}
125
126/* Initialize a Ping_Array.
127 * size represents the total size of the array and should be a power of 2.
128 * timeout represents the maximum timeout in seconds for the entry.
129 *
130 * return 0 on success.
131 * return -1 on failure.
132 */
133int ping_array_init(Ping_Array *empty_array, uint32_t size, uint32_t timeout)
134{
135 if (size == 0 || timeout == 0 || empty_array == NULL)
136 return -1;
137
138 empty_array->entries = calloc(size, sizeof(Ping_Array_Entry));
139
140 if (empty_array->entries == NULL)
141 return -1;
142
143 empty_array->last_deleted = empty_array->last_added = 0;
144 empty_array->total_size = size;
145 empty_array->timeout = timeout;
146 return 0;
147}
148
149/* Free all the allocated memory in a Ping_Array.
150 */
151void ping_array_free_all(Ping_Array *array)
152{
153 while (array->last_deleted != array->last_added) {
154 uint32_t index = array->last_deleted % array->total_size;
155 clear_entry(array, index);
156 ++array->last_deleted;
157 }
158
159 free(array->entries);
160 array->entries = NULL;
161}
162
diff --git a/toxcore/ping_array.h b/toxcore/ping_array.h
index 364ad833..b927bbd4 100644
--- a/toxcore/ping_array.h
+++ b/toxcore/ping_array.h
@@ -1,75 +1,67 @@
1/* ping_array.h 1/*
2 *
3 * Implementation of an efficient array to store that we pinged something. 2 * Implementation of an efficient array to store that we pinged something.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2013 Tox project.
4 * 8 *
5 * Copyright (C) 2013 Tox project All Rights Reserved. 9 * This file is part of Tox, the free peer to peer instant messenger.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23#ifndef PING_ARRAY_H 24#ifndef PING_ARRAY_H
24#define PING_ARRAY_H 25#define PING_ARRAY_H
25 26
26#include "network.h" 27#include "network.h"
27 28
28typedef struct { 29#ifndef PING_ARRAY_DEFINED
29 void *data; 30#define PING_ARRAY_DEFINED
30 uint32_t length; 31typedef struct Ping_Array Ping_Array;
31 uint64_t time; 32#endif /* PING_ARRAY_DEFINED */
32 uint64_t ping_id;
33} Ping_Array_Entry;
34
35 33
36typedef struct { 34/**
37 Ping_Array_Entry *entries; 35 * Initialize a Ping_Array.
38 36 * size represents the total size of the array and should be a power of 2.
39 uint32_t last_deleted; /* number representing the next entry to be deleted. */ 37 * timeout represents the maximum timeout in seconds for the entry.
40 uint32_t last_added; /* number representing the last entry to be added. */ 38 *
41 uint32_t total_size; /* The length of entries */ 39 * return 0 on success.
42 uint32_t timeout; /* The timeout after which entries are cleared. */ 40 * return -1 on failure.
43} Ping_Array; 41 */
42struct Ping_Array *ping_array_new(uint32_t size, uint32_t timeout);
44 43
44/**
45 * Free all the allocated memory in a Ping_Array.
46 */
47void ping_array_kill(struct Ping_Array *_array);
45 48
46/* Add a data with length to the Ping_Array list and return a ping_id. 49/**
50 * Add a data with length to the Ping_Array list and return a ping_id.
47 * 51 *
48 * return ping_id on success. 52 * return ping_id on success.
49 * return 0 on failure. 53 * return 0 on failure.
50 */ 54 */
51uint64_t ping_array_add(Ping_Array *array, const uint8_t *data, uint32_t length); 55uint64_t ping_array_add(struct Ping_Array *_array, const uint8_t *data, uint32_t length);
52 56
53/* Check if ping_id is valid and not timed out. 57/**
58 * Check if ping_id is valid and not timed out.
54 * 59 *
55 * On success, copies the data into data of length, 60 * On success, copies the data into data of length,
56 * 61 *
57 * return length of data copied on success. 62 * return length of data copied on success.
58 * return -1 on failure. 63 * return -1 on failure.
59 */ 64 */
60int ping_array_check(uint8_t *data, uint32_t length, Ping_Array *array, uint64_t ping_id); 65int32_t ping_array_check(struct Ping_Array *_array, uint8_t *data, size_t length, uint64_t ping_id);
61
62/* Initialize a Ping_Array.
63 * size represents the total size of the array and should be a power of 2.
64 * timeout represents the maximum timeout in seconds for the entry.
65 *
66 * return 0 on success.
67 * return -1 on failure.
68 */
69int ping_array_init(Ping_Array *empty_array, uint32_t size, uint32_t timeout);
70
71/* Free all the allocated memory in a Ping_Array.
72 */
73void ping_array_free_all(Ping_Array *array);
74 66
75#endif 67#endif
diff --git a/toxcore/tox.api.h b/toxcore/tox.api.h
new file mode 100644
index 00000000..1c3b1121
--- /dev/null
+++ b/toxcore/tox.api.h
@@ -0,0 +1,2606 @@
1%{
2/*
3 * The Tox public API.
4 */
5
6/*
7 * Copyright © 2016-2017 The TokTok team.
8 * Copyright © 2013 Tox project.
9 *
10 * This file is part of Tox, the free peer to peer instant messenger.
11 *
12 * Tox is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * Tox is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
24 */
25#ifndef TOX_H
26#define TOX_H
27
28#include <stdbool.h>
29#include <stddef.h>
30#include <stdint.h>
31
32#ifdef __cplusplus
33extern "C" {
34#endif
35%}
36
37
38/*****************************************************************************
39 * `tox.h` SHOULD *NOT* BE EDITED MANUALLY – any changes should be made to *
40 * `tox.api.h`, located in `toxcore/`. For instructions on how to *
41 * generate `tox.h` from `tox.api.h` please refer to `docs/apidsl.md` *
42 *****************************************************************************/
43
44
45/** \page core Public core API for Tox clients.
46 *
47 * Every function that can fail takes a function-specific error code pointer
48 * that can be used to diagnose problems with the Tox state or the function
49 * arguments. The error code pointer can be NULL, which does not influence the
50 * function's behaviour, but can be done if the reason for failure is irrelevant
51 * to the client.
52 *
53 * The exception to this rule are simple allocation functions whose only failure
54 * mode is allocation failure. They return NULL in that case, and do not set an
55 * error code.
56 *
57 * Every error code type has an OK value to which functions will set their error
58 * code value on success. Clients can keep their error code uninitialised before
59 * passing it to a function. The library guarantees that after returning, the
60 * value pointed to by the error code pointer has been initialised.
61 *
62 * Functions with pointer parameters often have a NULL error code, meaning they
63 * could not perform any operation, because one of the required parameters was
64 * NULL. Some functions operate correctly or are defined as effectless on NULL.
65 *
66 * Some functions additionally return a value outside their
67 * return type domain, or a bool containing true on success and false on
68 * failure.
69 *
70 * All functions that take a Tox instance pointer will cause undefined behaviour
71 * when passed a NULL Tox pointer.
72 *
73 * All integer values are expected in host byte order.
74 *
75 * Functions with parameters with enum types cause unspecified behaviour if the
76 * enumeration value is outside the valid range of the type. If possible, the
77 * function will try to use a sane default, but there will be no error code,
78 * and one possible action for the function to take is to have no effect.
79 *
80 * Integer constants and the memory layout of publicly exposed structs are not
81 * part of the ABI.
82 */
83
84/** \subsection events Events and callbacks
85 *
86 * Events are handled by callbacks. One callback can be registered per event.
87 * All events have a callback function type named `tox_{event}_cb` and a
88 * function to register it named `tox_callback_{event}`. Passing a NULL
89 * callback will result in no callback being registered for that event. Only
90 * one callback per event can be registered, so if a client needs multiple
91 * event listeners, it needs to implement the dispatch functionality itself.
92 *
93 * The last argument to a callback is the user data pointer. It is passed from
94 * ${tox.iterate} to each callback in sequence.
95 *
96 * The user data pointer is never stored or dereferenced by any library code, so
97 * can be any pointer, including NULL. Callbacks must all operate on the same
98 * object type. In the apidsl code (tox.in.h), this is denoted with `any`. The
99 * `any` in ${tox.iterate} must be the same `any` as in all callbacks. In C,
100 * lacking parametric polymorphism, this is a pointer to void.
101 *
102 * Old style callbacks that are registered together with a user data pointer
103 * receive that pointer as argument when they are called. They can each have
104 * their own user data pointer of their own type.
105 */
106
107/** \subsection threading Threading implications
108 *
109 * It is possible to run multiple concurrent threads with a Tox instance for
110 * each thread. It is also possible to run all Tox instances in the same thread.
111 * A common way to run Tox (multiple or single instance) is to have one thread
112 * running a simple ${tox.iterate} loop, sleeping for ${tox.iteration_interval}
113 * milliseconds on each iteration.
114 *
115 * If you want to access a single Tox instance from multiple threads, access
116 * to the instance must be synchronised. While multiple threads can concurrently
117 * access multiple different Tox instances, no more than one API function can
118 * operate on a single instance at any given time.
119 *
120 * Functions that write to variable length byte arrays will always have a size
121 * function associated with them. The result of this size function is only valid
122 * until another mutating function (one that takes a pointer to non-const Tox)
123 * is called. Thus, clients must ensure that no other thread calls a mutating
124 * function between the call to the size function and the call to the retrieval
125 * function.
126 *
127 * E.g. to get the current nickname, one would write
128 *
129 * \code
130 * size_t length = ${tox.self.name.size}(tox);
131 * uint8_t *name = malloc(length);
132 * if (!name) abort();
133 * ${tox.self.name.get}(tox, name);
134 * \endcode
135 *
136 * If any other thread calls ${tox.self.name.set} while this thread is allocating
137 * memory, the length may have become invalid, and the call to
138 * ${tox.self.name.get} may cause undefined behaviour.
139 */
140
141// The rest of this file is in class tox.
142class tox {
143
144/**
145 * The Tox instance type. All the state associated with a connection is held
146 * within the instance. Multiple instances can exist and operate concurrently.
147 * The maximum number of Tox instances that can exist on a single network
148 * device is limited. Note that this is not just a per-process limit, since the
149 * limiting factor is the number of usable ports on a device.
150 */
151struct this;
152
153
154/*******************************************************************************
155 *
156 * :: API version
157 *
158 ******************************************************************************/
159
160
161/**
162 * The major version number. Incremented when the API or ABI changes in an
163 * incompatible way.
164 *
165 * The function variants of these constants return the version number of the
166 * library. They can be used to display the Tox library version or to check
167 * whether the client is compatible with the dynamically linked version of Tox.
168 */
169const VERSION_MAJOR = 0;
170
171/**
172 * The minor version number. Incremented when functionality is added without
173 * breaking the API or ABI. Set to 0 when the major version number is
174 * incremented.
175 */
176const VERSION_MINOR = 2;
177
178/**
179 * The patch or revision number. Incremented when bugfixes are applied without
180 * changing any functionality or API or ABI.
181 */
182const VERSION_PATCH = 2;
183
184/**
185 * A macro to check at preprocessing time whether the client code is compatible
186 * with the installed version of Tox. Leading zeros in the version number are
187 * ignored. E.g. 0.1.5 is to 0.1.4 what 1.5 is to 1.4, that is: it can add new
188 * features, but can't break the API.
189 */
190#define TOX_VERSION_IS_API_COMPATIBLE(MAJOR, MINOR, PATCH) \
191 ((TOX_VERSION_MAJOR > 0 && TOX_VERSION_MAJOR == MAJOR) && ( \
192 /* 1.x.x, 2.x.x, etc. with matching major version. */ \
193 TOX_VERSION_MINOR > MINOR || \
194 (TOX_VERSION_MINOR == MINOR && TOX_VERSION_PATCH >= PATCH) \
195 )) || ((TOX_VERSION_MAJOR == 0 && MAJOR == 0) && ( \
196 /* 0.x.x makes minor behave like major above. */ \
197 ((TOX_VERSION_MINOR > 0 && TOX_VERSION_MINOR == MINOR) && ( \
198 TOX_VERSION_PATCH >= PATCH \
199 )) || ((TOX_VERSION_MINOR == 0 && MINOR == 0) && ( \
200 /* 0.0.x and 0.0.y are only compatible if x == y. */ \
201 TOX_VERSION_PATCH == PATCH \
202 )) \
203 ))
204
205static namespace version {
206
207 /**
208 * Return whether the compiled library version is compatible with the passed
209 * version numbers.
210 */
211 bool is_compatible(uint32_t major, uint32_t minor, uint32_t patch);
212
213}
214
215/**
216 * A convenience macro to call tox_version_is_compatible with the currently
217 * compiling API version.
218 */
219#define TOX_VERSION_IS_ABI_COMPATIBLE() \
220 tox_version_is_compatible(TOX_VERSION_MAJOR, TOX_VERSION_MINOR, TOX_VERSION_PATCH)
221
222/*******************************************************************************
223 *
224 * :: Numeric constants
225 *
226 * The values of these are not part of the ABI. Prefer to use the function
227 * versions of them for code that should remain compatible with future versions
228 * of toxcore.
229 *
230 ******************************************************************************/
231
232
233/**
234 * The size of a Tox Public Key in bytes.
235 */
236const PUBLIC_KEY_SIZE = 32;
237
238/**
239 * The size of a Tox Secret Key in bytes.
240 */
241const SECRET_KEY_SIZE = 32;
242
243/**
244 * The size of the nospam in bytes when written in a Tox address.
245 */
246const NOSPAM_SIZE = sizeof(uint32_t);
247
248/**
249 * The size of a Tox address in bytes. Tox addresses are in the format
250 * [Public Key ($PUBLIC_KEY_SIZE bytes)][nospam (4 bytes)][checksum (2 bytes)].
251 *
252 * The checksum is computed over the Public Key and the nospam value. The first
253 * byte is an XOR of all the even bytes (0, 2, 4, ...), the second byte is an
254 * XOR of all the odd bytes (1, 3, 5, ...) of the Public Key and nospam.
255 */
256const ADDRESS_SIZE = PUBLIC_KEY_SIZE + NOSPAM_SIZE + sizeof(uint16_t);
257
258/**
259 * Maximum length of a nickname in bytes.
260 *
261 * @deprecated The macro will be removed in 0.3.0. Use the function instead.
262 */
263const MAX_NAME_LENGTH = 128;
264
265/**
266 * Maximum length of a status message in bytes.
267 *
268 * @deprecated The macro will be removed in 0.3.0. Use the function instead.
269 */
270const MAX_STATUS_MESSAGE_LENGTH = 1007;
271
272/**
273 * Maximum length of a friend request message in bytes.
274 *
275 * @deprecated The macro will be removed in 0.3.0. Use the function instead.
276 */
277const MAX_FRIEND_REQUEST_LENGTH = 1016;
278
279/**
280 * Maximum length of a single message after which it should be split.
281 *
282 * @deprecated The macro will be removed in 0.3.0. Use the function instead.
283 */
284const MAX_MESSAGE_LENGTH = 1372;
285
286/**
287 * Maximum size of custom packets. TODO(iphydf): should be LENGTH?
288 *
289 * @deprecated The macro will be removed in 0.3.0. Use the function instead.
290 */
291const MAX_CUSTOM_PACKET_SIZE = 1373;
292
293/**
294 * The number of bytes in a hash generated by $hash.
295 */
296const HASH_LENGTH = 32;
297
298/**
299 * The number of bytes in a file id.
300 */
301const FILE_ID_LENGTH = 32;
302
303/**
304 * Maximum file name length for file transfers.
305 *
306 * @deprecated The macro will be removed in 0.3.0. Use the function instead.
307 */
308const MAX_FILENAME_LENGTH = 255;
309
310
311/*******************************************************************************
312 *
313 * :: Global enumerations
314 *
315 ******************************************************************************/
316
317
318/**
319 * Represents the possible statuses a client can have.
320 */
321enum class USER_STATUS {
322 /**
323 * User is online and available.
324 */
325 NONE,
326 /**
327 * User is away. Clients can set this e.g. after a user defined
328 * inactivity time.
329 */
330 AWAY,
331 /**
332 * User is busy. Signals to other clients that this client does not
333 * currently wish to communicate.
334 */
335 BUSY,
336}
337
338
339/**
340 * Represents message types for ${tox.friend.send.message} and conference
341 * messages.
342 */
343enum class MESSAGE_TYPE {
344 /**
345 * Normal text message. Similar to PRIVMSG on IRC.
346 */
347 NORMAL,
348 /**
349 * A message describing an user action. This is similar to /me (CTCP ACTION)
350 * on IRC.
351 */
352 ACTION,
353}
354
355
356/*******************************************************************************
357 *
358 * :: Startup options
359 *
360 ******************************************************************************/
361
362
363/**
364 * Type of proxy used to connect to TCP relays.
365 */
366enum class PROXY_TYPE {
367 /**
368 * Don't use a proxy.
369 */
370 NONE,
371 /**
372 * HTTP proxy using CONNECT.
373 */
374 HTTP,
375 /**
376 * SOCKS proxy for simple socket pipes.
377 */
378 SOCKS5,
379}
380
381/**
382 * Type of savedata to create the Tox instance from.
383 */
384enum class SAVEDATA_TYPE {
385 /**
386 * No savedata.
387 */
388 NONE,
389 /**
390 * Savedata is one that was obtained from ${savedata.get}.
391 */
392 TOX_SAVE,
393 /**
394 * Savedata is a secret key of length $SECRET_KEY_SIZE.
395 */
396 SECRET_KEY,
397}
398
399
400/**
401 * Severity level of log messages.
402 */
403enum class LOG_LEVEL {
404 /**
405 * Very detailed traces including all network activity.
406 */
407 TRACE,
408 /**
409 * Debug messages such as which port we bind to.
410 */
411 DEBUG,
412 /**
413 * Informational log messages such as video call status changes.
414 */
415 INFO,
416 /**
417 * Warnings about internal inconsistency or logic errors.
418 */
419 WARNING,
420 /**
421 * Severe unexpected errors caused by external or internal inconsistency.
422 */
423 ERROR,
424}
425
426/**
427 * This event is triggered when the toxcore library logs an internal message.
428 * This is mostly useful for debugging. This callback can be called from any
429 * function, not just $iterate. This means the user data lifetime must at
430 * least extend between registering and unregistering it or $kill.
431 *
432 * Other toxcore modules such as toxav may concurrently call this callback at
433 * any time. Thus, user code must make sure it is equipped to handle concurrent
434 * execution, e.g. by employing appropriate mutex locking.
435 *
436 * @param level The severity of the log message.
437 * @param file The source file from which the message originated.
438 * @param line The source line from which the message originated.
439 * @param func The function from which the message originated.
440 * @param message The log message.
441 * @param user_data The user data pointer passed to $new in options.
442 */
443typedef void log_cb(LOG_LEVEL level, string file, uint32_t line, string func, string message, any user_data);
444
445
446static class options {
447 /**
448 * This struct contains all the startup options for Tox. You must $new to
449 * allocate an object of this type.
450 *
451 * WARNING: Although this struct happens to be visible in the API, it is
452 * effectively private. Do not allocate this yourself or access members
453 * directly, as it *will* break binary compatibility frequently.
454 *
455 * @deprecated The memory layout of this struct (size, alignment, and field
456 * order) is not part of the ABI. To remain compatible, prefer to use $new to
457 * allocate the object and accessor functions to set the members. The struct
458 * will become opaque (i.e. the definition will become private) in v0.3.0.
459 */
460 struct this [get, set] {
461 /**
462 * The type of socket to create.
463 *
464 * If this is set to false, an IPv4 socket is created, which subsequently
465 * only allows IPv4 communication.
466 * If it is set to true, an IPv6 socket is created, allowing both IPv4 and
467 * IPv6 communication.
468 */
469 bool ipv6_enabled;
470
471 /**
472 * Enable the use of UDP communication when available.
473 *
474 * Setting this to false will force Tox to use TCP only. Communications will
475 * need to be relayed through a TCP relay node, potentially slowing them down.
476 * Disabling UDP support is necessary when using anonymous proxies or Tor.
477 */
478 bool udp_enabled;
479
480 /**
481 * Enable local network peer discovery.
482 *
483 * Disabling this will cause Tox to not look for peers on the local network.
484 */
485 bool local_discovery_enabled;
486
487 namespace proxy {
488 /**
489 * Pass communications through a proxy.
490 */
491 PROXY_TYPE type;
492
493 /**
494 * The IP address or DNS name of the proxy to be used.
495 *
496 * If used, this must be non-NULL and be a valid DNS name. The name must not
497 * exceed 255 characters, and be in a NUL-terminated C string format
498 * (255 chars + 1 NUL byte).
499 *
500 * This member is ignored (it can be NULL) if proxy_type is ${PROXY_TYPE.NONE}.
501 *
502 * The data pointed at by this member is owned by the user, so must
503 * outlive the options object.
504 */
505 string host;
506
507 /**
508 * The port to use to connect to the proxy server.
509 *
510 * Ports must be in the range (1, 65535). The value is ignored if
511 * proxy_type is ${PROXY_TYPE.NONE}.
512 */
513 uint16_t port;
514 }
515
516 /**
517 * The start port of the inclusive port range to attempt to use.
518 *
519 * If both start_port and end_port are 0, the default port range will be
520 * used: [33445, 33545].
521 *
522 * If either start_port or end_port is 0 while the other is non-zero, the
523 * non-zero port will be the only port in the range.
524 *
525 * Having start_port > end_port will yield the same behavior as if start_port
526 * and end_port were swapped.
527 */
528 uint16_t start_port;
529
530 /**
531 * The end port of the inclusive port range to attempt to use.
532 */
533 uint16_t end_port;
534
535 /**
536 * The port to use for the TCP server (relay). If 0, the TCP server is
537 * disabled.
538 *
539 * Enabling it is not required for Tox to function properly.
540 *
541 * When enabled, your Tox instance can act as a TCP relay for other Tox
542 * instance. This leads to increased traffic, thus when writing a client
543 * it is recommended to enable TCP server only if the user has an option
544 * to disable it.
545 */
546 uint16_t tcp_port;
547
548 /**
549 * Enables or disables UDP hole-punching in toxcore. (Default: enabled).
550 */
551 bool hole_punching_enabled;
552
553 namespace savedata {
554 /**
555 * The type of savedata to load from.
556 */
557 SAVEDATA_TYPE type;
558
559 /**
560 * The savedata.
561 *
562 * The data pointed at by this member is owned by the user, so must
563 * outlive the options object.
564 */
565 const uint8_t[length] data;
566
567 /**
568 * The length of the savedata.
569 */
570 size_t length;
571 }
572
573 namespace log {
574 /**
575 * Logging callback for the new tox instance.
576 */
577 log_cb *callback;
578
579 /**
580 * User data pointer passed to the logging callback.
581 */
582 any user_data;
583 }
584 }
585
586
587 /**
588 * Initialises a $this object with the default options.
589 *
590 * The result of this function is independent of the original options. All
591 * values will be overwritten, no values will be read (so it is permissible
592 * to pass an uninitialised object).
593 *
594 * If options is NULL, this function has no effect.
595 *
596 * @param options An options object to be filled with default options.
597 */
598 void default();
599
600
601 /**
602 * Allocates a new $this object and initialises it with the default
603 * options. This function can be used to preserve long term ABI compatibility by
604 * giving the responsibility of allocation and deallocation to the Tox library.
605 *
606 * Objects returned from this function must be freed using the $free
607 * function.
608 *
609 * @return A new $this object with default options or NULL on failure.
610 */
611 static this new() {
612 /**
613 * The function failed to allocate enough memory for the options struct.
614 */
615 MALLOC,
616 }
617
618
619 /**
620 * Releases all resources associated with an options objects.
621 *
622 * Passing a pointer that was not returned by $new results in
623 * undefined behaviour.
624 */
625 void free();
626}
627
628
629/*******************************************************************************
630 *
631 * :: Creation and destruction
632 *
633 ******************************************************************************/
634
635
636/**
637 * @brief Creates and initialises a new Tox instance with the options passed.
638 *
639 * This function will bring the instance into a valid state. Running the event
640 * loop with a new instance will operate correctly.
641 *
642 * If loading failed or succeeded only partially, the new or partially loaded
643 * instance is returned and an error code is set.
644 *
645 * @param options An options object as described above. If this parameter is
646 * NULL, the default options are used.
647 *
648 * @see $iterate for the event loop.
649 *
650 * @return A new Tox instance pointer on success or NULL on failure.
651 */
652static this new(const options_t *options) {
653 NULL,
654 /**
655 * The function was unable to allocate enough memory to store the internal
656 * structures for the Tox object.
657 */
658 MALLOC,
659 /**
660 * The function was unable to bind to a port. This may mean that all ports
661 * have already been bound, e.g. by other Tox instances, or it may mean
662 * a permission error. You may be able to gather more information from errno.
663 */
664 PORT_ALLOC,
665
666 namespace PROXY {
667 /**
668 * proxy_type was invalid.
669 */
670 BAD_TYPE,
671 /**
672 * proxy_type was valid but the proxy_host passed had an invalid format
673 * or was NULL.
674 */
675 BAD_HOST,
676 /**
677 * proxy_type was valid, but the proxy_port was invalid.
678 */
679 BAD_PORT,
680 /**
681 * The proxy address passed could not be resolved.
682 */
683 NOT_FOUND,
684 }
685
686 namespace LOAD {
687 /**
688 * The byte array to be loaded contained an encrypted save.
689 */
690 ENCRYPTED,
691 /**
692 * The data format was invalid. This can happen when loading data that was
693 * saved by an older version of Tox, or when the data has been corrupted.
694 * When loading from badly formatted data, some data may have been loaded,
695 * and the rest is discarded. Passing an invalid length parameter also
696 * causes this error.
697 */
698 BAD_FORMAT,
699 }
700}
701
702
703/**
704 * Releases all resources associated with the Tox instance and disconnects from
705 * the network.
706 *
707 * After calling this function, the Tox pointer becomes invalid. No other
708 * functions can be called, and the pointer value can no longer be read.
709 */
710void kill();
711
712
713uint8_t[size] savedata {
714 /**
715 * Calculates the number of bytes required to store the tox instance with
716 * $get. This function cannot fail. The result is always greater than 0.
717 *
718 * @see threading for concurrency implications.
719 */
720 size();
721
722 /**
723 * Store all information associated with the tox instance to a byte array.
724 *
725 * @param savedata A memory region large enough to store the tox instance
726 * data. Call $size to find the number of bytes required. If this parameter
727 * is NULL, this function has no effect.
728 */
729 get();
730}
731
732
733/*******************************************************************************
734 *
735 * :: Connection lifecycle and event loop
736 *
737 ******************************************************************************/
738
739
740/**
741 * Sends a "get nodes" request to the given bootstrap node with IP, port, and
742 * public key to setup connections.
743 *
744 * This function will attempt to connect to the node using UDP. You must use
745 * this function even if ${options.this.udp_enabled} was set to false.
746 *
747 * @param address The hostname or IP address (IPv4 or IPv6) of the node.
748 * @param port The port on the host on which the bootstrap Tox instance is
749 * listening.
750 * @param public_key The long term public key of the bootstrap node
751 * ($PUBLIC_KEY_SIZE bytes).
752 * @return true on success.
753 */
754bool bootstrap(string address, uint16_t port, const uint8_t[PUBLIC_KEY_SIZE] public_key) {
755 NULL,
756 /**
757 * The address could not be resolved to an IP address, or the IP address
758 * passed was invalid.
759 */
760 BAD_HOST,
761 /**
762 * The port passed was invalid. The valid port range is (1, 65535).
763 */
764 BAD_PORT,
765}
766
767
768/**
769 * Adds additional host:port pair as TCP relay.
770 *
771 * This function can be used to initiate TCP connections to different ports on
772 * the same bootstrap node, or to add TCP relays without using them as
773 * bootstrap nodes.
774 *
775 * @param address The hostname or IP address (IPv4 or IPv6) of the TCP relay.
776 * @param port The port on the host on which the TCP relay is listening.
777 * @param public_key The long term public key of the TCP relay
778 * ($PUBLIC_KEY_SIZE bytes).
779 * @return true on success.
780 */
781bool add_tcp_relay(string address, uint16_t port, const uint8_t[PUBLIC_KEY_SIZE] public_key)
782 with error for bootstrap;
783
784
785/**
786 * Protocols that can be used to connect to the network or friends.
787 */
788enum class CONNECTION {
789 /**
790 * There is no connection. This instance, or the friend the state change is
791 * about, is now offline.
792 */
793 NONE,
794 /**
795 * A TCP connection has been established. For the own instance, this means it
796 * is connected through a TCP relay, only. For a friend, this means that the
797 * connection to that particular friend goes through a TCP relay.
798 */
799 TCP,
800 /**
801 * A UDP connection has been established. For the own instance, this means it
802 * is able to send UDP packets to DHT nodes, but may still be connected to
803 * a TCP relay. For a friend, this means that the connection to that
804 * particular friend was built using direct UDP packets.
805 */
806 UDP,
807}
808
809
810inline namespace self {
811
812 CONNECTION connection_status {
813 /**
814 * Return whether we are connected to the DHT. The return value is equal to the
815 * last value received through the `${event connection_status}` callback.
816 *
817 * @deprecated This getter is deprecated. Use the event and store the status
818 * in the client state.
819 */
820 get();
821 }
822
823
824 /**
825 * This event is triggered whenever there is a change in the DHT connection
826 * state. When disconnected, a client may choose to call $bootstrap again, to
827 * reconnect to the DHT. Note that this state may frequently change for short
828 * amounts of time. Clients should therefore not immediately bootstrap on
829 * receiving a disconnect.
830 *
831 * TODO(iphydf): how long should a client wait before bootstrapping again?
832 */
833 event connection_status const {
834 /**
835 * @param connection_status Whether we are connected to the DHT.
836 */
837 typedef void(CONNECTION connection_status);
838 }
839
840}
841
842
843/**
844 * Return the time in milliseconds before $iterate() should be called again
845 * for optimal performance.
846 */
847const uint32_t iteration_interval();
848
849
850/**
851 * The main loop that needs to be run in intervals of $iteration_interval()
852 * milliseconds.
853 */
854void iterate(any user_data);
855
856
857/*******************************************************************************
858 *
859 * :: Internal client information (Tox address/id)
860 *
861 ******************************************************************************/
862
863
864inline namespace self {
865
866 uint8_t[ADDRESS_SIZE] address {
867 /**
868 * Writes the Tox friend address of the client to a byte array. The address is
869 * not in human-readable format. If a client wants to display the address,
870 * formatting is required.
871 *
872 * @param address A memory region of at least $ADDRESS_SIZE bytes. If this
873 * parameter is NULL, this function has no effect.
874 * @see $ADDRESS_SIZE for the address format.
875 */
876 get();
877 }
878
879
880 uint32_t nospam {
881 /**
882 * Set the 4-byte nospam part of the address. This value is expected in host
883 * byte order. I.e. 0x12345678 will form the bytes [12, 34, 56, 78] in the
884 * nospam part of the Tox friend address.
885 *
886 * @param nospam Any 32 bit unsigned integer.
887 */
888 set();
889
890 /**
891 * Get the 4-byte nospam part of the address. This value is returned in host
892 * byte order.
893 */
894 get();
895 }
896
897
898 uint8_t[PUBLIC_KEY_SIZE] public_key {
899 /**
900 * Copy the Tox Public Key (long term) from the Tox object.
901 *
902 * @param public_key A memory region of at least $PUBLIC_KEY_SIZE bytes. If
903 * this parameter is NULL, this function has no effect.
904 */
905 get();
906 }
907
908
909 uint8_t[SECRET_KEY_SIZE] secret_key {
910 /**
911 * Copy the Tox Secret Key from the Tox object.
912 *
913 * @param secret_key A memory region of at least $SECRET_KEY_SIZE bytes. If
914 * this parameter is NULL, this function has no effect.
915 */
916 get();
917 }
918
919}
920
921
922/*******************************************************************************
923 *
924 * :: User-visible client information (nickname/status)
925 *
926 ******************************************************************************/
927
928
929/**
930 * Common error codes for all functions that set a piece of user-visible
931 * client information.
932 */
933error for set_info {
934 NULL,
935 /**
936 * Information length exceeded maximum permissible size.
937 */
938 TOO_LONG,
939}
940
941
942inline namespace self {
943
944 uint8_t[length <= MAX_NAME_LENGTH] name {
945 /**
946 * Set the nickname for the Tox client.
947 *
948 * Nickname length cannot exceed $MAX_NAME_LENGTH. If length is 0, the name
949 * parameter is ignored (it can be NULL), and the nickname is set back to empty.
950 *
951 * @param name A byte array containing the new nickname.
952 * @param length The size of the name byte array.
953 *
954 * @return true on success.
955 */
956 set() with error for set_info;
957
958 /**
959 * Return the length of the current nickname as passed to $set.
960 *
961 * If no nickname was set before calling this function, the name is empty,
962 * and this function returns 0.
963 *
964 * @see threading for concurrency implications.
965 */
966 size();
967
968 /**
969 * Write the nickname set by $set to a byte array.
970 *
971 * If no nickname was set before calling this function, the name is empty,
972 * and this function has no effect.
973 *
974 * Call $size to find out how much memory to allocate for
975 * the result.
976 *
977 * @param name A valid memory location large enough to hold the nickname.
978 * If this parameter is NULL, the function has no effect.
979 */
980 get();
981 }
982
983
984 uint8_t[length <= MAX_STATUS_MESSAGE_LENGTH] status_message {
985 /**
986 * Set the client's status message.
987 *
988 * Status message length cannot exceed $MAX_STATUS_MESSAGE_LENGTH. If
989 * length is 0, the status parameter is ignored (it can be NULL), and the
990 * user status is set back to empty.
991 */
992 set() with error for set_info;
993
994 /**
995 * Return the length of the current status message as passed to $set.
996 *
997 * If no status message was set before calling this function, the status
998 * is empty, and this function returns 0.
999 *
1000 * @see threading for concurrency implications.
1001 */
1002 size();
1003
1004 /**
1005 * Write the status message set by $set to a byte array.
1006 *
1007 * If no status message was set before calling this function, the status is
1008 * empty, and this function has no effect.
1009 *
1010 * Call $size to find out how much memory to allocate for
1011 * the result.
1012 *
1013 * @param status_message A valid memory location large enough to hold the
1014 * status message. If this parameter is NULL, the function has no effect.
1015 */
1016 get();
1017 }
1018
1019
1020 USER_STATUS status {
1021 /**
1022 * Set the client's user status.
1023 *
1024 * @param status One of the user statuses listed in the enumeration above.
1025 */
1026 set();
1027
1028 /**
1029 * Returns the client's user status.
1030 */
1031 get();
1032 }
1033
1034}
1035
1036
1037/*******************************************************************************
1038 *
1039 * :: Friend list management
1040 *
1041 ******************************************************************************/
1042
1043
1044namespace friend {
1045
1046 /**
1047 * Add a friend to the friend list and send a friend request.
1048 *
1049 * A friend request message must be at least 1 byte long and at most
1050 * $MAX_FRIEND_REQUEST_LENGTH.
1051 *
1052 * Friend numbers are unique identifiers used in all functions that operate on
1053 * friends. Once added, a friend number is stable for the lifetime of the Tox
1054 * object. After saving the state and reloading it, the friend numbers may not
1055 * be the same as before. Deleting a friend creates a gap in the friend number
1056 * set, which is filled by the next adding of a friend. Any pattern in friend
1057 * numbers should not be relied on.
1058 *
1059 * If more than INT32_MAX friends are added, this function causes undefined
1060 * behaviour.
1061 *
1062 * @param address The address of the friend (returned by ${self.address.get} of
1063 * the friend you wish to add) it must be $ADDRESS_SIZE bytes.
1064 * @param message The message that will be sent along with the friend request.
1065 * @param length The length of the data byte array.
1066 *
1067 * @return the friend number on success, UINT32_MAX on failure.
1068 */
1069 uint32_t add(
1070 const uint8_t[ADDRESS_SIZE] address,
1071 const uint8_t[length <= MAX_FRIEND_REQUEST_LENGTH] message
1072 ) {
1073 NULL,
1074 /**
1075 * The length of the friend request message exceeded
1076 * $MAX_FRIEND_REQUEST_LENGTH.
1077 */
1078 TOO_LONG,
1079 /**
1080 * The friend request message was empty. This, and the TOO_LONG code will
1081 * never be returned from $add_norequest.
1082 */
1083 NO_MESSAGE,
1084 /**
1085 * The friend address belongs to the sending client.
1086 */
1087 OWN_KEY,
1088 /**
1089 * A friend request has already been sent, or the address belongs to a friend
1090 * that is already on the friend list.
1091 */
1092 ALREADY_SENT,
1093 /**
1094 * The friend address checksum failed.
1095 */
1096 BAD_CHECKSUM,
1097 /**
1098 * The friend was already there, but the nospam value was different.
1099 */
1100 SET_NEW_NOSPAM,
1101 /**
1102 * A memory allocation failed when trying to increase the friend list size.
1103 */
1104 MALLOC,
1105 }
1106
1107
1108 /**
1109 * Add a friend without sending a friend request.
1110 *
1111 * This function is used to add a friend in response to a friend request. If the
1112 * client receives a friend request, it can be reasonably sure that the other
1113 * client added this client as a friend, eliminating the need for a friend
1114 * request.
1115 *
1116 * This function is also useful in a situation where both instances are
1117 * controlled by the same entity, so that this entity can perform the mutual
1118 * friend adding. In this case, there is no need for a friend request, either.
1119 *
1120 * @param public_key A byte array of length $PUBLIC_KEY_SIZE containing the
1121 * Public Key (not the Address) of the friend to add.
1122 *
1123 * @return the friend number on success, UINT32_MAX on failure.
1124 * @see $add for a more detailed description of friend numbers.
1125 */
1126 uint32_t add_norequest(const uint8_t[PUBLIC_KEY_SIZE] public_key)
1127 with error for add;
1128
1129
1130 /**
1131 * Remove a friend from the friend list.
1132 *
1133 * This does not notify the friend of their deletion. After calling this
1134 * function, this client will appear offline to the friend and no communication
1135 * can occur between the two.
1136 *
1137 * @param friend_number Friend number for the friend to be deleted.
1138 *
1139 * @return true on success.
1140 */
1141 bool delete(uint32_t friend_number) {
1142 /**
1143 * There was no friend with the given friend number. No friends were deleted.
1144 */
1145 FRIEND_NOT_FOUND,
1146 }
1147
1148}
1149
1150
1151/*******************************************************************************
1152 *
1153 * :: Friend list queries
1154 *
1155 ******************************************************************************/
1156
1157namespace friend {
1158
1159 /**
1160 * Return the friend number associated with that Public Key.
1161 *
1162 * @return the friend number on success, UINT32_MAX on failure.
1163 * @param public_key A byte array containing the Public Key.
1164 */
1165 const uint32_t by_public_key(const uint8_t[PUBLIC_KEY_SIZE] public_key) {
1166 NULL,
1167 /**
1168 * No friend with the given Public Key exists on the friend list.
1169 */
1170 NOT_FOUND,
1171 }
1172
1173
1174 /**
1175 * Checks if a friend with the given friend number exists and returns true if
1176 * it does.
1177 */
1178 const bool exists(uint32_t friend_number);
1179
1180}
1181
1182inline namespace self {
1183
1184 uint32_t[size] friend_list {
1185 /**
1186 * Return the number of friends on the friend list.
1187 *
1188 * This function can be used to determine how much memory to allocate for
1189 * $get.
1190 */
1191 size();
1192
1193
1194 /**
1195 * Copy a list of valid friend numbers into an array.
1196 *
1197 * Call $size to determine the number of elements to allocate.
1198 *
1199 * @param friend_list A memory region with enough space to hold the friend
1200 * list. If this parameter is NULL, this function has no effect.
1201 */
1202 get();
1203 }
1204
1205}
1206
1207
1208
1209namespace friend {
1210
1211 uint8_t[PUBLIC_KEY_SIZE] public_key {
1212 /**
1213 * Copies the Public Key associated with a given friend number to a byte array.
1214 *
1215 * @param friend_number The friend number you want the Public Key of.
1216 * @param public_key A memory region of at least $PUBLIC_KEY_SIZE bytes. If
1217 * this parameter is NULL, this function has no effect.
1218 *
1219 * @return true on success.
1220 */
1221 get(uint32_t friend_number) {
1222 /**
1223 * No friend with the given number exists on the friend list.
1224 */
1225 FRIEND_NOT_FOUND,
1226 }
1227 }
1228
1229}
1230
1231namespace friend {
1232
1233 uint64_t last_online {
1234 /**
1235 * Return a unix-time timestamp of the last time the friend associated with a given
1236 * friend number was seen online. This function will return UINT64_MAX on error.
1237 *
1238 * @param friend_number The friend number you want to query.
1239 */
1240 get(uint32_t friend_number) {
1241 /**
1242 * No friend with the given number exists on the friend list.
1243 */
1244 FRIEND_NOT_FOUND,
1245 }
1246 }
1247
1248}
1249
1250/*******************************************************************************
1251 *
1252 * :: Friend-specific state queries (can also be received through callbacks)
1253 *
1254 ******************************************************************************/
1255
1256
1257namespace friend {
1258
1259 /**
1260 * Common error codes for friend state query functions.
1261 */
1262 error for query {
1263 /**
1264 * The pointer parameter for storing the query result (name, message) was
1265 * NULL. Unlike the `_self_` variants of these functions, which have no effect
1266 * when a parameter is NULL, these functions return an error in that case.
1267 */
1268 NULL,
1269 /**
1270 * The friend_number did not designate a valid friend.
1271 */
1272 FRIEND_NOT_FOUND,
1273 }
1274
1275
1276 uint8_t[length <= MAX_NAME_LENGTH] name {
1277 /**
1278 * Return the length of the friend's name. If the friend number is invalid, the
1279 * return value is unspecified.
1280 *
1281 * The return value is equal to the `length` argument received by the last
1282 * `${event name}` callback.
1283 */
1284 size(uint32_t friend_number)
1285 with error for query;
1286
1287 /**
1288 * Write the name of the friend designated by the given friend number to a byte
1289 * array.
1290 *
1291 * Call $size to determine the allocation size for the `name`
1292 * parameter.
1293 *
1294 * The data written to `name` is equal to the data received by the last
1295 * `${event name}` callback.
1296 *
1297 * @param name A valid memory region large enough to store the friend's name.
1298 *
1299 * @return true on success.
1300 */
1301 get(uint32_t friend_number)
1302 with error for query;
1303 }
1304
1305
1306 /**
1307 * This event is triggered when a friend changes their name.
1308 */
1309 event name const {
1310 /**
1311 * @param friend_number The friend number of the friend whose name changed.
1312 * @param name A byte array containing the same data as
1313 * ${name.get} would write to its `name` parameter.
1314 * @param length A value equal to the return value of
1315 * ${name.size}.
1316 */
1317 typedef void(uint32_t friend_number, const uint8_t[length <= MAX_NAME_LENGTH] name);
1318 }
1319
1320
1321 uint8_t[length <= MAX_STATUS_MESSAGE_LENGTH] status_message {
1322 /**
1323 * Return the length of the friend's status message. If the friend number is
1324 * invalid, the return value is SIZE_MAX.
1325 */
1326 size(uint32_t friend_number)
1327 with error for query;
1328
1329 /**
1330 * Write the status message of the friend designated by the given friend number to a byte
1331 * array.
1332 *
1333 * Call $size to determine the allocation size for the `status_name`
1334 * parameter.
1335 *
1336 * The data written to `status_message` is equal to the data received by the last
1337 * `${event status_message}` callback.
1338 *
1339 * @param status_message A valid memory region large enough to store the friend's status message.
1340 */
1341 get(uint32_t friend_number)
1342 with error for query;
1343 }
1344
1345
1346 /**
1347 * This event is triggered when a friend changes their status message.
1348 */
1349 event status_message const {
1350 /**
1351 * @param friend_number The friend number of the friend whose status message
1352 * changed.
1353 * @param message A byte array containing the same data as
1354 * ${status_message.get} would write to its `status_message` parameter.
1355 * @param length A value equal to the return value of
1356 * ${status_message.size}.
1357 */
1358 typedef void(uint32_t friend_number, const uint8_t[length <= MAX_STATUS_MESSAGE_LENGTH] message);
1359 }
1360
1361
1362 USER_STATUS status {
1363 /**
1364 * Return the friend's user status (away/busy/...). If the friend number is
1365 * invalid, the return value is unspecified.
1366 *
1367 * The status returned is equal to the last status received through the
1368 * `${event status}` callback.
1369 *
1370 * @deprecated This getter is deprecated. Use the event and store the status
1371 * in the client state.
1372 */
1373 get(uint32_t friend_number)
1374 with error for query;
1375 }
1376
1377
1378 /**
1379 * This event is triggered when a friend changes their user status.
1380 */
1381 event status const {
1382 /**
1383 * @param friend_number The friend number of the friend whose user status
1384 * changed.
1385 * @param status The new user status.
1386 */
1387 typedef void(uint32_t friend_number, USER_STATUS status);
1388 }
1389
1390
1391 CONNECTION connection_status {
1392 /**
1393 * Check whether a friend is currently connected to this client.
1394 *
1395 * The result of this function is equal to the last value received by the
1396 * `${event connection_status}` callback.
1397 *
1398 * @param friend_number The friend number for which to query the connection
1399 * status.
1400 *
1401 * @return the friend's connection status as it was received through the
1402 * `${event connection_status}` event.
1403 *
1404 * @deprecated This getter is deprecated. Use the event and store the status
1405 * in the client state.
1406 */
1407 get(uint32_t friend_number)
1408 with error for query;
1409 }
1410
1411
1412 /**
1413 * This event is triggered when a friend goes offline after having been online,
1414 * or when a friend goes online.
1415 *
1416 * This callback is not called when adding friends. It is assumed that when
1417 * adding friends, their connection status is initially offline.
1418 */
1419 event connection_status const {
1420 /**
1421 * @param friend_number The friend number of the friend whose connection status
1422 * changed.
1423 * @param connection_status The result of calling
1424 * ${connection_status.get} on the passed friend_number.
1425 */
1426 typedef void(uint32_t friend_number, CONNECTION connection_status);
1427 }
1428
1429
1430 bool typing {
1431 /**
1432 * Check whether a friend is currently typing a message.
1433 *
1434 * @param friend_number The friend number for which to query the typing status.
1435 *
1436 * @return true if the friend is typing.
1437 * @return false if the friend is not typing, or the friend number was
1438 * invalid. Inspect the error code to determine which case it is.
1439 *
1440 * @deprecated This getter is deprecated. Use the event and store the status
1441 * in the client state.
1442 */
1443 get(uint32_t friend_number)
1444 with error for query;
1445 }
1446
1447
1448 /**
1449 * This event is triggered when a friend starts or stops typing.
1450 */
1451 event typing const {
1452 /**
1453 * @param friend_number The friend number of the friend who started or stopped
1454 * typing.
1455 * @param is_typing The result of calling ${typing.get} on the passed
1456 * friend_number.
1457 */
1458 typedef void(uint32_t friend_number, bool is_typing);
1459 }
1460
1461}
1462
1463
1464/*******************************************************************************
1465 *
1466 * :: Sending private messages
1467 *
1468 ******************************************************************************/
1469
1470
1471inline namespace self {
1472
1473 bool typing {
1474 /**
1475 * Set the client's typing status for a friend.
1476 *
1477 * The client is responsible for turning it on or off.
1478 *
1479 * @param friend_number The friend to which the client is typing a message.
1480 * @param typing The typing status. True means the client is typing.
1481 *
1482 * @return true on success.
1483 */
1484 set(uint32_t friend_number) {
1485 /**
1486 * The friend number did not designate a valid friend.
1487 */
1488 FRIEND_NOT_FOUND,
1489 }
1490 }
1491
1492}
1493
1494
1495namespace friend {
1496
1497 namespace send {
1498
1499 /**
1500 * Send a text chat message to an online friend.
1501 *
1502 * This function creates a chat message packet and pushes it into the send
1503 * queue.
1504 *
1505 * The message length may not exceed $MAX_MESSAGE_LENGTH. Larger messages
1506 * must be split by the client and sent as separate messages. Other clients can
1507 * then reassemble the fragments. Messages may not be empty.
1508 *
1509 * The return value of this function is the message ID. If a read receipt is
1510 * received, the triggered `${event read_receipt}` event will be passed this message ID.
1511 *
1512 * Message IDs are unique per friend. The first message ID is 0. Message IDs are
1513 * incremented by 1 each time a message is sent. If UINT32_MAX messages were
1514 * sent, the next message ID is 0.
1515 *
1516 * @param type Message type (normal, action, ...).
1517 * @param friend_number The friend number of the friend to send the message to.
1518 * @param message A non-NULL pointer to the first element of a byte array
1519 * containing the message text.
1520 * @param length Length of the message to be sent.
1521 */
1522 uint32_t message(uint32_t friend_number, MESSAGE_TYPE type,
1523 const uint8_t[length <= MAX_MESSAGE_LENGTH] message) {
1524 NULL,
1525 /**
1526 * The friend number did not designate a valid friend.
1527 */
1528 FRIEND_NOT_FOUND,
1529 /**
1530 * This client is currently not connected to the friend.
1531 */
1532 FRIEND_NOT_CONNECTED,
1533 /**
1534 * An allocation error occurred while increasing the send queue size.
1535 */
1536 SENDQ,
1537 /**
1538 * Message length exceeded $MAX_MESSAGE_LENGTH.
1539 */
1540 TOO_LONG,
1541 /**
1542 * Attempted to send a zero-length message.
1543 */
1544 EMPTY,
1545 }
1546
1547 }
1548
1549
1550 /**
1551 * This event is triggered when the friend receives the message sent with
1552 * ${send.message} with the corresponding message ID.
1553 */
1554 event read_receipt const {
1555 /**
1556 * @param friend_number The friend number of the friend who received the message.
1557 * @param message_id The message ID as returned from ${send.message}
1558 * corresponding to the message sent.
1559 */
1560 typedef void(uint32_t friend_number, uint32_t message_id);
1561 }
1562
1563}
1564
1565
1566/*******************************************************************************
1567 *
1568 * :: Receiving private messages and friend requests
1569 *
1570 ******************************************************************************/
1571
1572
1573namespace friend {
1574
1575 /**
1576 * This event is triggered when a friend request is received.
1577 */
1578 event request const {
1579 /**
1580 * @param public_key The Public Key of the user who sent the friend request.
1581 * @param message The message they sent along with the request.
1582 * @param length The size of the message byte array.
1583 */
1584 typedef void(const uint8_t[PUBLIC_KEY_SIZE] public_key,
1585 const uint8_t[length <= MAX_MESSAGE_LENGTH] message);
1586 }
1587
1588
1589 /**
1590 * This event is triggered when a message from a friend is received.
1591 */
1592 event message const {
1593 /**
1594 * @param friend_number The friend number of the friend who sent the message.
1595 * @param message The message data they sent.
1596 * @param length The size of the message byte array.
1597 */
1598 typedef void(uint32_t friend_number, MESSAGE_TYPE type,
1599 const uint8_t[length <= MAX_MESSAGE_LENGTH] message);
1600 }
1601
1602}
1603
1604
1605/*******************************************************************************
1606 *
1607 * :: File transmission: common between sending and receiving
1608 *
1609 ******************************************************************************/
1610
1611
1612/**
1613 * Generates a cryptographic hash of the given data.
1614 *
1615 * This function may be used by clients for any purpose, but is provided
1616 * primarily for validating cached avatars. This use is highly recommended to
1617 * avoid unnecessary avatar updates.
1618 *
1619 * If hash is NULL or data is NULL while length is not 0 the function returns false,
1620 * otherwise it returns true.
1621 *
1622 * This function is a wrapper to internal message-digest functions.
1623 *
1624 * @param hash A valid memory location the hash data. It must be at least
1625 * $HASH_LENGTH bytes in size.
1626 * @param data Data to be hashed or NULL.
1627 * @param length Size of the data array or 0.
1628 *
1629 * @return true if hash was not NULL.
1630 */
1631static bool hash(uint8_t[HASH_LENGTH] hash, const uint8_t[length] data);
1632
1633
1634namespace file {
1635
1636 enum KIND {
1637 /**
1638 * Arbitrary file data. Clients can choose to handle it based on the file name
1639 * or magic or any other way they choose.
1640 */
1641 DATA,
1642 /**
1643 * Avatar file_id. This consists of $hash(image).
1644 * Avatar data. This consists of the image data.
1645 *
1646 * Avatars can be sent at any time the client wishes. Generally, a client will
1647 * send the avatar to a friend when that friend comes online, and to all
1648 * friends when the avatar changed. A client can save some traffic by
1649 * remembering which friend received the updated avatar already and only send
1650 * it if the friend has an out of date avatar.
1651 *
1652 * Clients who receive avatar send requests can reject it (by sending
1653 * ${CONTROL.CANCEL} before any other controls), or accept it (by
1654 * sending ${CONTROL.RESUME}). The file_id of length $HASH_LENGTH bytes
1655 * (same length as $FILE_ID_LENGTH) will contain the hash. A client can compare
1656 * this hash with a saved hash and send ${CONTROL.CANCEL} to terminate the avatar
1657 * transfer if it matches.
1658 *
1659 * When file_size is set to 0 in the transfer request it means that the client
1660 * has no avatar.
1661 */
1662 AVATAR,
1663 }
1664
1665
1666 enum class CONTROL {
1667 /**
1668 * Sent by the receiving side to accept a file send request. Also sent after a
1669 * $PAUSE command to continue sending or receiving.
1670 */
1671 RESUME,
1672 /**
1673 * Sent by clients to pause the file transfer. The initial state of a file
1674 * transfer is always paused on the receiving side and running on the sending
1675 * side. If both the sending and receiving side pause the transfer, then both
1676 * need to send $RESUME for the transfer to resume.
1677 */
1678 PAUSE,
1679 /**
1680 * Sent by the receiving side to reject a file send request before any other
1681 * commands are sent. Also sent by either side to terminate a file transfer.
1682 */
1683 CANCEL,
1684 }
1685
1686
1687 /**
1688 * Sends a file control command to a friend for a given file transfer.
1689 *
1690 * @param friend_number The friend number of the friend the file is being
1691 * transferred to or received from.
1692 * @param file_number The friend-specific identifier for the file transfer.
1693 * @param control The control command to send.
1694 *
1695 * @return true on success.
1696 */
1697 bool control(uint32_t friend_number, uint32_t file_number, CONTROL control) {
1698 /**
1699 * The friend_number passed did not designate a valid friend.
1700 */
1701 FRIEND_NOT_FOUND,
1702 /**
1703 * This client is currently not connected to the friend.
1704 */
1705 FRIEND_NOT_CONNECTED,
1706 /**
1707 * No file transfer with the given file number was found for the given friend.
1708 */
1709 NOT_FOUND,
1710 /**
1711 * A RESUME control was sent, but the file transfer is running normally.
1712 */
1713 NOT_PAUSED,
1714 /**
1715 * A RESUME control was sent, but the file transfer was paused by the other
1716 * party. Only the party that paused the transfer can resume it.
1717 */
1718 DENIED,
1719 /**
1720 * A PAUSE control was sent, but the file transfer was already paused.
1721 */
1722 ALREADY_PAUSED,
1723 /**
1724 * Packet queue is full.
1725 */
1726 SENDQ,
1727 }
1728
1729
1730 /**
1731 * This event is triggered when a file control command is received from a
1732 * friend.
1733 */
1734 event recv_control const {
1735 /**
1736 * When receiving ${CONTROL.CANCEL}, the client should release the
1737 * resources associated with the file number and consider the transfer failed.
1738 *
1739 * @param friend_number The friend number of the friend who is sending the file.
1740 * @param file_number The friend-specific file number the data received is
1741 * associated with.
1742 * @param control The file control command received.
1743 */
1744 typedef void(uint32_t friend_number, uint32_t file_number, CONTROL control);
1745 }
1746
1747 /**
1748 * Sends a file seek control command to a friend for a given file transfer.
1749 *
1750 * This function can only be called to resume a file transfer right before
1751 * ${CONTROL.RESUME} is sent.
1752 *
1753 * @param friend_number The friend number of the friend the file is being
1754 * received from.
1755 * @param file_number The friend-specific identifier for the file transfer.
1756 * @param position The position that the file should be seeked to.
1757 */
1758 bool seek(uint32_t friend_number, uint32_t file_number, uint64_t position) {
1759 /**
1760 * The friend_number passed did not designate a valid friend.
1761 */
1762 FRIEND_NOT_FOUND,
1763 /**
1764 * This client is currently not connected to the friend.
1765 */
1766 FRIEND_NOT_CONNECTED,
1767 /**
1768 * No file transfer with the given file number was found for the given friend.
1769 */
1770 NOT_FOUND,
1771 /**
1772 * File was not in a state where it could be seeked.
1773 */
1774 DENIED,
1775 /**
1776 * Seek position was invalid
1777 */
1778 INVALID_POSITION,
1779 /**
1780 * Packet queue is full.
1781 */
1782 SENDQ,
1783 }
1784
1785
1786 error for get {
1787 NULL,
1788 /**
1789 * The friend_number passed did not designate a valid friend.
1790 */
1791 FRIEND_NOT_FOUND,
1792 /**
1793 * No file transfer with the given file number was found for the given friend.
1794 */
1795 NOT_FOUND,
1796 }
1797
1798 uint8_t[FILE_ID_LENGTH] file_id {
1799 /**
1800 * Copy the file id associated to the file transfer to a byte array.
1801 *
1802 * @param friend_number The friend number of the friend the file is being
1803 * transferred to or received from.
1804 * @param file_number The friend-specific identifier for the file transfer.
1805 * @param file_id A memory region of at least $FILE_ID_LENGTH bytes. If
1806 * this parameter is NULL, this function has no effect.
1807 *
1808 * @return true on success.
1809 */
1810 get(uint32_t friend_number, uint32_t file_number)
1811 with error for get;
1812 }
1813
1814}
1815
1816
1817/*******************************************************************************
1818 *
1819 * :: File transmission: sending
1820 *
1821 ******************************************************************************/
1822
1823
1824namespace file {
1825
1826 /**
1827 * Send a file transmission request.
1828 *
1829 * Maximum filename length is $MAX_FILENAME_LENGTH bytes. The filename
1830 * should generally just be a file name, not a path with directory names.
1831 *
1832 * If a non-UINT64_MAX file size is provided, it can be used by both sides to
1833 * determine the sending progress. File size can be set to UINT64_MAX for streaming
1834 * data of unknown size.
1835 *
1836 * File transmission occurs in chunks, which are requested through the
1837 * `${event chunk_request}` event.
1838 *
1839 * When a friend goes offline, all file transfers associated with the friend are
1840 * purged from core.
1841 *
1842 * If the file contents change during a transfer, the behaviour is unspecified
1843 * in general. What will actually happen depends on the mode in which the file
1844 * was modified and how the client determines the file size.
1845 *
1846 * - If the file size was increased
1847 * - and sending mode was streaming (file_size = UINT64_MAX), the behaviour
1848 * will be as expected.
1849 * - and sending mode was file (file_size != UINT64_MAX), the
1850 * ${event chunk_request} callback will receive length = 0 when Core thinks
1851 * the file transfer has finished. If the client remembers the file size as
1852 * it was when sending the request, it will terminate the transfer normally.
1853 * If the client re-reads the size, it will think the friend cancelled the
1854 * transfer.
1855 * - If the file size was decreased
1856 * - and sending mode was streaming, the behaviour is as expected.
1857 * - and sending mode was file, the callback will return 0 at the new
1858 * (earlier) end-of-file, signalling to the friend that the transfer was
1859 * cancelled.
1860 * - If the file contents were modified
1861 * - at a position before the current read, the two files (local and remote)
1862 * will differ after the transfer terminates.
1863 * - at a position after the current read, the file transfer will succeed as
1864 * expected.
1865 * - In either case, both sides will regard the transfer as complete and
1866 * successful.
1867 *
1868 * @param friend_number The friend number of the friend the file send request
1869 * should be sent to.
1870 * @param kind The meaning of the file to be sent.
1871 * @param file_size Size in bytes of the file the client wants to send, UINT64_MAX if
1872 * unknown or streaming.
1873 * @param file_id A file identifier of length $FILE_ID_LENGTH that can be used to
1874 * uniquely identify file transfers across core restarts. If NULL, a random one will
1875 * be generated by core. It can then be obtained by using ${file_id.get}().
1876 * @param filename Name of the file. Does not need to be the actual name. This
1877 * name will be sent along with the file send request.
1878 * @param filename_length Size in bytes of the filename.
1879 *
1880 * @return A file number used as an identifier in subsequent callbacks. This
1881 * number is per friend. File numbers are reused after a transfer terminates.
1882 * On failure, this function returns UINT32_MAX. Any pattern in file numbers
1883 * should not be relied on.
1884 */
1885 uint32_t send(uint32_t friend_number, uint32_t kind, uint64_t file_size,
1886 const uint8_t[FILE_ID_LENGTH] file_id,
1887 const uint8_t[filename_length <= MAX_FILENAME_LENGTH] filename) {
1888 NULL,
1889 /**
1890 * The friend_number passed did not designate a valid friend.
1891 */
1892 FRIEND_NOT_FOUND,
1893 /**
1894 * This client is currently not connected to the friend.
1895 */
1896 FRIEND_NOT_CONNECTED,
1897 /**
1898 * Filename length exceeded $MAX_FILENAME_LENGTH bytes.
1899 */
1900 NAME_TOO_LONG,
1901 /**
1902 * Too many ongoing transfers. The maximum number of concurrent file transfers
1903 * is 256 per friend per direction (sending and receiving).
1904 */
1905 TOO_MANY,
1906 }
1907
1908
1909 /**
1910 * Send a chunk of file data to a friend.
1911 *
1912 * This function is called in response to the `${event chunk_request}` callback. The
1913 * length parameter should be equal to the one received though the callback.
1914 * If it is zero, the transfer is assumed complete. For files with known size,
1915 * Core will know that the transfer is complete after the last byte has been
1916 * received, so it is not necessary (though not harmful) to send a zero-length
1917 * chunk to terminate. For streams, core will know that the transfer is finished
1918 * if a chunk with length less than the length requested in the callback is sent.
1919 *
1920 * @param friend_number The friend number of the receiving friend for this file.
1921 * @param file_number The file transfer identifier returned by tox_file_send.
1922 * @param position The file or stream position from which to continue reading.
1923 * @return true on success.
1924 */
1925 bool send_chunk(uint32_t friend_number, uint32_t file_number, uint64_t position, const uint8_t[length] data) {
1926 /**
1927 * The length parameter was non-zero, but data was NULL.
1928 */
1929 NULL,
1930 /**
1931 * The friend_number passed did not designate a valid friend.
1932 */
1933 FRIEND_NOT_FOUND,
1934 /**
1935 * This client is currently not connected to the friend.
1936 */
1937 FRIEND_NOT_CONNECTED,
1938 /**
1939 * No file transfer with the given file number was found for the given friend.
1940 */
1941 NOT_FOUND,
1942 /**
1943 * File transfer was found but isn't in a transferring state: (paused, done,
1944 * broken, etc...) (happens only when not called from the request chunk callback).
1945 */
1946 NOT_TRANSFERRING,
1947 /**
1948 * Attempted to send more or less data than requested. The requested data size is
1949 * adjusted according to maximum transmission unit and the expected end of
1950 * the file. Trying to send less or more than requested will return this error.
1951 */
1952 INVALID_LENGTH,
1953 /**
1954 * Packet queue is full.
1955 */
1956 SENDQ,
1957 /**
1958 * Position parameter was wrong.
1959 */
1960 WRONG_POSITION,
1961 }
1962
1963
1964 /**
1965 * This event is triggered when Core is ready to send more file data.
1966 */
1967 event chunk_request const {
1968 /**
1969 * If the length parameter is 0, the file transfer is finished, and the client's
1970 * resources associated with the file number should be released. After a call
1971 * with zero length, the file number can be reused for future file transfers.
1972 *
1973 * If the requested position is not equal to the client's idea of the current
1974 * file or stream position, it will need to seek. In case of read-once streams,
1975 * the client should keep the last read chunk so that a seek back can be
1976 * supported. A seek-back only ever needs to read from the last requested chunk.
1977 * This happens when a chunk was requested, but the send failed. A seek-back
1978 * request can occur an arbitrary number of times for any given chunk.
1979 *
1980 * In response to receiving this callback, the client should call the function
1981 * `$send_chunk` with the requested chunk. If the number of bytes sent
1982 * through that function is zero, the file transfer is assumed complete. A
1983 * client must send the full length of data requested with this callback.
1984 *
1985 * @param friend_number The friend number of the receiving friend for this file.
1986 * @param file_number The file transfer identifier returned by $send.
1987 * @param position The file or stream position from which to continue reading.
1988 * @param length The number of bytes requested for the current chunk.
1989 */
1990 typedef void(uint32_t friend_number, uint32_t file_number, uint64_t position, size_t length);
1991 }
1992
1993}
1994
1995
1996/*******************************************************************************
1997 *
1998 * :: File transmission: receiving
1999 *
2000 ******************************************************************************/
2001
2002
2003namespace file {
2004
2005 /**
2006 * This event is triggered when a file transfer request is received.
2007 */
2008 event recv const {
2009 /**
2010 * The client should acquire resources to be associated with the file transfer.
2011 * Incoming file transfers start in the PAUSED state. After this callback
2012 * returns, a transfer can be rejected by sending a ${CONTROL.CANCEL}
2013 * control command before any other control commands. It can be accepted by
2014 * sending ${CONTROL.RESUME}.
2015 *
2016 * @param friend_number The friend number of the friend who is sending the file
2017 * transfer request.
2018 * @param file_number The friend-specific file number the data received is
2019 * associated with.
2020 * @param kind The meaning of the file to be sent.
2021 * @param file_size Size in bytes of the file the client wants to send,
2022 * UINT64_MAX if unknown or streaming.
2023 * @param filename Name of the file. Does not need to be the actual name. This
2024 * name will be sent along with the file send request.
2025 * @param filename_length Size in bytes of the filename.
2026 */
2027 typedef void(uint32_t friend_number, uint32_t file_number, uint32_t kind,
2028 uint64_t file_size, const uint8_t[filename_length <= MAX_FILENAME_LENGTH] filename);
2029 }
2030
2031
2032 /**
2033 * This event is first triggered when a file transfer request is received, and
2034 * subsequently when a chunk of file data for an accepted request was received.
2035 */
2036 event recv_chunk const {
2037 /**
2038 * When length is 0, the transfer is finished and the client should release the
2039 * resources it acquired for the transfer. After a call with length = 0, the
2040 * file number can be reused for new file transfers.
2041 *
2042 * If position is equal to file_size (received in the file_receive callback)
2043 * when the transfer finishes, the file was received completely. Otherwise, if
2044 * file_size was UINT64_MAX, streaming ended successfully when length is 0.
2045 *
2046 * @param friend_number The friend number of the friend who is sending the file.
2047 * @param file_number The friend-specific file number the data received is
2048 * associated with.
2049 * @param position The file position of the first byte in data.
2050 * @param data A byte array containing the received chunk.
2051 * @param length The length of the received chunk.
2052 */
2053 typedef void(uint32_t friend_number, uint32_t file_number, uint64_t position,
2054 const uint8_t[length] data);
2055 }
2056
2057}
2058
2059
2060/*******************************************************************************
2061 *
2062 * :: Conference management
2063 *
2064 ******************************************************************************/
2065
2066namespace conference {
2067
2068 /**
2069 * Conference types for the ${event invite} event.
2070 */
2071 enum class TYPE {
2072 /**
2073 * Text-only conferences that must be accepted with the $join function.
2074 */
2075 TEXT,
2076 /**
2077 * Video conference. The function to accept these is in toxav.
2078 */
2079 AV,
2080 }
2081
2082
2083 /**
2084 * This event is triggered when the client is invited to join a conference.
2085 */
2086 event invite const {
2087 /**
2088 * The invitation will remain valid until the inviting friend goes offline
2089 * or exits the conference.
2090 *
2091 * @param friend_number The friend who invited us.
2092 * @param type The conference type (text only or audio/video).
2093 * @param cookie A piece of data of variable length required to join the
2094 * conference.
2095 * @param length The length of the cookie.
2096 */
2097 typedef void(uint32_t friend_number, TYPE type, const uint8_t[length] cookie);
2098 }
2099
2100
2101 /**
2102 * This event is triggered when the client receives a conference message.
2103 */
2104 event message const {
2105 /**
2106 * @param conference_number The conference number of the conference the message is intended for.
2107 * @param peer_number The ID of the peer who sent the message.
2108 * @param type The type of message (normal, action, ...).
2109 * @param message The message data.
2110 * @param length The length of the message.
2111 */
2112 typedef void(uint32_t conference_number, uint32_t peer_number, MESSAGE_TYPE type,
2113 const uint8_t[length] message);
2114 }
2115
2116
2117 /**
2118 * This event is triggered when a peer changes the conference title.
2119 *
2120 * If peer_number == UINT32_MAX, then author is unknown (e.g. initial joining the conference).
2121 */
2122 event title const {
2123 /**
2124 * @param conference_number The conference number of the conference the title change is intended for.
2125 * @param peer_number The ID of the peer who changed the title.
2126 * @param title The title data.
2127 * @param length The title length.
2128 */
2129 typedef void(uint32_t conference_number, uint32_t peer_number, const uint8_t[length] title);
2130 }
2131
2132 namespace peer {
2133
2134 /**
2135 * This event is triggered when a peer changes their name.
2136 */
2137 event name const {
2138 /**
2139 * @param conference_number The conference number of the conference the
2140 * peer is in.
2141 * @param peer_number The ID of the peer who changed their nickname.
2142 * @param name A byte array containing the new nickname.
2143 * @param length The size of the name byte array.
2144 */
2145 typedef void(uint32_t conference_number, uint32_t peer_number, const uint8_t[length] name);
2146 }
2147
2148 /**
2149 * This event is triggered when a peer joins or leaves the conference.
2150 */
2151 event list_changed const {
2152 /**
2153 * @param conference_number The conference number of the conference the
2154 * peer is in.
2155 */
2156 typedef void(uint32_t conference_number);
2157 }
2158
2159 }
2160
2161
2162 /**
2163 * Creates a new conference.
2164 *
2165 * This function creates a new text conference.
2166 *
2167 * @return conference number on success, or UINT32_MAX on failure.
2168 */
2169 uint32_t new() {
2170 /**
2171 * The conference instance failed to initialize.
2172 */
2173 INIT,
2174 }
2175
2176 /**
2177 * This function deletes a conference.
2178 *
2179 * @param conference_number The conference number of the conference to be deleted.
2180 *
2181 * @return true on success.
2182 */
2183 bool delete(uint32_t conference_number) {
2184 /**
2185 * The conference number passed did not designate a valid conference.
2186 */
2187 CONFERENCE_NOT_FOUND,
2188 }
2189
2190
2191 namespace peer {
2192
2193 /**
2194 * Error codes for peer info queries.
2195 */
2196 error for query {
2197 /**
2198 * The conference number passed did not designate a valid conference.
2199 */
2200 CONFERENCE_NOT_FOUND,
2201 /**
2202 * The peer number passed did not designate a valid peer.
2203 */
2204 PEER_NOT_FOUND,
2205 /**
2206 * The client is not connected to the conference.
2207 */
2208 NO_CONNECTION,
2209 }
2210
2211 /**
2212 * Return the number of peers in the conference. Return value is unspecified on failure.
2213 */
2214 const uint32_t count(uint32_t conference_number)
2215 with error for query;
2216
2217 uint8_t[size] name {
2218
2219 /**
2220 * Return the length of the peer's name. Return value is unspecified on failure.
2221 */
2222 size(uint32_t conference_number, uint32_t peer_number)
2223 with error for query;
2224
2225 /**
2226 * Copy the name of peer_number who is in conference_number to name.
2227 * name must be at least $MAX_NAME_LENGTH long.
2228 *
2229 * @return true on success.
2230 */
2231 get(uint32_t conference_number, uint32_t peer_number)
2232 with error for query;
2233 }
2234
2235 /**
2236 * Copy the public key of peer_number who is in conference_number to public_key.
2237 * public_key must be $PUBLIC_KEY_SIZE long.
2238 *
2239 * @return true on success.
2240 */
2241 uint8_t[PUBLIC_KEY_SIZE] public_key {
2242 get(uint32_t conference_number, uint32_t peer_number)
2243 with error for query;
2244 }
2245
2246 /**
2247 * Return true if passed peer_number corresponds to our own.
2248 */
2249 const bool number_is_ours(uint32_t conference_number, uint32_t peer_number)
2250 with error for query;
2251
2252 }
2253
2254
2255 /**
2256 * Invites a friend to a conference.
2257 *
2258 * @param friend_number The friend number of the friend we want to invite.
2259 * @param conference_number The conference number of the conference we want to invite the friend to.
2260 *
2261 * @return true on success.
2262 */
2263 bool invite(uint32_t friend_number, uint32_t conference_number) {
2264 /**
2265 * The conference number passed did not designate a valid conference.
2266 */
2267 CONFERENCE_NOT_FOUND,
2268 /**
2269 * The invite packet failed to send.
2270 */
2271 FAIL_SEND,
2272 }
2273
2274
2275 /**
2276 * Joins a conference that the client has been invited to.
2277 *
2278 * @param friend_number The friend number of the friend who sent the invite.
2279 * @param cookie Received via the `${event invite}` event.
2280 * @param length The size of cookie.
2281 *
2282 * @return conference number on success, UINT32_MAX on failure.
2283 */
2284 uint32_t join(uint32_t friend_number, const uint8_t[length] cookie) {
2285 /**
2286 * The cookie passed has an invalid length.
2287 */
2288 INVALID_LENGTH,
2289 /**
2290 * The conference is not the expected type. This indicates an invalid cookie.
2291 */
2292 WRONG_TYPE,
2293 /**
2294 * The friend number passed does not designate a valid friend.
2295 */
2296 FRIEND_NOT_FOUND,
2297 /**
2298 * Client is already in this conference.
2299 */
2300 DUPLICATE,
2301 /**
2302 * Conference instance failed to initialize.
2303 */
2304 INIT_FAIL,
2305 /**
2306 * The join packet failed to send.
2307 */
2308 FAIL_SEND,
2309 }
2310
2311
2312 namespace send {
2313
2314 /**
2315 * Send a text chat message to the conference.
2316 *
2317 * This function creates a conference message packet and pushes it into the send
2318 * queue.
2319 *
2320 * The message length may not exceed $MAX_MESSAGE_LENGTH. Larger messages
2321 * must be split by the client and sent as separate messages. Other clients can
2322 * then reassemble the fragments.
2323 *
2324 * @param conference_number The conference number of the conference the message is intended for.
2325 * @param type Message type (normal, action, ...).
2326 * @param message A non-NULL pointer to the first element of a byte array
2327 * containing the message text.
2328 * @param length Length of the message to be sent.
2329 *
2330 * @return true on success.
2331 */
2332 bool message(uint32_t conference_number, MESSAGE_TYPE type, const uint8_t[length] message) {
2333 /**
2334 * The conference number passed did not designate a valid conference.
2335 */
2336 CONFERENCE_NOT_FOUND,
2337 /**
2338 * The message is too long.
2339 */
2340 TOO_LONG,
2341 /**
2342 * The client is not connected to the conference.
2343 */
2344 NO_CONNECTION,
2345 /**
2346 * The message packet failed to send.
2347 */
2348 FAIL_SEND,
2349 }
2350 }
2351
2352 error for title {
2353 /**
2354 * The conference number passed did not designate a valid conference.
2355 */
2356 CONFERENCE_NOT_FOUND,
2357 /**
2358 * The title is too long or empty.
2359 */
2360 INVALID_LENGTH,
2361 /**
2362 * The title packet failed to send.
2363 */
2364 FAIL_SEND,
2365 }
2366
2367 uint8_t[length <= MAX_NAME_LENGTH] title {
2368
2369 /**
2370 * Return the length of the conference title. Return value is unspecified on failure.
2371 *
2372 * The return value is equal to the `length` argument received by the last
2373 * `${event title}` callback.
2374 */
2375 size(uint32_t conference_number)
2376 with error for title;
2377
2378 /**
2379 * Write the title designated by the given conference number to a byte array.
2380 *
2381 * Call $size to determine the allocation size for the `title` parameter.
2382 *
2383 * The data written to `title` is equal to the data received by the last
2384 * `${event title}` callback.
2385 *
2386 * @param title A valid memory region large enough to store the title.
2387 * If this parameter is NULL, this function has no effect.
2388 *
2389 * @return true on success.
2390 */
2391 get(uint32_t conference_number)
2392 with error for title;
2393
2394 /**
2395 * Set the conference title and broadcast it to the rest of the conference.
2396 *
2397 * Title length cannot be longer than $MAX_NAME_LENGTH.
2398 *
2399 * @return true on success.
2400 */
2401 set(uint32_t conference_number)
2402 with error for title;
2403 }
2404
2405
2406 uint32_t[size] chatlist {
2407 /**
2408 * Return the number of conferences in the Tox instance.
2409 * This should be used to determine how much memory to allocate for `$get`.
2410 */
2411 size();
2412
2413 /**
2414 * Copy a list of valid conference IDs into the array chatlist. Determine how much space
2415 * to allocate for the array with the `$size` function.
2416 */
2417 get();
2418 }
2419
2420
2421 /**
2422 * Returns the type of conference ($TYPE) that conference_number is. Return value is
2423 * unspecified on failure.
2424 */
2425 TYPE type {
2426 get(uint32_t conference_number) {
2427 /**
2428 * The conference number passed did not designate a valid conference.
2429 */
2430 CONFERENCE_NOT_FOUND,
2431 }
2432 }
2433
2434}
2435
2436
2437/*******************************************************************************
2438 *
2439 * :: Low-level custom packet sending and receiving
2440 *
2441 ******************************************************************************/
2442
2443
2444namespace friend {
2445
2446 inline namespace send {
2447
2448 error for custom_packet {
2449 NULL,
2450 /**
2451 * The friend number did not designate a valid friend.
2452 */
2453 FRIEND_NOT_FOUND,
2454 /**
2455 * This client is currently not connected to the friend.
2456 */
2457 FRIEND_NOT_CONNECTED,
2458 /**
2459 * The first byte of data was not in the specified range for the packet type.
2460 * This range is 200-254 for lossy, and 160-191 for lossless packets.
2461 */
2462 INVALID,
2463 /**
2464 * Attempted to send an empty packet.
2465 */
2466 EMPTY,
2467 /**
2468 * Packet data length exceeded $MAX_CUSTOM_PACKET_SIZE.
2469 */
2470 TOO_LONG,
2471 /**
2472 * Packet queue is full.
2473 */
2474 SENDQ,
2475 }
2476
2477 /**
2478 * Send a custom lossy packet to a friend.
2479 *
2480 * The first byte of data must be in the range 200-254. Maximum length of a
2481 * custom packet is $MAX_CUSTOM_PACKET_SIZE.
2482 *
2483 * Lossy packets behave like UDP packets, meaning they might never reach the
2484 * other side or might arrive more than once (if someone is messing with the
2485 * connection) or might arrive in the wrong order.
2486 *
2487 * Unless latency is an issue, it is recommended that you use lossless custom
2488 * packets instead.
2489 *
2490 * @param friend_number The friend number of the friend this lossy packet
2491 * should be sent to.
2492 * @param data A byte array containing the packet data.
2493 * @param length The length of the packet data byte array.
2494 *
2495 * @return true on success.
2496 */
2497 bool lossy_packet(uint32_t friend_number, const uint8_t[length <= MAX_CUSTOM_PACKET_SIZE] data)
2498 with error for custom_packet;
2499
2500
2501 /**
2502 * Send a custom lossless packet to a friend.
2503 *
2504 * The first byte of data must be in the range 160-191. Maximum length of a
2505 * custom packet is $MAX_CUSTOM_PACKET_SIZE.
2506 *
2507 * Lossless packet behaviour is comparable to TCP (reliability, arrive in order)
2508 * but with packets instead of a stream.
2509 *
2510 * @param friend_number The friend number of the friend this lossless packet
2511 * should be sent to.
2512 * @param data A byte array containing the packet data.
2513 * @param length The length of the packet data byte array.
2514 *
2515 * @return true on success.
2516 */
2517 bool lossless_packet(uint32_t friend_number, const uint8_t[length <= MAX_CUSTOM_PACKET_SIZE] data)
2518 with error for custom_packet;
2519
2520 }
2521
2522
2523 event lossy_packet const {
2524 /**
2525 * @param friend_number The friend number of the friend who sent a lossy packet.
2526 * @param data A byte array containing the received packet data.
2527 * @param length The length of the packet data byte array.
2528 */
2529 typedef void(uint32_t friend_number, const uint8_t[length <= MAX_CUSTOM_PACKET_SIZE] data);
2530 }
2531
2532
2533 event lossless_packet const {
2534 /**
2535 * @param friend_number The friend number of the friend who sent the packet.
2536 * @param data A byte array containing the received packet data.
2537 * @param length The length of the packet data byte array.
2538 */
2539 typedef void(uint32_t friend_number, const uint8_t[length <= MAX_CUSTOM_PACKET_SIZE] data);
2540 }
2541
2542}
2543
2544
2545
2546/*******************************************************************************
2547 *
2548 * :: Low-level network information
2549 *
2550 ******************************************************************************/
2551
2552
2553inline namespace self {
2554
2555 uint8_t[PUBLIC_KEY_SIZE] dht_id {
2556 /**
2557 * Writes the temporary DHT public key of this instance to a byte array.
2558 *
2559 * This can be used in combination with an externally accessible IP address and
2560 * the bound port (from ${udp_port.get}) to run a temporary bootstrap node.
2561 *
2562 * Be aware that every time a new instance is created, the DHT public key
2563 * changes, meaning this cannot be used to run a permanent bootstrap node.
2564 *
2565 * @param dht_id A memory region of at least $PUBLIC_KEY_SIZE bytes. If this
2566 * parameter is NULL, this function has no effect.
2567 */
2568 get();
2569 }
2570
2571
2572 error for get_port {
2573 /**
2574 * The instance was not bound to any port.
2575 */
2576 NOT_BOUND,
2577 }
2578
2579
2580 uint16_t udp_port {
2581 /**
2582 * Return the UDP port this Tox instance is bound to.
2583 */
2584 get() with error for get_port;
2585 }
2586
2587
2588 uint16_t tcp_port {
2589 /**
2590 * Return the TCP port this Tox instance is bound to. This is only relevant if
2591 * the instance is acting as a TCP relay.
2592 */
2593 get() with error for get_port;
2594 }
2595
2596}
2597
2598} // class tox
2599
2600%{
2601#ifdef __cplusplus
2602}
2603#endif
2604
2605#endif
2606%}
diff --git a/toxcore/tox.c b/toxcore/tox.c
index 23d0d3e4..2f210209 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -1,65 +1,68 @@
1/* tox.c 1/*
2 *
3 * The Tox public API. 2 * The Tox public API.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2013 Tox project.
4 * 8 *
5 * Copyright (C) 2013 Tox project All Rights Reserved. 9 * This file is part of Tox, the free peer to peer instant messenger.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23
24#ifdef HAVE_CONFIG_H 24#ifdef HAVE_CONFIG_H
25#include "config.h" 25#include "config.h"
26#endif 26#endif
27 27
28#define _XOPEN_SOURCE 600
29
30#define TOX_DEFINED
31typedef struct Messenger Tox;
32#include "tox.h"
33
34#include <string.h>
35
28#include "Messenger.h" 36#include "Messenger.h"
29#include "group.h" 37#include "group.h"
30#include "logger.h" 38#include "logger.h"
31 39
32#include "../toxencryptsave/defines.h" 40#include "../toxencryptsave/defines.h"
33 41
34#define TOX_DEFINED
35typedef struct Messenger Tox;
36
37#include "tox.h"
38
39#define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}} 42#define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}}
40 43
41#if TOX_HASH_LENGTH != crypto_hash_sha256_BYTES 44#if TOX_HASH_LENGTH != CRYPTO_SHA256_SIZE
42#error TOX_HASH_LENGTH is assumed to be equal to crypto_hash_sha256_BYTES 45#error TOX_HASH_LENGTH is assumed to be equal to CRYPTO_SHA256_SIZE
43#endif 46#endif
44 47
45#if FILE_ID_LENGTH != crypto_box_KEYBYTES 48#if FILE_ID_LENGTH != CRYPTO_SYMMETRIC_KEY_SIZE
46#error FILE_ID_LENGTH is assumed to be equal to crypto_box_KEYBYTES 49#error FILE_ID_LENGTH is assumed to be equal to CRYPTO_SYMMETRIC_KEY_SIZE
47#endif 50#endif
48 51
49#if TOX_FILE_ID_LENGTH != crypto_box_KEYBYTES 52#if TOX_FILE_ID_LENGTH != CRYPTO_SYMMETRIC_KEY_SIZE
50#error TOX_FILE_ID_LENGTH is assumed to be equal to crypto_box_KEYBYTES 53#error TOX_FILE_ID_LENGTH is assumed to be equal to CRYPTO_SYMMETRIC_KEY_SIZE
51#endif 54#endif
52 55
53#if TOX_FILE_ID_LENGTH != TOX_HASH_LENGTH 56#if TOX_FILE_ID_LENGTH != TOX_HASH_LENGTH
54#error TOX_FILE_ID_LENGTH is assumed to be equal to TOX_HASH_LENGTH 57#error TOX_FILE_ID_LENGTH is assumed to be equal to TOX_HASH_LENGTH
55#endif 58#endif
56 59
57#if TOX_PUBLIC_KEY_SIZE != crypto_box_PUBLICKEYBYTES 60#if TOX_PUBLIC_KEY_SIZE != CRYPTO_PUBLIC_KEY_SIZE
58#error TOX_PUBLIC_KEY_SIZE is assumed to be equal to crypto_box_PUBLICKEYBYTES 61#error TOX_PUBLIC_KEY_SIZE is assumed to be equal to CRYPTO_PUBLIC_KEY_SIZE
59#endif 62#endif
60 63
61#if TOX_SECRET_KEY_SIZE != crypto_box_SECRETKEYBYTES 64#if TOX_SECRET_KEY_SIZE != CRYPTO_SECRET_KEY_SIZE
62#error TOX_SECRET_KEY_SIZE is assumed to be equal to crypto_box_SECRETKEYBYTES 65#error TOX_SECRET_KEY_SIZE is assumed to be equal to CRYPTO_SECRET_KEY_SIZE
63#endif 66#endif
64 67
65#if TOX_MAX_NAME_LENGTH != MAX_NAME_LENGTH 68#if TOX_MAX_NAME_LENGTH != MAX_NAME_LENGTH
@@ -70,107 +73,62 @@ typedef struct Messenger Tox;
70#error TOX_MAX_STATUS_MESSAGE_LENGTH is assumed to be equal to MAX_STATUSMESSAGE_LENGTH 73#error TOX_MAX_STATUS_MESSAGE_LENGTH is assumed to be equal to MAX_STATUSMESSAGE_LENGTH
71#endif 74#endif
72 75
73uint32_t tox_version_major(void)
74{
75 return TOX_VERSION_MAJOR;
76}
77
78uint32_t tox_version_minor(void)
79{
80 return TOX_VERSION_MINOR;
81}
82
83uint32_t tox_version_patch(void)
84{
85 return TOX_VERSION_PATCH;
86}
87 76
88bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch) 77bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch)
89{ 78{
90 return (TOX_VERSION_MAJOR == major && /* Force the major version */ 79 return TOX_VERSION_IS_API_COMPATIBLE(major, minor, patch);
91 (TOX_VERSION_MINOR > minor || /* Current minor version must be newer than requested -- or -- */
92 (TOX_VERSION_MINOR == minor && TOX_VERSION_PATCH >= patch) /* the patch must be the same or newer */
93 )
94 );
95} 80}
96 81
97 82
98void tox_options_default(struct Tox_Options *options)
99{
100 if (options) {
101 memset(options, 0, sizeof(struct Tox_Options));
102 options->ipv6_enabled = 1;
103 options->udp_enabled = 1;
104 options->proxy_type = TOX_PROXY_TYPE_NONE;
105 }
106}
107
108struct Tox_Options *tox_options_new(TOX_ERR_OPTIONS_NEW *error)
109{
110 struct Tox_Options *options = calloc(sizeof(struct Tox_Options), 1);
111
112 if (options) {
113 tox_options_default(options);
114 SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_OK);
115 return options;
116 }
117
118 SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_MALLOC);
119 return NULL;
120}
121
122void tox_options_free(struct Tox_Options *options)
123{
124 free(options);
125}
126
127Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error) 83Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error)
128{ 84{
129 if (!logger_get_global())
130 logger_set_global(logger_new(LOGGER_OUTPUT_FILE, LOGGER_LEVEL, "toxcore"));
131
132 Messenger_Options m_options = {0}; 85 Messenger_Options m_options = {0};
133 86
134 _Bool load_savedata_sk = 0, load_savedata_tox = 0; 87 bool load_savedata_sk = false, load_savedata_tox = false;
135 88
136 if (options == NULL) { 89 if (options == nullptr) {
137 m_options.ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; 90 m_options.ipv6enabled = TOX_ENABLE_IPV6_DEFAULT;
138 } else { 91 } else {
139 if (options->savedata_type != TOX_SAVEDATA_TYPE_NONE) { 92 if (tox_options_get_savedata_type(options) != TOX_SAVEDATA_TYPE_NONE) {
140 if (options->savedata_data == NULL || options->savedata_length == 0) { 93 if (tox_options_get_savedata_data(options) == nullptr || tox_options_get_savedata_length(options) == 0) {
141 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT); 94 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
142 return NULL; 95 return nullptr;
143 } 96 }
144 } 97 }
145 98
146 if (options->savedata_type == TOX_SAVEDATA_TYPE_SECRET_KEY) { 99 if (tox_options_get_savedata_type(options) == TOX_SAVEDATA_TYPE_SECRET_KEY) {
147 if (options->savedata_length != TOX_SECRET_KEY_SIZE) { 100 if (tox_options_get_savedata_length(options) != TOX_SECRET_KEY_SIZE) {
148 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT); 101 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
149 return NULL; 102 return nullptr;
150 } 103 }
151 104
152 load_savedata_sk = 1; 105 load_savedata_sk = true;
153 } else if (options->savedata_type == TOX_SAVEDATA_TYPE_TOX_SAVE) { 106 } else if (tox_options_get_savedata_type(options) == TOX_SAVEDATA_TYPE_TOX_SAVE) {
154 if (options->savedata_length < TOX_ENC_SAVE_MAGIC_LENGTH) { 107 if (tox_options_get_savedata_length(options) < TOX_ENC_SAVE_MAGIC_LENGTH) {
155 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT); 108 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
156 return NULL; 109 return nullptr;
157 } 110 }
158 111
159 if (sodium_memcmp(options->savedata_data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) { 112 if (crypto_memcmp(tox_options_get_savedata_data(options), TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) {
160 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_ENCRYPTED); 113 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_ENCRYPTED);
161 return NULL; 114 return nullptr;
162 } 115 }
163 116
164 load_savedata_tox = 1; 117 load_savedata_tox = true;
165 } 118 }
166 119
167 m_options.ipv6enabled = options->ipv6_enabled; 120 m_options.ipv6enabled = tox_options_get_ipv6_enabled(options);
168 m_options.udp_disabled = !options->udp_enabled; 121 m_options.udp_disabled = !tox_options_get_udp_enabled(options);
169 m_options.port_range[0] = options->start_port; 122 m_options.port_range[0] = tox_options_get_start_port(options);
170 m_options.port_range[1] = options->end_port; 123 m_options.port_range[1] = tox_options_get_end_port(options);
171 m_options.tcp_server_port = options->tcp_port; 124 m_options.tcp_server_port = tox_options_get_tcp_port(options);
125 m_options.hole_punching_enabled = tox_options_get_hole_punching_enabled(options);
126 m_options.local_discovery_enabled = tox_options_get_local_discovery_enabled(options);
172 127
173 switch (options->proxy_type) { 128 m_options.log_callback = (logger_cb *)tox_options_get_log_callback(options);
129 m_options.log_user_data = tox_options_get_log_user_data(options);
130
131 switch (tox_options_get_proxy_type(options)) {
174 case TOX_PROXY_TYPE_HTTP: 132 case TOX_PROXY_TYPE_HTTP:
175 m_options.proxy_info.proxy_type = TCP_PROXY_HTTP; 133 m_options.proxy_info.proxy_type = TCP_PROXY_HTTP;
176 break; 134 break;
@@ -185,27 +143,28 @@ Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error)
185 143
186 default: 144 default:
187 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_TYPE); 145 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_TYPE);
188 return NULL; 146 return nullptr;
189 } 147 }
190 148
191 if (m_options.proxy_info.proxy_type != TCP_PROXY_NONE) { 149 if (m_options.proxy_info.proxy_type != TCP_PROXY_NONE) {
192 if (options->proxy_port == 0) { 150 if (tox_options_get_proxy_port(options) == 0) {
193 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_PORT); 151 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_PORT);
194 return NULL; 152 return nullptr;
195 } 153 }
196 154
197 ip_init(&m_options.proxy_info.ip_port.ip, m_options.ipv6enabled); 155 ip_init(&m_options.proxy_info.ip_port.ip, m_options.ipv6enabled);
198 156
199 if (m_options.ipv6enabled) 157 if (m_options.ipv6enabled) {
200 m_options.proxy_info.ip_port.ip.family = AF_UNSPEC; 158 m_options.proxy_info.ip_port.ip.family = net_family_unspec;
159 }
201 160
202 if (!addr_resolve_or_parse_ip(options->proxy_host, &m_options.proxy_info.ip_port.ip, NULL)) { 161 if (addr_resolve_or_parse_ip(tox_options_get_proxy_host(options), &m_options.proxy_info.ip_port.ip, nullptr) == 0) {
203 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_HOST); 162 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_HOST);
204 //TODO: TOX_ERR_NEW_PROXY_NOT_FOUND if domain. 163 // TODO(irungentoo): TOX_ERR_NEW_PROXY_NOT_FOUND if domain.
205 return NULL; 164 return nullptr;
206 } 165 }
207 166
208 m_options.proxy_info.ip_port.port = htons(options->proxy_port); 167 m_options.proxy_info.ip_port.port = net_htons(tox_options_get_proxy_port(options));
209 } 168 }
210 } 169 }
211 170
@@ -223,13 +182,14 @@ Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error)
223 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC); 182 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
224 } 183 }
225 184
226 return NULL; 185 return nullptr;
227 } 186 }
228 187
229 if (load_savedata_tox && messenger_load(m, options->savedata_data, options->savedata_length) == -1) { 188 if (load_savedata_tox
189 && messenger_load(m, tox_options_get_savedata_data(options), tox_options_get_savedata_length(options)) == -1) {
230 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT); 190 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
231 } else if (load_savedata_sk) { 191 } else if (load_savedata_sk) {
232 load_secret_key(m->net_crypto, options->savedata_data); 192 load_secret_key(m->net_crypto, tox_options_get_savedata_data(options));
233 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK); 193 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK);
234 } else { 194 } else {
235 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK); 195 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK);
@@ -240,10 +200,13 @@ Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error)
240 200
241void tox_kill(Tox *tox) 201void tox_kill(Tox *tox)
242{ 202{
203 if (tox == nullptr) {
204 return;
205 }
206
243 Messenger *m = tox; 207 Messenger *m = tox;
244 kill_groupchats(m->group_chat_object); 208 kill_groupchats((Group_Chats *)m->conferences_object);
245 kill_messenger(m); 209 kill_messenger(m);
246 logger_kill_global();
247} 210}
248 211
249size_t tox_get_savedata_size(const Tox *tox) 212size_t tox_get_savedata_size(const Tox *tox)
@@ -252,11 +215,11 @@ size_t tox_get_savedata_size(const Tox *tox)
252 return messenger_size(m); 215 return messenger_size(m);
253} 216}
254 217
255void tox_get_savedata(const Tox *tox, uint8_t *data) 218void tox_get_savedata(const Tox *tox, uint8_t *savedata)
256{ 219{
257 if (data) { 220 if (savedata) {
258 const Messenger *m = tox; 221 const Messenger *m = tox;
259 messenger_save(m, data); 222 messenger_save(m, savedata);
260 } 223 }
261} 224}
262 225
@@ -272,49 +235,35 @@ bool tox_bootstrap(Tox *tox, const char *address, uint16_t port, const uint8_t *
272 return 0; 235 return 0;
273 } 236 }
274 237
275 struct addrinfo *root, *info; 238 IP_Port *root;
239
240 int32_t count = net_getipport(address, &root, TOX_SOCK_DGRAM);
276 241
277 if (getaddrinfo(address, NULL, NULL, &root) != 0) { 242 if (count == -1) {
243 net_freeipport(root);
278 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST); 244 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
279 return 0; 245 return 0;
280 } 246 }
281 247
282 info = root; 248 unsigned int i;
283 249
284 unsigned int count = 0; 250 for (i = 0; i < count; i++) {
285 251 root[i].port = net_htons(port);
286 do {
287 IP_Port ip_port;
288 ip_port.port = htons(port);
289 ip_port.ip.family = info->ai_family;
290
291 if (info->ai_socktype && info->ai_socktype != SOCK_DGRAM) {
292 continue;
293 }
294
295 if (info->ai_family == AF_INET) {
296 ip_port.ip.ip4.in_addr = ((struct sockaddr_in *)info->ai_addr)->sin_addr;
297 } else if (info->ai_family == AF_INET6) {
298 ip_port.ip.ip6.in6_addr = ((struct sockaddr_in6 *)info->ai_addr)->sin6_addr;
299 } else {
300 continue;
301 }
302 252
303 Messenger *m = tox; 253 Messenger *m = tox;
304 onion_add_bs_path_node(m->onion_c, ip_port, public_key); 254 onion_add_bs_path_node(m->onion_c, root[i], public_key);
305 DHT_bootstrap(m->dht, ip_port, public_key); 255 DHT_bootstrap(m->dht, root[i], public_key);
306 ++count; 256 }
307 } while ((info = info->ai_next));
308 257
309 freeaddrinfo(root); 258 net_freeipport(root);
310 259
311 if (count) { 260 if (count) {
312 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK); 261 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK);
313 return 1; 262 return 1;
314 } else {
315 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
316 return 0;
317 } 263 }
264
265 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
266 return 0;
318} 267}
319 268
320bool tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key, 269bool tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key,
@@ -330,48 +279,34 @@ bool tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8
330 return 0; 279 return 0;
331 } 280 }
332 281
333 struct addrinfo *root, *info; 282 IP_Port *root;
283
284 int32_t count = net_getipport(address, &root, TOX_SOCK_STREAM);
334 285
335 if (getaddrinfo(address, NULL, NULL, &root) != 0) { 286 if (count == -1) {
287 net_freeipport(root);
336 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST); 288 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
337 return 0; 289 return 0;
338 } 290 }
339 291
340 info = root; 292 unsigned int i;
341 293
342 unsigned int count = 0; 294 for (i = 0; i < count; i++) {
343 295 root[i].port = net_htons(port);
344 do {
345 IP_Port ip_port;
346 ip_port.port = htons(port);
347 ip_port.ip.family = info->ai_family;
348
349 if (info->ai_socktype && info->ai_socktype != SOCK_STREAM) {
350 continue;
351 }
352
353 if (info->ai_family == AF_INET) {
354 ip_port.ip.ip4.in_addr = ((struct sockaddr_in *)info->ai_addr)->sin_addr;
355 } else if (info->ai_family == AF_INET6) {
356 ip_port.ip.ip6.in6_addr = ((struct sockaddr_in6 *)info->ai_addr)->sin6_addr;
357 } else {
358 continue;
359 }
360 296
361 Messenger *m = tox; 297 Messenger *m = tox;
362 add_tcp_relay(m->net_crypto, ip_port, public_key); 298 add_tcp_relay(m->net_crypto, root[i], public_key);
363 ++count; 299 }
364 } while ((info = info->ai_next));
365 300
366 freeaddrinfo(root); 301 net_freeipport(root);
367 302
368 if (count) { 303 if (count) {
369 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK); 304 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK);
370 return 1; 305 return 1;
371 } else {
372 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
373 return 0;
374 } 306 }
307
308 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
309 return 0;
375} 310}
376 311
377TOX_CONNECTION tox_self_get_connection_status(const Tox *tox) 312TOX_CONNECTION tox_self_get_connection_status(const Tox *tox)
@@ -382,18 +317,20 @@ TOX_CONNECTION tox_self_get_connection_status(const Tox *tox)
382 317
383 if (ret == 2) { 318 if (ret == 2) {
384 return TOX_CONNECTION_UDP; 319 return TOX_CONNECTION_UDP;
385 } else if (ret == 1) { 320 }
321
322 if (ret == 1) {
386 return TOX_CONNECTION_TCP; 323 return TOX_CONNECTION_TCP;
387 } else {
388 return TOX_CONNECTION_NONE;
389 } 324 }
325
326 return TOX_CONNECTION_NONE;
390} 327}
391 328
392 329
393void tox_callback_self_connection_status(Tox *tox, tox_self_connection_status_cb *function, void *user_data) 330void tox_callback_self_connection_status(Tox *tox, tox_self_connection_status_cb *callback)
394{ 331{
395 Messenger *m = tox; 332 Messenger *m = tox;
396 m_callback_core_connection(m, function, user_data); 333 m_callback_core_connection(m, (void (*)(Messenger *, unsigned int, void *))callback);
397} 334}
398 335
399uint32_t tox_iteration_interval(const Tox *tox) 336uint32_t tox_iteration_interval(const Tox *tox)
@@ -402,11 +339,11 @@ uint32_t tox_iteration_interval(const Tox *tox)
402 return messenger_run_interval(m); 339 return messenger_run_interval(m);
403} 340}
404 341
405void tox_iterate(Tox *tox) 342void tox_iterate(Tox *tox, void *user_data)
406{ 343{
407 Messenger *m = tox; 344 Messenger *m = tox;
408 do_messenger(m); 345 do_messenger(m, user_data);
409 do_groupchats(m->group_chat_object); 346 do_groupchats((Group_Chats *)m->conferences_object, user_data);
410} 347}
411 348
412void tox_self_get_address(const Tox *tox, uint8_t *address) 349void tox_self_get_address(const Tox *tox, uint8_t *address)
@@ -420,29 +357,31 @@ void tox_self_get_address(const Tox *tox, uint8_t *address)
420void tox_self_set_nospam(Tox *tox, uint32_t nospam) 357void tox_self_set_nospam(Tox *tox, uint32_t nospam)
421{ 358{
422 Messenger *m = tox; 359 Messenger *m = tox;
423 set_nospam(&(m->fr), nospam); 360 set_nospam(m->fr, net_htonl(nospam));
424} 361}
425 362
426uint32_t tox_self_get_nospam(const Tox *tox) 363uint32_t tox_self_get_nospam(const Tox *tox)
427{ 364{
428 const Messenger *m = tox; 365 const Messenger *m = tox;
429 return get_nospam(&(m->fr)); 366 return net_ntohl(get_nospam(m->fr));
430} 367}
431 368
432void tox_self_get_public_key(const Tox *tox, uint8_t *public_key) 369void tox_self_get_public_key(const Tox *tox, uint8_t *public_key)
433{ 370{
434 const Messenger *m = tox; 371 const Messenger *m = tox;
435 372
436 if (public_key) 373 if (public_key) {
437 memcpy(public_key, m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES); 374 memcpy(public_key, nc_get_self_public_key(m->net_crypto), CRYPTO_PUBLIC_KEY_SIZE);
375 }
438} 376}
439 377
440void tox_self_get_secret_key(const Tox *tox, uint8_t *secret_key) 378void tox_self_get_secret_key(const Tox *tox, uint8_t *secret_key)
441{ 379{
442 const Messenger *m = tox; 380 const Messenger *m = tox;
443 381
444 if (secret_key) 382 if (secret_key) {
445 memcpy(secret_key, m->net_crypto->self_secret_key, crypto_box_SECRETKEYBYTES); 383 memcpy(secret_key, nc_get_self_secret_key(m->net_crypto), CRYPTO_SECRET_KEY_SIZE);
384 }
446} 385}
447 386
448bool tox_self_set_name(Tox *tox, const uint8_t *name, size_t length, TOX_ERR_SET_INFO *error) 387bool tox_self_set_name(Tox *tox, const uint8_t *name, size_t length, TOX_ERR_SET_INFO *error)
@@ -455,14 +394,14 @@ bool tox_self_set_name(Tox *tox, const uint8_t *name, size_t length, TOX_ERR_SET
455 Messenger *m = tox; 394 Messenger *m = tox;
456 395
457 if (setname(m, name, length) == 0) { 396 if (setname(m, name, length) == 0) {
458 //TODO: function to set different per group names? 397 // TODO(irungentoo): function to set different per group names?
459 send_name_all_groups(m->group_chat_object); 398 send_name_all_groups((Group_Chats *)m->conferences_object);
460 SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_OK); 399 SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_OK);
461 return 1; 400 return 1;
462 } else {
463 SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_TOO_LONG);
464 return 0;
465 } 401 }
402
403 SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_TOO_LONG);
404 return 0;
466} 405}
467 406
468size_t tox_self_get_name_size(const Tox *tox) 407size_t tox_self_get_name_size(const Tox *tox)
@@ -479,22 +418,22 @@ void tox_self_get_name(const Tox *tox, uint8_t *name)
479 } 418 }
480} 419}
481 420
482bool tox_self_set_status_message(Tox *tox, const uint8_t *status, size_t length, TOX_ERR_SET_INFO *error) 421bool tox_self_set_status_message(Tox *tox, const uint8_t *status_message, size_t length, TOX_ERR_SET_INFO *error)
483{ 422{
484 if (!status && length != 0) { 423 if (!status_message && length != 0) {
485 SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_NULL); 424 SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_NULL);
486 return 0; 425 return 0;
487 } 426 }
488 427
489 Messenger *m = tox; 428 Messenger *m = tox;
490 429
491 if (m_set_statusmessage(m, status, length) == 0) { 430 if (m_set_statusmessage(m, status_message, length) == 0) {
492 SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_OK); 431 SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_OK);
493 return 1; 432 return 1;
494 } else {
495 SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_TOO_LONG);
496 return 0;
497 } 433 }
434
435 SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_TOO_LONG);
436 return 0;
498} 437}
499 438
500size_t tox_self_get_status_message_size(const Tox *tox) 439size_t tox_self_get_status_message_size(const Tox *tox)
@@ -503,24 +442,25 @@ size_t tox_self_get_status_message_size(const Tox *tox)
503 return m_get_self_statusmessage_size(m); 442 return m_get_self_statusmessage_size(m);
504} 443}
505 444
506void tox_self_get_status_message(const Tox *tox, uint8_t *status) 445void tox_self_get_status_message(const Tox *tox, uint8_t *status_message)
507{ 446{
508 if (status) { 447 if (status_message) {
509 const Messenger *m = tox; 448 const Messenger *m = tox;
510 m_copy_self_statusmessage(m, status); 449 m_copy_self_statusmessage(m, status_message);
511 } 450 }
512} 451}
513 452
514void tox_self_set_status(Tox *tox, TOX_USER_STATUS user_status) 453void tox_self_set_status(Tox *tox, TOX_USER_STATUS status)
515{ 454{
516 Messenger *m = tox; 455 Messenger *m = tox;
517 m_set_userstatus(m, user_status); 456 m_set_userstatus(m, status);
518} 457}
519 458
520TOX_USER_STATUS tox_self_get_status(const Tox *tox) 459TOX_USER_STATUS tox_self_get_status(const Tox *tox)
521{ 460{
522 const Messenger *m = tox; 461 const Messenger *m = tox;
523 return m_get_self_userstatus(m); 462 const uint8_t status = m_get_self_userstatus(m);
463 return (TOX_USER_STATUS)status;
524} 464}
525 465
526static void set_friend_error(int32_t ret, TOX_ERR_FRIEND_ADD *error) 466static void set_friend_error(int32_t ret, TOX_ERR_FRIEND_ADD *error)
@@ -553,7 +493,6 @@ static void set_friend_error(int32_t ret, TOX_ERR_FRIEND_ADD *error)
553 case FAERR_NOMEM: 493 case FAERR_NOMEM:
554 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_MALLOC); 494 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_MALLOC);
555 break; 495 break;
556
557 } 496 }
558} 497}
559 498
@@ -601,7 +540,7 @@ bool tox_friend_delete(Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_DELETE *
601 Messenger *m = tox; 540 Messenger *m = tox;
602 int ret = m_delfriend(m, friend_number); 541 int ret = m_delfriend(m, friend_number);
603 542
604 //TODO handle if realloc fails? 543 // TODO(irungentoo): handle if realloc fails?
605 if (ret == -1) { 544 if (ret == -1) {
606 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND); 545 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND);
607 return 0; 546 return 0;
@@ -674,12 +613,12 @@ size_t tox_self_get_friend_list_size(const Tox *tox)
674 return count_friendlist(m); 613 return count_friendlist(m);
675} 614}
676 615
677void tox_self_get_friend_list(const Tox *tox, uint32_t *list) 616void tox_self_get_friend_list(const Tox *tox, uint32_t *friend_list)
678{ 617{
679 if (list) { 618 if (friend_list) {
680 const Messenger *m = tox; 619 const Messenger *m = tox;
681 //TODO: size parameter? 620 // TODO(irungentoo): size parameter?
682 copy_friendlist(m, list, tox_self_get_friend_list_size(tox)); 621 copy_friendlist(m, friend_list, tox_self_get_friend_list_size(tox));
683 } 622 }
684} 623}
685 624
@@ -716,10 +655,10 @@ bool tox_friend_get_name(const Tox *tox, uint32_t friend_number, uint8_t *name,
716 return 1; 655 return 1;
717} 656}
718 657
719void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *function, void *user_data) 658void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *callback)
720{ 659{
721 Messenger *m = tox; 660 Messenger *m = tox;
722 m_callback_namechange(m, function, user_data); 661 m_callback_namechange(m, callback);
723} 662}
724 663
725size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) 664size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error)
@@ -736,17 +675,17 @@ size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number
736 return ret; 675 return ret;
737} 676}
738 677
739bool tox_friend_get_status_message(const Tox *tox, uint32_t friend_number, uint8_t *message, 678bool tox_friend_get_status_message(const Tox *tox, uint32_t friend_number, uint8_t *status_message,
740 TOX_ERR_FRIEND_QUERY *error) 679 TOX_ERR_FRIEND_QUERY *error)
741{ 680{
742 if (!message) { 681 if (!status_message) {
743 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_NULL); 682 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_NULL);
744 return 0; 683 return 0;
745 } 684 }
746 685
747 const Messenger *m = tox; 686 const Messenger *m = tox;
748 //TODO: size parameter? 687 // TODO(irungentoo): size parameter?
749 int ret = m_copy_statusmessage(m, friend_number, message, m_get_statusmessage_size(m, friend_number)); 688 int ret = m_copy_statusmessage(m, friend_number, status_message, m_get_statusmessage_size(m, friend_number));
750 689
751 if (ret == -1) { 690 if (ret == -1) {
752 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); 691 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
@@ -757,10 +696,10 @@ bool tox_friend_get_status_message(const Tox *tox, uint32_t friend_number, uint8
757 return 1; 696 return 1;
758} 697}
759 698
760void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *function, void *user_data) 699void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *callback)
761{ 700{
762 Messenger *m = tox; 701 Messenger *m = tox;
763 m_callback_statusmessage(m, function, user_data); 702 m_callback_statusmessage(m, callback);
764} 703}
765 704
766TOX_USER_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) 705TOX_USER_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error)
@@ -771,17 +710,17 @@ TOX_USER_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TO
771 710
772 if (ret == USERSTATUS_INVALID) { 711 if (ret == USERSTATUS_INVALID) {
773 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); 712 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
774 return TOX_USER_STATUS_BUSY + 1; 713 return (TOX_USER_STATUS)(TOX_USER_STATUS_BUSY + 1);
775 } 714 }
776 715
777 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK); 716 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
778 return ret; 717 return (TOX_USER_STATUS)ret;
779} 718}
780 719
781void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *function, void *user_data) 720void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *callback)
782{ 721{
783 Messenger *m = tox; 722 Messenger *m = tox;
784 m_callback_userstatus(m, function, user_data); 723 m_callback_userstatus(m, (void (*)(Messenger *, uint32_t, unsigned int, void *))callback);
785} 724}
786 725
787TOX_CONNECTION tox_friend_get_connection_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) 726TOX_CONNECTION tox_friend_get_connection_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error)
@@ -796,13 +735,13 @@ TOX_CONNECTION tox_friend_get_connection_status(const Tox *tox, uint32_t friend_
796 } 735 }
797 736
798 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK); 737 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
799 return ret; 738 return (TOX_CONNECTION)ret;
800} 739}
801 740
802void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_status_cb *function, void *user_data) 741void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_status_cb *callback)
803{ 742{
804 Messenger *m = tox; 743 Messenger *m = tox;
805 m_callback_connectionstatus(m, function, user_data); 744 m_callback_connectionstatus(m, (void (*)(Messenger *, uint32_t, unsigned int, void *))callback);
806} 745}
807 746
808bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) 747bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error)
@@ -819,17 +758,17 @@ bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEN
819 return !!ret; 758 return !!ret;
820} 759}
821 760
822void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *function, void *user_data) 761void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *callback)
823{ 762{
824 Messenger *m = tox; 763 Messenger *m = tox;
825 m_callback_typingchange(m, function, user_data); 764 m_callback_typingchange(m, callback);
826} 765}
827 766
828bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool is_typing, TOX_ERR_SET_TYPING *error) 767bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool typing, TOX_ERR_SET_TYPING *error)
829{ 768{
830 Messenger *m = tox; 769 Messenger *m = tox;
831 770
832 if (m_set_usertyping(m, friend_number, is_typing) == -1) { 771 if (m_set_usertyping(m, friend_number, typing) == -1) {
833 SET_ERROR_PARAMETER(error, TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND); 772 SET_ERROR_PARAMETER(error, TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND);
834 return 0; 773 return 0;
835 } 774 }
@@ -886,22 +825,22 @@ uint32_t tox_friend_send_message(Tox *tox, uint32_t friend_number, TOX_MESSAGE_T
886 return message_id; 825 return message_id;
887} 826}
888 827
889void tox_callback_friend_read_receipt(Tox *tox, tox_friend_read_receipt_cb *function, void *user_data) 828void tox_callback_friend_read_receipt(Tox *tox, tox_friend_read_receipt_cb *callback)
890{ 829{
891 Messenger *m = tox; 830 Messenger *m = tox;
892 m_callback_read_receipt(m, function, user_data); 831 m_callback_read_receipt(m, callback);
893} 832}
894 833
895void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *function, void *user_data) 834void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *callback)
896{ 835{
897 Messenger *m = tox; 836 Messenger *m = tox;
898 m_callback_friendrequest(m, function, user_data); 837 m_callback_friendrequest(m, callback);
899} 838}
900 839
901void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *function, void *user_data) 840void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *callback)
902{ 841{
903 Messenger *m = tox; 842 Messenger *m = tox;
904 m_callback_friendmessage(m, function, user_data); 843 m_callback_friendmessage(m, (void (*)(Messenger *, uint32_t, unsigned int, const uint8_t *, size_t, void *))callback);
905} 844}
906 845
907bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length) 846bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length)
@@ -910,7 +849,7 @@ bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length)
910 return 0; 849 return 0;
911 } 850 }
912 851
913 crypto_hash_sha256(hash, data, length); 852 crypto_sha256(hash, data, length);
914 return 1; 853 return 1;
915} 854}
916 855
@@ -987,7 +926,7 @@ bool tox_file_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint6
987 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_NOT_FOUND); 926 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_NOT_FOUND);
988 return 0; 927 return 0;
989 928
990 case -4: 929 case -4: // fall-through
991 case -5: 930 case -5:
992 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_DENIED); 931 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_DENIED);
993 return 0; 932 return 0;
@@ -1005,10 +944,10 @@ bool tox_file_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint6
1005 return 0; 944 return 0;
1006} 945}
1007 946
1008void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *function, void *user_data) 947void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *callback)
1009{ 948{
1010 Messenger *m = tox; 949 Messenger *m = tox;
1011 callback_file_control(m, function, user_data); 950 callback_file_control(m, (void (*)(Messenger *, uint32_t, uint32_t, unsigned int, void *))callback);
1012} 951}
1013 952
1014bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t *file_id, 953bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t *file_id,
@@ -1025,7 +964,9 @@ bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_
1025 if (ret == 0) { 964 if (ret == 0) {
1026 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_OK); 965 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_OK);
1027 return 1; 966 return 1;
1028 } else if (ret == -1) { 967 }
968
969 if (ret == -1) {
1029 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_FRIEND_NOT_FOUND); 970 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_FRIEND_NOT_FOUND);
1030 } else { 971 } else {
1031 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_NOT_FOUND); 972 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_NOT_FOUND);
@@ -1125,22 +1066,363 @@ bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number,
1125 return 0; 1066 return 0;
1126} 1067}
1127 1068
1128void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *function, void *user_data) 1069void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *callback)
1070{
1071 Messenger *m = tox;
1072 callback_file_reqchunk(m, callback);
1073}
1074
1075void tox_callback_file_recv(Tox *tox, tox_file_recv_cb *callback)
1129{ 1076{
1130 Messenger *m = tox; 1077 Messenger *m = tox;
1131 callback_file_reqchunk(m, function, user_data); 1078 callback_file_sendrequest(m, callback);
1132} 1079}
1133 1080
1134void tox_callback_file_recv(Tox *tox, tox_file_recv_cb *function, void *user_data) 1081void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *callback)
1135{ 1082{
1136 Messenger *m = tox; 1083 Messenger *m = tox;
1137 callback_file_sendrequest(m, function, user_data); 1084 callback_file_data(m, callback);
1138} 1085}
1139 1086
1140void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *function, void *user_data) 1087void tox_callback_conference_invite(Tox *tox, tox_conference_invite_cb *callback)
1141{ 1088{
1142 Messenger *m = tox; 1089 Messenger *m = tox;
1143 callback_file_data(m, function, user_data); 1090 g_callback_group_invite((Group_Chats *)m->conferences_object, (void (*)(Messenger * m, uint32_t, int, const uint8_t *,
1091 size_t,
1092 void *))callback);
1093}
1094
1095void tox_callback_conference_message(Tox *tox, tox_conference_message_cb *callback)
1096{
1097 Messenger *m = tox;
1098 g_callback_group_message((Group_Chats *)m->conferences_object, (void (*)(Messenger * m, uint32_t, uint32_t, int,
1099 const uint8_t *,
1100 size_t, void *))callback);
1101}
1102
1103void tox_callback_conference_title(Tox *tox, tox_conference_title_cb *callback)
1104{
1105 Messenger *m = tox;
1106 g_callback_group_title((Group_Chats *)m->conferences_object, callback);
1107}
1108
1109void tox_callback_conference_peer_name(Tox *tox, tox_conference_peer_name_cb *callback)
1110{
1111 Messenger *m = tox;
1112 g_callback_peer_name((Group_Chats *)m->conferences_object, callback);
1113}
1114
1115void tox_callback_conference_peer_list_changed(Tox *tox, tox_conference_peer_list_changed_cb *callback)
1116{
1117 Messenger *m = tox;
1118 g_callback_peer_list_changed((Group_Chats *)m->conferences_object, callback);
1119}
1120
1121uint32_t tox_conference_new(Tox *tox, TOX_ERR_CONFERENCE_NEW *error)
1122{
1123 Messenger *m = tox;
1124 int ret = add_groupchat((Group_Chats *)m->conferences_object, GROUPCHAT_TYPE_TEXT);
1125
1126 if (ret == -1) {
1127 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_NEW_INIT);
1128 return UINT32_MAX;
1129 }
1130
1131 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_NEW_OK);
1132 return ret;
1133}
1134
1135bool tox_conference_delete(Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_DELETE *error)
1136{
1137 Messenger *m = tox;
1138 int ret = del_groupchat((Group_Chats *)m->conferences_object, conference_number);
1139
1140 if (ret == -1) {
1141 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_DELETE_CONFERENCE_NOT_FOUND);
1142 return false;
1143 }
1144
1145 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_DELETE_OK);
1146 return true;
1147}
1148
1149uint32_t tox_conference_peer_count(const Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_PEER_QUERY *error)
1150{
1151 const Messenger *m = tox;
1152 int ret = group_number_peers((Group_Chats *)m->conferences_object, conference_number);
1153
1154 if (ret == -1) {
1155 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
1156 return UINT32_MAX;
1157 }
1158
1159 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
1160 return ret;
1161}
1162
1163size_t tox_conference_peer_get_name_size(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
1164 TOX_ERR_CONFERENCE_PEER_QUERY *error)
1165{
1166 const Messenger *m = tox;
1167 int ret = group_peername_size((Group_Chats *)m->conferences_object, conference_number, peer_number);
1168
1169 switch (ret) {
1170 case -1:
1171 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
1172 return -1;
1173
1174 case -2:
1175 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
1176 return -1;
1177 }
1178
1179 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
1180 return ret;
1181}
1182
1183bool tox_conference_peer_get_name(const Tox *tox, uint32_t conference_number, uint32_t peer_number, uint8_t *name,
1184 TOX_ERR_CONFERENCE_PEER_QUERY *error)
1185{
1186 const Messenger *m = tox;
1187 int ret = group_peername((Group_Chats *)m->conferences_object, conference_number, peer_number, name);
1188
1189 switch (ret) {
1190 case -1:
1191 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
1192 return false;
1193
1194 case -2:
1195 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
1196 return false;
1197 }
1198
1199 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
1200 return true;
1201}
1202
1203bool tox_conference_peer_get_public_key(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
1204 uint8_t *public_key, TOX_ERR_CONFERENCE_PEER_QUERY *error)
1205{
1206 const Messenger *m = tox;
1207 int ret = group_peer_pubkey((Group_Chats *)m->conferences_object, conference_number, peer_number, public_key);
1208
1209 switch (ret) {
1210 case -1:
1211 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
1212 return false;
1213
1214 case -2:
1215 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
1216 return false;
1217 }
1218
1219 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
1220 return true;
1221}
1222
1223bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
1224 TOX_ERR_CONFERENCE_PEER_QUERY *error)
1225{
1226 const Messenger *m = tox;
1227 int ret = group_peernumber_is_ours((Group_Chats *)m->conferences_object, conference_number, peer_number);
1228
1229 switch (ret) {
1230 case -1:
1231 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
1232 return false;
1233
1234 case -2:
1235 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
1236 return false;
1237
1238 case -3:
1239 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_NO_CONNECTION);
1240 return false;
1241 }
1242
1243 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
1244 return ret;
1245}
1246
1247bool tox_conference_invite(Tox *tox, uint32_t friend_number, uint32_t conference_number,
1248 TOX_ERR_CONFERENCE_INVITE *error)
1249{
1250 Messenger *m = tox;
1251 int ret = invite_friend((Group_Chats *)m->conferences_object, friend_number, conference_number);
1252
1253 switch (ret) {
1254 case -1:
1255 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_CONFERENCE_NOT_FOUND);
1256 return false;
1257
1258 case -2:
1259 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_FAIL_SEND);
1260 return false;
1261 }
1262
1263 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_OK);
1264 return true;
1265}
1266
1267uint32_t tox_conference_join(Tox *tox, uint32_t friend_number, const uint8_t *cookie, size_t length,
1268 TOX_ERR_CONFERENCE_JOIN *error)
1269{
1270 Messenger *m = tox;
1271 int ret = join_groupchat((Group_Chats *)m->conferences_object, friend_number, GROUPCHAT_TYPE_TEXT, cookie, length);
1272
1273 switch (ret) {
1274 case -1:
1275 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_INVALID_LENGTH);
1276 return UINT32_MAX;
1277
1278 case -2:
1279 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_WRONG_TYPE);
1280 return UINT32_MAX;
1281
1282 case -3:
1283 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_FRIEND_NOT_FOUND);
1284 return UINT32_MAX;
1285
1286 case -4:
1287 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_DUPLICATE);
1288 return UINT32_MAX;
1289
1290 case -5:
1291 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_INIT_FAIL);
1292 return UINT32_MAX;
1293
1294 case -6:
1295 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_FAIL_SEND);
1296 return UINT32_MAX;
1297 }
1298
1299 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_OK);
1300 return ret;
1301}
1302
1303bool tox_conference_send_message(Tox *tox, uint32_t conference_number, TOX_MESSAGE_TYPE type, const uint8_t *message,
1304 size_t length, TOX_ERR_CONFERENCE_SEND_MESSAGE *error)
1305{
1306 Messenger *m = tox;
1307 int ret = 0;
1308
1309 if (type == TOX_MESSAGE_TYPE_NORMAL) {
1310 ret = group_message_send((Group_Chats *)m->conferences_object, conference_number, message, length);
1311 } else {
1312 ret = group_action_send((Group_Chats *)m->conferences_object, conference_number, message, length);
1313 }
1314
1315 switch (ret) {
1316 case -1:
1317 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_CONFERENCE_NOT_FOUND);
1318 return false;
1319
1320 case -2:
1321 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_TOO_LONG);
1322 return false;
1323
1324 case -3:
1325 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_NO_CONNECTION);
1326 return false;
1327
1328 case -4:
1329 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_FAIL_SEND);
1330 return false;
1331 }
1332
1333 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_OK);
1334 return true;
1335}
1336
1337size_t tox_conference_get_title_size(const Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_TITLE *error)
1338{
1339 const Messenger *m = tox;
1340 int ret = group_title_get_size((Group_Chats *)m->conferences_object, conference_number);
1341
1342 switch (ret) {
1343 case -1:
1344 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND);
1345 return -1;
1346
1347 case -2:
1348 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH);
1349 return -1;
1350 }
1351
1352 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_OK);
1353 return ret;
1354}
1355
1356bool tox_conference_get_title(const Tox *tox, uint32_t conference_number, uint8_t *title,
1357 TOX_ERR_CONFERENCE_TITLE *error)
1358{
1359 const Messenger *m = tox;
1360 int ret = group_title_get((Group_Chats *)m->conferences_object, conference_number, title);
1361
1362 switch (ret) {
1363 case -1:
1364 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND);
1365 return false;
1366
1367 case -2:
1368 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH);
1369 return false;
1370 }
1371
1372 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_OK);
1373 return true;
1374}
1375
1376bool tox_conference_set_title(Tox *tox, uint32_t conference_number, const uint8_t *title, size_t length,
1377 TOX_ERR_CONFERENCE_TITLE *error)
1378{
1379 Messenger *m = tox;
1380 int ret = group_title_send((Group_Chats *)m->conferences_object, conference_number, title, length);
1381
1382 switch (ret) {
1383 case -1:
1384 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND);
1385 return false;
1386
1387 case -2:
1388 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH);
1389 return false;
1390
1391 case -3:
1392 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_FAIL_SEND);
1393 return false;
1394 }
1395
1396 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_OK);
1397 return true;
1398}
1399
1400size_t tox_conference_get_chatlist_size(const Tox *tox)
1401{
1402 const Messenger *m = tox;
1403 return count_chatlist((Group_Chats *)m->conferences_object);
1404}
1405
1406void tox_conference_get_chatlist(const Tox *tox, uint32_t *chatlist)
1407{
1408 const Messenger *m = tox;
1409 size_t list_size = tox_conference_get_chatlist_size(tox);
1410 copy_chatlist((Group_Chats *)m->conferences_object, chatlist, list_size);
1411}
1412
1413TOX_CONFERENCE_TYPE tox_conference_get_type(const Tox *tox, uint32_t conference_number,
1414 TOX_ERR_CONFERENCE_GET_TYPE *error)
1415{
1416 const Messenger *m = tox;
1417 int ret = group_get_type((Group_Chats *)m->conferences_object, conference_number);
1418
1419 if (ret == -1) {
1420 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_GET_TYPE_CONFERENCE_NOT_FOUND);
1421 return (TOX_CONFERENCE_TYPE)ret;
1422 }
1423
1424 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_GET_TYPE_OK);
1425 return (TOX_CONFERENCE_TYPE)ret;
1144} 1426}
1145 1427
1146static void set_custom_packet_error(int ret, TOX_ERR_FRIEND_CUSTOM_PACKET *error) 1428static void set_custom_packet_error(int ret, TOX_ERR_FRIEND_CUSTOM_PACKET *error)
@@ -1192,21 +1474,21 @@ bool tox_friend_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_
1192 return 0; 1474 return 0;
1193 } 1475 }
1194 1476
1195 int ret = send_custom_lossy_packet(m, friend_number, data, length); 1477 int ret = m_send_custom_lossy_packet(m, friend_number, data, length);
1196 1478
1197 set_custom_packet_error(ret, error); 1479 set_custom_packet_error(ret, error);
1198 1480
1199 if (ret == 0) { 1481 if (ret == 0) {
1200 return 1; 1482 return 1;
1201 } else {
1202 return 0;
1203 } 1483 }
1484
1485 return 0;
1204} 1486}
1205 1487
1206void tox_callback_friend_lossy_packet(Tox *tox, tox_friend_lossy_packet_cb *function, void *user_data) 1488void tox_callback_friend_lossy_packet(Tox *tox, tox_friend_lossy_packet_cb *callback)
1207{ 1489{
1208 Messenger *m = tox; 1490 Messenger *m = tox;
1209 custom_lossy_packet_registerhandler(m, function, user_data); 1491 custom_lossy_packet_registerhandler(m, callback);
1210} 1492}
1211 1493
1212bool tox_friend_send_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, 1494bool tox_friend_send_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
@@ -1230,29 +1512,29 @@ bool tox_friend_send_lossless_packet(Tox *tox, uint32_t friend_number, const uin
1230 1512
1231 if (ret == 0) { 1513 if (ret == 0) {
1232 return 1; 1514 return 1;
1233 } else {
1234 return 0;
1235 } 1515 }
1516
1517 return 0;
1236} 1518}
1237 1519
1238void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb *function, void *user_data) 1520void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb *callback)
1239{ 1521{
1240 Messenger *m = tox; 1522 Messenger *m = tox;
1241 custom_lossless_packet_registerhandler(m, function, user_data); 1523 custom_lossless_packet_registerhandler(m, callback);
1242} 1524}
1243 1525
1244void tox_self_get_dht_id(const Tox *tox, uint8_t *dht_id) 1526void tox_self_get_dht_id(const Tox *tox, uint8_t *dht_id)
1245{ 1527{
1246 if (dht_id) { 1528 if (dht_id) {
1247 const Messenger *m = tox; 1529 const Messenger *m = tox;
1248 memcpy(dht_id , m->dht->self_public_key, crypto_box_PUBLICKEYBYTES); 1530 memcpy(dht_id, dht_get_self_public_key(m->dht), CRYPTO_PUBLIC_KEY_SIZE);
1249 } 1531 }
1250} 1532}
1251 1533
1252uint16_t tox_self_get_udp_port(const Tox *tox, TOX_ERR_GET_PORT *error) 1534uint16_t tox_self_get_udp_port(const Tox *tox, TOX_ERR_GET_PORT *error)
1253{ 1535{
1254 const Messenger *m = tox; 1536 const Messenger *m = tox;
1255 uint16_t port = htons(m->net->port); 1537 uint16_t port = net_htons(net_port(m->net));
1256 1538
1257 if (port) { 1539 if (port) {
1258 SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK); 1540 SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK);
@@ -1270,10 +1552,8 @@ uint16_t tox_self_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error)
1270 if (m->tcp_server) { 1552 if (m->tcp_server) {
1271 SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK); 1553 SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK);
1272 return m->options.tcp_server_port; 1554 return m->options.tcp_server_port;
1273 } else {
1274 SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND);
1275 return 0;
1276 } 1555 }
1277}
1278 1556
1279#include "tox_old_code.h" 1557 SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND);
1558 return 0;
1559}
diff --git a/toxcore/tox.h b/toxcore/tox.h
index 1655d9c1..d5834095 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -1,26 +1,26 @@
1/* tox.h 1/*
2 *
3 * The Tox public API. 2 * The Tox public API.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2013 Tox project.
4 * 8 *
5 * Copyright (C) 2013 Tox project All Rights Reserved. 9 * This file is part of Tox, the free peer to peer instant messenger.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23
24#ifndef TOX_H 24#ifndef TOX_H
25#define TOX_H 25#define TOX_H
26 26
@@ -35,8 +35,8 @@ extern "C" {
35 35
36/******************************************************************************* 36/*******************************************************************************
37 * `tox.h` SHOULD *NOT* BE EDITED MANUALLY – any changes should be made to * 37 * `tox.h` SHOULD *NOT* BE EDITED MANUALLY – any changes should be made to *
38 * `tox.in.h`, located in `other/apidsl/`. For instructions on how to * 38 * `tox.api.h`, located in `toxcore/`. For instructions on how to *
39 * generate `tox.h` from `tox.in.h` please refer to `other/apidsl/README.md` * 39 * generate `tox.h` from `tox.api.h` please refer to `docs/apidsl.md` *
40 ******************************************************************************/ 40 ******************************************************************************/
41 41
42 42
@@ -75,6 +75,9 @@ extern "C" {
75 * enumeration value is outside the valid range of the type. If possible, the 75 * enumeration value is outside the valid range of the type. If possible, the
76 * function will try to use a sane default, but there will be no error code, 76 * function will try to use a sane default, but there will be no error code,
77 * and one possible action for the function to take is to have no effect. 77 * and one possible action for the function to take is to have no effect.
78 *
79 * Integer constants and the memory layout of publicly exposed structs are not
80 * part of the ABI.
78 */ 81 */
79/** \subsection events Events and callbacks 82/** \subsection events Events and callbacks
80 * 83 *
@@ -84,6 +87,19 @@ extern "C" {
84 * callback will result in no callback being registered for that event. Only 87 * callback will result in no callback being registered for that event. Only
85 * one callback per event can be registered, so if a client needs multiple 88 * one callback per event can be registered, so if a client needs multiple
86 * event listeners, it needs to implement the dispatch functionality itself. 89 * event listeners, it needs to implement the dispatch functionality itself.
90 *
91 * The last argument to a callback is the user data pointer. It is passed from
92 * tox_iterate to each callback in sequence.
93 *
94 * The user data pointer is never stored or dereferenced by any library code, so
95 * can be any pointer, including NULL. Callbacks must all operate on the same
96 * object type. In the apidsl code (tox.in.h), this is denoted with `any`. The
97 * `any` in tox_iterate must be the same `any` as in all callbacks. In C,
98 * lacking parametric polymorphism, this is a pointer to void.
99 *
100 * Old style callbacks that are registered together with a user data pointer
101 * receive that pointer as argument when they are called. They can each have
102 * their own user data pointer of their own type.
87 */ 103 */
88/** \subsection threading Threading implications 104/** \subsection threading Threading implications
89 * 105 *
@@ -142,55 +158,52 @@ typedef struct Tox Tox;
142/** 158/**
143 * The major version number. Incremented when the API or ABI changes in an 159 * The major version number. Incremented when the API or ABI changes in an
144 * incompatible way. 160 * incompatible way.
161 *
162 * The function variants of these constants return the version number of the
163 * library. They can be used to display the Tox library version or to check
164 * whether the client is compatible with the dynamically linked version of Tox.
145 */ 165 */
146#define TOX_VERSION_MAJOR 0u 166#define TOX_VERSION_MAJOR 0
167
168uint32_t tox_version_major(void);
147 169
148/** 170/**
149 * The minor version number. Incremented when functionality is added without 171 * The minor version number. Incremented when functionality is added without
150 * breaking the API or ABI. Set to 0 when the major version number is 172 * breaking the API or ABI. Set to 0 when the major version number is
151 * incremented. 173 * incremented.
152 */ 174 */
153#define TOX_VERSION_MINOR 0u 175#define TOX_VERSION_MINOR 2
176
177uint32_t tox_version_minor(void);
154 178
155/** 179/**
156 * The patch or revision number. Incremented when bugfixes are applied without 180 * The patch or revision number. Incremented when bugfixes are applied without
157 * changing any functionality or API or ABI. 181 * changing any functionality or API or ABI.
158 */ 182 */
159#define TOX_VERSION_PATCH 0u 183#define TOX_VERSION_PATCH 2
160
161/**
162 * A macro to check at preprocessing time whether the client code is compatible
163 * with the installed version of Tox.
164 */
165#define TOX_VERSION_IS_API_COMPATIBLE(MAJOR, MINOR, PATCH) \
166 (TOX_VERSION_MAJOR == MAJOR && \
167 (TOX_VERSION_MINOR > MINOR || \
168 (TOX_VERSION_MINOR == MINOR && \
169 TOX_VERSION_PATCH >= PATCH)))
170
171/**
172 * A macro to make compilation fail if the client code is not compatible with
173 * the installed version of Tox.
174 */
175#define TOX_VERSION_REQUIRE(MAJOR, MINOR, PATCH) \
176 typedef char tox_required_version[TOX_IS_COMPATIBLE(MAJOR, MINOR, PATCH) ? 1 : -1]
177
178/**
179 * Return the major version number of the library. Can be used to display the
180 * Tox library version or to check whether the client is compatible with the
181 * dynamically linked version of Tox.
182 */
183uint32_t tox_version_major(void);
184 184
185/** 185uint32_t tox_version_patch(void);
186 * Return the minor version number of the library.
187 */
188uint32_t tox_version_minor(void);
189 186
190/** 187/**
191 * Return the patch number of the library. 188 * A macro to check at preprocessing time whether the client code is compatible
192 */ 189 * with the installed version of Tox. Leading zeros in the version number are
193uint32_t tox_version_patch(void); 190 * ignored. E.g. 0.1.5 is to 0.1.4 what 1.5 is to 1.4, that is: it can add new
191 * features, but can't break the API.
192 */
193#define TOX_VERSION_IS_API_COMPATIBLE(MAJOR, MINOR, PATCH) \
194 ((TOX_VERSION_MAJOR > 0 && TOX_VERSION_MAJOR == MAJOR) && ( \
195 /* 1.x.x, 2.x.x, etc. with matching major version. */ \
196 TOX_VERSION_MINOR > MINOR || \
197 (TOX_VERSION_MINOR == MINOR && TOX_VERSION_PATCH >= PATCH) \
198 )) || ((TOX_VERSION_MAJOR == 0 && MAJOR == 0) && ( \
199 /* 0.x.x makes minor behave like major above. */ \
200 ((TOX_VERSION_MINOR > 0 && TOX_VERSION_MINOR == MINOR) && ( \
201 TOX_VERSION_PATCH >= PATCH \
202 )) || ((TOX_VERSION_MINOR == 0 && MINOR == 0) && ( \
203 /* 0.0.x and 0.0.y are only compatible if x == y. */ \
204 TOX_VERSION_PATCH == PATCH \
205 )) \
206 ))
194 207
195/** 208/**
196 * Return whether the compiled library version is compatible with the passed 209 * Return whether the compiled library version is compatible with the passed
@@ -210,6 +223,10 @@ bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch);
210 * 223 *
211 * :: Numeric constants 224 * :: Numeric constants
212 * 225 *
226 * The values of these are not part of the ABI. Prefer to use the function
227 * versions of them for code that should remain compatible with future versions
228 * of toxcore.
229 *
213 ******************************************************************************/ 230 ******************************************************************************/
214 231
215 232
@@ -219,11 +236,22 @@ bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch);
219 */ 236 */
220#define TOX_PUBLIC_KEY_SIZE 32 237#define TOX_PUBLIC_KEY_SIZE 32
221 238
239uint32_t tox_public_key_size(void);
240
222/** 241/**
223 * The size of a Tox Secret Key in bytes. 242 * The size of a Tox Secret Key in bytes.
224 */ 243 */
225#define TOX_SECRET_KEY_SIZE 32 244#define TOX_SECRET_KEY_SIZE 32
226 245
246uint32_t tox_secret_key_size(void);
247
248/**
249 * The size of the nospam in bytes when written in a Tox address.
250 */
251#define TOX_NOSPAM_SIZE (sizeof(uint32_t))
252
253uint32_t tox_nospam_size(void);
254
227/** 255/**
228 * The size of a Tox address in bytes. Tox addresses are in the format 256 * The size of a Tox address in bytes. Tox addresses are in the format
229 * [Public Key (TOX_PUBLIC_KEY_SIZE bytes)][nospam (4 bytes)][checksum (2 bytes)]. 257 * [Public Key (TOX_PUBLIC_KEY_SIZE bytes)][nospam (4 bytes)][checksum (2 bytes)].
@@ -232,48 +260,78 @@ bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch);
232 * byte is an XOR of all the even bytes (0, 2, 4, ...), the second byte is an 260 * byte is an XOR of all the even bytes (0, 2, 4, ...), the second byte is an
233 * XOR of all the odd bytes (1, 3, 5, ...) of the Public Key and nospam. 261 * XOR of all the odd bytes (1, 3, 5, ...) of the Public Key and nospam.
234 */ 262 */
235#define TOX_ADDRESS_SIZE (TOX_PUBLIC_KEY_SIZE + sizeof(uint32_t) + sizeof(uint16_t)) 263#define TOX_ADDRESS_SIZE (TOX_PUBLIC_KEY_SIZE + TOX_NOSPAM_SIZE + sizeof(uint16_t))
264
265uint32_t tox_address_size(void);
236 266
237/** 267/**
238 * Maximum length of a nickname in bytes. 268 * Maximum length of a nickname in bytes.
269 *
270 * @deprecated The macro will be removed in 0.3.0. Use the function instead.
239 */ 271 */
240#define TOX_MAX_NAME_LENGTH 128 272#define TOX_MAX_NAME_LENGTH 128
241 273
274uint32_t tox_max_name_length(void);
275
242/** 276/**
243 * Maximum length of a status message in bytes. 277 * Maximum length of a status message in bytes.
278 *
279 * @deprecated The macro will be removed in 0.3.0. Use the function instead.
244 */ 280 */
245#define TOX_MAX_STATUS_MESSAGE_LENGTH 1007 281#define TOX_MAX_STATUS_MESSAGE_LENGTH 1007
246 282
283uint32_t tox_max_status_message_length(void);
284
247/** 285/**
248 * Maximum length of a friend request message in bytes. 286 * Maximum length of a friend request message in bytes.
287 *
288 * @deprecated The macro will be removed in 0.3.0. Use the function instead.
249 */ 289 */
250#define TOX_MAX_FRIEND_REQUEST_LENGTH 1016 290#define TOX_MAX_FRIEND_REQUEST_LENGTH 1016
251 291
292uint32_t tox_max_friend_request_length(void);
293
252/** 294/**
253 * Maximum length of a single message after which it should be split. 295 * Maximum length of a single message after which it should be split.
296 *
297 * @deprecated The macro will be removed in 0.3.0. Use the function instead.
254 */ 298 */
255#define TOX_MAX_MESSAGE_LENGTH 1372 299#define TOX_MAX_MESSAGE_LENGTH 1372
256 300
301uint32_t tox_max_message_length(void);
302
257/** 303/**
258 * Maximum size of custom packets. TODO: should be LENGTH? 304 * Maximum size of custom packets. TODO(iphydf): should be LENGTH?
305 *
306 * @deprecated The macro will be removed in 0.3.0. Use the function instead.
259 */ 307 */
260#define TOX_MAX_CUSTOM_PACKET_SIZE 1373 308#define TOX_MAX_CUSTOM_PACKET_SIZE 1373
261 309
310uint32_t tox_max_custom_packet_size(void);
311
262/** 312/**
263 * The number of bytes in a hash generated by tox_hash. 313 * The number of bytes in a hash generated by tox_hash.
264 */ 314 */
265#define TOX_HASH_LENGTH 32 315#define TOX_HASH_LENGTH 32
266 316
317uint32_t tox_hash_length(void);
318
267/** 319/**
268 * The number of bytes in a file id. 320 * The number of bytes in a file id.
269 */ 321 */
270#define TOX_FILE_ID_LENGTH 32 322#define TOX_FILE_ID_LENGTH 32
271 323
324uint32_t tox_file_id_length(void);
325
272/** 326/**
273 * Maximum file name length for file transfers. 327 * Maximum file name length for file transfers.
328 *
329 * @deprecated The macro will be removed in 0.3.0. Use the function instead.
274 */ 330 */
275#define TOX_MAX_FILENAME_LENGTH 255 331#define TOX_MAX_FILENAME_LENGTH 255
276 332
333uint32_t tox_max_filename_length(void);
334
277 335
278/******************************************************************************* 336/*******************************************************************************
279 * 337 *
@@ -309,7 +367,7 @@ typedef enum TOX_USER_STATUS {
309 367
310 368
311/** 369/**
312 * Represents message types for tox_friend_send_message and group chat 370 * Represents message types for tox_friend_send_message and conference
313 * messages. 371 * messages.
314 */ 372 */
315typedef enum TOX_MESSAGE_TYPE { 373typedef enum TOX_MESSAGE_TYPE {
@@ -371,12 +429,12 @@ typedef enum TOX_SAVEDATA_TYPE {
371 TOX_SAVEDATA_TYPE_NONE, 429 TOX_SAVEDATA_TYPE_NONE,
372 430
373 /** 431 /**
374 * Savedata is one that was obtained from tox_get_savedata 432 * Savedata is one that was obtained from tox_get_savedata.
375 */ 433 */
376 TOX_SAVEDATA_TYPE_TOX_SAVE, 434 TOX_SAVEDATA_TYPE_TOX_SAVE,
377 435
378 /** 436 /**
379 * Savedata is a secret key of length TOX_SECRET_KEY_SIZE 437 * Savedata is a secret key of length TOX_SECRET_KEY_SIZE.
380 */ 438 */
381 TOX_SAVEDATA_TYPE_SECRET_KEY, 439 TOX_SAVEDATA_TYPE_SECRET_KEY,
382 440
@@ -384,9 +442,71 @@ typedef enum TOX_SAVEDATA_TYPE {
384 442
385 443
386/** 444/**
387 * This struct contains all the startup options for Tox. You can either allocate 445 * Severity level of log messages.
388 * this object yourself, and pass it to tox_options_default, or call 446 */
389 * tox_options_new to get a new default options object. 447typedef enum TOX_LOG_LEVEL {
448
449 /**
450 * Very detailed traces including all network activity.
451 */
452 TOX_LOG_LEVEL_TRACE,
453
454 /**
455 * Debug messages such as which port we bind to.
456 */
457 TOX_LOG_LEVEL_DEBUG,
458
459 /**
460 * Informational log messages such as video call status changes.
461 */
462 TOX_LOG_LEVEL_INFO,
463
464 /**
465 * Warnings about internal inconsistency or logic errors.
466 */
467 TOX_LOG_LEVEL_WARNING,
468
469 /**
470 * Severe unexpected errors caused by external or internal inconsistency.
471 */
472 TOX_LOG_LEVEL_ERROR,
473
474} TOX_LOG_LEVEL;
475
476
477/**
478 * This event is triggered when the toxcore library logs an internal message.
479 * This is mostly useful for debugging. This callback can be called from any
480 * function, not just tox_iterate. This means the user data lifetime must at
481 * least extend between registering and unregistering it or tox_kill.
482 *
483 * Other toxcore modules such as toxav may concurrently call this callback at
484 * any time. Thus, user code must make sure it is equipped to handle concurrent
485 * execution, e.g. by employing appropriate mutex locking.
486 *
487 * @param level The severity of the log message.
488 * @param file The source file from which the message originated.
489 * @param line The source line from which the message originated.
490 * @param func The function from which the message originated.
491 * @param message The log message.
492 * @param user_data The user data pointer passed to tox_new in options.
493 */
494typedef void tox_log_cb(Tox *tox, TOX_LOG_LEVEL level, const char *file, uint32_t line, const char *func,
495 const char *message, void *user_data);
496
497
498/**
499 * This struct contains all the startup options for Tox. You must tox_options_new to
500 * allocate an object of this type.
501 *
502 * WARNING: Although this struct happens to be visible in the API, it is
503 * effectively private. Do not allocate this yourself or access members
504 * directly, as it *will* break binary compatibility frequently.
505 *
506 * @deprecated The memory layout of this struct (size, alignment, and field
507 * order) is not part of the ABI. To remain compatible, prefer to use tox_options_new to
508 * allocate the object and accessor functions to set the members. The struct
509 * will become opaque (i.e. the definition will become private) in v0.3.0.
390 */ 510 */
391struct Tox_Options { 511struct Tox_Options {
392 512
@@ -412,6 +532,14 @@ struct Tox_Options {
412 532
413 533
414 /** 534 /**
535 * Enable local network peer discovery.
536 *
537 * Disabling this will cause Tox to not look for peers on the local network.
538 */
539 bool local_discovery_enabled;
540
541
542 /**
415 * Pass communications through a proxy. 543 * Pass communications through a proxy.
416 */ 544 */
417 TOX_PROXY_TYPE proxy_type; 545 TOX_PROXY_TYPE proxy_type;
@@ -425,6 +553,9 @@ struct Tox_Options {
425 * (255 chars + 1 NUL byte). 553 * (255 chars + 1 NUL byte).
426 * 554 *
427 * This member is ignored (it can be NULL) if proxy_type is TOX_PROXY_TYPE_NONE. 555 * This member is ignored (it can be NULL) if proxy_type is TOX_PROXY_TYPE_NONE.
556 *
557 * The data pointed at by this member is owned by the user, so must
558 * outlive the options object.
428 */ 559 */
429 const char *proxy_host; 560 const char *proxy_host;
430 561
@@ -474,6 +605,12 @@ struct Tox_Options {
474 605
475 606
476 /** 607 /**
608 * Enables or disables UDP hole-punching in toxcore. (Default: enabled).
609 */
610 bool hole_punching_enabled;
611
612
613 /**
477 * The type of savedata to load from. 614 * The type of savedata to load from.
478 */ 615 */
479 TOX_SAVEDATA_TYPE savedata_type; 616 TOX_SAVEDATA_TYPE savedata_type;
@@ -481,6 +618,9 @@ struct Tox_Options {
481 618
482 /** 619 /**
483 * The savedata. 620 * The savedata.
621 *
622 * The data pointed at by this member is owned by the user, so must
623 * outlive the options object.
484 */ 624 */
485 const uint8_t *savedata_data; 625 const uint8_t *savedata_data;
486 626
@@ -490,9 +630,81 @@ struct Tox_Options {
490 */ 630 */
491 size_t savedata_length; 631 size_t savedata_length;
492 632
633
634 /**
635 * Logging callback for the new tox instance.
636 */
637 tox_log_cb *log_callback;
638
639
640 /**
641 * User data pointer passed to the logging callback.
642 */
643 void *log_user_data;
644
493}; 645};
494 646
495 647
648bool tox_options_get_ipv6_enabled(const struct Tox_Options *options);
649
650void tox_options_set_ipv6_enabled(struct Tox_Options *options, bool ipv6_enabled);
651
652bool tox_options_get_udp_enabled(const struct Tox_Options *options);
653
654void tox_options_set_udp_enabled(struct Tox_Options *options, bool udp_enabled);
655
656bool tox_options_get_local_discovery_enabled(const struct Tox_Options *options);
657
658void tox_options_set_local_discovery_enabled(struct Tox_Options *options, bool local_discovery_enabled);
659
660TOX_PROXY_TYPE tox_options_get_proxy_type(const struct Tox_Options *options);
661
662void tox_options_set_proxy_type(struct Tox_Options *options, TOX_PROXY_TYPE type);
663
664const char *tox_options_get_proxy_host(const struct Tox_Options *options);
665
666void tox_options_set_proxy_host(struct Tox_Options *options, const char *host);
667
668uint16_t tox_options_get_proxy_port(const struct Tox_Options *options);
669
670void tox_options_set_proxy_port(struct Tox_Options *options, uint16_t port);
671
672uint16_t tox_options_get_start_port(const struct Tox_Options *options);
673
674void tox_options_set_start_port(struct Tox_Options *options, uint16_t start_port);
675
676uint16_t tox_options_get_end_port(const struct Tox_Options *options);
677
678void tox_options_set_end_port(struct Tox_Options *options, uint16_t end_port);
679
680uint16_t tox_options_get_tcp_port(const struct Tox_Options *options);
681
682void tox_options_set_tcp_port(struct Tox_Options *options, uint16_t tcp_port);
683
684bool tox_options_get_hole_punching_enabled(const struct Tox_Options *options);
685
686void tox_options_set_hole_punching_enabled(struct Tox_Options *options, bool hole_punching_enabled);
687
688TOX_SAVEDATA_TYPE tox_options_get_savedata_type(const struct Tox_Options *options);
689
690void tox_options_set_savedata_type(struct Tox_Options *options, TOX_SAVEDATA_TYPE type);
691
692const uint8_t *tox_options_get_savedata_data(const struct Tox_Options *options);
693
694void tox_options_set_savedata_data(struct Tox_Options *options, const uint8_t *data, size_t length);
695
696size_t tox_options_get_savedata_length(const struct Tox_Options *options);
697
698void tox_options_set_savedata_length(struct Tox_Options *options, size_t length);
699
700tox_log_cb *tox_options_get_log_callback(const struct Tox_Options *options);
701
702void tox_options_set_log_callback(struct Tox_Options *options, tox_log_cb *callback);
703
704void *tox_options_get_log_user_data(const struct Tox_Options *options);
705
706void tox_options_set_log_user_data(struct Tox_Options *options, void *user_data);
707
496/** 708/**
497 * Initialises a Tox_Options object with the default options. 709 * Initialises a Tox_Options object with the default options.
498 * 710 *
@@ -651,8 +863,8 @@ size_t tox_get_savedata_size(const Tox *tox);
651/** 863/**
652 * Store all information associated with the tox instance to a byte array. 864 * Store all information associated with the tox instance to a byte array.
653 * 865 *
654 * @param data A memory region large enough to store the tox instance data. 866 * @param savedata A memory region large enough to store the tox instance
655 * Call tox_get_savedata_size to find the number of bytes required. If this parameter 867 * data. Call tox_get_savedata_size to find the number of bytes required. If this parameter
656 * is NULL, this function has no effect. 868 * is NULL, this function has no effect.
657 */ 869 */
658void tox_get_savedata(const Tox *tox, uint8_t *savedata); 870void tox_get_savedata(const Tox *tox, uint8_t *savedata);
@@ -756,6 +968,9 @@ typedef enum TOX_CONNECTION {
756/** 968/**
757 * Return whether we are connected to the DHT. The return value is equal to the 969 * Return whether we are connected to the DHT. The return value is equal to the
758 * last value received through the `self_connection_status` callback. 970 * last value received through the `self_connection_status` callback.
971 *
972 * @deprecated This getter is deprecated. Use the event and store the status
973 * in the client state.
759 */ 974 */
760TOX_CONNECTION tox_self_get_connection_status(const Tox *tox); 975TOX_CONNECTION tox_self_get_connection_status(const Tox *tox);
761 976
@@ -774,9 +989,9 @@ typedef void tox_self_connection_status_cb(Tox *tox, TOX_CONNECTION connection_s
774 * amounts of time. Clients should therefore not immediately bootstrap on 989 * amounts of time. Clients should therefore not immediately bootstrap on
775 * receiving a disconnect. 990 * receiving a disconnect.
776 * 991 *
777 * TODO: how long should a client wait before bootstrapping again? 992 * TODO(iphydf): how long should a client wait before bootstrapping again?
778 */ 993 */
779void tox_callback_self_connection_status(Tox *tox, tox_self_connection_status_cb *callback, void *user_data); 994void tox_callback_self_connection_status(Tox *tox, tox_self_connection_status_cb *callback);
780 995
781/** 996/**
782 * Return the time in milliseconds before tox_iterate() should be called again 997 * Return the time in milliseconds before tox_iterate() should be called again
@@ -788,7 +1003,7 @@ uint32_t tox_iteration_interval(const Tox *tox);
788 * The main loop that needs to be run in intervals of tox_iteration_interval() 1003 * The main loop that needs to be run in intervals of tox_iteration_interval()
789 * milliseconds. 1004 * milliseconds.
790 */ 1005 */
791void tox_iterate(Tox *tox); 1006void tox_iterate(Tox *tox, void *user_data);
792 1007
793 1008
794/******************************************************************************* 1009/*******************************************************************************
@@ -811,14 +1026,17 @@ void tox_iterate(Tox *tox);
811void tox_self_get_address(const Tox *tox, uint8_t *address); 1026void tox_self_get_address(const Tox *tox, uint8_t *address);
812 1027
813/** 1028/**
814 * Set the 4-byte nospam part of the address. 1029 * Set the 4-byte nospam part of the address. This value is expected in host
1030 * byte order. I.e. 0x12345678 will form the bytes [12, 34, 56, 78] in the
1031 * nospam part of the Tox friend address.
815 * 1032 *
816 * @param nospam Any 32 bit unsigned integer. 1033 * @param nospam Any 32 bit unsigned integer.
817 */ 1034 */
818void tox_self_set_nospam(Tox *tox, uint32_t nospam); 1035void tox_self_set_nospam(Tox *tox, uint32_t nospam);
819 1036
820/** 1037/**
821 * Get the 4-byte nospam part of the address. 1038 * Get the 4-byte nospam part of the address. This value is returned in host
1039 * byte order.
822 */ 1040 */
823uint32_t tox_self_get_nospam(const Tox *tox); 1041uint32_t tox_self_get_nospam(const Tox *tox);
824 1042
@@ -936,15 +1154,15 @@ size_t tox_self_get_status_message_size(const Tox *tox);
936 * Call tox_self_get_status_message_size to find out how much memory to allocate for 1154 * Call tox_self_get_status_message_size to find out how much memory to allocate for
937 * the result. 1155 * the result.
938 * 1156 *
939 * @param status A valid memory location large enough to hold the status message. 1157 * @param status_message A valid memory location large enough to hold the
940 * If this parameter is NULL, the function has no effect. 1158 * status message. If this parameter is NULL, the function has no effect.
941 */ 1159 */
942void tox_self_get_status_message(const Tox *tox, uint8_t *status_message); 1160void tox_self_get_status_message(const Tox *tox, uint8_t *status_message);
943 1161
944/** 1162/**
945 * Set the client's user status. 1163 * Set the client's user status.
946 * 1164 *
947 * @param user_status One of the user statuses listed in the enumeration above. 1165 * @param status One of the user statuses listed in the enumeration above.
948 */ 1166 */
949void tox_self_set_status(Tox *tox, TOX_USER_STATUS status); 1167void tox_self_set_status(Tox *tox, TOX_USER_STATUS status);
950 1168
@@ -1145,8 +1363,8 @@ size_t tox_self_get_friend_list_size(const Tox *tox);
1145 * 1363 *
1146 * Call tox_self_get_friend_list_size to determine the number of elements to allocate. 1364 * Call tox_self_get_friend_list_size to determine the number of elements to allocate.
1147 * 1365 *
1148 * @param list A memory region with enough space to hold the friend list. If 1366 * @param friend_list A memory region with enough space to hold the friend
1149 * this parameter is NULL, this function has no effect. 1367 * list. If this parameter is NULL, this function has no effect.
1150 */ 1368 */
1151void tox_self_get_friend_list(const Tox *tox, uint32_t *friend_list); 1369void tox_self_get_friend_list(const Tox *tox, uint32_t *friend_list);
1152 1370
@@ -1274,7 +1492,7 @@ typedef void tox_friend_name_cb(Tox *tox, uint32_t friend_number, const uint8_t
1274 * 1492 *
1275 * This event is triggered when a friend changes their name. 1493 * This event is triggered when a friend changes their name.
1276 */ 1494 */
1277void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *callback, void *user_data); 1495void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *callback);
1278 1496
1279/** 1497/**
1280 * Return the length of the friend's status message. If the friend number is 1498 * Return the length of the friend's status message. If the friend number is
@@ -1314,7 +1532,7 @@ typedef void tox_friend_status_message_cb(Tox *tox, uint32_t friend_number, cons
1314 * 1532 *
1315 * This event is triggered when a friend changes their status message. 1533 * This event is triggered when a friend changes their status message.
1316 */ 1534 */
1317void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *callback, void *user_data); 1535void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *callback);
1318 1536
1319/** 1537/**
1320 * Return the friend's user status (away/busy/...). If the friend number is 1538 * Return the friend's user status (away/busy/...). If the friend number is
@@ -1322,6 +1540,9 @@ void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *
1322 * 1540 *
1323 * The status returned is equal to the last status received through the 1541 * The status returned is equal to the last status received through the
1324 * `friend_status` callback. 1542 * `friend_status` callback.
1543 *
1544 * @deprecated This getter is deprecated. Use the event and store the status
1545 * in the client state.
1325 */ 1546 */
1326TOX_USER_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); 1547TOX_USER_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error);
1327 1548
@@ -1338,7 +1559,7 @@ typedef void tox_friend_status_cb(Tox *tox, uint32_t friend_number, TOX_USER_STA
1338 * 1559 *
1339 * This event is triggered when a friend changes their user status. 1560 * This event is triggered when a friend changes their user status.
1340 */ 1561 */
1341void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *callback, void *user_data); 1562void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *callback);
1342 1563
1343/** 1564/**
1344 * Check whether a friend is currently connected to this client. 1565 * Check whether a friend is currently connected to this client.
@@ -1351,6 +1572,9 @@ void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *callback, void *
1351 * 1572 *
1352 * @return the friend's connection status as it was received through the 1573 * @return the friend's connection status as it was received through the
1353 * `friend_connection_status` event. 1574 * `friend_connection_status` event.
1575 *
1576 * @deprecated This getter is deprecated. Use the event and store the status
1577 * in the client state.
1354 */ 1578 */
1355TOX_CONNECTION tox_friend_get_connection_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); 1579TOX_CONNECTION tox_friend_get_connection_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error);
1356 1580
@@ -1373,7 +1597,7 @@ typedef void tox_friend_connection_status_cb(Tox *tox, uint32_t friend_number, T
1373 * This callback is not called when adding friends. It is assumed that when 1597 * This callback is not called when adding friends. It is assumed that when
1374 * adding friends, their connection status is initially offline. 1598 * adding friends, their connection status is initially offline.
1375 */ 1599 */
1376void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_status_cb *callback, void *user_data); 1600void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_status_cb *callback);
1377 1601
1378/** 1602/**
1379 * Check whether a friend is currently typing a message. 1603 * Check whether a friend is currently typing a message.
@@ -1383,6 +1607,9 @@ void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_statu
1383 * @return true if the friend is typing. 1607 * @return true if the friend is typing.
1384 * @return false if the friend is not typing, or the friend number was 1608 * @return false if the friend is not typing, or the friend number was
1385 * invalid. Inspect the error code to determine which case it is. 1609 * invalid. Inspect the error code to determine which case it is.
1610 *
1611 * @deprecated This getter is deprecated. Use the event and store the status
1612 * in the client state.
1386 */ 1613 */
1387bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); 1614bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error);
1388 1615
@@ -1400,7 +1627,7 @@ typedef void tox_friend_typing_cb(Tox *tox, uint32_t friend_number, bool is_typi
1400 * 1627 *
1401 * This event is triggered when a friend starts or stops typing. 1628 * This event is triggered when a friend starts or stops typing.
1402 */ 1629 */
1403void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *callback, void *user_data); 1630void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *callback);
1404 1631
1405 1632
1406/******************************************************************************* 1633/*******************************************************************************
@@ -1518,7 +1745,7 @@ typedef void tox_friend_read_receipt_cb(Tox *tox, uint32_t friend_number, uint32
1518 * This event is triggered when the friend receives the message sent with 1745 * This event is triggered when the friend receives the message sent with
1519 * tox_friend_send_message with the corresponding message ID. 1746 * tox_friend_send_message with the corresponding message ID.
1520 */ 1747 */
1521void tox_callback_friend_read_receipt(Tox *tox, tox_friend_read_receipt_cb *callback, void *user_data); 1748void tox_callback_friend_read_receipt(Tox *tox, tox_friend_read_receipt_cb *callback);
1522 1749
1523 1750
1524/******************************************************************************* 1751/*******************************************************************************
@@ -1531,11 +1758,6 @@ void tox_callback_friend_read_receipt(Tox *tox, tox_friend_read_receipt_cb *call
1531 1758
1532/** 1759/**
1533 * @param public_key The Public Key of the user who sent the friend request. 1760 * @param public_key The Public Key of the user who sent the friend request.
1534 * @param time_delta A delta in seconds between when the message was composed
1535 * and when it is being transmitted. For messages that are sent immediately,
1536 * it will be 0. If a message was written and couldn't be sent immediately
1537 * (due to a connection failure, for example), the time_delta is an
1538 * approximation of when it was composed.
1539 * @param message The message they sent along with the request. 1761 * @param message The message they sent along with the request.
1540 * @param length The size of the message byte array. 1762 * @param length The size of the message byte array.
1541 */ 1763 */
@@ -1548,15 +1770,12 @@ typedef void tox_friend_request_cb(Tox *tox, const uint8_t *public_key, const ui
1548 * 1770 *
1549 * This event is triggered when a friend request is received. 1771 * This event is triggered when a friend request is received.
1550 */ 1772 */
1551void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *callback, void *user_data); 1773void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *callback);
1552 1774
1553/** 1775/**
1554 * @param friend_number The friend number of the friend who sent the message. 1776 * @param friend_number The friend number of the friend who sent the message.
1555 * @param time_delta Time between composition and sending.
1556 * @param message The message data they sent. 1777 * @param message The message data they sent.
1557 * @param length The size of the message byte array. 1778 * @param length The size of the message byte array.
1558 *
1559 * @see friend_request for more information on time_delta.
1560 */ 1779 */
1561typedef void tox_friend_message_cb(Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type, const uint8_t *message, 1780typedef void tox_friend_message_cb(Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type, const uint8_t *message,
1562 size_t length, void *user_data); 1781 size_t length, void *user_data);
@@ -1567,7 +1786,7 @@ typedef void tox_friend_message_cb(Tox *tox, uint32_t friend_number, TOX_MESSAGE
1567 * 1786 *
1568 * This event is triggered when a message from a friend is received. 1787 * This event is triggered when a message from a friend is received.
1569 */ 1788 */
1570void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *callback, void *user_data); 1789void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *callback);
1571 1790
1572 1791
1573/******************************************************************************* 1792/*******************************************************************************
@@ -1735,7 +1954,7 @@ typedef void tox_file_recv_control_cb(Tox *tox, uint32_t friend_number, uint32_t
1735 * This event is triggered when a file control command is received from a 1954 * This event is triggered when a file control command is received from a
1736 * friend. 1955 * friend.
1737 */ 1956 */
1738void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *callback, void *user_data); 1957void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *callback);
1739 1958
1740typedef enum TOX_ERR_FILE_SEEK { 1959typedef enum TOX_ERR_FILE_SEEK {
1741 1960
@@ -2039,7 +2258,7 @@ typedef void tox_file_chunk_request_cb(Tox *tox, uint32_t friend_number, uint32_
2039 * 2258 *
2040 * This event is triggered when Core is ready to send more file data. 2259 * This event is triggered when Core is ready to send more file data.
2041 */ 2260 */
2042void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *callback, void *user_data); 2261void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *callback);
2043 2262
2044 2263
2045/******************************************************************************* 2264/*******************************************************************************
@@ -2077,7 +2296,7 @@ typedef void tox_file_recv_cb(Tox *tox, uint32_t friend_number, uint32_t file_nu
2077 * 2296 *
2078 * This event is triggered when a file transfer request is received. 2297 * This event is triggered when a file transfer request is received.
2079 */ 2298 */
2080void tox_callback_file_recv(Tox *tox, tox_file_recv_cb *callback, void *user_data); 2299void tox_callback_file_recv(Tox *tox, tox_file_recv_cb *callback);
2081 2300
2082/** 2301/**
2083 * When length is 0, the transfer is finished and the client should release the 2302 * When length is 0, the transfer is finished and the client should release the
@@ -2105,25 +2324,462 @@ typedef void tox_file_recv_chunk_cb(Tox *tox, uint32_t friend_number, uint32_t f
2105 * This event is first triggered when a file transfer request is received, and 2324 * This event is first triggered when a file transfer request is received, and
2106 * subsequently when a chunk of file data for an accepted request was received. 2325 * subsequently when a chunk of file data for an accepted request was received.
2107 */ 2326 */
2108void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *callback, void *user_data); 2327void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *callback);
2109 2328
2110 2329
2111/******************************************************************************* 2330/*******************************************************************************
2112 * 2331 *
2113 * :: Group chat management 2332 * :: Conference management
2114 * 2333 *
2115 ******************************************************************************/ 2334 ******************************************************************************/
2116 2335
2117 2336
2118 2337
2338/**
2339 * Conference types for the conference_invite event.
2340 */
2341typedef enum TOX_CONFERENCE_TYPE {
2119 2342
2120/******************************************************************************* 2343 /**
2344 * Text-only conferences that must be accepted with the tox_conference_join function.
2345 */
2346 TOX_CONFERENCE_TYPE_TEXT,
2347
2348 /**
2349 * Video conference. The function to accept these is in toxav.
2350 */
2351 TOX_CONFERENCE_TYPE_AV,
2352
2353} TOX_CONFERENCE_TYPE;
2354
2355
2356/**
2357 * The invitation will remain valid until the inviting friend goes offline
2358 * or exits the conference.
2121 * 2359 *
2122 * :: Group chat message sending and receiving 2360 * @param friend_number The friend who invited us.
2361 * @param type The conference type (text only or audio/video).
2362 * @param cookie A piece of data of variable length required to join the
2363 * conference.
2364 * @param length The length of the cookie.
2365 */
2366typedef void tox_conference_invite_cb(Tox *tox, uint32_t friend_number, TOX_CONFERENCE_TYPE type, const uint8_t *cookie,
2367 size_t length, void *user_data);
2368
2369
2370/**
2371 * Set the callback for the `conference_invite` event. Pass NULL to unset.
2123 * 2372 *
2124 ******************************************************************************/ 2373 * This event is triggered when the client is invited to join a conference.
2374 */
2375void tox_callback_conference_invite(Tox *tox, tox_conference_invite_cb *callback);
2376
2377/**
2378 * @param conference_number The conference number of the conference the message is intended for.
2379 * @param peer_number The ID of the peer who sent the message.
2380 * @param type The type of message (normal, action, ...).
2381 * @param message The message data.
2382 * @param length The length of the message.
2383 */
2384typedef void tox_conference_message_cb(Tox *tox, uint32_t conference_number, uint32_t peer_number,
2385 TOX_MESSAGE_TYPE type, const uint8_t *message, size_t length, void *user_data);
2386
2387
2388/**
2389 * Set the callback for the `conference_message` event. Pass NULL to unset.
2390 *
2391 * This event is triggered when the client receives a conference message.
2392 */
2393void tox_callback_conference_message(Tox *tox, tox_conference_message_cb *callback);
2394
2395/**
2396 * @param conference_number The conference number of the conference the title change is intended for.
2397 * @param peer_number The ID of the peer who changed the title.
2398 * @param title The title data.
2399 * @param length The title length.
2400 */
2401typedef void tox_conference_title_cb(Tox *tox, uint32_t conference_number, uint32_t peer_number, const uint8_t *title,
2402 size_t length, void *user_data);
2403
2404
2405/**
2406 * Set the callback for the `conference_title` event. Pass NULL to unset.
2407 *
2408 * This event is triggered when a peer changes the conference title.
2409 *
2410 * If peer_number == UINT32_MAX, then author is unknown (e.g. initial joining the conference).
2411 */
2412void tox_callback_conference_title(Tox *tox, tox_conference_title_cb *callback);
2413
2414/**
2415 * @param conference_number The conference number of the conference the
2416 * peer is in.
2417 * @param peer_number The ID of the peer who changed their nickname.
2418 * @param name A byte array containing the new nickname.
2419 * @param length The size of the name byte array.
2420 */
2421typedef void tox_conference_peer_name_cb(Tox *tox, uint32_t conference_number, uint32_t peer_number,
2422 const uint8_t *name, size_t length, void *user_data);
2423
2424
2425/**
2426 * Set the callback for the `conference_peer_name` event. Pass NULL to unset.
2427 *
2428 * This event is triggered when a peer changes their name.
2429 */
2430void tox_callback_conference_peer_name(Tox *tox, tox_conference_peer_name_cb *callback);
2431
2432/**
2433 * @param conference_number The conference number of the conference the
2434 * peer is in.
2435 */
2436typedef void tox_conference_peer_list_changed_cb(Tox *tox, uint32_t conference_number, void *user_data);
2437
2438
2439/**
2440 * Set the callback for the `conference_peer_list_changed` event. Pass NULL to unset.
2441 *
2442 * This event is triggered when a peer joins or leaves the conference.
2443 */
2444void tox_callback_conference_peer_list_changed(Tox *tox, tox_conference_peer_list_changed_cb *callback);
2445
2446typedef enum TOX_ERR_CONFERENCE_NEW {
2447
2448 /**
2449 * The function returned successfully.
2450 */
2451 TOX_ERR_CONFERENCE_NEW_OK,
2452
2453 /**
2454 * The conference instance failed to initialize.
2455 */
2456 TOX_ERR_CONFERENCE_NEW_INIT,
2457
2458} TOX_ERR_CONFERENCE_NEW;
2459
2460
2461/**
2462 * Creates a new conference.
2463 *
2464 * This function creates a new text conference.
2465 *
2466 * @return conference number on success, or UINT32_MAX on failure.
2467 */
2468uint32_t tox_conference_new(Tox *tox, TOX_ERR_CONFERENCE_NEW *error);
2469
2470typedef enum TOX_ERR_CONFERENCE_DELETE {
2471
2472 /**
2473 * The function returned successfully.
2474 */
2475 TOX_ERR_CONFERENCE_DELETE_OK,
2476
2477 /**
2478 * The conference number passed did not designate a valid conference.
2479 */
2480 TOX_ERR_CONFERENCE_DELETE_CONFERENCE_NOT_FOUND,
2481
2482} TOX_ERR_CONFERENCE_DELETE;
2483
2484
2485/**
2486 * This function deletes a conference.
2487 *
2488 * @param conference_number The conference number of the conference to be deleted.
2489 *
2490 * @return true on success.
2491 */
2492bool tox_conference_delete(Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_DELETE *error);
2493
2494/**
2495 * Error codes for peer info queries.
2496 */
2497typedef enum TOX_ERR_CONFERENCE_PEER_QUERY {
2498
2499 /**
2500 * The function returned successfully.
2501 */
2502 TOX_ERR_CONFERENCE_PEER_QUERY_OK,
2503
2504 /**
2505 * The conference number passed did not designate a valid conference.
2506 */
2507 TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND,
2508
2509 /**
2510 * The peer number passed did not designate a valid peer.
2511 */
2512 TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND,
2513
2514 /**
2515 * The client is not connected to the conference.
2516 */
2517 TOX_ERR_CONFERENCE_PEER_QUERY_NO_CONNECTION,
2518
2519} TOX_ERR_CONFERENCE_PEER_QUERY;
2520
2521
2522/**
2523 * Return the number of peers in the conference. Return value is unspecified on failure.
2524 */
2525uint32_t tox_conference_peer_count(const Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_PEER_QUERY *error);
2526
2527/**
2528 * Return the length of the peer's name. Return value is unspecified on failure.
2529 */
2530size_t tox_conference_peer_get_name_size(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
2531 TOX_ERR_CONFERENCE_PEER_QUERY *error);
2532
2533/**
2534 * Copy the name of peer_number who is in conference_number to name.
2535 * name must be at least TOX_MAX_NAME_LENGTH long.
2536 *
2537 * @return true on success.
2538 */
2539bool tox_conference_peer_get_name(const Tox *tox, uint32_t conference_number, uint32_t peer_number, uint8_t *name,
2540 TOX_ERR_CONFERENCE_PEER_QUERY *error);
2541
2542/**
2543 * Copy the public key of peer_number who is in conference_number to public_key.
2544 * public_key must be TOX_PUBLIC_KEY_SIZE long.
2545 *
2546 * @return true on success.
2547 */
2548bool tox_conference_peer_get_public_key(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
2549 uint8_t *public_key, TOX_ERR_CONFERENCE_PEER_QUERY *error);
2550
2551/**
2552 * Return true if passed peer_number corresponds to our own.
2553 */
2554bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
2555 TOX_ERR_CONFERENCE_PEER_QUERY *error);
2556
2557typedef enum TOX_ERR_CONFERENCE_INVITE {
2558
2559 /**
2560 * The function returned successfully.
2561 */
2562 TOX_ERR_CONFERENCE_INVITE_OK,
2563
2564 /**
2565 * The conference number passed did not designate a valid conference.
2566 */
2567 TOX_ERR_CONFERENCE_INVITE_CONFERENCE_NOT_FOUND,
2568
2569 /**
2570 * The invite packet failed to send.
2571 */
2572 TOX_ERR_CONFERENCE_INVITE_FAIL_SEND,
2573
2574} TOX_ERR_CONFERENCE_INVITE;
2575
2576
2577/**
2578 * Invites a friend to a conference.
2579 *
2580 * @param friend_number The friend number of the friend we want to invite.
2581 * @param conference_number The conference number of the conference we want to invite the friend to.
2582 *
2583 * @return true on success.
2584 */
2585bool tox_conference_invite(Tox *tox, uint32_t friend_number, uint32_t conference_number,
2586 TOX_ERR_CONFERENCE_INVITE *error);
2587
2588typedef enum TOX_ERR_CONFERENCE_JOIN {
2589
2590 /**
2591 * The function returned successfully.
2592 */
2593 TOX_ERR_CONFERENCE_JOIN_OK,
2594
2595 /**
2596 * The cookie passed has an invalid length.
2597 */
2598 TOX_ERR_CONFERENCE_JOIN_INVALID_LENGTH,
2599
2600 /**
2601 * The conference is not the expected type. This indicates an invalid cookie.
2602 */
2603 TOX_ERR_CONFERENCE_JOIN_WRONG_TYPE,
2604
2605 /**
2606 * The friend number passed does not designate a valid friend.
2607 */
2608 TOX_ERR_CONFERENCE_JOIN_FRIEND_NOT_FOUND,
2609
2610 /**
2611 * Client is already in this conference.
2612 */
2613 TOX_ERR_CONFERENCE_JOIN_DUPLICATE,
2614
2615 /**
2616 * Conference instance failed to initialize.
2617 */
2618 TOX_ERR_CONFERENCE_JOIN_INIT_FAIL,
2619
2620 /**
2621 * The join packet failed to send.
2622 */
2623 TOX_ERR_CONFERENCE_JOIN_FAIL_SEND,
2624
2625} TOX_ERR_CONFERENCE_JOIN;
2626
2627
2628/**
2629 * Joins a conference that the client has been invited to.
2630 *
2631 * @param friend_number The friend number of the friend who sent the invite.
2632 * @param cookie Received via the `conference_invite` event.
2633 * @param length The size of cookie.
2634 *
2635 * @return conference number on success, UINT32_MAX on failure.
2636 */
2637uint32_t tox_conference_join(Tox *tox, uint32_t friend_number, const uint8_t *cookie, size_t length,
2638 TOX_ERR_CONFERENCE_JOIN *error);
2639
2640typedef enum TOX_ERR_CONFERENCE_SEND_MESSAGE {
2641
2642 /**
2643 * The function returned successfully.
2644 */
2645 TOX_ERR_CONFERENCE_SEND_MESSAGE_OK,
2646
2647 /**
2648 * The conference number passed did not designate a valid conference.
2649 */
2650 TOX_ERR_CONFERENCE_SEND_MESSAGE_CONFERENCE_NOT_FOUND,
2651
2652 /**
2653 * The message is too long.
2654 */
2655 TOX_ERR_CONFERENCE_SEND_MESSAGE_TOO_LONG,
2656
2657 /**
2658 * The client is not connected to the conference.
2659 */
2660 TOX_ERR_CONFERENCE_SEND_MESSAGE_NO_CONNECTION,
2125 2661
2662 /**
2663 * The message packet failed to send.
2664 */
2665 TOX_ERR_CONFERENCE_SEND_MESSAGE_FAIL_SEND,
2126 2666
2667} TOX_ERR_CONFERENCE_SEND_MESSAGE;
2668
2669
2670/**
2671 * Send a text chat message to the conference.
2672 *
2673 * This function creates a conference message packet and pushes it into the send
2674 * queue.
2675 *
2676 * The message length may not exceed TOX_MAX_MESSAGE_LENGTH. Larger messages
2677 * must be split by the client and sent as separate messages. Other clients can
2678 * then reassemble the fragments.
2679 *
2680 * @param conference_number The conference number of the conference the message is intended for.
2681 * @param type Message type (normal, action, ...).
2682 * @param message A non-NULL pointer to the first element of a byte array
2683 * containing the message text.
2684 * @param length Length of the message to be sent.
2685 *
2686 * @return true on success.
2687 */
2688bool tox_conference_send_message(Tox *tox, uint32_t conference_number, TOX_MESSAGE_TYPE type, const uint8_t *message,
2689 size_t length, TOX_ERR_CONFERENCE_SEND_MESSAGE *error);
2690
2691typedef enum TOX_ERR_CONFERENCE_TITLE {
2692
2693 /**
2694 * The function returned successfully.
2695 */
2696 TOX_ERR_CONFERENCE_TITLE_OK,
2697
2698 /**
2699 * The conference number passed did not designate a valid conference.
2700 */
2701 TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND,
2702
2703 /**
2704 * The title is too long or empty.
2705 */
2706 TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH,
2707
2708 /**
2709 * The title packet failed to send.
2710 */
2711 TOX_ERR_CONFERENCE_TITLE_FAIL_SEND,
2712
2713} TOX_ERR_CONFERENCE_TITLE;
2714
2715
2716/**
2717 * Return the length of the conference title. Return value is unspecified on failure.
2718 *
2719 * The return value is equal to the `length` argument received by the last
2720 * `conference_title` callback.
2721 */
2722size_t tox_conference_get_title_size(const Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_TITLE *error);
2723
2724/**
2725 * Write the title designated by the given conference number to a byte array.
2726 *
2727 * Call tox_conference_get_title_size to determine the allocation size for the `title` parameter.
2728 *
2729 * The data written to `title` is equal to the data received by the last
2730 * `conference_title` callback.
2731 *
2732 * @param title A valid memory region large enough to store the title.
2733 * If this parameter is NULL, this function has no effect.
2734 *
2735 * @return true on success.
2736 */
2737bool tox_conference_get_title(const Tox *tox, uint32_t conference_number, uint8_t *title,
2738 TOX_ERR_CONFERENCE_TITLE *error);
2739
2740/**
2741 * Set the conference title and broadcast it to the rest of the conference.
2742 *
2743 * Title length cannot be longer than TOX_MAX_NAME_LENGTH.
2744 *
2745 * @return true on success.
2746 */
2747bool tox_conference_set_title(Tox *tox, uint32_t conference_number, const uint8_t *title, size_t length,
2748 TOX_ERR_CONFERENCE_TITLE *error);
2749
2750/**
2751 * Return the number of conferences in the Tox instance.
2752 * This should be used to determine how much memory to allocate for `tox_conference_get_chatlist`.
2753 */
2754size_t tox_conference_get_chatlist_size(const Tox *tox);
2755
2756/**
2757 * Copy a list of valid conference IDs into the array chatlist. Determine how much space
2758 * to allocate for the array with the `tox_conference_get_chatlist_size` function.
2759 */
2760void tox_conference_get_chatlist(const Tox *tox, uint32_t *chatlist);
2761
2762/**
2763 * Returns the type of conference (TOX_CONFERENCE_TYPE) that conference_number is. Return value is
2764 * unspecified on failure.
2765 */
2766typedef enum TOX_ERR_CONFERENCE_GET_TYPE {
2767
2768 /**
2769 * The function returned successfully.
2770 */
2771 TOX_ERR_CONFERENCE_GET_TYPE_OK,
2772
2773 /**
2774 * The conference number passed did not designate a valid conference.
2775 */
2776 TOX_ERR_CONFERENCE_GET_TYPE_CONFERENCE_NOT_FOUND,
2777
2778} TOX_ERR_CONFERENCE_GET_TYPE;
2779
2780
2781TOX_CONFERENCE_TYPE tox_conference_get_type(const Tox *tox, uint32_t conference_number,
2782 TOX_ERR_CONFERENCE_GET_TYPE *error);
2127 2783
2128 2784
2129/******************************************************************************* 2785/*******************************************************************************
@@ -2235,7 +2891,7 @@ typedef void tox_friend_lossy_packet_cb(Tox *tox, uint32_t friend_number, const
2235 * Set the callback for the `friend_lossy_packet` event. Pass NULL to unset. 2891 * Set the callback for the `friend_lossy_packet` event. Pass NULL to unset.
2236 * 2892 *
2237 */ 2893 */
2238void tox_callback_friend_lossy_packet(Tox *tox, tox_friend_lossy_packet_cb *callback, void *user_data); 2894void tox_callback_friend_lossy_packet(Tox *tox, tox_friend_lossy_packet_cb *callback);
2239 2895
2240/** 2896/**
2241 * @param friend_number The friend number of the friend who sent the packet. 2897 * @param friend_number The friend number of the friend who sent the packet.
@@ -2250,7 +2906,7 @@ typedef void tox_friend_lossless_packet_cb(Tox *tox, uint32_t friend_number, con
2250 * Set the callback for the `friend_lossless_packet` event. Pass NULL to unset. 2906 * Set the callback for the `friend_lossless_packet` event. Pass NULL to unset.
2251 * 2907 *
2252 */ 2908 */
2253void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb *callback, void *user_data); 2909void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb *callback);
2254 2910
2255 2911
2256/******************************************************************************* 2912/*******************************************************************************
@@ -2301,8 +2957,6 @@ uint16_t tox_self_get_udp_port(const Tox *tox, TOX_ERR_GET_PORT *error);
2301 */ 2957 */
2302uint16_t tox_self_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error); 2958uint16_t tox_self_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error);
2303 2959
2304#include "tox_old.h"
2305
2306#ifdef __cplusplus 2960#ifdef __cplusplus
2307} 2961}
2308#endif 2962#endif
diff --git a/toxcore/tox_api.c b/toxcore/tox_api.c
new file mode 100644
index 00000000..8fee8c80
--- /dev/null
+++ b/toxcore/tox_api.c
@@ -0,0 +1,100 @@
1#include "tox.h"
2
3#include "ccompat.h"
4
5#include <stdlib.h>
6#include <string.h>
7
8#define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}}
9
10
11#define CONST_FUNCTION(lowercase, uppercase) \
12uint32_t tox_##lowercase(void) \
13{ \
14 return TOX_##uppercase; \
15}
16
17CONST_FUNCTION(version_major, VERSION_MAJOR)
18CONST_FUNCTION(version_minor, VERSION_MINOR)
19CONST_FUNCTION(version_patch, VERSION_PATCH)
20CONST_FUNCTION(public_key_size, PUBLIC_KEY_SIZE)
21CONST_FUNCTION(secret_key_size, SECRET_KEY_SIZE)
22CONST_FUNCTION(nospam_size, NOSPAM_SIZE)
23CONST_FUNCTION(address_size, ADDRESS_SIZE)
24CONST_FUNCTION(max_name_length, MAX_NAME_LENGTH)
25CONST_FUNCTION(max_status_message_length, MAX_STATUS_MESSAGE_LENGTH)
26CONST_FUNCTION(max_friend_request_length, MAX_FRIEND_REQUEST_LENGTH)
27CONST_FUNCTION(max_message_length, MAX_MESSAGE_LENGTH)
28CONST_FUNCTION(max_custom_packet_size, MAX_CUSTOM_PACKET_SIZE)
29CONST_FUNCTION(hash_length, HASH_LENGTH)
30CONST_FUNCTION(file_id_length, FILE_ID_LENGTH)
31CONST_FUNCTION(max_filename_length, MAX_FILENAME_LENGTH)
32
33
34#define ACCESSORS(type, ns, name) \
35type tox_options_get_##ns##name(const struct Tox_Options *options) \
36{ \
37 return options->ns##name; \
38} \
39void tox_options_set_##ns##name(struct Tox_Options *options, type name) \
40{ \
41 options->ns##name = name; \
42}
43
44ACCESSORS(bool,, ipv6_enabled)
45ACCESSORS(bool,, udp_enabled)
46ACCESSORS(TOX_PROXY_TYPE, proxy_, type)
47ACCESSORS(const char *, proxy_, host)
48ACCESSORS(uint16_t, proxy_, port)
49ACCESSORS(uint16_t,, start_port)
50ACCESSORS(uint16_t,, end_port)
51ACCESSORS(uint16_t,, tcp_port)
52ACCESSORS(bool,, hole_punching_enabled)
53ACCESSORS(TOX_SAVEDATA_TYPE, savedata_, type)
54ACCESSORS(size_t, savedata_, length)
55ACCESSORS(tox_log_cb *, log_, callback)
56ACCESSORS(void *, log_, user_data)
57ACCESSORS(bool,, local_discovery_enabled)
58
59const uint8_t *tox_options_get_savedata_data(const struct Tox_Options *options)
60{
61 return options->savedata_data;
62}
63
64void tox_options_set_savedata_data(struct Tox_Options *options, const uint8_t *data, size_t length)
65{
66 options->savedata_data = data;
67 options->savedata_length = length;
68}
69
70void tox_options_default(struct Tox_Options *options)
71{
72 if (options) {
73 struct Tox_Options default_options = { 0 };
74 *options = default_options;
75 tox_options_set_ipv6_enabled(options, true);
76 tox_options_set_udp_enabled(options, true);
77 tox_options_set_proxy_type(options, TOX_PROXY_TYPE_NONE);
78 tox_options_set_hole_punching_enabled(options, true);
79 tox_options_set_local_discovery_enabled(options, true);
80 }
81}
82
83struct Tox_Options *tox_options_new(TOX_ERR_OPTIONS_NEW *error)
84{
85 struct Tox_Options *options = (struct Tox_Options *)malloc(sizeof(struct Tox_Options));
86
87 if (options) {
88 tox_options_default(options);
89 SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_OK);
90 return options;
91 }
92
93 SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_MALLOC);
94 return nullptr;
95}
96
97void tox_options_free(struct Tox_Options *options)
98{
99 free(options);
100}
diff --git a/toxcore/tox_old.h b/toxcore/tox_old.h
deleted file mode 100644
index a926cdf7..00000000
--- a/toxcore/tox_old.h
+++ /dev/null
@@ -1,173 +0,0 @@
1/**********GROUP CHAT FUNCTIONS ************/
2
3/* Group chat types for tox_callback_group_invite function.
4 *
5 * TOX_GROUPCHAT_TYPE_TEXT groupchats must be accepted with the tox_join_groupchat() function.
6 * The function to accept TOX_GROUPCHAT_TYPE_AV is in toxav.
7 */
8enum {
9 TOX_GROUPCHAT_TYPE_TEXT,
10 TOX_GROUPCHAT_TYPE_AV
11};
12
13/* Set the callback for group invites.
14 *
15 * Function(Tox *tox, int32_t friendnumber, uint8_t type, const uint8_t *data, uint16_t length, void *userdata)
16 *
17 * data of length is what needs to be passed to join_groupchat().
18 *
19 * for what type means see the enum right above this comment.
20 */
21void tox_callback_group_invite(Tox *tox, void (*function)(Tox *tox, int32_t, uint8_t, const uint8_t *, uint16_t,
22 void *), void *userdata);
23
24/* Set the callback for group messages.
25 *
26 * Function(Tox *tox, int groupnumber, int peernumber, const uint8_t * message, uint16_t length, void *userdata)
27 */
28void tox_callback_group_message(Tox *tox, void (*function)(Tox *tox, int, int, const uint8_t *, uint16_t, void *),
29 void *userdata);
30
31/* Set the callback for group actions.
32 *
33 * Function(Tox *tox, int groupnumber, int peernumber, const uint8_t * action, uint16_t length, void *userdata)
34 */
35void tox_callback_group_action(Tox *tox, void (*function)(Tox *tox, int, int, const uint8_t *, uint16_t, void *),
36 void *userdata);
37
38/* Set callback function for title changes.
39 *
40 * Function(Tox *tox, int groupnumber, int peernumber, uint8_t * title, uint8_t length, void *userdata)
41 * if peernumber == -1, then author is unknown (e.g. initial joining the group)
42 */
43void tox_callback_group_title(Tox *tox, void (*function)(Tox *tox, int, int, const uint8_t *, uint8_t,
44 void *), void *userdata);
45
46/* Set callback function for peer name list changes.
47 *
48 * It gets called every time the name list changes(new peer/name, deleted peer)
49 * Function(Tox *tox, int groupnumber, int peernumber, TOX_CHAT_CHANGE change, void *userdata)
50 */
51typedef enum {
52 TOX_CHAT_CHANGE_PEER_ADD,
53 TOX_CHAT_CHANGE_PEER_DEL,
54 TOX_CHAT_CHANGE_PEER_NAME,
55} TOX_CHAT_CHANGE;
56
57void tox_callback_group_namelist_change(Tox *tox, void (*function)(Tox *tox, int, int, uint8_t, void *),
58 void *userdata);
59
60/* Creates a new groupchat and puts it in the chats array.
61 *
62 * return group number on success.
63 * return -1 on failure.
64 */
65int tox_add_groupchat(Tox *tox);
66
67/* Delete a groupchat from the chats array.
68 *
69 * return 0 on success.
70 * return -1 if failure.
71 */
72int tox_del_groupchat(Tox *tox, int groupnumber);
73
74/* Copy the name of peernumber who is in groupnumber to name.
75 * name must be at least TOX_MAX_NAME_LENGTH long.
76 *
77 * return length of name if success
78 * return -1 if failure
79 */
80int tox_group_peername(const Tox *tox, int groupnumber, int peernumber, uint8_t *name);
81
82/* Copy the public key of peernumber who is in groupnumber to public_key.
83 * public_key must be TOX_PUBLIC_KEY_SIZE long.
84 *
85 * returns 0 on success
86 * returns -1 on failure
87 */
88int tox_group_peer_pubkey(const Tox *tox, int groupnumber, int peernumber, uint8_t *public_key);
89
90/* invite friendnumber to groupnumber
91 * return 0 on success
92 * return -1 on failure
93 */
94int tox_invite_friend(Tox *tox, int32_t friendnumber, int groupnumber);
95
96/* Join a group (you need to have been invited first.) using data of length obtained
97 * in the group invite callback.
98 *
99 * returns group number on success
100 * returns -1 on failure.
101 */
102int tox_join_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length);
103
104/* send a group message
105 * return 0 on success
106 * return -1 on failure
107 */
108int tox_group_message_send(Tox *tox, int groupnumber, const uint8_t *message, uint16_t length);
109
110/* send a group action
111 * return 0 on success
112 * return -1 on failure
113 */
114int tox_group_action_send(Tox *tox, int groupnumber, const uint8_t *action, uint16_t length);
115
116/* set the group's title, limited to MAX_NAME_LENGTH
117 * return 0 on success
118 * return -1 on failure
119 */
120int tox_group_set_title(Tox *tox, int groupnumber, const uint8_t *title, uint8_t length);
121
122/* Get group title from groupnumber and put it in title.
123 * title needs to be a valid memory location with a max_length size of at least MAX_NAME_LENGTH (128) bytes.
124 *
125 * return length of copied title if success.
126 * return -1 if failure.
127 */
128int tox_group_get_title(Tox *tox, int groupnumber, uint8_t *title, uint32_t max_length);
129
130/* Check if the current peernumber corresponds to ours.
131 *
132 * return 1 if the peernumber corresponds to ours.
133 * return 0 on failure.
134 */
135unsigned int tox_group_peernumber_is_ours(const Tox *tox, int groupnumber, int peernumber);
136
137/* Return the number of peers in the group chat on success.
138 * return -1 on failure
139 */
140int tox_group_number_peers(const Tox *tox, int groupnumber);
141
142/* List all the peers in the group chat.
143 *
144 * Copies the names of the peers to the name[length][TOX_MAX_NAME_LENGTH] array.
145 *
146 * Copies the lengths of the names to lengths[length]
147 *
148 * returns the number of peers on success.
149 *
150 * return -1 on failure.
151 */
152int tox_group_get_names(const Tox *tox, int groupnumber, uint8_t names[][TOX_MAX_NAME_LENGTH], uint16_t lengths[],
153 uint16_t length);
154
155/* Return the number of chats in the instance m.
156 * You should use this to determine how much memory to allocate
157 * for copy_chatlist. */
158uint32_t tox_count_chatlist(const Tox *tox);
159
160/* Copy a list of valid chat IDs into the array out_list.
161 * If out_list is NULL, returns 0.
162 * Otherwise, returns the number of elements copied.
163 * If the array was too small, the contents
164 * of out_list will be truncated to list_size. */
165uint32_t tox_get_chatlist(const Tox *tox, int32_t *out_list, uint32_t list_size);
166
167/* return the type of groupchat (TOX_GROUPCHAT_TYPE_) that groupnumber is.
168 *
169 * return -1 on failure.
170 * return type on success.
171 */
172int tox_group_get_type(const Tox *tox, int groupnumber);
173
diff --git a/toxcore/tox_old_code.h b/toxcore/tox_old_code.h
deleted file mode 100644
index 2a422575..00000000
--- a/toxcore/tox_old_code.h
+++ /dev/null
@@ -1,237 +0,0 @@
1/**********GROUP CHAT FUNCTIONS: WARNING Group chats will be rewritten so this might change ************/
2
3/* Set the callback for group invites.
4 *
5 * Function(Tox *tox, int32_t friendnumber, uint8_t type, uint8_t *data, uint16_t length, void *userdata)
6 *
7 * data of length is what needs to be passed to join_groupchat().
8 */
9void tox_callback_group_invite(Tox *tox, void (*function)(Messenger *tox, int32_t, uint8_t, const uint8_t *, uint16_t,
10 void *), void *userdata)
11{
12 Messenger *m = tox;
13 g_callback_group_invite(m->group_chat_object, function, userdata);
14}
15
16/* Set the callback for group messages.
17 *
18 * Function(Tox *tox, int groupnumber, int peernumber, uint8_t * message, uint16_t length, void *userdata)
19 */
20void tox_callback_group_message(Tox *tox, void (*function)(Messenger *tox, int, int, const uint8_t *, uint16_t, void *),
21 void *userdata)
22{
23 Messenger *m = tox;
24 g_callback_group_message(m->group_chat_object, function, userdata);
25}
26
27/* Set the callback for group actions.
28 *
29 * Function(Tox *tox, int groupnumber, int peernumber, uint8_t * action, uint16_t length, void *userdata)
30 */
31void tox_callback_group_action(Tox *tox, void (*function)(Messenger *tox, int, int, const uint8_t *, uint16_t, void *),
32 void *userdata)
33{
34 Messenger *m = tox;
35 g_callback_group_action(m->group_chat_object, function, userdata);
36}
37
38/* Set callback function for title changes.
39 *
40 * Function(Tox *tox, int groupnumber, int peernumber, uint8_t * title, uint8_t length, void *userdata)
41 * if peernumber == -1, then author is unknown (e.g. initial joining the group)
42 */
43void tox_callback_group_title(Tox *tox, void (*function)(Messenger *tox, int, int, const uint8_t *, uint8_t,
44 void *), void *userdata)
45{
46 Messenger *m = tox;
47 g_callback_group_title(m->group_chat_object, function, userdata);
48}
49
50/* Set callback function for peer name list changes.
51 *
52 * It gets called every time the name list changes(new peer/name, deleted peer)
53 * Function(Tox *tox, int groupnumber, void *userdata)
54 */
55void tox_callback_group_namelist_change(Tox *tox, void (*function)(Tox *tox, int, int, uint8_t, void *), void *userdata)
56{
57 Messenger *m = tox;
58 g_callback_group_namelistchange(m->group_chat_object, function, userdata);
59}
60
61/* Creates a new groupchat and puts it in the chats array.
62 *
63 * return group number on success.
64 * return -1 on failure.
65 */
66int tox_add_groupchat(Tox *tox)
67{
68 Messenger *m = tox;
69 return add_groupchat(m->group_chat_object, GROUPCHAT_TYPE_TEXT);
70}
71
72/* Delete a groupchat from the chats array.
73 *
74 * return 0 on success.
75 * return -1 if failure.
76 */
77int tox_del_groupchat(Tox *tox, int groupnumber)
78{
79 Messenger *m = tox;
80 return del_groupchat(m->group_chat_object, groupnumber);
81}
82
83/* Copy the name of peernumber who is in groupnumber to name.
84 * name must be at least MAX_NICK_BYTES long.
85 *
86 * return length of name if success
87 * return -1 if failure
88 */
89int tox_group_peername(const Tox *tox, int groupnumber, int peernumber, uint8_t *name)
90{
91 const Messenger *m = tox;
92 return group_peername(m->group_chat_object, groupnumber, peernumber, name);
93}
94
95/* Copy the public key of peernumber who is in groupnumber to public_key.
96 * public_key must be crypto_box_PUBLICKEYBYTES long.
97 *
98 * returns 0 on success
99 * returns -1 on failure
100 */
101int tox_group_peer_pubkey(const Tox *tox, int groupnumber, int peernumber, uint8_t *public_key)
102{
103 const Messenger *m = tox;
104 return group_peer_pubkey(m->group_chat_object, groupnumber, peernumber, public_key);
105}
106
107/* invite friendnumber to groupnumber
108 * return 0 on success
109 * return -1 on failure
110 */
111int tox_invite_friend(Tox *tox, int32_t friendnumber, int groupnumber)
112{
113 Messenger *m = tox;
114 return invite_friend(m->group_chat_object, friendnumber, groupnumber);
115}
116
117/* Join a group (you need to have been invited first.) using data of length obtained
118 * in the group invite callback.
119 *
120 * returns group number on success
121 * returns -1 on failure.
122 */
123int tox_join_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length)
124{
125 Messenger *m = tox;
126 return join_groupchat(m->group_chat_object, friendnumber, GROUPCHAT_TYPE_TEXT, data, length);
127}
128
129/* send a group message
130 * return 0 on success
131 * return -1 on failure
132 */
133int tox_group_message_send(Tox *tox, int groupnumber, const uint8_t *message, uint16_t length)
134{
135 Messenger *m = tox;
136 return group_message_send(m->group_chat_object, groupnumber, message, length);
137}
138
139/* send a group action
140 * return 0 on success
141 * return -1 on failure
142 */
143int tox_group_action_send(Tox *tox, int groupnumber, const uint8_t *action, uint16_t length)
144{
145 Messenger *m = tox;
146 return group_action_send(m->group_chat_object, groupnumber, action, length);
147}
148
149/* set the group's title, limited to MAX_NAME_LENGTH
150 * return 0 on success
151 * return -1 on failure
152 */
153int tox_group_set_title(Tox *tox, int groupnumber, const uint8_t *title, uint8_t length)
154{
155 Messenger *m = tox;
156 return group_title_send(m->group_chat_object, groupnumber, title, length);
157}
158
159/* Get group title from groupnumber and put it in title.
160 * title needs to be a valid memory location with a max_length size of at least MAX_NAME_LENGTH (128) bytes.
161 *
162 * return length of copied title if success.
163 * return -1 if failure.
164 */
165int tox_group_get_title(Tox *tox, int groupnumber, uint8_t *title, uint32_t max_length)
166{
167 Messenger *m = tox;
168 return group_title_get(m->group_chat_object, groupnumber, title, max_length);
169}
170
171/* Check if the current peernumber corresponds to ours.
172 *
173 * return 1 if the peernumber corresponds to ours.
174 * return 0 on failure.
175 */
176unsigned int tox_group_peernumber_is_ours(const Tox *tox, int groupnumber, int peernumber)
177{
178 const Messenger *m = tox;
179 return group_peernumber_is_ours(m->group_chat_object, groupnumber, peernumber);
180}
181
182/* Return the number of peers in the group chat on success.
183 * return -1 on failure
184 */
185int tox_group_number_peers(const Tox *tox, int groupnumber)
186{
187 const Messenger *m = tox;
188 return group_number_peers(m->group_chat_object, groupnumber);
189}
190
191/* List all the peers in the group chat.
192 *
193 * Copies the names of the peers to the name[length][MAX_NICK_BYTES] array.
194 *
195 * Copies the lengths of the names to lengths[length]
196 *
197 * returns the number of peers on success.
198 *
199 * return -1 on failure.
200 */
201int tox_group_get_names(const Tox *tox, int groupnumber, uint8_t names[][TOX_MAX_NAME_LENGTH], uint16_t lengths[],
202 uint16_t length)
203{
204 const Messenger *m = tox;
205 return group_names(m->group_chat_object, groupnumber, names, lengths, length);
206}
207
208/* Return the number of chats in the instance m.
209 * You should use this to determine how much memory to allocate
210 * for copy_chatlist. */
211uint32_t tox_count_chatlist(const Tox *tox)
212{
213 const Messenger *m = tox;
214 return count_chatlist(m->group_chat_object);
215}
216
217/* Copy a list of valid chat IDs into the array out_list.
218 * If out_list is NULL, returns 0.
219 * Otherwise, returns the number of elements copied.
220 * If the array was too small, the contents
221 * of out_list will be truncated to list_size. */
222uint32_t tox_get_chatlist(const Tox *tox, int32_t *out_list, uint32_t list_size)
223{
224 const Messenger *m = tox;
225 return copy_chatlist(m->group_chat_object, out_list, list_size);
226}
227
228/* return the type of groupchat (TOX_GROUPCHAT_TYPE_) that groupnumber is.
229 *
230 * return -1 on failure.
231 * return type on success.
232 */
233int tox_group_get_type(const Tox *tox, int groupnumber)
234{
235 const Messenger *m = tox;
236 return group_get_type(m->group_chat_object, groupnumber);
237}
diff --git a/toxcore/util.c b/toxcore/util.c
index ea1988e4..082e453f 100644
--- a/toxcore/util.c
+++ b/toxcore/util.c
@@ -1,52 +1,61 @@
1/* 1/*
2 * util.c -- Utilities. 2 * Utilities.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2013 Tox project.
8 * Copyright © 2013 plutooo
3 * 9 *
10 * This file is part of Tox, the free peer to peer instant messenger.
4 * This file is donated to the Tox Project. 11 * This file is donated to the Tox Project.
5 * Copyright 2013 plutooo
6 * 12 *
7 * Copyright (C) 2013 Tox project All Rights Reserved. 13 * Tox is free software: you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation, either version 3 of the License, or
16 * (at your option) any later version.
8 * 17 *
9 * This file is part of Tox. 18 * Tox is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
10 * 22 *
11 * Tox is free software: you can redistribute it and/or modify 23 * You should have received a copy of the GNU General Public License
12 * it under the terms of the GNU General Public License as published by 24 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * Tox is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
23 */ 25 */
24
25#ifdef HAVE_CONFIG_H 26#ifdef HAVE_CONFIG_H
26#include "config.h" 27#include "config.h"
27#endif 28#endif
28 29
29#include <time.h> 30#ifndef _XOPEN_SOURCE
30 31#define _XOPEN_SOURCE 600
31/* for crypto_box_PUBLICKEYBYTES */ 32#endif
32#include "crypto_core.h"
33 33
34#include "util.h" 34#include "util.h"
35 35
36#include "crypto_core.h" /* for CRYPTO_PUBLIC_KEY_SIZE */
37#include "network.h" /* for current_time_monotonic */
38
39#include <string.h>
40#include <time.h>
41
36 42
37/* don't call into system billions of times for no reason */ 43/* don't call into system billions of times for no reason */
38static uint64_t unix_time_value; 44static uint64_t unix_time_value;
39static uint64_t unix_base_time_value; 45static uint64_t unix_base_time_value;
40 46
41void unix_time_update() 47/* XXX: note that this is not thread-safe; if multiple threads call unix_time_update() concurrently, the return value of
48 * unix_time() may fail to increase monotonically with increasing time */
49void unix_time_update(void)
42{ 50{
43 if (unix_base_time_value == 0) 51 if (unix_base_time_value == 0) {
44 unix_base_time_value = ((uint64_t)time(NULL) - (current_time_monotonic() / 1000ULL)); 52 unix_base_time_value = ((uint64_t)time(nullptr) - (current_time_monotonic() / 1000ULL));
53 }
45 54
46 unix_time_value = (current_time_monotonic() / 1000ULL) + unix_base_time_value; 55 unix_time_value = (current_time_monotonic() / 1000ULL) + unix_base_time_value;
47} 56}
48 57
49uint64_t unix_time() 58uint64_t unix_time(void)
50{ 59{
51 return unix_time_value; 60 return unix_time_value;
52} 61}
@@ -65,15 +74,15 @@ bool id_equal(const uint8_t *dest, const uint8_t *src)
65 74
66uint32_t id_copy(uint8_t *dest, const uint8_t *src) 75uint32_t id_copy(uint8_t *dest, const uint8_t *src)
67{ 76{
68 memcpy(dest, src, crypto_box_PUBLICKEYBYTES); 77 memcpy(dest, src, CRYPTO_PUBLIC_KEY_SIZE);
69 return crypto_box_PUBLICKEYBYTES; 78 return CRYPTO_PUBLIC_KEY_SIZE;
70} 79}
71 80
72void host_to_net(uint8_t *num, uint16_t numbytes) 81void host_to_net(uint8_t *num, uint16_t numbytes)
73{ 82{
74#ifndef WORDS_BIGENDIAN 83#ifndef WORDS_BIGENDIAN
75 uint32_t i; 84 uint32_t i;
76 uint8_t buff[numbytes]; 85 VLA(uint8_t, buff, numbytes);
77 86
78 for (i = 0; i < numbytes; ++i) { 87 for (i = 0; i < numbytes; ++i) {
79 buff[i] = num[numbytes - i - 1]; 88 buff[i] = num[numbytes - i - 1];
@@ -81,13 +90,12 @@ void host_to_net(uint8_t *num, uint16_t numbytes)
81 90
82 memcpy(num, buff, numbytes); 91 memcpy(num, buff, numbytes);
83#endif 92#endif
84 return;
85} 93}
86 94
87uint16_t lendian_to_host16(uint16_t lendian) 95uint16_t lendian_to_host16(uint16_t lendian)
88{ 96{
89#ifdef WORDS_BIGENDIAN 97#ifdef WORDS_BIGENDIAN
90 return (lendian << 8) | (lendian >> 8 ); 98 return (lendian << 8) | (lendian >> 8);
91#else 99#else
92 return lendian; 100 return lendian;
93#endif 101#endif
@@ -96,7 +104,7 @@ uint16_t lendian_to_host16(uint16_t lendian)
96void host_to_lendian32(uint8_t *dest, uint32_t num) 104void host_to_lendian32(uint8_t *dest, uint32_t num)
97{ 105{
98#ifdef WORDS_BIGENDIAN 106#ifdef WORDS_BIGENDIAN
99 num = ((num << 8) & 0xFF00FF00 ) | ((num >> 8) & 0xFF00FF ); 107 num = ((num << 8) & 0xFF00FF00) | ((num >> 8) & 0xFF00FF);
100 num = (num << 16) | (num >> 16); 108 num = (num << 16) | (num >> 16);
101#endif 109#endif
102 memcpy(dest, &num, sizeof(uint32_t)); 110 memcpy(dest, &num, sizeof(uint32_t));
@@ -107,25 +115,22 @@ void lendian_to_host32(uint32_t *dest, const uint8_t *lendian)
107 uint32_t d; 115 uint32_t d;
108 memcpy(&d, lendian, sizeof(uint32_t)); 116 memcpy(&d, lendian, sizeof(uint32_t));
109#ifdef WORDS_BIGENDIAN 117#ifdef WORDS_BIGENDIAN
110 d = ((d << 8) & 0xFF00FF00 ) | ((d >> 8) & 0xFF00FF ); 118 d = ((d << 8) & 0xFF00FF00) | ((d >> 8) & 0xFF00FF);
111 d = (d << 16) | (d >> 16); 119 d = (d << 16) | (d >> 16);
112#endif 120#endif
113 *dest = d; 121 *dest = d;
114} 122}
115 123
116/* state load/save */ 124/* state load/save */
117int load_state(load_state_callback_func load_state_callback, void *outer, 125int load_state(load_state_callback_func load_state_callback, Logger *log, void *outer,
118 const uint8_t *data, uint32_t length, uint16_t cookie_inner) 126 const uint8_t *data, uint32_t length, uint16_t cookie_inner)
119{ 127{
120 if (!load_state_callback || !data) { 128 if (!load_state_callback || !data) {
121#ifdef DEBUG 129 LOGGER_ERROR(log, "load_state() called with invalid args.\n");
122 fprintf(stderr, "load_state() called with invalid args.\n");
123#endif
124 return -1; 130 return -1;
125 } 131 }
126 132
127 133
128 uint16_t type;
129 uint32_t length_sub, cookie_type; 134 uint32_t length_sub, cookie_type;
130 uint32_t size_head = sizeof(uint32_t) * 2; 135 uint32_t size_head = sizeof(uint32_t) * 2;
131 136
@@ -137,45 +142,42 @@ int load_state(load_state_callback_func load_state_callback, void *outer,
137 142
138 if (length < length_sub) { 143 if (length < length_sub) {
139 /* file truncated */ 144 /* file truncated */
140#ifdef DEBUG 145 LOGGER_ERROR(log, "state file too short: %u < %u\n", length, length_sub);
141 fprintf(stderr, "state file too short: %u < %u\n", length, length_sub);
142#endif
143 return -1; 146 return -1;
144 } 147 }
145 148
146 if (lendian_to_host16((cookie_type >> 16)) != cookie_inner) { 149 if (lendian_to_host16((cookie_type >> 16)) != cookie_inner) {
147 /* something is not matching up in a bad way, give up */ 150 /* something is not matching up in a bad way, give up */
148#ifdef DEBUG 151 LOGGER_ERROR(log, "state file garbled: %04x != %04x\n", (cookie_type >> 16), cookie_inner);
149 fprintf(stderr, "state file garbeled: %04hx != %04hx\n", (cookie_type >> 16), cookie_inner);
150#endif
151 return -1; 152 return -1;
152 } 153 }
153 154
154 type = lendian_to_host16(cookie_type & 0xFFFF); 155 const uint16_t type = lendian_to_host16(cookie_type & 0xFFFF);
155 156 const int ret = load_state_callback(outer, data, length_sub, type);
156 int ret = load_state_callback(outer, data, length_sub, type);
157 157
158 if (ret == -1) { 158 if (ret == -1) {
159 return -1; 159 return -1;
160 } 160 }
161 161
162 /* -2 means end of save. */ 162 /* -2 means end of save. */
163 if (ret == -2) 163 if (ret == -2) {
164 return 0; 164 return 0;
165 }
165 166
166 data += length_sub; 167 data += length_sub;
167 length -= length_sub; 168 length -= length_sub;
168 } 169 }
169 170
170 return length == 0 ? 0 : -1; 171 return length == 0 ? 0 : -1;
171}; 172}
172 173
173int create_recursive_mutex(pthread_mutex_t *mutex) 174int create_recursive_mutex(pthread_mutex_t *mutex)
174{ 175{
175 pthread_mutexattr_t attr; 176 pthread_mutexattr_t attr;
176 177
177 if (pthread_mutexattr_init(&attr) != 0) 178 if (pthread_mutexattr_init(&attr) != 0) {
178 return -1; 179 return -1;
180 }
179 181
180 if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0) { 182 if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0) {
181 pthread_mutexattr_destroy(&attr); 183 pthread_mutexattr_destroy(&attr);
@@ -193,86 +195,12 @@ int create_recursive_mutex(pthread_mutex_t *mutex)
193 return 0; 195 return 0;
194} 196}
195 197
196 198int32_t max_s32(int32_t a, int32_t b)
197struct RingBuffer {
198 uint16_t size; /* Max size */
199 uint16_t start;
200 uint16_t end;
201 void **data;
202};
203
204bool rb_full(const RingBuffer *b)
205{
206 return (b->end + 1) % b->size == b->start;
207}
208bool rb_empty(const RingBuffer *b)
209{
210 return b->end == b->start;
211}
212void *rb_write(RingBuffer *b, void *p)
213{
214 void *rc = NULL;
215
216 if ((b->end + 1) % b->size == b->start) /* full */
217 rc = b->data[b->start];
218
219 b->data[b->end] = p;
220 b->end = (b->end + 1) % b->size;
221
222 if (b->end == b->start)
223 b->start = (b->start + 1) % b->size;
224
225 return rc;
226}
227bool rb_read(RingBuffer *b, void **p)
228{
229 if (b->end == b->start) { /* Empty */
230 *p = NULL;
231 return false;
232 }
233
234 *p = b->data[b->start];
235 b->start = (b->start + 1) % b->size;
236 return true;
237}
238RingBuffer *rb_new(int size)
239{
240 RingBuffer *buf = calloc(sizeof(RingBuffer), 1);
241
242 if (!buf) return NULL;
243
244 buf->size = size + 1; /* include empty elem */
245
246 if (!(buf->data = calloc(buf->size, sizeof(void *)))) {
247 free(buf);
248 return NULL;
249 }
250
251 return buf;
252}
253void rb_kill(RingBuffer *b)
254{ 199{
255 if (b) { 200 return a > b ? a : b;
256 free(b->data);
257 free(b);
258 }
259} 201}
260uint16_t rb_size(const RingBuffer *b)
261{
262 if (rb_empty(b))
263 return 0;
264 202
265 return 203uint64_t min_u64(uint64_t a, uint64_t b)
266 b->end > b->start ?
267 b->end - b->start :
268 (b->size - b->start) + b->end;
269}
270uint16_t rb_data(const RingBuffer *b, void **dest)
271{ 204{
272 uint16_t i = 0; 205 return a < b ? a : b;
273
274 for (; i < rb_size(b); i++)
275 dest[i] = b->data[(b->start + i) % b->size];
276
277 return i;
278} 206}
diff --git a/toxcore/util.h b/toxcore/util.h
index bdbf7d3b..a9faa863 100644
--- a/toxcore/util.h
+++ b/toxcore/util.h
@@ -1,39 +1,46 @@
1/* 1/*
2 * util.h -- Utilities. 2 * Utilities.
3 */
4
5/*
6 * Copyright © 2016-2017 The TokTok team.
7 * Copyright © 2013 Tox project.
8 * Copyright © 2013 plutooo
3 * 9 *
10 * This file is part of Tox, the free peer to peer instant messenger.
4 * This file is donated to the Tox Project. 11 * This file is donated to the Tox Project.
5 * Copyright 2013 plutooo
6 * 12 *
7 * Copyright (C) 2013 Tox project All Rights Reserved. 13 * Tox is free software: you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation, either version 3 of the License, or
16 * (at your option) any later version.
8 * 17 *
9 * This file is part of Tox. 18 * Tox is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
10 * 22 *
11 * Tox is free software: you can redistribute it and/or modify 23 * You should have received a copy of the GNU General Public License
12 * it under the terms of the GNU General Public License as published by 24 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * Tox is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
23 */ 25 */
26#ifndef UTIL_H
27#define UTIL_H
24 28
25#ifndef __UTIL_H__ 29#include <pthread.h>
26#define __UTIL_H__
27
28#include <stdbool.h> 30#include <stdbool.h>
29#include <stdint.h> 31#include <stdint.h>
30#include <pthread.h> 32
33#include "logger.h"
34
35#ifdef __cplusplus
36extern "C" {
37#endif
31 38
32#define MIN(a,b) (((a)<(b))?(a):(b)) 39#define MIN(a,b) (((a)<(b))?(a):(b))
33#define PAIR(TYPE1__, TYPE2__) struct { TYPE1__ first; TYPE2__ second; } 40#define PAIR(TYPE1__, TYPE2__) struct { TYPE1__ first; TYPE2__ second; }
34 41
35void unix_time_update(); 42void unix_time_update(void);
36uint64_t unix_time(); 43uint64_t unix_time(void);
37int is_timeout(uint64_t timestamp, uint64_t timeout); 44int is_timeout(uint64_t timestamp, uint64_t timeout);
38 45
39 46
@@ -52,21 +59,17 @@ void lendian_to_host32(uint32_t *dest, const uint8_t *lendian);
52 59
53/* state load/save */ 60/* state load/save */
54typedef int (*load_state_callback_func)(void *outer, const uint8_t *data, uint32_t len, uint16_t type); 61typedef int (*load_state_callback_func)(void *outer, const uint8_t *data, uint32_t len, uint16_t type);
55int load_state(load_state_callback_func load_state_callback, void *outer, 62int load_state(load_state_callback_func load_state_callback, Logger *log, void *outer,
56 const uint8_t *data, uint32_t length, uint16_t cookie_inner); 63 const uint8_t *data, uint32_t length, uint16_t cookie_inner);
57 64
58/* Returns -1 if failed or 0 if success */ 65/* Returns -1 if failed or 0 if success */
59int create_recursive_mutex(pthread_mutex_t *mutex); 66int create_recursive_mutex(pthread_mutex_t *mutex);
60 67
61/* Ring buffer */ 68int32_t max_s32(int32_t a, int32_t b);
62typedef struct RingBuffer RingBuffer; 69uint64_t min_u64(uint64_t a, uint64_t b);
63bool rb_full(const RingBuffer *b); 70
64bool rb_empty(const RingBuffer *b); 71#ifdef __cplusplus
65void *rb_write(RingBuffer *b, void *p); 72} // extern "C"
66bool rb_read(RingBuffer *b, void **p); 73#endif
67RingBuffer *rb_new(int size); 74
68void rb_kill(RingBuffer *b); 75#endif /* UTIL_H */
69uint16_t rb_size(const RingBuffer *b);
70uint16_t rb_data(const RingBuffer *b, void **dest);
71
72#endif /* __UTIL_H__ */
diff --git a/toxcore/util_test.cpp b/toxcore/util_test.cpp
new file mode 100644
index 00000000..8de63848
--- /dev/null
+++ b/toxcore/util_test.cpp
@@ -0,0 +1,55 @@
1#include "util.h"
2
3#include "crypto_core.h"
4
5#include <gtest/gtest.h>
6
7TEST(Util, UnixTimeIncreasesOverTime)
8{
9 unix_time_update();
10 uint64_t const start = unix_time();
11
12 while (start == unix_time()) {
13 unix_time_update();
14 }
15
16 uint64_t const end = unix_time();
17 EXPECT_GT(end, start);
18}
19
20TEST(Util, IsTimeout)
21{
22 uint64_t const start = unix_time();
23 EXPECT_FALSE(is_timeout(start, 1));
24
25 while (start == unix_time()) {
26 unix_time_update();
27 }
28
29 EXPECT_TRUE(is_timeout(start, 1));
30}
31
32TEST(Util, TwoRandomIdsAreNotEqual)
33{
34 uint8_t pk1[CRYPTO_PUBLIC_KEY_SIZE];
35 uint8_t sk1[CRYPTO_SECRET_KEY_SIZE];
36 uint8_t pk2[CRYPTO_PUBLIC_KEY_SIZE];
37 uint8_t sk2[CRYPTO_SECRET_KEY_SIZE];
38
39 crypto_new_keypair(pk1, sk1);
40 crypto_new_keypair(pk2, sk2);
41
42 EXPECT_FALSE(id_equal(pk1, pk2));
43}
44
45TEST(Util, IdCopyMakesKeysEqual)
46{
47 uint8_t pk1[CRYPTO_PUBLIC_KEY_SIZE];
48 uint8_t sk1[CRYPTO_SECRET_KEY_SIZE];
49 uint8_t pk2[CRYPTO_PUBLIC_KEY_SIZE] = {0};
50
51 crypto_new_keypair(pk1, sk1);
52 id_copy(pk2, pk1);
53
54 EXPECT_TRUE(id_equal(pk1, pk2));
55}