diff options
Diffstat (limited to 'toxcore')
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 @@ | |||
1 | load("//tools:no_undefined.bzl", "cc_library") | ||
2 | |||
3 | filegroup( | ||
4 | name = "public_headers", | ||
5 | srcs = ["tox.h"], | ||
6 | visibility = ["//c-toxcore:__pkg__"], | ||
7 | ) | ||
8 | |||
9 | cc_library( | ||
10 | name = "ccompat", | ||
11 | hdrs = ["ccompat.h"], | ||
12 | visibility = ["//c-toxcore:__subpackages__"], | ||
13 | ) | ||
14 | |||
15 | cc_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 | |||
31 | cc_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 | |||
40 | cc_library( | ||
41 | name = "list", | ||
42 | srcs = ["list.c"], | ||
43 | hdrs = ["list.h"], | ||
44 | deps = [":ccompat"], | ||
45 | ) | ||
46 | |||
47 | cc_library( | ||
48 | name = "logger", | ||
49 | srcs = ["logger.c"], | ||
50 | hdrs = ["logger.h"], | ||
51 | deps = [":ccompat"], | ||
52 | ) | ||
53 | |||
54 | cc_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 | |||
76 | cc_test( | ||
77 | name = "util_test", | ||
78 | srcs = ["util_test.cpp"], | ||
79 | deps = [ | ||
80 | ":network", | ||
81 | "@com_google_googletest//:gtest_main", | ||
82 | ], | ||
83 | ) | ||
84 | |||
85 | cc_library( | ||
86 | name = "ping_array", | ||
87 | srcs = ["ping_array.c"], | ||
88 | hdrs = ["ping_array.h"], | ||
89 | deps = [":network"], | ||
90 | ) | ||
91 | |||
92 | cc_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 | |||
112 | cc_library( | ||
113 | name = "onion", | ||
114 | srcs = ["onion.c"], | ||
115 | hdrs = ["onion.h"], | ||
116 | deps = [":DHT"], | ||
117 | ) | ||
118 | |||
119 | cc_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 | |||
143 | cc_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 | |||
153 | cc_library( | ||
154 | name = "onion_announce", | ||
155 | srcs = ["onion_announce.c"], | ||
156 | hdrs = ["onion_announce.h"], | ||
157 | deps = [":onion"], | ||
158 | ) | ||
159 | |||
160 | cc_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 | |||
170 | cc_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 | |||
181 | cc_library( | ||
182 | name = "friend_requests", | ||
183 | srcs = ["friend_requests.c"], | ||
184 | hdrs = ["friend_requests.h"], | ||
185 | deps = [":friend_connection"], | ||
186 | ) | ||
187 | |||
188 | cc_library( | ||
189 | name = "Messenger", | ||
190 | srcs = ["Messenger.c"], | ||
191 | hdrs = ["Messenger.h"], | ||
192 | visibility = ["//c-toxcore/toxav:__pkg__"], | ||
193 | deps = [":friend_requests"], | ||
194 | ) | ||
195 | |||
196 | cc_library( | ||
197 | name = "group", | ||
198 | srcs = ["group.c"], | ||
199 | hdrs = ["group.h"], | ||
200 | visibility = ["//c-toxcore/toxav:__pkg__"], | ||
201 | deps = [":Messenger"], | ||
202 | ) | ||
203 | |||
204 | cc_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 | |||
218 | cc_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 | |||
64 | struct 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 | |||
87 | struct 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 | |||
122 | const uint8_t *dht_friend_public_key(const DHT_Friend *dht_friend) | ||
123 | { | ||
124 | return dht_friend->public_key; | ||
125 | } | ||
126 | |||
127 | const Client_data *dht_friend_client(const DHT_Friend *dht_friend, size_t index) | ||
128 | { | ||
129 | return &dht_friend->client_list[index]; | ||
130 | } | ||
131 | |||
132 | const uint8_t *dht_get_self_public_key(const DHT *dht) | ||
133 | { | ||
134 | return dht->self_public_key; | ||
135 | } | ||
136 | const uint8_t *dht_get_self_secret_key(const DHT *dht) | ||
137 | { | ||
138 | return dht->self_secret_key; | ||
139 | } | ||
140 | |||
141 | void dht_set_self_public_key(DHT *dht, const uint8_t *key) | ||
142 | { | ||
143 | memcpy(dht->self_public_key, key, CRYPTO_PUBLIC_KEY_SIZE); | ||
144 | } | ||
145 | void 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 | |||
150 | Networking_Core *dht_get_net(const DHT *dht) | ||
151 | { | ||
152 | return dht->net; | ||
153 | } | ||
154 | struct Ping *dht_get_ping(const DHT *dht) | ||
155 | { | ||
156 | return dht->ping; | ||
157 | } | ||
158 | const Client_data *dht_get_close_clientlist(const DHT *dht) | ||
159 | { | ||
160 | return dht->close_clientlist; | ||
161 | } | ||
162 | const 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 | } | ||
167 | uint16_t dht_get_num_friends(const DHT *dht) | ||
168 | { | ||
169 | return dht->num_friends; | ||
170 | } | ||
171 | |||
172 | DHT_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 | } | ||
177 | const 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 | */ |
74 | int id_closest(const uint8_t *pk, const uint8_t *pk1, const uint8_t *pk2) | 189 | int 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 | */ |
96 | static unsigned int bit_by_bit_cmp(const uint8_t *pk1, const uint8_t *pk2) | 209 | static 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 | */ |
121 | void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t *secret_key, const uint8_t *public_key) | 239 | void 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 | ||
180 | void 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 | */ | ||
311 | int 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 | ||
188 | int 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 | */ | ||
349 | int 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 | */ |
207 | int packed_node_size(uint8_t ip_family) | 388 | int 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 | */ | ||
407 | int 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 | |||
458 | static 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 | */ | ||
485 | int 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 | */ |
228 | int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_t number) | 548 | int 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 | */ |
365 | static 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) | 628 | static 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; | 633 | static 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)) { | 638 | static 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 | */ | ||
647 | static 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 | */ |
661 | static 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 | */ |
444 | static int client_in_nodelist(const Node_format *list, uint16_t length, const uint8_t *public_key) | 701 | static 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 | } |
459 | static 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, | 748 | bool 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 | */ |
513 | static void get_close_nodes_inner(const uint8_t *public_key, Node_format *nodes_list, | 787 | static 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 | */ |
579 | static int get_somewhat_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, | 852 | static 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 | ||
600 | int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, sa_family_t sa_family, | 879 | int 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) | 886 | typedef 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 | 891 | static 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 | ||
660 | static uint8_t cmp_public_key[crypto_box_PUBLICKEYBYTES]; | 917 | #define INCORRECT_HARDENING(assoc) hardening_correct(&(assoc).hardening) != HARDENING_ALL_OK |
661 | static 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 | */ |
707 | static unsigned int store_node_ok(const Client_data *client, const uint8_t *public_key, const uint8_t *comp_public_key) | 948 | static 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 | ||
717 | static void sort_client_list(Client_data *list, unsigned int length, const uint8_t *comp_public_key) | 955 | static 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 | |||
973 | static 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 */ |
736 | static int replace_all( Client_data *list, | 1010 | static 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 | */ |
785 | static int add_to_close(DHT *dht, const uint8_t *public_key, IP_Port ip_port, _Bool simulate) | 1041 | static 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) | 1073 | bool 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 | |||
1078 | static 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 | ||
840 | static _Bool is_pk_in_client_list(Client_data *list, unsigned int client_list_length, const uint8_t *public_key, | 1094 | static 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 | */ |
863 | static unsigned int ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_key, IP_Port ip_port) | 1111 | static 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 | */ |
919 | int addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key) | 1175 | uint32_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) { | 1229 | static 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 | */ |
993 | static int returnedip_ports(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const uint8_t *nodepublic_key) | 1257 | static 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 | ||
1042 | end: | 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 | ||
1167 | static 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 | |||
1379 | static 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 |
1200 | static 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) | 1416 | static 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, | |||
1226 | static int handle_sendnodes_core(void *object, IP_Port source, const uint8_t *packet, uint16_t length, | 1443 | static 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 | ||
1288 | static int handle_sendnodes_ipv6(void *object, IP_Port source, const uint8_t *packet, uint16_t length) | 1514 | static 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 | |||
1316 | int DHT_addfriend(DHT *dht, const uint8_t *public_key, void (*ip_callback)(void *data, int32_t number, IP_Port), | 1541 | int 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 | ||
1369 | int DHT_delfriend(DHT *dht, const uint8_t *public_key, uint16_t lock_count) | 1598 | int 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. */ |
1414 | int DHT_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port) | 1642 | int 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 */ |
1447 | static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, const uint8_t *public_key, | 1676 | static 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 | */ |
1515 | static void do_DHT_friends(DHT *dht) | 1746 | static 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 | */ |
1536 | static void do_Close(DHT *dht) | 1767 | static 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 | ||
1570 | void DHT_getnodes(DHT *dht, const IP_Port *from_ipp, const uint8_t *from_id, const uint8_t *which_id) | 1806 | void 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 | ||
1575 | void DHT_bootstrap(DHT *dht, IP_Port ip_port, const uint8_t *public_key) | 1811 | void 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 | } |
1589 | int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled, | 1815 | int 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 | */ |
1622 | int route_packet(const DHT *dht, const uint8_t *public_key, const uint8_t *packet, uint16_t length) | 1849 | int 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 | */ |
1649 | static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) | 1878 | static 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 | */ |
1717 | int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint16_t length) | 1950 | int 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 | */ |
1772 | static int routeone_tofriend(DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint16_t length) | 2003 | static 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. */ |
1849 | static int handle_NATping(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet, | 2082 | static 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 | */ |
1918 | static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t len, IP ip) | 2157 | static 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 | ||
1933 | static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports, uint16_t friend_num) | 2171 | static 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 | ||
1982 | static void do_NAT(DHT *dht) | 2229 | static 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 | 2279 | enum { |
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 | ||
2031 | static int send_hardening_req(DHT *dht, Node_format *sendto, uint8_t type, uint8_t *contents, uint16_t length) | 2289 | static 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 */ |
2050 | static int send_hardening_getnode_req(DHT *dht, Node_format *dest, Node_format *node_totest, uint8_t *search_id) | 2311 | static 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 */ |
2059 | static int send_hardening_getnode_res(const DHT *dht, const Node_format *sendto, const uint8_t *queried_client_id, | 2321 | static 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 */ |
2080 | static IPPTsPng *get_closelist_IPPTsPng(DHT *dht, const uint8_t *public_key, sa_family_t sa_family) | 2345 | static 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 | */ |
2101 | static uint32_t have_nodes_closelist(DHT *dht, Node_format *nodes, uint16_t num) | 2368 | static 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 */ |
2129 | static int handle_hardening(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet, | 2394 | static 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 | */ |
2197 | Node_format random_node(DHT *dht, sa_family_t sa_family) | 2475 | static 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 | */ |
2221 | uint16_t list_nodes(Client_data *list, unsigned int length, Node_format *nodes, uint16_t max_num) | 2500 | static 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 | */ |
2260 | uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num) | 2541 | uint16_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 | ||
2288 | void do_hardening(DHT *dht) | 2571 | #if DHT_HARDENING |
2572 | static 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 | ||
2346 | static int cryptopacket_handle(void *object, IP_Port source, const uint8_t *packet, uint16_t length) | 2632 | static 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 | ||
2382 | DHT *new_DHT(Networking_Core *net) | 2676 | DHT *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 | |||
2458 | void kill_DHT(DHT *dht) | 2750 | void 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). */ |
2485 | uint32_t DHT_size(const DHT *dht) | 2774 | uint32_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 | ||
2508 | static uint8_t *z_state_save_subheader(uint8_t *data, uint32_t len, uint16_t type) | 2799 | static 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(). */ |
2519 | void DHT_save(DHT *dht, uint8_t *data) | 2810 | void 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 */ |
2572 | int DHT_connect_after_load(DHT *dht) | 2863 | int 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 | ||
2599 | static int dht_load_state_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type) | 2890 | static 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 | */ |
2642 | int DHT_load(DHT *dht, const uint8_t *data, uint32_t length) | 2929 | int 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 | */ |
2661 | int DHT_isconnected(const DHT *dht) | 2949 | bool 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 | */ |
2680 | int DHT_non_lan_connected(const DHT *dht) | 2968 | bool 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 |
69 | void 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. |
72 | int 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 | */ | ||
82 | int 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. */ | ||
89 | int 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 | ||
74 | typedef struct { | 92 | typedef 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 | ||
97 | typedef struct { | 115 | typedef struct { |
@@ -106,7 +124,7 @@ typedef struct { | |||
106 | } IPPTsPng; | 124 | } IPPTsPng; |
107 | 125 | ||
108 | typedef struct { | 126 | typedef 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 | ||
131 | typedef struct { | 149 | typedef 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 | } |
135 | Node_format; | 153 | Node_format; |
136 | 154 | ||
137 | typedef struct { | 155 | typedef 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. */ | 157 | const uint8_t *dht_friend_public_key(const DHT_Friend *dht_friend); |
147 | NAT nat; | 158 | const 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; | 163 | int 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 | */ | ||
170 | int 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 | */ |
163 | int packed_node_size(uint8_t ip_family); | 177 | int 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 | |||
187 | typedef struct { | 202 | typedef 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 | |
210 | typedef struct { | ||
211 | Shared_Key keys[256 * MAX_KEYS_PER_SLOT]; | ||
195 | } Shared_Keys; | 212 | } Shared_Keys; |
196 | 213 | ||
197 | /*----------------------------------------------------------------------------------*/ | 214 | /*----------------------------------------------------------------------------------*/ |
198 | 215 | ||
199 | typedef int (*cryptopacket_handler_callback)(void *object, IP_Port ip_port, const uint8_t *source_pubkey, | 216 | typedef 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 | ||
202 | typedef struct { | 219 | typedef 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 | ||
207 | typedef struct { | 224 | #define DHT_DEFINED |
208 | Networking_Core *net; | 225 | typedef 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; | 227 | const uint8_t *dht_get_self_public_key(const DHT *dht); |
221 | uint16_t num_friends; | 228 | const uint8_t *dht_get_self_secret_key(const DHT *dht); |
229 | void dht_set_self_public_key(DHT *dht, const uint8_t *key); | ||
230 | void dht_set_self_secret_key(DHT *dht, const uint8_t *key); | ||
222 | 231 | ||
223 | Node_format *loaded_nodes_list; | 232 | Networking_Core *dht_get_net(const DHT *dht); |
224 | uint32_t loaded_num_nodes; | 233 | struct Ping *dht_get_ping(const DHT *dht); |
225 | unsigned int loaded_nodes_index; | 234 | const Client_data *dht_get_close_clientlist(const DHT *dht); |
235 | const Client_data *dht_get_close_client(const DHT *dht, uint32_t client_num); | ||
236 | uint16_t dht_get_num_friends(const DHT *dht); | ||
226 | 237 | ||
227 | Shared_Keys shared_keys_recv; | 238 | DHT_Friend *dht_get_friend(DHT *dht, uint32_t friend_num); |
228 | Shared_Keys shared_keys_sent; | 239 | const 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 | |||
264 | void DHT_getnodes(DHT *dht, const IP_Port *from_ipp, const uint8_t *from_id, const uint8_t *which_id); | 262 | void 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 | |||
287 | int DHT_delfriend(DHT *dht, const uint8_t *public_key, uint16_t lock_count); | 285 | int 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, | 310 | bool 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); | 315 | bool 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 | */ |
329 | int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, sa_family_t sa_family, | 327 | int 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 | |||
397 | uint32_t DHT_size(const DHT *dht); | 395 | uint32_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(). */ |
400 | void DHT_save(DHT *dht, uint8_t *data); | 398 | void 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); | |||
407 | int DHT_load(DHT *dht, const uint8_t *data, uint32_t length); | 405 | int DHT_load(DHT *dht, const uint8_t *data, uint32_t length); |
408 | 406 | ||
409 | /* Initialize DHT. */ | 407 | /* Initialize DHT. */ |
410 | DHT *new_DHT(Networking_Core *net); | 408 | DHT *new_DHT(Logger *log, Networking_Core *net, bool holepunching_enabled); |
411 | 409 | ||
412 | void kill_DHT(DHT *dht); | 410 | void 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 | */ |
417 | int DHT_isconnected(const DHT *dht); | 415 | bool 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 | */ |
422 | int DHT_non_lan_connected(const DHT *dht); | 420 | bool DHT_non_lan_connected(const DHT *dht); |
423 | 421 | ||
424 | 422 | ||
425 | int addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key); | 423 | uint32_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 | |||
31 | class dHT { struct this; } | ||
32 | class iP { struct this; } | ||
33 | |||
34 | namespace lan_discovery { | ||
35 | |||
36 | /** | ||
37 | * Interval in seconds between LAN discovery packet sending. | ||
38 | */ | ||
39 | const INTERVAL = 10; | ||
40 | |||
41 | /** | ||
42 | * Send a LAN discovery pcaket to the broadcast address with port port. | ||
43 | */ | ||
44 | static int32_t send(uint16_t port, dHT::this *dht); | ||
45 | |||
46 | /** | ||
47 | * Sets up packet handlers. | ||
48 | */ | ||
49 | static void init(dHT::this *dht); | ||
50 | |||
51 | /** | ||
52 | * Clear packet handlers. | ||
53 | */ | ||
54 | static void kill(dHT::this *dht); | ||
55 | |||
56 | } | ||
57 | |||
58 | /** | ||
59 | * Is IP a local ip or not. | ||
60 | */ | ||
61 | static 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 | */ | ||
69 | static 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. */ | ||
41 | static int broadcast_count = -1; | 39 | static int broadcast_count = -1; |
42 | static IP_Port broadcast_ip_port[MAX_INTERFACES]; | 40 | static 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 | ||
48 | static void fetch_broadcast_info(uint16_t port) | 54 | static 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 | ||
104 | static void fetch_broadcast_info(uint16_t port) | 135 | static 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 | ||
169 | static void fetch_broadcast_info(uint16_t port) | 215 | static 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. */ |
199 | static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast) | 246 | static 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) | 273 | bool 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 | */ |
259 | int LAN_ip(IP ip) | 303 | int 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 | ||
309 | static int handle_LANdiscovery(void *object, IP_Port source, const uint8_t *packet, uint16_t length) | 359 | static 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 | ||
324 | int send_LANdiscovery(uint16_t port, DHT *dht) | 379 | int 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 | ||
356 | void LANdiscovery_init(DHT *dht) | 415 | void 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 | ||
361 | void LANdiscovery_kill(DHT *dht) | 420 | void 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 |
31 | typedef 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 |
35 | int send_LANdiscovery(uint16_t port, DHT *dht); | 35 | #define IP_DEFINED |
36 | typedef struct IP IP; | ||
37 | #endif /* IP_DEFINED */ | ||
36 | 38 | ||
37 | /* Sets up packet handlers. */ | 39 | /** |
38 | void 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. */ | 44 | uint32_t lan_discovery_interval(void); |
41 | void 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 | */ | ||
49 | int32_t lan_discovery_send(uint16_t port, DHT *dht); | ||
50 | |||
51 | /** | ||
52 | * Sets up packet handlers. | ||
53 | */ | ||
54 | void lan_discovery_init(DHT *dht); | ||
55 | |||
56 | /** | ||
57 | * Clear packet handlers. | ||
58 | */ | ||
59 | void lan_discovery_kill(DHT *dht); | ||
60 | |||
61 | /** | ||
62 | * Is IP a local ip or not. | ||
63 | */ | ||
64 | bool 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 | */ |
51 | int LAN_ip(IP ip); | 72 | int32_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 @@ | |||
1 | lib_LTLIBRARIES += libtoxcore.la | 1 | lib_LTLIBRARIES += libtoxcore.la |
2 | 2 | ||
3 | libtoxcore_la_include_HEADERS = \ | 3 | libtoxcore_la_include_HEADERS = \ |
4 | ../toxcore/tox.h \ | 4 | ../toxcore/tox.h |
5 | ../toxcore/tox_old.h | ||
6 | 5 | ||
7 | libtoxcore_la_includedir = $(includedir)/tox | 6 | libtoxcore_la_includedir = $(includedir)/tox |
8 | 7 | ||
9 | libtoxcore_la_SOURCES = ../toxcore/DHT.h \ | 8 | libtoxcore_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 | ||
56 | libtoxcore_la_CFLAGS = -I$(top_srcdir) \ | 54 | libtoxcore_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 | ||
62 | libtoxcore_la_LDFLAGS = $(TOXCORE_LT_LDFLAGS) \ | 60 | libtoxcore_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 | |||
73 | if SET_SO_VERSION | ||
74 | |||
75 | EXTRA_libtoxcore_la_DEPENDENCIES = ../so.version | ||
76 | |||
77 | endif | ||
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 | |||
39 | static void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status); | ||
40 | static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data, | 40 | static 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 | */ |
59 | int realloc_friendlist(Messenger *m, uint32_t num) | 59 | static 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 | */ |
98 | int get_real_pk(const Messenger *m, int32_t friendnumber, uint8_t *real_pk) | 101 | int 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 | */ |
110 | int getfriendcon_id(const Messenger *m, int32_t friendnumber) | 114 | int 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 | */ |
138 | void getaddress(const Messenger *m, uint8_t *address) | 144 | void 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 | ||
147 | static int send_online_packet(Messenger *m, int32_t friendnumber) | 153 | static 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 | ||
164 | static int handle_status(void *object, int i, uint8_t status); | 171 | static int m_handle_status(void *object, int i, uint8_t status, void *userdata); |
165 | static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len); | 172 | static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t len, void *userdata); |
166 | static int handle_custom_lossy_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length); | 173 | static int m_handle_custom_lossy_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length, |
174 | void *userdata); | ||
167 | 175 | ||
168 | static int32_t init_new_friend(Messenger *m, const uint8_t *real_pk, uint8_t status) | 176 | static 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 | */ |
226 | int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, uint16_t length) | 237 | int32_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 | ||
279 | int32_t m_addfriend_norequest(Messenger *m, const uint8_t *real_pk) | 297 | int32_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 | ||
293 | static int clear_receipts(Messenger *m, int32_t friendnumber) | 314 | static 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 | ||
311 | static int add_receipt(Messenger *m, int32_t friendnumber, uint32_t packet_num, uint32_t msg_id) | 333 | static 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 | */ |
338 | static int friend_received_packet(const Messenger *m, int32_t friendnumber, uint32_t number) | 362 | static 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 | ||
347 | static int do_receipts(Messenger *m, int32_t friendnumber) | 372 | static 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 | */ |
379 | int m_delfriend(Messenger *m, int32_t friendnumber) | 410 | int 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 | ||
412 | int m_get_friend_connectionstatus(const Messenger *m, int32_t friendnumber) | 448 | int 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 | ||
437 | int m_friend_exists(const Messenger *m, int32_t friendnumber) | 474 | int 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) | |||
454 | int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, const uint8_t *message, uint32_t length, | 492 | int 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 | */ |
494 | static int m_sendname(const Messenger *m, int32_t friendnumber, const uint8_t *name, uint16_t length) | 539 | static 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 | */ |
507 | int setfriendname(Messenger *m, int32_t friendnumber, const uint8_t *name, uint16_t length) | 553 | int 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 | */ |
528 | int setname(Messenger *m, const uint8_t *name, uint16_t length) | 576 | int 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 | */ |
553 | uint16_t getself_name(const Messenger *m, uint8_t *name) | 605 | uint16_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 | */ |
570 | int getname(const Messenger *m, int32_t friendnumber, uint8_t *name) | 622 | int 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 | ||
579 | int m_get_name_size(const Messenger *m, int32_t friendnumber) | 632 | int 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 | ||
592 | int m_set_statusmessage(Messenger *m, const uint8_t *status, uint16_t length) | 646 | int 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 | ||
613 | int m_set_userstatus(Messenger *m, uint8_t status) | 671 | int 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 | */ |
633 | int m_get_statusmessage_size(const Messenger *m, int32_t friendnumber) | 694 | int 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 | */ |
644 | int m_copy_statusmessage(const Messenger *m, int32_t friendnumber, uint8_t *buf, uint32_t maxlen) | 706 | int 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 | ||
670 | uint8_t m_get_userstatus(const Messenger *m, int32_t friendnumber) | 733 | uint8_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 | ||
689 | uint64_t m_get_last_online(const Messenger *m, int32_t friendnumber) | 753 | uint64_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 | ||
697 | int m_set_usertyping(Messenger *m, int32_t friendnumber, uint8_t is_typing) | 762 | int 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 | ||
715 | int m_get_istyping(const Messenger *m, int32_t friendnumber) | 782 | int 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 | ||
739 | static int set_friend_statusmessage(const Messenger *m, int32_t friendnumber, const uint8_t *status, uint16_t length) | 807 | static 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 | ||
754 | static void set_friend_userstatus(const Messenger *m, int32_t friendnumber, uint8_t status) | 825 | static 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 | ||
759 | static void set_friend_typing(const Messenger *m, int32_t friendnumber, uint8_t is_typing) | 830 | static 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 | ||
835 | void 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. */ |
765 | void m_callback_friendrequest(Messenger *m, void (*function)(Messenger *m, const uint8_t *, const uint8_t *, size_t, | 841 | void 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. */ |
773 | void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, const uint8_t *, | 848 | void 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 | ||
780 | void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *), | 854 | void 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 | ||
787 | void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *), | 859 | void 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 | ||
794 | void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *), void *userdata) | 864 | void 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 | ||
800 | void m_callback_typingchange(Messenger *m, void(*function)(Messenger *m, uint32_t, _Bool, void *), void *userdata) | 869 | void 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 | ||
806 | void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, void *), void *userdata) | 874 | void 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 | ||
812 | void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *), | 879 | void 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 | ||
819 | void m_callback_core_connection(Messenger *m, void (*function)(Messenger *m, unsigned int, void *), void *userdata) | 884 | void 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 | ||
825 | void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, void *), | 889 | void 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 | ||
832 | static void check_friend_tcp_udp(Messenger *m, int32_t friendnumber) | 896 | static 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 | ||
857 | static void break_files(const Messenger *m, int32_t friendnumber); | 923 | static void break_files(const Messenger *m, int32_t friendnumber); |
858 | static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, uint8_t status) | 924 | static 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 | ||
887 | void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status) | 955 | static 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 | ||
893 | static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data, | 961 | static 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 | */ |
919 | void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, uint16_t)) | 990 | void 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 | */ |
930 | int send_group_invite_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length) | 1002 | int 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 | */ |
942 | void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint32_t, uint64_t, | 1014 | void 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 | */ |
954 | void callback_file_control(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, unsigned int, void *), | 1025 | void 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 | */ |
966 | void callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, const uint8_t *, | 1035 | void 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 | */ |
978 | void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *), | 1046 | void 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 | */ |
993 | int file_get_id(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint8_t *file_id) | 1059 | int 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 | |||
1037 | static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint32_t file_type, | 1107 | static 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 | |||
1070 | long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_type, uint64_t filesize, | 1142 | long 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 | ||
1106 | int send_file_control_packet(const Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber, | 1190 | static 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 | */ |
1137 | int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber, unsigned int control) | 1222 | int 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 | */ |
1230 | int file_seek(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position) | 1323 | int 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 | |||
1287 | static int64_t send_file_data_packet(const Messenger *m, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, | 1378 | static 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 | |||
1318 | int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data, | 1410 | int 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 | */ |
1384 | uint64_t file_dataremaining(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t send_receive) | 1482 | uint64_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 | ||
1404 | static 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 | */ | ||
1522 | static 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 | |||
1598 | static 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 | */ |
1490 | static void break_files(const Messenger *m, int32_t friendnumber) | 1637 | static 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. | 1651 | static struct File_Transfers *get_file_transfer(uint8_t receive_send, uint8_t filenumber, |
1505 | */ | 1652 | uint32_t *real_filenumber, Friend *sender) |
1506 | static 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 | */ | ||
1673 | static 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 | ||
1615 | static int handle_custom_lossy_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length) | 1805 | static 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 | ||
1637 | void custom_lossy_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m, | 1831 | void 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 | ||
1644 | int m_callback_rtp_packet(Messenger *m, int32_t friendnumber, uint8_t byte, int (*packet_handler_callback)(Messenger *m, | 1837 | int 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 | ||
1663 | int send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length) | 1858 | int 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 | ||
1688 | static int handle_custom_lossless_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length) | 1888 | static 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 | ||
1707 | void custom_lossless_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m, | 1912 | void 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 | ||
1714 | int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length) | 1918 | int 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*/ |
1740 | static int friend_already_added(const uint8_t *real_pk, void *data) | 1949 | static 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. */ |
1751 | Messenger *new_messenger(Messenger_Options *options, unsigned int *error) | 1961 | Messenger *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. */ |
1848 | void kill_messenger(Messenger *m) | 2095 | void 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 | */ |
1880 | static void check_friend_request_timed_out(Messenger *m, uint32_t i, uint64_t t) | 2130 | static 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 | ||
1893 | static int handle_status(void *object, int i, uint8_t status) | 2143 | static 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 | ||
1908 | static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) | 2158 | static 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 | ||
2178 | void do_friends(Messenger *m) | 2471 | static 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 | ||
2235 | static void connection_status_cb(Messenger *m) | 2532 | static 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 |
2250 | static time_t lastdump = 0; | 2547 | |
2251 | static char IDString[crypto_box_PUBLICKEYBYTES * 2 + 1]; | 2548 | #define IDSTRING_LEN (CRYPTO_PUBLIC_KEY_SIZE * 2 + 1) |
2252 | static char *ID2String(const uint8_t *pk) | 2549 | /* id_str should be of length at least IDSTRING_LEN */ |
2550 | static 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. */ |
2285 | void do_messenger(Messenger *m) | 2586 | void 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 | |||
2443 | struct SAVED_FRIEND { | 2755 | struct 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 | ||
2769 | static 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 | |||
2457 | static uint32_t saved_friendslist_size(const Messenger *m) | 2799 | static 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 | |||
2804 | static 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 | ||
2462 | static uint32_t friends_list_save(const Messenger *m, uint8_t *data) | 2836 | static 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 | |||
2883 | static 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 | ||
2504 | static int friends_list_load(Messenger *m, const uint8_t *data, uint32_t length) | 2915 | static 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 | ||
2560 | static uint8_t *z_state_save_subheader(uint8_t *data, uint32_t len, uint16_t type) | 2978 | static 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 | ||
2653 | static int messenger_load_state_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type) | 3069 | static 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. */ |
2789 | uint32_t copy_friendlist(Messenger const *m, uint32_t *out_list, uint32_t list_size) | 3204 | uint32_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 | ||
39 | enum { | 47 | enum { |
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 | ||
68 | typedef struct { | 76 | typedef 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 | |||
158 | enum { | 169 | enum { |
159 | FILECONTROL_ACCEPT, | 170 | FILECONTROL_ACCEPT, |
160 | FILECONTROL_PAUSE, | 171 | FILECONTROL_PAUSE, |
@@ -171,7 +182,7 @@ enum { | |||
171 | typedef struct Messenger Messenger; | 182 | typedef struct Messenger Messenger; |
172 | 183 | ||
173 | typedef struct { | 184 | typedef 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 | |||
211 | struct Messenger { | 221 | struct 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); | |||
322 | int32_t getfriend_id(const Messenger *m, const uint8_t *real_pk); | 321 | int32_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 | */ |
471 | int m_get_istyping(const Messenger *m, int32_t friendnumber); | 470 | int m_get_istyping(const Messenger *m, int32_t friendnumber); |
472 | 471 | ||
472 | /* Set the logger callback. | ||
473 | */ | ||
474 | void 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 | */ |
476 | void m_callback_friendrequest(Messenger *m, void (*function)(Messenger *m, const uint8_t *, const uint8_t *, size_t, | 479 | void 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 | */ |
482 | void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, const uint8_t *, | 485 | void 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 | */ |
489 | void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *), | 492 | void 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 | */ |
497 | void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *), | 499 | void 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 | */ |
503 | void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *), | 504 | void 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 | */ |
509 | void m_callback_typingchange(Messenger *m, void(*function)(Messenger *m, uint32_t, _Bool, void *), void *userdata); | 509 | void 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 | */ |
520 | void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, void *), void *userdata); | 520 | void 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 | */ |
533 | void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *), | 533 | void 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 */ |
536 | void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, void *), | 536 | void 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 | */ |
543 | void m_callback_core_connection(Messenger *m, void (*function)(Messenger *m, unsigned int, void *), void *userdata); | 543 | void 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 | */ |
551 | void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, uint16_t)); | 551 | void 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 | */ |
558 | int send_group_invite_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length); | 559 | int 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 | */ |
567 | void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint32_t, uint64_t, | 568 | void 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 | */ |
576 | void callback_file_control(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, unsigned int, void *), | 577 | void 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 | */ |
584 | void callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, const uint8_t *, | 584 | void 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 | */ |
592 | void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *), | 592 | void 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 | */ |
695 | void custom_lossy_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m, | 694 | void 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 | */ |
707 | int send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length); | 706 | int 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 | */ |
713 | void custom_lossless_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m, | 712 | void 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); | |||
747 | void kill_messenger(Messenger *m); | 746 | void 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. */ |
750 | void do_messenger(Messenger *m); | 749 | void 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 | ||
36 | struct 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 | |||
87 | const uint8_t *tcp_con_public_key(const TCP_Client_Connection *con) | ||
88 | { | ||
89 | return con->public_key; | ||
90 | } | ||
91 | |||
92 | IP_Port tcp_con_ip_port(const TCP_Client_Connection *con) | ||
93 | { | ||
94 | return con->ip_port; | ||
95 | } | ||
96 | |||
97 | TCP_CLIENT_STATUS tcp_con_status(const TCP_Client_Connection *con) | ||
98 | { | ||
99 | return con->status; | ||
100 | } | ||
101 | void *tcp_con_custom_object(const TCP_Client_Connection *con) | ||
102 | { | ||
103 | return con->custom_object; | ||
104 | } | ||
105 | uint32_t tcp_con_custom_uint(const TCP_Client_Connection *con) | ||
106 | { | ||
107 | return con->custom_uint; | ||
108 | } | ||
109 | void tcp_con_set_custom_object(TCP_Client_Connection *con, void *object) | ||
110 | { | ||
111 | con->custom_object = object; | ||
112 | } | ||
113 | void 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 | */ |
38 | static int connect_sock_to(sock_t sock, IP_Port ip_port, TCP_Proxy_Info *proxy_info) | 121 | static 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 | */ |
190 | static int proxy_socks5_read_connection_response(TCP_Client_Connection *TCP_conn) | 253 | static 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 | */ |
219 | static int generate_handshake(TCP_Client_Connection *TCP_conn) | 285 | static 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 | */ |
243 | static int handle_handshake(TCP_Client_Connection *TCP_conn, const uint8_t *data) | 310 | static 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 | */ |
261 | static int send_pending_data_nonpriority(TCP_Client_Connection *con) | 329 | static 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 | */ |
286 | static int send_pending_data(TCP_Client_Connection *con) | 355 | static 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 | */ |
325 | static _Bool add_priority(TCP_Client_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent) | 394 | static 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 | */ |
365 | static int write_packet_TCP_secure_connection(TCP_Client_Connection *con, const uint8_t *data, uint16_t length, | 433 | static 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 | */ |
426 | int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key) | 498 | int 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 | ||
434 | void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id, | 506 | void 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 | ||
448 | static int send_ping_response(TCP_Client_Connection *con); | 520 | static int tcp_send_ping_response(TCP_Client_Connection *con); |
449 | static int send_ping_request(TCP_Client_Connection *con); | 521 | static 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 | */ |
455 | int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length) | 527 | int 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 | */ |
476 | int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data, uint16_t length) | 551 | int 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 | */ |
496 | int set_tcp_connection_number(TCP_Client_Connection *con, uint8_t con_id, uint32_t number) | 572 | int 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 | ||
508 | void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number, | 586 | void 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 | ||
515 | void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, const uint8_t *public_key, | 593 | void 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 | */ |
526 | static int send_disconnect_notification(TCP_Client_Connection *con, uint8_t id) | 604 | static 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 | */ |
538 | static int send_ping_request(TCP_Client_Connection *con) | 616 | static 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 | */ |
559 | static int send_ping_response(TCP_Client_Connection *con) | 638 | static 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 | */ |
580 | int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id) | 660 | int 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 | */ |
594 | int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t length) | 675 | int 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 | ||
602 | void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, const uint8_t *data, | 683 | void 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 | */ |
695 | static int handle_TCP_packet(TCP_Client_Connection *conn, const uint8_t *data, uint16_t length) | 777 | static 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 | ||
827 | static int do_confirmed_TCP(TCP_Client_Connection *conn) | 930 | static 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 | */ |
870 | void do_TCP_connection(TCP_Client_Connection *TCP_connection) | 974 | void 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 | */ |
958 | void kill_TCP_connection(TCP_Client_Connection *TCP_connection) | 1062 | void 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 | ||
43 | enum { | 43 | typedef 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; |
53 | typedef struct { | 53 | typedef struct TCP_Client_Connection TCP_Client_Connection; |
54 | uint8_t status; | 54 | |
55 | sock_t sock; | 55 | const uint8_t *tcp_con_public_key(const TCP_Client_Connection *con); |
56 | uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; /* our public key */ | 56 | IP_Port tcp_con_ip_port(const TCP_Client_Connection *con); |
57 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* public key of the server */ | 57 | TCP_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; | 59 | void *tcp_con_custom_object(const TCP_Client_Connection *con); |
60 | uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */ | 60 | uint32_t tcp_con_custom_uint(const TCP_Client_Connection *con); |
61 | uint8_t sent_nonce[crypto_box_NONCEBYTES]; /* Nonce of sent packets. */ | 61 | void tcp_con_set_custom_object(TCP_Client_Connection *con, void *object); |
62 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; | 62 | void 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 | */ |
110 | void do_TCP_connection(TCP_Client_Connection *TCP_connection); | 71 | void 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 | */ |
120 | int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t length); | 81 | int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t length); |
121 | void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, const uint8_t *data, | 82 | void 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 | */ |
153 | int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length); | 114 | int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length); |
154 | void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number, | 115 | void 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 | */ |
161 | int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data, uint16_t length); | 122 | int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data, uint16_t length); |
162 | void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, const uint8_t *public_key, | 123 | void 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 | |||
37 | struct 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 | |||
66 | const 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) \ |
78 | static 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 | |||
97 | MAKE_REALLOC(TCP_Connection_to) | ||
98 | MAKE_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 | */ |
42 | static _Bool connections_number_not_valid(const TCP_Connections *tcp_c, int connections_number) | 104 | static 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 | */ |
59 | static _Bool tcp_connections_number_not_valid(const TCP_Connections *tcp_c, int tcp_connections_number) | 124 | static 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 | */ |
133 | static int wipe_connection(TCP_Connections *tcp_c, int connections_number) | 198 | static 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 | */ |
160 | static int wipe_tcp_connection(TCP_Connections *tcp_c, int tcp_connections_number) | 226 | static 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 | ||
182 | static TCP_Connection_to *get_connection(const TCP_Connections *tcp_c, int connections_number) | 249 | static 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 | ||
190 | static TCP_con *get_tcp_connection(const TCP_Connections *tcp_c, int tcp_connections_number) | 258 | static 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 | */ |
348 | void set_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_data_callback)(void *object, int id, | 423 | void 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 | */ |
357 | void set_oob_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_oob_callback)(void *object, | 432 | void 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 | */ |
366 | void set_onion_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_onion_callback)(void *object, | 442 | void 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 | */ |
433 | int new_tcp_connection_to(TCP_Connections *tcp_c, const uint8_t *public_key, int id) | 509 | int 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 | */ |
499 | int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number, _Bool status) | 579 | int 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 | ||
555 | static _Bool tcp_connection_in_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number) | 640 | static 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 | ||
818 | static int tcp_response_callback(void *object, uint8_t connection_id, const uint8_t *public_key) | 915 | static 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 | ||
847 | static int tcp_status_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t status) | 948 | static 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 | ||
882 | static int tcp_data_callback(void *object, uint32_t number, uint8_t connection_id, const uint8_t *data, uint16_t length) | 986 | static 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 | ||
908 | static int tcp_oob_callback(void *object, const uint8_t *public_key, const uint8_t *data, uint16_t length) | 1016 | static 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 | ||
937 | static int tcp_onion_callback(void *object, const uint8_t *data, uint16_t length) | 1049 | static 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 | ||
1011 | static int add_tcp_relay_instance(TCP_Connections *tcp_c, IP_Port ip_port, const uint8_t *relay_pk) | 1126 | static 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 | */ |
1184 | int set_tcp_onion_status(TCP_Connections *tcp_c, _Bool status) | 1311 | int 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 | */ |
1251 | TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *proxy_info) | 1381 | TCP_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 | ||
1268 | static void do_tcp_conns(TCP_Connections *tcp_c) | 1400 | static 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 | ||
1310 | static void kill_nonused_tcp(TCP_Connections *tcp_c) | 1445 | static 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 | ||
1346 | void do_tcp_connections(TCP_Connections *tcp_c) | 1486 | void 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 | ||
54 | typedef struct { | 54 | typedef 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 | ||
81 | typedef struct { | 81 | typedef 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; | 83 | const 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 | */ |
141 | int set_tcp_onion_status(TCP_Connections *tcp_c, _Bool status); | 117 | int 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 | */ |
153 | void set_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_data_callback)(void *object, int id, | 129 | void 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 | */ |
158 | void set_onion_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_onion_callback)(void *object, | 134 | void 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 | */ |
163 | void set_oob_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_oob_callback)(void *object, | 139 | void 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 | */ |
192 | int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number, _Bool status); | 169 | int 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 | */ |
240 | TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *proxy_info); | 217 | TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *proxy_info); |
241 | 218 | ||
242 | void do_tcp_connections(TCP_Connections *tcp_c); | 219 | void do_tcp_connections(TCP_Connections *tcp_c, void *userdata); |
243 | void kill_tcp_connections(TCP_Connections *tcp_c); | 220 | void 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 | 44 | typedef struct TCP_Secure_Connection { |
36 | * return 0 on failure | 45 | Socket sock; |
37 | */ | 46 | uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; |
38 | static 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); | 71 | struct 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 | |||
97 | const uint8_t *tcp_server_public_key(const TCP_Server *tcp_server) | ||
98 | { | ||
99 | return tcp_server->public_key; | ||
100 | } | ||
101 | |||
102 | size_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 | */ |
161 | static int del_accepted(TCP_Server *TCP_server, int index) | 218 | static 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 | */ | ||
184 | unsigned 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 | */ |
204 | uint16_t read_TCP_length(sock_t sock) | 249 | uint16_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 | */ |
234 | int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length) | 279 | int 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 | */ |
256 | int read_packet_TCP_secure_connection(sock_t sock, uint16_t *next_packet_length, const uint8_t *shared_key, | 301 | int 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 | */ |
360 | static _Bool add_priority(TCP_Secure_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent) | 410 | static 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 | */ |
388 | static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length, | 438 | static 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 | */ |
447 | static void kill_TCP_connection(TCP_Secure_Connection *con) | 501 | static 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 | ||
453 | static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number); | 507 | static 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 | */ |
460 | static int kill_accepted(TCP_Server *TCP_server, int index) | 514 | static 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) | |||
483 | static int handle_TCP_handshake(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length, | 539 | static 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 | */ |
546 | static int send_routing_response(TCP_Secure_Connection *con, uint8_t rpid, const uint8_t *public_key) | 607 | static 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 | */ |
560 | static int send_connect_notification(TCP_Secure_Connection *con, uint8_t id) | 621 | static 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 | */ |
570 | static int send_disconnect_notification(TCP_Secure_Connection *con, uint8_t id) | 631 | static 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 | |||
657 | static int handle_TCP_oob_send(TCP_Server *TCP_server, uint32_t con_id, const uint8_t *public_key, const uint8_t *data, | 722 | static 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 | */ |
684 | static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number) | 750 | static 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 | ||
714 | static int handle_onion_recv_1(void *object, IP_Port dest, const uint8_t *data, uint16_t length) | 782 | static 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 | */ |
740 | static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, const uint8_t *data, uint16_t length) | 811 | static 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 | */ |
884 | static int accept_connection(TCP_Server *TCP_server, sock_t sock) | 968 | static 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 | ||
914 | static sock_t new_listening_TCP_socket(int family, uint16_t port) | 1000 | static 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) | |||
942 | TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, const uint16_t *ports, const uint8_t *secret_key, | 1028 | TCP_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 | ||
1026 | static void do_TCP_accept_new(TCP_Server *TCP_server) | 1109 | static 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 | ||
1041 | static int do_incoming(TCP_Server *TCP_server, uint32_t i) | 1123 | static 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 | ||
1089 | static void do_confirmed_recv(TCP_Server *TCP_server, uint32_t i) | 1176 | static 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 | ||
1110 | static void do_TCP_incomming(TCP_Server *TCP_server) | 1197 | #ifndef TCP_SERVER_USE_EPOLL |
1198 | static 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 | ||
1128 | static void do_TCP_confirmed(TCP_Server *TCP_server) | 1217 | static 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 | ||
91 | typedef struct TCP_Secure_Connection { | 88 | typedef 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; | 90 | const uint8_t *tcp_server_public_key(const TCP_Server *tcp_server); |
112 | 91 | size_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 | |||
118 | typedef 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 | */ |
155 | void kill_TCP_server(TCP_Server *TCP_server); | 104 | void 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 | */ | ||
160 | unsigned 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 | */ |
169 | uint16_t read_TCP_length(sock_t sock); | 113 | uint16_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 | */ |
176 | int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length); | 120 | int 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 | */ |
182 | int read_packet_TCP_secure_connection(sock_t sock, uint16_t *next_packet_length, const uint8_t *shared_key, | 126 | int 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 */ | ||
54 | typedef uint16_t bucket_t; | ||
55 | typedef uint32_t hash_t; | ||
56 | typedef uint16_t usecnt_t; | ||
57 | |||
58 | /* abbreviations ... */ | ||
59 | typedef Assoc_distance_relative_callback dist_rel_cb; | ||
60 | typedef Assoc_distance_absolute_callback dist_abs_cb; | ||
61 | |||
62 | /* | ||
63 | * Client_data wrapped with additional data | ||
64 | */ | ||
65 | typedef 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 | |||
84 | typedef struct candidates_bucket { | ||
85 | Client_entry *list; /* hashed list */ | ||
86 | } candidates_bucket; | ||
87 | |||
88 | struct 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 */ | ||
106 | static 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 */ | ||
124 | static 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 */ | ||
139 | static 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 */ | ||
161 | static 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 */ | ||
172 | static 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. */ | ||
199 | static 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 */ | ||
216 | static 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 */ | ||
244 | static 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 */ | ||
259 | static 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 */ | ||
274 | static 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() */ | ||
318 | static 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 | |||
324 | static 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 | |||
344 | static bucket_t candidates_id_bucket(const Assoc *assoc, const uint8_t *id) | ||
345 | { | ||
346 | return id_bucket(id, assoc->candidates_bucket_bits); | ||
347 | } | ||
348 | |||
349 | static 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 | |||
369 | static 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 | |||
401 | static 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 | |||
458 | static 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 | |||
511 | static 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 | */ | ||
552 | uint8_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 | |||
602 | uint8_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 | |||
753 | static 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 | |||
767 | static 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 */ | ||
779 | Assoc *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 | |||
864 | Assoc *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 */ | ||
872 | void 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 | ||
882 | static char *idpart2str(uint8_t *id, size_t len); | ||
883 | #endif /* TOX_LOGGER */ | ||
884 | |||
885 | /* refresh buckets */ | ||
886 | void 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 */ | ||
968 | void 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 | |||
979 | static char buffer[crypto_box_PUBLICKEYBYTES * 2 + 1]; | ||
980 | static 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 | |||
994 | void 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 */ | ||
11 | enum 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 | |||
18 | typedef struct Assoc Assoc; | ||
19 | |||
20 | /*****************************************************************************/ | ||
21 | |||
22 | /* custom distance handler, if it's not ID-distance based | ||
23 | * return values exactly like id_closest() */ | ||
24 | typedef 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 */ | ||
31 | typedef 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 */ | ||
38 | uint8_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 | |||
43 | typedef enum AssocCloseEntriesFlags { | ||
44 | ProtoIPv4 = 1, | ||
45 | ProtoIPv6 = 2, | ||
46 | LANOk = 4, | ||
47 | } AssocCloseEntriesFlags; | ||
48 | |||
49 | typedef 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 | */ | ||
71 | uint8_t Assoc_get_close_entries(Assoc *assoc, Assoc_close_entries *close_entries); | ||
72 | |||
73 | /*****************************************************************************/ | ||
74 | |||
75 | /* create: default sizes (6, 5 => 320 entries) */ | ||
76 | Assoc *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) */ | ||
85 | Assoc *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 */ | ||
88 | void 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 */ | ||
95 | void do_Assoc(Assoc *assoc, DHT *dht); | ||
96 | |||
97 | /* destroy */ | ||
98 | void kill_Assoc(Assoc *assoc); | ||
99 | |||
100 | #ifdef TOX_LOGGER | ||
101 | void 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 | ||
33 | extern "C" { | ||
34 | #endif | ||
35 | %} | ||
36 | |||
37 | /** | ||
38 | * The number of bytes in a Tox public key. | ||
39 | */ | ||
40 | const CRYPTO_PUBLIC_KEY_SIZE = 32; | ||
41 | |||
42 | /** | ||
43 | * The number of bytes in a Tox secret key. | ||
44 | */ | ||
45 | const CRYPTO_SECRET_KEY_SIZE = 32; | ||
46 | |||
47 | /** | ||
48 | * The number of bytes in a shared key computed from public and secret keys. | ||
49 | */ | ||
50 | const CRYPTO_SHARED_KEY_SIZE = 32; | ||
51 | |||
52 | /** | ||
53 | * The number of bytes in a symmetric key. | ||
54 | */ | ||
55 | const 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 | */ | ||
61 | const CRYPTO_MAC_SIZE = 16; | ||
62 | |||
63 | /** | ||
64 | * The number of bytes in a nonce used for encryption/decryption. | ||
65 | */ | ||
66 | const CRYPTO_NONCE_SIZE = 24; | ||
67 | |||
68 | /** | ||
69 | * The number of bytes in a SHA256 hash. | ||
70 | */ | ||
71 | const CRYPTO_SHA256_SIZE = 32; | ||
72 | |||
73 | /** | ||
74 | * The number of bytes in a SHA512 hash. | ||
75 | */ | ||
76 | const 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 | */ | ||
87 | static 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 | */ | ||
95 | static void crypto_memzero(void *data, size_t length); | ||
96 | |||
97 | /** | ||
98 | * Compute a SHA256 hash (32 bytes). | ||
99 | */ | ||
100 | static void crypto_sha256(uint8_t[CRYPTO_SHA256_SIZE] hash, const uint8_t[length] data); | ||
101 | |||
102 | /** | ||
103 | * Compute a SHA512 hash (64 bytes). | ||
104 | */ | ||
105 | static 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 | */ | ||
113 | static int32_t public_key_cmp( | ||
114 | const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] pk1, | ||
115 | const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] pk2); | ||
116 | |||
117 | namespace random { | ||
118 | |||
119 | /** | ||
120 | * Return a random 8 bit integer. | ||
121 | */ | ||
122 | static uint8_t u08(); | ||
123 | |||
124 | /** | ||
125 | * Return a random 16 bit integer. | ||
126 | */ | ||
127 | static uint16_t u16(); | ||
128 | |||
129 | /** | ||
130 | * Return a random 32 bit integer. | ||
131 | */ | ||
132 | static uint32_t u32(); | ||
133 | |||
134 | /** | ||
135 | * Return a random 64 bit integer. | ||
136 | */ | ||
137 | static uint64_t u64(); | ||
138 | |||
139 | /** | ||
140 | * Fill the given nonce with random bytes. | ||
141 | */ | ||
142 | static void nonce(uint8_t[CRYPTO_NONCE_SIZE] nonce); | ||
143 | |||
144 | /** | ||
145 | * Fill an array of bytes with random values. | ||
146 | */ | ||
147 | static 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 | */ | ||
157 | static 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 | */ | ||
163 | static 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 | */ | ||
170 | static 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 | */ | ||
183 | static 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 | */ | ||
200 | static 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 | */ | ||
212 | static 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 | */ | ||
225 | static 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 | */ | ||
239 | static 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 | */ | ||
249 | static 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 | */ | ||
255 | static 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 | */ | ||
260 | static 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 |
39 | int 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 | |||
81 | int32_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. | 89 | uint8_t random_u08(void) |
45 | */ | 90 | { |
46 | uint32_t random_int(void) | 91 | uint8_t randnum; |
92 | randombytes(&randnum, 1); | ||
93 | return randnum; | ||
94 | } | ||
95 | |||
96 | uint16_t random_u16(void) | ||
97 | { | ||
98 | uint16_t randnum; | ||
99 | randombytes((uint8_t *)&randnum, sizeof(randnum)); | ||
100 | return randnum; | ||
101 | } | ||
102 | |||
103 | uint32_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 | ||
53 | uint64_t random_64b(void) | 110 | uint64_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. | 117 | bool 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 | */ | ||
66 | int 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 | */ |
79 | void encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key, uint8_t *enc_key) | 131 | int32_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 | ||
84 | int encrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *plain, uint32_t length, | 136 | int32_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 | ||
104 | int decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *encrypted, uint32_t length, | 158 | int32_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 | ||
123 | int encrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce, | 179 | int32_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 | ||
136 | int decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce, | 193 | int32_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. */ |
151 | void increment_nonce(uint8_t *nonce) | 209 | void 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 | |||
227 | static 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 */ |
169 | void increment_nonce_number(uint8_t *nonce, uint32_t host_order_num) | 241 | void 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 */ |
201 | void new_symmetric_key(uint8_t *key) | 273 | void 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.*/ | 278 | int32_t crypto_new_keypair(uint8_t *public_key, uint8_t *secret_key) |
207 | void 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. | 283 | void 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 | */ | ||
222 | int 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 | 288 | void 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 | */ | ||
256 | int 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) | 293 | void 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]; | 298 | void 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 | 32 | extern "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. | 40 | uint32_t crypto_public_key_size(void); |
48 | returns 0 if both mem locations of length are equal, | ||
49 | return -1 if they are not. */ | ||
50 | int 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 | */ |
57 | uint32_t random_int(void); | 45 | #define CRYPTO_SECRET_KEY_SIZE 32 |
58 | uint64_t random_64b(void); | ||
59 | 46 | ||
60 | /* Check if a Tox public key crypto_box_PUBLICKEYBYTES is valid or not. | 47 | uint32_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 | */ |
66 | int 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 | 54 | uint32_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 | */ |
74 | int 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 | ||
61 | uint32_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 | */ |
84 | int 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. | 69 | uint32_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 | /** |
90 | void 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 | 76 | uint32_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 | |||
83 | uint32_t crypto_sha256_size(void); | ||
84 | |||
85 | /** | ||
86 | * The number of bytes in a SHA512 hash. | ||
87 | */ | ||
88 | #define CRYPTO_SHA512_SIZE 64 | ||
89 | |||
90 | uint32_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 | */ |
98 | int encrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *plain, uint32_t length, | 101 | int32_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 | */ | ||
109 | void crypto_memzero(void *data, size_t length); | ||
110 | |||
111 | /** | ||
112 | * Compute a SHA256 hash (32 bytes). | ||
113 | */ | ||
114 | void crypto_sha256(uint8_t *hash, const uint8_t *data, size_t length); | ||
115 | |||
116 | /** | ||
117 | * Compute a SHA512 hash (64 bytes). | ||
118 | */ | ||
119 | void 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 | */ |
107 | int decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *encrypted, uint32_t length, | 127 | int32_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 | /** |
111 | void increment_nonce(uint8_t *nonce); | 130 | * Return a random 8 bit integer. |
131 | */ | ||
132 | uint8_t random_u08(void); | ||
112 | 133 | ||
113 | /* increment the given nonce by num */ | 134 | /** |
114 | void increment_nonce_number(uint8_t *nonce, uint32_t host_order_num); | 135 | * Return a random 16 bit integer. |
136 | */ | ||
137 | uint16_t random_u16(void); | ||
138 | |||
139 | /** | ||
140 | * Return a random 32 bit integer. | ||
141 | */ | ||
142 | uint32_t random_u32(void); | ||
115 | 143 | ||
116 | /* Fill the given nonce with random bytes. */ | 144 | /** |
145 | * Return a random 64 bit integer. | ||
146 | */ | ||
147 | uint64_t random_u64(void); | ||
148 | |||
149 | /** | ||
150 | * Fill the given nonce with random bytes. | ||
151 | */ | ||
117 | void random_nonce(uint8_t *nonce); | 152 | void random_nonce(uint8_t *nonce); |
118 | 153 | ||
119 | /* Fill a key crypto_box_KEYBYTES big with random bytes */ | 154 | /** |
120 | void new_symmetric_key(uint8_t *key); | 155 | * Fill an array of bytes with random values. |
156 | */ | ||
157 | void random_bytes(uint8_t *bytes, size_t length); | ||
121 | 158 | ||
122 | /*Gives a nonce guaranteed to be different from previous ones.*/ | 159 | /** |
123 | void 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 | */ | ||
165 | bool 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 | */ | ||
171 | int32_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. */ | 176 | void 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 | */ | ||
187 | int32_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 | */ |
142 | int create_request(const uint8_t *send_public_key, const uint8_t *send_secret_key, uint8_t *packet, | 199 | int32_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. |
149 | int 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); | 207 | int32_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 | */ | ||
217 | int32_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 | */ | ||
228 | int32_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 | */ | ||
235 | void 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 | */ | ||
241 | void 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 | */ | ||
246 | void 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 | |||
36 | void 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 | |||
68 | int32_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 | |||
7 | namespace | ||
8 | { | ||
9 | |||
10 | enum { | ||
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 | |||
31 | clock_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 | */ | ||
43 | void 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 | */ | ||
64 | TEST(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, ¬_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 | */ | ||
34 | static 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) | 38 | typedef 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 | |||
71 | struct 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 | |||
89 | Net_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 | */ | ||
98 | static 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 | */ |
54 | static int realloc_friendconns(Friend_Connections *fr_c, uint32_t num) | 111 | static 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 | */ |
76 | static int create_friend_conn(Friend_Connections *fr_c) | 134 | static 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 | */ |
101 | static int wipe_friend_conn(Friend_Connections *fr_c, int friendcon_id) | 158 | static 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 | ||
122 | static Friend_Conn *get_conn(const Friend_Connections *fr_c, int friendcon_id) | 182 | static 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 | */ |
133 | int getfriend_conn_id_pk(Friend_Connections *fr_c, const uint8_t *real_pk) | 194 | int 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 | */ |
154 | int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, IP_Port ip_port, const uint8_t *public_key) | 214 | int 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. */ |
189 | static void connect_to_saved_tcp_relays(Friend_Connections *fr_c, int friendcon_id, unsigned int number) | 248 | static 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 | ||
210 | static unsigned int send_relays(Friend_Connections *fr_c, int friendcon_id) | 268 | static 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. */ |
248 | static int tcp_relay_node_callback(void *object, uint32_t number, IP_Port ip_port, const uint8_t *public_key) | 305 | static 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 | ||
263 | static int friend_new_connection(Friend_Connections *fr_c, int friendcon_id); | 321 | static 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. */ |
265 | static void dht_ip_callback(void *object, int32_t number, IP_Port ip_port) | 323 | static 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 | ||
287 | static void change_dht_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_public_key) | 346 | static 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 | ||
309 | static int handle_status(void *object, int number, uint8_t status) | 369 | static 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. */ |
351 | static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_public_key) | 414 | static 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 | ||
375 | static int handle_packet(void *object, int number, uint8_t *data, uint16_t length) | 440 | static 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 | ||
426 | static int handle_lossy_packet(void *object, int number, const uint8_t *data, uint16_t length) | 498 | static 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 | ||
453 | static int handle_new_connections(void *object, New_Connection *n_c) | 528 | static 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 | ||
493 | static int friend_new_connection(Friend_Connections *fr_c, int friendcon_id) | 568 | static 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 | ||
523 | static int send_ping(const Friend_Connections *fr_c, int friendcon_id) | 600 | static 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 | */ |
546 | int friend_connection_lock(Friend_Connections *fr_c, int friendcon_id) | 624 | int 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 | */ |
561 | unsigned int friend_con_connected(Friend_Connections *fr_c, int friendcon_id) | 640 | unsigned 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 | */ |
576 | int get_friendcon_public_keys(uint8_t *real_pk, uint8_t *dht_temp_pk, Friend_Connections *fr_c, int friendcon_id) | 656 | int 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 | */ |
594 | void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_temp_pk) | 677 | void 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 | */ |
605 | int friend_connection_callbacks(Friend_Connections *fr_c, int friendcon_id, unsigned int index, | 688 | int 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 | */ |
637 | int friend_connection_crypt_connection_id(Friend_Connections *fr_c, int friendcon_id) | 719 | int 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 | */ |
690 | int kill_friend_connection(Friend_Connections *fr_c, int friendcon_id) | 775 | int 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 | */ |
717 | void set_friend_request_callback(Friend_Connections *fr_c, int (*fr_request_callback)(void *, const uint8_t *, | 803 | void 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 | |||
731 | int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint32_t nospam_num, const uint8_t *data, | 817 | int 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. */ |
761 | Friend_Connections *new_friend_connections(Onion_Client *onion_c) | 850 | Friend_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) | |||
782 | static void LANdiscovery(Friend_Connections *fr_c) | 879 | static 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. */ |
791 | void do_friend_connections(Friend_Connections *fr_c) | 901 | void 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. */ |
842 | void kill_friend_connections(Friend_Connections *fr_c) | 953 | void 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 | ||
66 | typedef struct { | 64 | typedef 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 | |||
104 | typedef 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; | 66 | Net_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 | */ |
145 | void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_temp_pk); | 95 | void 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 | */ |
160 | int friend_connection_callbacks(Friend_Connections *fr_c, int friendcon_id, unsigned int index, | 110 | int 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 | */ |
200 | void set_friend_request_callback(Friend_Connections *fr_c, int (*fr_request_callback)(void *, const uint8_t *, | 151 | void 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. */ |
204 | Friend_Connections *new_friend_connections(Onion_Client *onion_c); | 155 | Friend_Connections *new_friend_connections(Onion_Client *onion_c, bool local_discovery_enabled); |
205 | 156 | ||
206 | /* main friend_connections loop. */ | 157 | /* main friend_connections loop. */ |
207 | void do_friend_connections(Friend_Connections *fr_c); | 158 | void 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. */ |
210 | void kill_friend_connections(Friend_Connections *fr_c); | 161 | void 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 | ||
35 | struct 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. */ |
33 | void set_nospam(Friend_Requests *fr, uint32_t num) | 54 | void 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. */ |
45 | void callback_friendrequest(Friend_Requests *fr, void (*function)(void *, const uint8_t *, const uint8_t *, size_t, | 66 | void 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. */ |
54 | void set_filter_function(Friend_Requests *fr, int (*function)(const uint8_t *, void *), void *userdata) | 75 | void 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. */ |
61 | static void addto_receivedlist(Friend_Requests *fr, const uint8_t *real_pk) | 82 | static 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 | */ |
75 | static int request_received(Friend_Requests *fr, const uint8_t *real_pk) | 97 | static 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 | */ |
91 | int remove_request_received(Friend_Requests *fr, const uint8_t *real_pk) | 113 | int 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 | ||
106 | static int friendreq_handlepacket(void *object, const uint8_t *source_pubkey, const uint8_t *packet, uint16_t length) | 126 | static 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 | |||
172 | Friend_Requests *friendreq_new(void) | ||
173 | { | ||
174 | return (Friend_Requests *)calloc(1, sizeof(Friend_Requests)); | ||
175 | } | ||
176 | |||
177 | void 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 | ||
31 | typedef struct { | 31 | typedef 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. */ |
51 | void set_nospam(Friend_Requests *fr, uint32_t num); | 34 | void 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 | */ |
64 | void callback_friendrequest(Friend_Requests *fr, void (*function)(void *, const uint8_t *, const uint8_t *, size_t, | 47 | void 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. */ |
74 | void friendreq_init(Friend_Requests *fr, Friend_Connections *fr_c); | 57 | void friendreq_init(Friend_Requests *fr, Friend_Connections *fr_c); |
75 | 58 | ||
59 | Friend_Requests *friendreq_new(void); | ||
60 | void 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 | */ |
34 | static uint8_t groupnumber_not_valid(const Group_Chats *g_c, int groupnumber) | 38 | static 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 | */ |
103 | static int wipe_group_chat(Group_Chats *g_c, int groupnumber) | 112 | static 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 | ||
124 | static Group_c *get_group_c(const Group_Chats *g_c, int groupnumber) | 135 | static 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 | ||
141 | static int peer_in_chat(const Group_c *chat, const uint8_t *real_pk) | 153 | static 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 | */ |
160 | static int get_group_num(const Group_Chats *g_c, const uint8_t *identifier) | 174 | static 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 | */ |
179 | static int get_peer_index(Group_c *g, uint16_t peer_number) | 195 | static 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 | ||
211 | static int friend_in_close(Group_c *g, int friendcon_id); | 229 | static int friend_in_close(Group_c *g, int friendcon_id); |
212 | static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnumber, uint8_t closest, uint8_t lock); | 230 | static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, uint32_t groupnumber, uint8_t closest, |
231 | uint8_t lock); | ||
213 | 232 | ||
214 | static int add_to_closest(Group_Chats *g_c, int groupnumber, const uint8_t *real_pk, const uint8_t *temp_pk) | 233 | static 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 | ||
310 | static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t *identifier); | 333 | static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t *identifier); |
311 | 334 | ||
312 | static int connect_to_closest(Group_Chats *g_c, int groupnumber) | 335 | static 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 | */ |
384 | static int addpeer(Group_Chats *g_c, int groupnumber, const uint8_t *real_pk, const uint8_t *temp_pk, | 415 | static 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 | ||
437 | static int remove_close_conn(Group_Chats *g_c, int groupnumber, int friendcon_id) | 472 | static 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 | */ |
467 | static int delpeer(Group_Chats *g_c, int groupnumber, int peer_index) | 504 | static 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 | ||
519 | static 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 | */ | ||
569 | static 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 | ||
545 | static int settitle(Group_Chats *g_c, int groupnumber, int peer_index, const uint8_t *title, uint8_t title_len) | 602 | static 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 | ||
568 | static void set_conns_type_close(Group_Chats *g_c, int groupnumber, int friendcon_id, uint8_t type) | 630 | static 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 | ||
601 | static int handle_status(void *object, int friendcon_id, uint8_t status) | 666 | static 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 | ||
615 | static int handle_packet(void *object, int friendcon_id, uint8_t *data, uint16_t length); | 680 | static int g_handle_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata); |
616 | static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uint16_t length); | 681 | static 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 | */ |
623 | static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnumber, uint8_t closest, uint8_t lock) | 688 | static 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 | ||
693 | static int group_kill_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_num); | 763 | static 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 | */ |
699 | int del_groupchat(Group_Chats *g_c, int groupnumber) | 769 | int 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 | */ |
737 | int group_peer_pubkey(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *pk) | 812 | int 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 | */ | ||
834 | int 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 | */ |
757 | int group_peername(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *name) | 860 | int 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 | */ |
786 | int group_names(const Group_Chats *g_c, int groupnumber, uint8_t names[][MAX_NAME_LENGTH], uint16_t lengths[], | 890 | int 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 | */ |
806 | int group_number_peers(const Group_Chats *g_c, int groupnumber) | 911 | int 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 | */ |
819 | unsigned int group_peernumber_is_ours(const Group_Chats *g_c, int groupnumber, int peernumber) | 928 | int 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 | */ |
840 | int group_get_type(const Group_Chats *g_c, int groupnumber) | 952 | int 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) | |||
855 | static unsigned int send_packet_group_peer(Friend_Connections *fr_c, int friendcon_id, uint8_t packet_id, | 968 | static 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 | |||
875 | static unsigned int send_lossy_group_peer(Friend_Connections *fr_c, int friendcon_id, uint8_t packet_id, | 989 | static 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 | */ |
900 | int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber) | 1017 | int 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 | ||
921 | static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num); | 1039 | static 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 | */ |
930 | int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t expected_type, const uint8_t *data, uint16_t length) | 1053 | int 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 | */ |
990 | void g_callback_group_invite(Group_Chats *g_c, void (*function)(Messenger *m, int32_t, uint8_t, const uint8_t *, | 1118 | void 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 | */ |
1001 | void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t, | 1131 | void 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 | */ |
1012 | void g_callback_group_action(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t, | 1142 | void 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 | */ |
1025 | void group_lossy_packet_registerhandler(Group_Chats *g_c, uint8_t byte, int (*function)(void *, int, int, void *, | 1153 | void 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 | */ |
1036 | void g_callback_group_namelistchange(Group_Chats *g_c, void (*function)(Messenger *m, int, int, uint8_t, void *), | 1164 | void 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 | */ |
1048 | void g_callback_group_title(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint8_t, | 1175 | void 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 | */ |
1062 | int callback_groupchat_peer_new(const Group_Chats *g_c, int groupnumber, void (*function)(void *, int, int)) | 1188 | int 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 | */ |
1080 | int callback_groupchat_peer_delete(Group_Chats *g_c, int groupnumber, void (*function)(void *, int, int, void *)) | 1208 | int 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 | */ |
1098 | int callback_groupchat_delete(Group_Chats *g_c, int groupnumber, void (*function)(void *, int)) | 1228 | int 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 | ||
1109 | static unsigned int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data, | 1240 | static 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 |
1113 | int group_ping_send(const Group_Chats *g_c, int groupnumber) | 1244 | static 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 | */ |
1128 | int group_new_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_num, const uint8_t *real_pk, | 1259 | static 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 | */ |
1152 | static int group_kill_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_num) | 1283 | static 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 | */ |
1172 | static int group_name_send(const Group_Chats *g_c, int groupnumber, const uint8_t *nick, uint16_t nick_len) | 1303 | static 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 | */ |
1190 | int group_title_send(const Group_Chats *g_c, int groupnumber, const uint8_t *title, uint8_t title_len) | 1324 | int 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 | */ | ||
1359 | int 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 | */ |
1222 | int group_title_get(const Group_Chats *g_c, int groupnumber, uint8_t *title, uint32_t max_length) | 1381 | int 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 | ||
1239 | static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length) | 1397 | static 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) | |||
1359 | static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t *identifier) | 1527 | static 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 | ||
1370 | static unsigned int send_peer_kill(Group_Chats *g_c, int friendcon_id, uint16_t group_num); | 1538 | static unsigned int send_peer_kill(Group_Chats *g_c, int friendcon_id, uint16_t group_num); |
1371 | 1539 | ||
1372 | static int handle_packet_online(Group_Chats *g_c, int friendcon_id, uint8_t *data, uint16_t length) | 1540 | static 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 | */ |
1451 | static unsigned int send_peers(Group_Chats *g_c, int groupnumber, int friendcon_id, uint16_t group_num) | 1628 | static 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 | ||
1505 | static int handle_send_peers(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length) | 1683 | static 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 | ||
1548 | static void handle_direct_packet(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length, | 1731 | static 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 | */ |
1601 | static unsigned int send_message_all_close(const Group_Chats *g_c, int groupnumber, const uint8_t *data, | 1787 | static 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 | */ |
1631 | static unsigned int send_lossy_all_close(const Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length, | 1821 | static 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 | */ |
1717 | static unsigned int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data, | 1915 | static 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 | */ |
1755 | int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *message, uint16_t length) | 1960 | int 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 | */ |
1768 | int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *action, uint16_t length) | 1975 | int 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 | */ |
1782 | int send_group_lossy_packet(const Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length) | 1991 | int 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 | ||
1805 | static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length, | 2015 | static 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 | ||
1933 | static int handle_packet(void *object, int friendcon_id, uint8_t *data, uint16_t length) | 2154 | static 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 | */ |
1987 | static unsigned int lossy_packet_not_received(Group_c *g, int peer_index, uint16_t message_number) | 2213 | static 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 | ||
2038 | static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uint16_t length) | 2266 | static 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 | */ |
2101 | int group_set_object(const Group_Chats *g_c, int groupnumber, void *object) | 2336 | int 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 | */ |
2117 | int group_peer_set_object(const Group_Chats *g_c, int groupnumber, int peernumber, void *object) | 2353 | int 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 | */ |
2136 | void *group_get_object(const Group_Chats *g_c, int groupnumber) | 2374 | void *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 | */ |
2151 | void *group_peer_get_object(const Group_Chats *g_c, int groupnumber, int peernumber) | 2390 | void *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 | ||
2167 | static int ping_groupchat(Group_Chats *g_c, int groupnumber) | 2408 | static 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 | ||
2182 | static int groupchat_clear_timedout(Group_Chats *g_c, int groupnumber) | 2425 | static 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. */ |
2222 | Group_Chats *new_groupchats(Messenger *m) | 2468 | Group_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. */ |
2241 | void do_groupchats(Group_Chats *g_c) | 2489 | void 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. */ |
2298 | uint32_t copy_chatlist(Group_Chats *g_c, int32_t *out_list, uint32_t list_size) | 2547 | uint32_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 | ||
43 | typedef struct { | 42 | typedef 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 | ||
65 | enum { | 64 | enum { |
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 | ||
112 | typedef struct { | 111 | typedef 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 | */ |
141 | void g_callback_group_invite(Group_Chats *g_c, void (*function)(Messenger *m, int32_t, uint8_t, const uint8_t *, | 135 | void 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 | */ |
148 | void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t, | 142 | void 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 | */ | ||
155 | void 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 | */ |
163 | void g_callback_group_title(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint8_t, | 151 | void 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 | */ |
171 | enum { | 159 | void 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 | * |
176 | void 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 | */ | ||
167 | void 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 | */ |
193 | int del_groupchat(Group_Chats *g_c, int groupnumber); | 183 | int 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 | */ |
201 | int group_peer_pubkey(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *pk); | 192 | int 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 | */ | ||
200 | int 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 | */ |
209 | int group_peername(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *name); | 209 | int 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 | */ |
215 | int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber); | 217 | int 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 | */ |
224 | int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t expected_type, const uint8_t *data, uint16_t length); | 231 | int 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 | */ |
230 | int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *message, uint16_t length); | 238 | int 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 | */ |
236 | int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *action, uint16_t length); | 244 | int 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 | */ |
242 | int group_title_send(const Group_Chats *g_c, int groupnumber, const uint8_t *title, uint8_t title_len); | 252 | int 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 | */ | ||
259 | int 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 | */ |
251 | int group_title_get(const Group_Chats *g_c, int groupnumber, uint8_t *title, uint32_t max_length); | 268 | int 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 | */ |
256 | int group_number_peers(const Group_Chats *g_c, int groupnumber); | 273 | int 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 | */ |
261 | unsigned int group_peernumber_is_ours(const Group_Chats *g_c, int groupnumber, int peernumber); | 281 | int 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 | */ |
273 | int group_names(const Group_Chats *g_c, int groupnumber, uint8_t names[][MAX_NAME_LENGTH], uint16_t lengths[], | 293 | int 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 | */ |
282 | void group_lossy_packet_registerhandler(Group_Chats *g_c, uint8_t byte, int (*function)(void *, int, int, void *, | 302 | void 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 | */ |
290 | int send_group_lossy_packet(const Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length); | 311 | int 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. */ |
303 | uint32_t copy_chatlist(Group_Chats *g_c, int32_t *out_list, uint32_t list_size); | 324 | uint32_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 | */ |
310 | int group_get_type(const Group_Chats *g_c, int groupnumber); | 331 | int 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 | */ |
321 | int group_set_object(const Group_Chats *g_c, int groupnumber, void *object); | 342 | int 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 | */ |
328 | int group_peer_set_object(const Group_Chats *g_c, int groupnumber, int peernumber, void *object); | 349 | int 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 | */ |
335 | void *group_get_object(const Group_Chats *g_c, int groupnumber); | 356 | void *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 | */ |
342 | void *group_peer_get_object(const Group_Chats *g_c, int groupnumber, int peernumber); | 363 | void *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 | */ |
351 | int callback_groupchat_peer_new(const Group_Chats *g_c, int groupnumber, void (*function)(void *, int, int)); | 372 | int 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 | */ |
360 | int callback_groupchat_peer_delete(Group_Chats *g_c, int groupnumber, void (*function)(void *, int, int, void *)); | 382 | int 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 | */ |
369 | int callback_groupchat_delete(Group_Chats *g_c, int groupnumber, void (*function)(void *, int)); | 392 | int 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. */ |
372 | Group_Chats *new_groupchats(Messenger *m); | 395 | Group_Chats *new_groupchats(Messenger *m); |
373 | 396 | ||
374 | /* main groupchats loop. */ | 397 | /* main groupchats loop. */ |
375 | void do_groupchats(Group_Chats *g_c); | 398 | void do_groupchats(Group_Chats *g_c, void *userdata); |
376 | 399 | ||
377 | /* Free everything related with group chats. */ | 400 | /* Free everything related with group chats. */ |
378 | void kill_groupchats(Group_Chats *g_c); | 401 | void 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 | */ |
114 | static int resize(BS_LIST *list, uint32_t new_size) | 123 | static 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 | ||
165 | int bs_list_find(const BS_LIST *list, const uint8_t *data) | 180 | int 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 | ||
33 | typedef struct { | 31 | typedef 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 | ||
47 | struct Logger { | 37 | struct 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 | |||
62 | Logger *global = NULL; | ||
63 | |||
64 | const 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 | ||
72 | char *strtime(char *dest, size_t max_len) | 43 | #ifdef USE_STDERR_LOGGER |
73 | { | 44 | static 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 | */ | ||
88 | Logger *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 | |||
136 | FAILURE: | ||
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 | ||
148 | void logger_kill(Logger *log) | 66 | static 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 | ||
172 | void logger_kill_global(void) | 73 | static const Logger logger_stderr = { |
74 | logger_stderr_handler, | ||
75 | nullptr, | ||
76 | nullptr, | ||
77 | }; | ||
78 | #endif | ||
79 | |||
80 | /** | ||
81 | * Public Functions | ||
82 | */ | ||
83 | Logger *logger_new(void) | ||
173 | { | 84 | { |
174 | logger_kill(global); | 85 | return (Logger *)calloc(1, sizeof(Logger)); |
175 | global = NULL; | ||
176 | } | 86 | } |
177 | 87 | ||
178 | void logger_set_global(Logger *log) | 88 | void 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 | ||
187 | Logger *logger_get_global(void) | 93 | void 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 | ||
196 | void logger_write (Logger *log, LOG_LEVEL level, const char *file, int line, const char *format, ...) | 100 | void 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 | |||
38 | typedef enum { | 35 | typedef 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 | ||
46 | typedef struct Logger Logger; | 43 | typedef struct Logger Logger; |
47 | 44 | ||
45 | typedef 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 | */ |
51 | Logger *logger_new (const char *file_name, LOG_LEVEL level, const char *id); | 51 | Logger *logger_new(void); |
52 | 52 | ||
53 | void logger_kill (Logger *log); | 53 | /** |
54 | void logger_kill_global (void); | 54 | * Frees all resources associated with the logger. |
55 | */ | ||
56 | void 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 | */ |
59 | void logger_set_global (Logger *log); | 62 | void logger_callback_log(Logger *log, logger_cb *function, void *context, void *userdata); |
60 | Logger *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 | */ |
65 | void logger_write (Logger *log, LOG_LEVEL level, const char *file, int line, const char *format, ...); | 74 | void 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) \ | ||
42 | void 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) \ | ||
46 | void 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" | 38 | typedef struct { |
39 | uint64_t sent_time; | ||
40 | uint16_t length; | ||
41 | uint8_t data[MAX_CRYPTO_DATA_SIZE]; | ||
42 | } Packet_Data; | ||
43 | |||
44 | typedef 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 | |||
50 | typedef 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 | |||
129 | struct 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 | |||
159 | const uint8_t *nc_get_self_public_key(const Net_Crypto *c) | ||
160 | { | ||
161 | return c->self_public_key; | ||
162 | } | ||
163 | |||
164 | const uint8_t *nc_get_self_secret_key(const Net_Crypto *c) | ||
165 | { | ||
166 | return c->self_secret_key; | ||
167 | } | ||
168 | |||
169 | TCP_Connections *nc_get_tcp_c(const Net_Crypto *c) | ||
170 | { | ||
171 | return c->tcp_c; | ||
172 | } | ||
173 | |||
174 | DHT *nc_get_dht(const Net_Crypto *c) | ||
175 | { | ||
176 | return c->dht; | ||
177 | } | ||
34 | 178 | ||
35 | static uint8_t crypt_connection_id_not_valid(const Net_Crypto *c, int crypt_connection_id) | 179 | static 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 | |||
117 | static int open_cookie(uint8_t *bytes, const uint8_t *cookie, const uint8_t *encryption_key) | 266 | static 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 | |||
174 | static int handle_cookie_request(const Net_Crypto *c, uint8_t *request_plain, uint8_t *shared_key, | 327 | static 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 | */ |
194 | static int udp_handle_cookie_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length) | 349 | static 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 | |||
217 | static int tcp_handle_cookie_request(Net_Crypto *c, int connections_number, const uint8_t *packet, uint16_t length) | 376 | static 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 | |||
267 | static int handle_cookie_response(uint8_t *cookie, uint64_t *number, const uint8_t *packet, uint16_t length, | 431 | static 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 | |||
294 | static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const uint8_t *cookie, const uint8_t *nonce, | 460 | static 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 | |||
340 | static int handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t *session_pk, uint8_t *peer_real_pk, | 508 | static 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 | ||
379 | static Crypto_Connection *get_crypto_connection(const Net_Crypto *c, int crypt_connection_id) | 553 | static 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 | */ |
428 | IP_Port return_ip_port_connection(Net_Crypto *c, int crypt_connection_id) | 606 | static 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 | */ |
465 | static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length) | 647 | static 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 | */ |
541 | static int add_data_to_buffer(Packets_Array *array, uint32_t number, const Packet_Data *data) | 724 | static 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 | */ |
592 | static int64_t add_data_end_of_buffer(Packets_Array *array, const Packet_Data *data) | 781 | static 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 | */ |
614 | static int64_t read_data_beg_buffer(Packets_Array *array, Packet_Data *data) | 805 | static 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 | */ |
681 | static int set_buffer_end(Packets_Array *array, uint32_t number) | 875 | static 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 | */ |
699 | static int generate_request_packet(uint8_t *data, uint16_t length, const Packets_Array *recv_array) | 895 | static 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 | |||
748 | static int handle_request_packet(Packets_Array *send_array, const uint8_t *data, uint16_t length, | 948 | static 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 | */ |
828 | static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length) | 1035 | static 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_ | |||
860 | static int send_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint32_t buffer_start, uint32_t num, | 1069 | static 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 | ||
878 | static int reset_max_speed_reached(Net_Crypto *c, int crypt_connection_id) | 1088 | static 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) | |||
918 | static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length, | 1129 | static 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 | |||
968 | static uint16_t get_nonce_uint16(const uint8_t *nonce) | 1183 | static 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) | |||
984 | static int handle_data_packet(const Net_Crypto *c, int crypt_connection_id, uint8_t *data, const uint8_t *packet, | 1199 | static 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 | */ |
1043 | static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32_t max_num) | 1263 | static 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 | */ |
1090 | static int new_temp_packet(const Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length) | 1315 | static 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 | ||
1206 | static void connection_kill(Net_Crypto *c, int crypt_connection_id) | 1444 | static 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 | */ |
1225 | static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length, | 1465 | static 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 | */ |
1362 | static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length, | 1610 | static 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 | */ |
1513 | static int wipe_crypto_connection(Net_Crypto *c, int crypt_connection_id) | 1774 | static 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 | */ |
1612 | static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, const uint8_t *data, uint16_t length) | 1881 | static 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 | */ |
1667 | int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) | 1938 | int 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 | */ |
1779 | int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, _Bool connected) | 2058 | int 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 | ||
1808 | static int tcp_data_callback(void *object, int id, const uint8_t *data, uint16_t length) | 2082 | static 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 | ||
1835 | static int tcp_oob_callback(void *object, const uint8_t *public_key, unsigned int tcp_connections_number, | 2114 | static 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 | */ |
1928 | unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, uint16_t num) | 2212 | unsigned 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 | ||
1940 | static void do_tcp(Net_Crypto *c) | 2225 | static 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 | */ |
1981 | int connection_status_handler(const Net_Crypto *c, int crypt_connection_id, | 2267 | int 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 | */ |
2003 | int connection_data_handler(const Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object, | 2290 | int 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 | */ |
2025 | int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id, | 2313 | int 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 | */ |
2050 | int nc_dht_pk_callback(Net_Crypto *c, int crypt_connection_id, void (*function)(void *data, int32_t number, | 2340 | int 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 | */ |
2084 | static int udp_handle_packet(void *object, IP_Port source, const uint8_t *packet, uint16_t length) | 2375 | static 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) | 2672 | bool 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 | |||
2403 | int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length, | 2704 | int64_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 | */ |
2447 | int cryptpacket_received(Net_Crypto *c, int crypt_connection_id, uint32_t packet_number) | 2762 | int 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 | */ |
2469 | int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length) | 2785 | int 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 | */ |
2508 | int crypto_kill(Net_Crypto *c, int crypt_connection_id) | 2827 | int 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 | */ |
2550 | unsigned int crypto_connection_status(const Net_Crypto *c, int crypt_connection_id, _Bool *direct_connected, | 2870 | unsigned 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 | ||
2577 | void new_keys(Net_Crypto *c) | 2900 | void 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 | */ |
2587 | void save_keys(const Net_Crypto *c, uint8_t *keys) | 2910 | void 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 | */ |
2596 | void load_secret_key(Net_Crypto *c, const uint8_t *sk) | 2919 | void 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 | */ |
2605 | Net_Crypto *new_net_crypto(DHT *dht, TCP_Proxy_Info *proxy_info) | 2928 | Net_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 | ||
2651 | static void kill_timedout(Net_Crypto *c) | 2978 | static 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. */ |
2688 | void do_net_crypto(Net_Crypto *c) | 3021 | void 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 | ||
90 | typedef struct { | 92 | typedef struct Net_Crypto Net_Crypto; |
91 | uint64_t sent_time; | 93 | |
92 | uint16_t length; | 94 | const uint8_t *nc_get_self_public_key(const Net_Crypto *c); |
93 | uint8_t data[MAX_CRYPTO_DATA_SIZE]; | 95 | const uint8_t *nc_get_self_secret_key(const Net_Crypto *c); |
94 | } Packet_Data; | 96 | TCP_Connections *nc_get_tcp_c(const Net_Crypto *c); |
95 | 97 | DHT *nc_get_dht(const Net_Crypto *c); | |
96 | typedef struct { | 98 | |
97 | Packet_Data *buffer[CRYPTO_PACKET_BUFFER_SIZE]; | 99 | typedef 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 | |||
102 | typedef 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 | |||
181 | typedef 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 | ||
191 | typedef 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 | */ |
251 | int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, _Bool connected); | 140 | int 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 | */ |
263 | int connection_status_handler(const Net_Crypto *c, int crypt_connection_id, | 152 | int 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 | */ |
274 | int connection_data_handler(const Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object, | 163 | int 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 | */ |
286 | int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id, | 175 | int 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 | */ |
300 | int nc_dht_pk_callback(Net_Crypto *c, int crypt_connection_id, void (*function)(void *data, int32_t number, | 190 | int 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); | 201 | bool 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 | */ |
367 | int send_tcp_onion_request(Net_Crypto *c, unsigned int TCP_conn_number, const uint8_t *data, uint16_t length); | 257 | int 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 | */ |
389 | unsigned int crypto_connection_status(const Net_Crypto *c, int crypt_connection_id, _Bool *direct_connected, | 279 | unsigned 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_ | |||
395 | void new_keys(Net_Crypto *c); | 285 | void 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 | */ |
400 | void save_keys(const Net_Crypto *c, uint8_t *keys); | 290 | void 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 | */ |
405 | void load_secret_key(Net_Crypto *c, const uint8_t *sk); | 295 | void 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 | */ |
410 | Net_Crypto *new_net_crypto(DHT *dht, TCP_Proxy_Info *proxy_info); | 300 | Net_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 | */ |
414 | uint32_t crypto_run_interval(const Net_Crypto *c); | 304 | uint32_t crypto_run_interval(const Net_Crypto *c); |
415 | 305 | ||
416 | /* Main loop. */ | 306 | /* Main loop. */ |
417 | void do_net_crypto(Net_Crypto *c); | 307 | void do_net_crypto(Net_Crypto *c, void *userdata); |
418 | 308 | ||
419 | void kill_net_crypto(Net_Crypto *c); | 309 | void 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 | ||
48 | static const char *inet_ntop(sa_family_t family, void *addr, char *buf, size_t bufsize) | 97 | static 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 | ||
81 | static int inet_pton(sa_family_t family, const char *addrString, void *addrbuf) | 132 | static 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 | |||
194 | static int make_proto(int proto); | ||
195 | static int make_socktype(int type); | ||
196 | |||
197 | static 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 | |||
214 | static 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 | |||
231 | static void get_ip4(IP4 *result, const struct in_addr *addr) | ||
232 | { | ||
233 | result->uint32 = addr->s_addr; | ||
234 | } | ||
235 | |||
236 | static 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 | |||
242 | static void fill_addr4(IP4 ip, struct in_addr *addr) | ||
243 | { | ||
244 | addr->s_addr = ip.uint32; | ||
245 | } | ||
246 | |||
247 | static 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 | |||
257 | const IP4 IP4_BROADCAST = { INADDR_BROADCAST }; | ||
258 | const IP6 IP6_BROADCAST = { | ||
259 | { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } | ||
260 | }; | ||
261 | |||
262 | IP4 get_ip4_loopback(void) | ||
263 | { | ||
264 | IP4 loopback; | ||
265 | loopback.uint32 = htonl(INADDR_LOOPBACK); | ||
266 | return loopback; | ||
267 | } | ||
268 | |||
269 | IP6 get_ip6_loopback(void) | ||
270 | { | ||
271 | IP6 loopback; | ||
272 | get_ip6(&loopback, &in6addr_loopback); | ||
273 | return loopback; | ||
274 | } | ||
275 | |||
276 | const Socket net_invalid_socket = { | ||
277 | #ifdef OS_WIN32 | ||
278 | (int)INVALID_SOCKET, | ||
279 | #else | ||
280 | -1, | ||
281 | #endif | ||
282 | }; | ||
283 | |||
284 | const Family net_family_unspec = {TOX_AF_UNSPEC}; | ||
285 | const Family net_family_ipv4 = {TOX_AF_INET}; | ||
286 | const Family net_family_ipv6 = {TOX_AF_INET6}; | ||
287 | const Family net_family_tcp_family = {TCP_FAMILY}; | ||
288 | const Family net_family_tcp_onion = {TCP_ONION_FAMILY}; | ||
289 | const Family net_family_tcp_ipv4 = {TCP_INET}; | ||
290 | const Family net_family_tcp_ipv6 = {TCP_INET6}; | ||
291 | const Family net_family_tox_tcp_ipv4 = {TOX_TCP_INET}; | ||
292 | const Family net_family_tox_tcp_ipv6 = {TOX_TCP_INET6}; | ||
293 | |||
294 | bool net_family_is_unspec(Family family) | ||
295 | { | ||
296 | return family.value == net_family_unspec.value; | ||
297 | } | ||
298 | |||
299 | bool net_family_is_ipv4(Family family) | ||
300 | { | ||
301 | return family.value == net_family_ipv4.value; | ||
302 | } | ||
303 | |||
304 | bool net_family_is_ipv6(Family family) | ||
305 | { | ||
306 | return family.value == net_family_ipv6.value; | ||
307 | } | ||
308 | |||
309 | bool net_family_is_tcp_family(Family family) | ||
310 | { | ||
311 | return family.value == net_family_tcp_family.value; | ||
312 | } | ||
313 | |||
314 | bool net_family_is_tcp_onion(Family family) | ||
315 | { | ||
316 | return family.value == net_family_tcp_onion.value; | ||
317 | } | ||
318 | |||
319 | bool net_family_is_tcp_ipv4(Family family) | ||
320 | { | ||
321 | return family.value == net_family_tcp_ipv4.value; | ||
322 | } | ||
323 | |||
324 | bool net_family_is_tcp_ipv6(Family family) | ||
325 | { | ||
326 | return family.value == net_family_tcp_ipv6.value; | ||
327 | } | ||
328 | |||
329 | bool net_family_is_tox_tcp_ipv4(Family family) | ||
330 | { | ||
331 | return family.value == net_family_tox_tcp_ipv4.value; | ||
332 | } | ||
333 | |||
334 | bool 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 | */ |
119 | int sock_valid(sock_t sock) | 344 | int 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 | */ |
136 | void kill_sock(sock_t sock) | 351 | void 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 | */ |
150 | int set_socket_nonblock(sock_t sock) | 365 | int 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 | */ |
165 | int set_socket_nosigpipe(sock_t sock) | 380 | int 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 | */ |
180 | int set_socket_reuseaddr(sock_t sock) | 395 | int 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 | */ |
191 | int set_socket_dualstack(sock_t sock) | 406 | int 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) | |||
206 | static uint64_t current_time_actual(void) | 422 | static 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 |
228 | static uint64_t last_monotime; | 444 | static uint64_t last_monotime; |
229 | static uint64_t add_monotime; | 445 | static uint64_t add_monotime; |
230 | #endif | 446 | #endif |
@@ -233,12 +449,17 @@ static uint64_t add_monotime; | |||
233 | uint64_t current_time_monotonic(void) | 449 | uint64_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 */ | 489 | static 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 | 493 | static 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 */ \ | 498 | static 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 | |||
524 | typedef struct { | ||
525 | packet_handler_callback function; | ||
526 | void *object; | ||
527 | } Packet_Handler; | ||
528 | |||
529 | struct 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 | |||
539 | Family net_family(const Networking_Core *net) | ||
540 | { | ||
541 | return net->family; | ||
542 | } | ||
543 | |||
544 | uint16_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 | */ |
295 | int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint16_t length) | 552 | int 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 | */ |
363 | static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t *length) | 619 | static 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 | ||
415 | void networking_poll(Networking_Core *net) | 690 | void 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 | ||
443 | uint8_t at_startup_ran = 0; | 722 | static uint8_t at_startup_ran = 0; |
444 | int networking_at_startup(void) | 723 | int 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 | ||
472 | static void at_shutdown(void) | 758 | static 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 | */ |
483 | Networking_Core *new_networking(IP ip, uint16_t port) | 769 | Networking_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 | */ |
498 | Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to, unsigned int *error) | 784 | Networking_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; | 999 | Networking_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. */ |
700 | void kill_networking(Networking_Core *net) | 1014 | void 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 | */ |
719 | int ip_equal(const IP *a, const IP *b) | 1035 | int 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 | */ |
752 | int ipport_equal(const IP_Port *a, const IP_Port *b) | 1083 | int 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 */ |
764 | void ip_reset(IP *ip) | 1097 | void 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 */ |
773 | void ip_init(IP *ip, uint8_t ipv6enabled) | 1107 | void 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 */ |
783 | int ip_isset(const IP *ip) | 1118 | bool 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 */ |
792 | int ipport_isset(const IP_Port *ipport) | 1128 | bool 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!) */ |
804 | void ip_copy(IP *target, const IP *source) | 1142 | void 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!) */ |
813 | void ipport_copy(IP_Port *target, const IP_Port *source) | 1152 | void 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 */ | 1170 | const char *ip_ntoa(const IP *ip, char *ip_str, size_t length) |
829 | static char addresstext[96]; // FIXME magic number. Why not INET6_ADDRSTRLEN ? | ||
830 | const 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 | */ |
903 | int addr_parse_ip(const char *address, IP *to) | 1256 | int 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 | */ |
944 | int addr_resolve(const char *address, IP *to, IP *extra) | 1298 | int 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 | */ |
1046 | int addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra) | 1403 | int 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 | |||
1414 | int 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 | |||
1440 | int32_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 | |||
1517 | void net_freeipport(IP_Port *ip_ports) | ||
1518 | { | ||
1519 | free(ip_ports); | ||
1520 | } | ||
1521 | |||
1522 | /* return 1 on success | ||
1523 | * return 0 on failure | ||
1524 | */ | ||
1525 | int 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 | |||
1549 | static 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 | |||
1563 | static 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 | |||
1577 | Socket 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 | |||
1586 | int net_send(Socket sock, const void *buf, size_t len) | ||
1587 | { | ||
1588 | return send(sock.socket, (const char *)buf, len, MSG_NOSIGNAL); | ||
1589 | } | ||
1590 | |||
1591 | int net_recv(Socket sock, void *buf, size_t len) | ||
1592 | { | ||
1593 | return recv(sock.socket, (char *)buf, len, MSG_NOSIGNAL); | ||
1594 | } | ||
1595 | |||
1596 | int net_listen(Socket sock, int backlog) | ||
1597 | { | ||
1598 | return listen(sock.socket, backlog); | ||
1599 | } | ||
1600 | |||
1601 | Socket net_accept(Socket sock) | ||
1602 | { | ||
1603 | const Socket newsock = {accept(sock.socket, nullptr, nullptr)}; | ||
1604 | return newsock; | ||
1605 | } | ||
1606 | |||
1607 | size_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 | |||
1620 | uint32_t net_htonl(uint32_t hostlong) | ||
1621 | { | ||
1622 | return htonl(hostlong); | ||
1623 | } | ||
1624 | |||
1625 | uint16_t net_htons(uint16_t hostshort) | ||
1626 | { | ||
1627 | return htons(hostshort); | ||
1628 | } | ||
1629 | |||
1630 | uint32_t net_ntohl(uint32_t hostlong) | ||
1631 | { | ||
1632 | return ntohl(hostlong); | ||
1633 | } | ||
1634 | |||
1635 | uint16_t net_ntohs(uint16_t hostshort) | ||
1636 | { | ||
1637 | return ntohs(hostshort); | ||
1638 | } | ||
1639 | |||
1640 | size_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 | |||
1647 | size_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 | |||
1655 | size_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 | |||
1663 | size_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 | |||
1671 | size_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 | |||
1681 | size_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 | |||
1691 | int net_error(void) | ||
1692 | { | ||
1693 | #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) | ||
1694 | return WSAGetLastError(); | ||
1695 | #else | ||
1696 | return errno; | ||
1697 | #endif | ||
1698 | } | ||
1699 | |||
1700 | const 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 | |||
1719 | void 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 | 34 | extern "C" { |
49 | #endif | 35 | #endif |
50 | 36 | ||
51 | typedef unsigned int sock_t; | 37 | typedef struct Family { |
52 | /* sa_family_t is the sockaddr_in / sockaddr_in6 family field */ | 38 | uint8_t value; |
53 | typedef short sa_family_t; | 39 | } Family; |
54 | 40 | ||
55 | #ifndef EWOULDBLOCK | 41 | bool net_family_is_unspec(Family family); |
56 | #define EWOULDBLOCK WSAEWOULDBLOCK | 42 | bool net_family_is_ipv4(Family family); |
57 | #endif | 43 | bool net_family_is_ipv6(Family family); |
58 | 44 | bool net_family_is_tcp_family(Family family); | |
59 | #else // Linux includes | 45 | bool net_family_is_tcp_onion(Family family); |
60 | 46 | bool net_family_is_tcp_ipv4(Family family); | |
61 | #include <fcntl.h> | 47 | bool net_family_is_tcp_ipv6(Family family); |
62 | #include <sys/socket.h> | 48 | bool net_family_is_tox_tcp_ipv4(Family family); |
63 | #include <netinet/in.h> | 49 | bool net_family_is_tox_tcp_ipv6(Family family); |
64 | #include <arpa/inet.h> | 50 | |
65 | #include <errno.h> | 51 | extern const Family net_family_unspec; |
66 | #include <sys/time.h> | 52 | extern const Family net_family_ipv4; |
67 | #include <sys/types.h> | 53 | extern const Family net_family_ipv6; |
68 | #include <netdb.h> | 54 | extern const Family net_family_tcp_family; |
69 | #include <unistd.h> | 55 | extern const Family net_family_tcp_onion; |
56 | extern const Family net_family_tcp_ipv4; | ||
57 | extern const Family net_family_tcp_ipv6; | ||
58 | extern const Family net_family_tox_tcp_ipv4; | ||
59 | extern const Family net_family_tox_tcp_ipv6; | ||
60 | |||
61 | typedef struct Socket { | ||
62 | int socket; | ||
63 | } Socket; | ||
64 | |||
65 | Socket net_socket(Family domain, int type, int protocol); | ||
70 | 66 | ||
71 | typedef 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 | */ | ||
72 | int sock_valid(Socket sock); | ||
74 | 73 | ||
75 | #if defined(__AIX__) | 74 | extern 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 | 79 | int 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 | 83 | int net_recv(Socket sockfd, void *buf, size_t len); |
84 | /** | ||
85 | * Calls listen(sockfd, backlog). | ||
86 | */ | ||
87 | int net_listen(Socket sockfd, int backlog); | ||
88 | /** | ||
89 | * Calls accept(sockfd, nullptr, nullptr). | ||
90 | */ | ||
91 | Socket 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 | 97 | size_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. */ | 101 | typedef 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 | ||
136 | typedef union { | 156 | typedef 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]; |
142 | IP4; | 160 | } IP4; |
161 | |||
162 | IP4 get_ip4_loopback(void); | ||
163 | extern const IP4 IP4_BROADCAST; | ||
143 | 164 | ||
144 | typedef union { | 165 | typedef 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 | |
151 | IP6; | 172 | IP6 get_ip6_loopback(void); |
173 | extern const IP6 IP6_BROADCAST; | ||
152 | 174 | ||
153 | typedef struct { | 175 | #define IP_DEFINED |
154 | uint8_t family; | 176 | typedef 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; |
160 | IP; | ||
161 | 183 | ||
162 | typedef struct { | 184 | #define IP_PORT_DEFINED |
185 | typedef struct IP_Port { | ||
163 | IP ip; | 186 | IP ip; |
164 | uint16_t port; | 187 | uint16_t port; |
165 | } | 188 | } IP_Port; |
166 | IP_Port; | 189 | |
190 | /* Convert values between host and network byte order. | ||
191 | */ | ||
192 | uint32_t net_htonl(uint32_t hostlong); | ||
193 | uint16_t net_htons(uint16_t hostshort); | ||
194 | uint32_t net_ntohl(uint32_t hostlong); | ||
195 | uint16_t net_ntohs(uint16_t hostshort); | ||
196 | |||
197 | size_t net_pack_u16(uint8_t *bytes, uint16_t v); | ||
198 | size_t net_pack_u32(uint8_t *bytes, uint32_t v); | ||
199 | size_t net_pack_u64(uint8_t *bytes, uint64_t v); | ||
200 | |||
201 | size_t net_unpack_u16(const uint8_t *bytes, uint16_t *v); | ||
202 | size_t net_unpack_u32(const uint8_t *bytes, uint32_t *v); | ||
203 | size_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 | */ |
190 | const 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 ? | ||
234 | const 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 */ |
241 | void ip_reset(IP *ip); | 285 | void ip_reset(IP *ip); |
242 | /* nulls out ip, sets family according to flag */ | 286 | /* nulls out ip, sets family according to flag */ |
243 | void ip_init(IP *ip, uint8_t ipv6enabled); | 287 | void ip_init(IP *ip, bool ipv6enabled); |
244 | /* checks if ip is valid */ | 288 | /* checks if ip is valid */ |
245 | int ip_isset(const IP *ip); | 289 | bool ip_isset(const IP *ip); |
246 | /* checks if ip is valid */ | 290 | /* checks if ip is valid */ |
247 | int ipport_isset(const IP_Port *ipport); | 291 | bool ipport_isset(const IP_Port *ipport); |
248 | /* copies an ip structure */ | 292 | /* copies an ip structure */ |
249 | void ip_copy(IP *target, const IP *source); | 293 | void 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 | */ |
270 | int addr_resolve(const char *address, IP *to, IP *extra); | 314 | int 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 | */ |
293 | typedef int (*packet_handler_callback)(void *object, IP_Port ip_port, const uint8_t *data, uint16_t len); | 337 | typedef int (*packet_handler_callback)(void *object, IP_Port ip_port, const uint8_t *data, uint16_t len, |
294 | 338 | void *userdata); | |
295 | typedef struct { | ||
296 | packet_handler_callback function; | ||
297 | void *object; | ||
298 | } Packet_Handles; | ||
299 | 339 | ||
300 | typedef struct { | 340 | typedef struct Networking_Core Networking_Core; |
301 | Packet_Handles packethandlers[256]; | ||
302 | 341 | ||
303 | sa_family_t family; | 342 | Family net_family(const Networking_Core *net); |
304 | uint16_t port; | 343 | uint16_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 | */ |
314 | int networking_at_startup(void); | 350 | int 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 | */ | ||
321 | int sock_valid(sock_t sock); | ||
322 | |||
323 | /* Close the socket. | 352 | /* Close the socket. |
324 | */ | 353 | */ |
325 | void kill_sock(sock_t sock); | 354 | void 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 | */ |
332 | int set_socket_nonblock(sock_t sock); | 361 | int 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 | */ |
339 | int set_socket_nosigpipe(sock_t sock); | 368 | int 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 | */ |
346 | int set_socket_reuseaddr(sock_t sock); | 375 | int 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 | */ |
353 | int set_socket_dualstack(sock_t sock); | 382 | int set_socket_dualstack(Socket sock); |
354 | 383 | ||
355 | /* return current monotonic time in milliseconds (ms). */ | 384 | /* return current monotonic time in milliseconds (ms). */ |
356 | uint64_t current_time_monotonic(void); | 385 | uint64_t current_time_monotonic(void); |
@@ -364,7 +393,60 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint1 | |||
364 | void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object); | 393 | void 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. */ |
367 | void networking_poll(Networking_Core *net); | 396 | void networking_poll(Networking_Core *net, void *userdata); |
397 | |||
398 | /* Connect a socket to the address specified by the ip_port. */ | ||
399 | int 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 | */ | ||
412 | int32_t net_getipport(const char *node, IP_Port **res, int tox_type); | ||
413 | |||
414 | /* Deallocates memory allocated by net_getipport | ||
415 | */ | ||
416 | void net_freeipport(IP_Port *ip_ports); | ||
417 | |||
418 | /* return 1 on success | ||
419 | * return 0 on failure | ||
420 | */ | ||
421 | int 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 | */ | ||
435 | int 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 | */ | ||
443 | const 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 | */ | ||
449 | void 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 | */ |
379 | Networking_Core *new_networking(IP ip, uint16_t port); | 461 | Networking_Core *new_networking(Logger *log, IP ip, uint16_t port); |
380 | Networking_Core *new_networking_ex(IP ip, uint16_t port_from, uint16_t port_to, unsigned int *error); | 462 | Networking_Core *new_networking_ex(Logger *log, IP ip, uint16_t port_from, uint16_t port_to, unsigned int *error); |
463 | Networking_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). */ |
383 | void kill_networking(Networking_Core *net); | 466 | void 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 */ |
49 | static void ip_pack(uint8_t *data, IP source) | 55 | static 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. */ |
64 | static int ip_unpack(IP *target, const uint8_t *data, unsigned int data_size, _Bool disable_family_check) | 68 | static 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 | ||
85 | static void ipport_pack(uint8_t *data, const IP_Port *source) | 90 | static 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. */ |
92 | static int ipport_unpack(IP_Port *target, const uint8_t *data, unsigned int data_size, _Bool disable_family_check) | 97 | static 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 | */ |
114 | int create_onion_path(const DHT *dht, Onion_Path *new_path, const Node_format *nodes) | 121 | int 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 | */ |
149 | int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_Path *path) | 157 | int 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_ | |||
173 | int create_onion_packet(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, IP_Port dest, | 182 | int 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 | |||
228 | int create_onion_packet_tcp(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, IP_Port dest, | 241 | int 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 | */ |
293 | int send_onion_response(Networking_Core *net, IP_Port dest, const uint8_t *data, uint16_t length, const uint8_t *ret) | 311 | int 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 | ||
309 | static int handle_send_initial(void *object, IP_Port source, const uint8_t *packet, uint16_t length) | 329 | static 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 | ||
333 | int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, IP_Port source, const uint8_t *nonce) | 356 | int 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 | ||
370 | static int handle_send_1(void *object, IP_Port source, const uint8_t *packet, uint16_t length) | 398 | static 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 | ||
420 | static int handle_send_2(void *object, IP_Port source, const uint8_t *packet, uint16_t length) | 454 | static 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 | ||
478 | static int handle_recv_3(void *object, IP_Port source, const uint8_t *packet, uint16_t length) | 518 | static 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 | ||
519 | static int handle_recv_2(void *object, IP_Port source, const uint8_t *packet, uint16_t length) | 564 | static 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 | ||
560 | static int handle_recv_1(void *object, IP_Port source, const uint8_t *packet, uint16_t length) | 610 | static 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 | ||
606 | Onion *new_onion(DHT *dht) | 664 | Onion *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 | ||
632 | void kill_onion(Onion *onion) | 692 | void 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 @@ | |||
28 | typedef struct { | 29 | typedef 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 | ||
58 | typedef struct { | 59 | typedef 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 | */ |
150 | int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, IP_Port source, const uint8_t *nonce); | 151 | int 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 | ||
43 | typedef 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 | |||
51 | struct 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 | |||
61 | uint8_t *onion_announce_entry_public_key(Onion_Announce *onion_a, uint32_t entry) | ||
62 | { | ||
63 | return onion_a->entries[entry].public_key; | ||
64 | } | ||
65 | |||
66 | void 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 | |||
89 | int create_data_request(uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key, | 125 | int 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 | ||
221 | static uint8_t cmp_public_key[crypto_box_PUBLICKEYBYTES]; | 267 | typedef struct { |
268 | const uint8_t *base_public_key; | ||
269 | Onion_Announce_Entry entry; | ||
270 | } Cmp_data; | ||
271 | |||
222 | static int cmp_entry(const void *a, const void *b) | 272 | static 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 | ||
309 | static 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 | ||
289 | static int handle_announce_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length) | 366 | static 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 | ||
383 | static int handle_data_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length) | 465 | static 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 | ||
409 | Onion_Announce *new_onion_announce(DHT *dht) | 495 | Onion_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 | ||
429 | void kill_onion_announce(Onion_Announce *onion_a) | 517 | void 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 | ||
48 | typedef struct { | 49 | typedef 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]; | 52 | uint8_t *onion_announce_entry_public_key(Onion_Announce *onion_a, uint32_t entry); |
52 | uint8_t data_public_key[crypto_box_PUBLICKEYBYTES]; | 53 | void onion_announce_entry_set_time(Onion_Announce *onion_a, uint32_t entry, uint64_t time); |
53 | uint64_t time; | ||
54 | } Onion_Announce_Entry; | ||
55 | |||
56 | typedef 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 | ||
42 | typedef 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 | |||
60 | typedef 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 | |||
69 | typedef struct { | ||
70 | uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; | ||
71 | uint64_t timestamp; | ||
72 | } Last_Pinged; | ||
73 | |||
74 | typedef 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 | |||
109 | struct 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 | |||
149 | DHT *onion_get_dht(const Onion_Client *onion_c) | ||
150 | { | ||
151 | return onion_c->dht; | ||
152 | } | ||
153 | |||
154 | Net_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 | */ |
41 | int onion_add_bs_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *public_key) | 164 | int 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 | */ |
71 | static int onion_add_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *public_key) | 197 | static 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 */ |
203 | static _Bool path_timed_out(Onion_Client_Paths *onion_paths, uint32_t pathnum) | 338 | static 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 */ | ||
351 | static 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 | */ |
221 | static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_paths, uint32_t pathnum, Onion_Path *path) | 367 | static 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. */ |
263 | static _Bool path_exists(Onion_Client_Paths *onion_paths, uint32_t path_num) | 414 | static 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 | */ |
274 | static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, uint32_t path_num) | 426 | static 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 | |||
312 | static int send_onion_packet_tcp_udp(const Onion_Client *onion_c, const Onion_Path *path, IP_Port dest, | 465 | static 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 | |||
354 | static int new_sendback(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, IP_Port ip_port, | 512 | static 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 | |||
399 | static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, const uint8_t *dest_pubkey, | 559 | static 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 | ||
444 | static uint8_t cmp_public_key[crypto_box_PUBLICKEYBYTES]; | 609 | typedef struct { |
445 | static 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 | |||
614 | static 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 | ||
651 | static 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 | |||
473 | static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, IP_Port ip_port, | 669 | static 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 | |||
561 | static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_format *nodes, uint16_t num_nodes, | 767 | static 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 | ||
620 | static int handle_announce_response(void *object, IP_Port source, const uint8_t *packet, uint16_t length) | 830 | static 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 | ||
678 | static int handle_data_response(void *object, IP_Port source, const uint8_t *packet, uint16_t length) | 899 | static 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) |
712 | static int handle_dhtpk_announce(void *object, const uint8_t *source_pubkey, const uint8_t *data, uint16_t length) | 939 | static 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 | ||
773 | static int handle_tcp_onion(void *object, const uint8_t *data, uint16_t length) | 1007 | static 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 | */ |
798 | int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length) | 1035 | int 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 | */ |
867 | static int send_dht_dhtpk(const Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length) | 1114 | static 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 | ||
897 | static int handle_dht_dhtpk(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet, | 1149 | static 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 | */ |
930 | static int send_dhtpk_announce(Onion_Client *onion_c, uint16_t friend_num, uint8_t onion_dht_both) | 1187 | static 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 | */ |
1055 | int onion_delfriend(Onion_Client *onion_c, int friend_num) | 1323 | int 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 | */ |
1087 | int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num, int (*tcp_relay_node_callback)(void *object, | 1357 | int 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 | */ |
1107 | int onion_dht_pk_callback(Onion_Client *onion_c, int friend_num, void (*function)(void *data, int32_t number, | 1378 | int 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 | */ |
1124 | int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uint8_t *dht_key) | 1396 | int 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 | */ |
1152 | unsigned int onion_getfriend_DHT_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key) | 1426 | unsigned 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 | */ |
1174 | int onion_getfriendip(const Onion_Client *onion_c, int friend_num, IP_Port *ip_port) | 1451 | int 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 | */ |
1194 | int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_online) | 1472 | int 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 | |||
1244 | static void do_friend(Onion_Client *onion_c, uint16_t friendnum) | 1526 | static 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 | |||
1326 | static void do_announce(Onion_Client *onion_c) | 1656 | static 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 | ||
1438 | void do_onion_client(Onion_Client *onion_c) | 1804 | void 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 | ||
1485 | Onion_Client *new_onion_client(Net_Crypto *c) | 1849 | Onion_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 | ||
1514 | void kill_onion_client(Onion_Client *onion_c) | 1882 | void 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 | ||
63 | typedef struct { | 68 | typedef 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 | |||
77 | typedef 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 | |||
86 | typedef struct { | ||
87 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; | ||
88 | uint64_t timestamp; | ||
89 | } Last_Pinged; | ||
90 | |||
91 | typedef 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 | |||
124 | typedef int (*oniondata_handler_callback)(void *object, const uint8_t *source_pubkey, const uint8_t *data, | ||
125 | uint16_t len); | ||
126 | |||
127 | typedef 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 | ||
70 | DHT *onion_get_dht(const Onion_Client *onion_c); | ||
71 | Net_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 | */ |
241 | int onion_dht_pk_callback(Onion_Client *onion_c, int friend_num, void (*function)(void *data, int32_t number, | 147 | int 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 | */ |
258 | unsigned int onion_getfriend_DHT_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key); | 164 | unsigned 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 | */ |
272 | int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length); | 178 | int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length); |
273 | 179 | ||
180 | typedef 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. */ |
275 | void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object); | 184 | void 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 | |||
36 | class iP_Port { struct this; } | ||
37 | class dHT { struct this; } | ||
38 | |||
39 | class ping { | ||
40 | |||
41 | struct this; | ||
42 | |||
43 | static this new(dHT::this *dht); | ||
44 | void 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 | */ | ||
56 | int32_t add(const uint8_t *public_key, iP_Port::this ip_port); | ||
57 | void iterate(); | ||
58 | |||
59 | int32_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 | ||
48 | struct PING { | 49 | struct 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 | ||
61 | int send_ping_request(PING *ping, IP_Port ipp, const uint8_t *public_key) | 62 | int32_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 | ||
103 | static int send_ping_response(PING *ping, IP_Port ipp, const uint8_t *public_key, uint64_t ping_id, | 107 | static 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 | ||
132 | static int handle_ping_request(void *_dht, IP_Port source, const uint8_t *packet, uint16_t length) | 138 | static 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 | ||
171 | static int handle_ping_response(void *_dht, IP_Port source, const uint8_t *packet, uint16_t length) | 181 | static 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 | */ |
260 | int add_to_ping(PING *ping, const uint8_t *public_key, IP_Port ip_port) | 278 | int32_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 | */ |
302 | void do_to_ping(PING *ping) | 324 | void 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 | ||
328 | PING *new_ping(DHT *dht) | 355 | Ping *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 | ||
347 | void kill_ping(PING *ping) | 377 | void 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 | ||
36 | typedef struct IP_Port IP_Port; | ||
37 | #endif /* IP_PORT_DEFINED */ | ||
38 | |||
39 | #ifndef DHT_DEFINED | ||
40 | #define DHT_DEFINED | ||
41 | typedef struct DHT DHT; | ||
42 | #endif /* DHT_DEFINED */ | ||
43 | |||
44 | #ifndef PING_DEFINED | ||
45 | #define PING_DEFINED | ||
46 | typedef struct Ping Ping; | ||
47 | #endif /* PING_DEFINED */ | ||
48 | |||
49 | Ping *ping_new(DHT *dht); | ||
26 | 50 | ||
27 | typedef struct PING PING; | 51 | void 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 | */ |
39 | int add_to_ping(PING *ping, const uint8_t *public_key, IP_Port ip_port); | 63 | int32_t ping_add(Ping *ping, const uint8_t *public_key, struct IP_Port ip_port); |
40 | void do_to_ping(PING *ping); | ||
41 | 64 | ||
42 | PING *new_ping(DHT *dht); | 65 | void ping_iterate(Ping *ping); |
43 | void kill_ping(PING *ping); | ||
44 | 66 | ||
45 | int send_ping_request(PING *ping, IP_Port ipp, const uint8_t *public_key); | 67 | int32_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 | |||
31 | class ping_Array { | ||
32 | |||
33 | struct 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 | */ | ||
43 | static this new(uint32_t size, uint32_t timeout); | ||
44 | |||
45 | /** | ||
46 | * Free all the allocated memory in a Ping_Array. | ||
47 | */ | ||
48 | void 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 | */ | ||
56 | uint64_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 | */ | ||
66 | int32_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 | |||
37 | typedef struct { | ||
38 | void *data; | ||
39 | uint32_t length; | ||
40 | uint64_t time; | ||
41 | uint64_t ping_id; | ||
42 | } Ping_Array_Entry; | ||
43 | |||
44 | struct 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 | */ | ||
60 | Ping_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 | |||
33 | static void clear_entry(Ping_Array *array, uint32_t index) | 85 | static 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 | */ | ||
96 | void 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 | */ |
44 | static void ping_array_clear_timedout(Ping_Array *array) | 110 | static 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 | */ |
101 | int ping_array_check(uint8_t *data, uint32_t length, Ping_Array *array, uint64_t ping_id) | 170 | int32_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 | */ | ||
133 | int 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 | */ | ||
151 | void 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 | ||
28 | typedef struct { | 29 | #ifndef PING_ARRAY_DEFINED |
29 | void *data; | 30 | #define PING_ARRAY_DEFINED |
30 | uint32_t length; | 31 | typedef 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 | ||
36 | typedef 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 | */ |
42 | struct 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 | */ | ||
47 | void 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 | */ |
51 | uint64_t ping_array_add(Ping_Array *array, const uint8_t *data, uint32_t length); | 55 | uint64_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 | */ |
60 | int ping_array_check(uint8_t *data, uint32_t length, Ping_Array *array, uint64_t ping_id); | 65 | int32_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 | */ | ||
69 | int 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 | */ | ||
73 | void 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 | ||
33 | extern "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. | ||
142 | class 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 | */ | ||
151 | struct 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 | */ | ||
169 | const 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 | */ | ||
176 | const 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 | */ | ||
182 | const 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 | |||
205 | static 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 | */ | ||
236 | const PUBLIC_KEY_SIZE = 32; | ||
237 | |||
238 | /** | ||
239 | * The size of a Tox Secret Key in bytes. | ||
240 | */ | ||
241 | const SECRET_KEY_SIZE = 32; | ||
242 | |||
243 | /** | ||
244 | * The size of the nospam in bytes when written in a Tox address. | ||
245 | */ | ||
246 | const 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 | */ | ||
256 | const 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 | */ | ||
263 | const 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 | */ | ||
270 | const 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 | */ | ||
277 | const 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 | */ | ||
284 | const 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 | */ | ||
291 | const MAX_CUSTOM_PACKET_SIZE = 1373; | ||
292 | |||
293 | /** | ||
294 | * The number of bytes in a hash generated by $hash. | ||
295 | */ | ||
296 | const HASH_LENGTH = 32; | ||
297 | |||
298 | /** | ||
299 | * The number of bytes in a file id. | ||
300 | */ | ||
301 | const 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 | */ | ||
308 | const 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 | */ | ||
321 | enum 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 | */ | ||
343 | enum 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 | */ | ||
366 | enum 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 | */ | ||
384 | enum 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 | */ | ||
403 | enum 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 | */ | ||
443 | typedef void log_cb(LOG_LEVEL level, string file, uint32_t line, string func, string message, any user_data); | ||
444 | |||
445 | |||
446 | static 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 | */ | ||
652 | static 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 | */ | ||
710 | void kill(); | ||
711 | |||
712 | |||
713 | uint8_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 | */ | ||
754 | bool 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 | */ | ||
781 | bool 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 | */ | ||
788 | enum 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 | |||
810 | inline 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 | */ | ||
847 | const uint32_t iteration_interval(); | ||
848 | |||
849 | |||
850 | /** | ||
851 | * The main loop that needs to be run in intervals of $iteration_interval() | ||
852 | * milliseconds. | ||
853 | */ | ||
854 | void iterate(any user_data); | ||
855 | |||
856 | |||
857 | /******************************************************************************* | ||
858 | * | ||
859 | * :: Internal client information (Tox address/id) | ||
860 | * | ||
861 | ******************************************************************************/ | ||
862 | |||
863 | |||
864 | inline 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 | */ | ||
933 | error for set_info { | ||
934 | NULL, | ||
935 | /** | ||
936 | * Information length exceeded maximum permissible size. | ||
937 | */ | ||
938 | TOO_LONG, | ||
939 | } | ||
940 | |||
941 | |||
942 | inline 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 | |||
1044 | namespace 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 | |||
1157 | namespace 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 | |||
1182 | inline 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 | |||
1209 | namespace 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 | |||
1231 | namespace 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 | |||
1257 | namespace 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 | |||
1471 | inline 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 | |||
1495 | namespace 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 | |||
1573 | namespace 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 | */ | ||
1631 | static bool hash(uint8_t[HASH_LENGTH] hash, const uint8_t[length] data); | ||
1632 | |||
1633 | |||
1634 | namespace 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 | |||
1824 | namespace 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 | |||
2003 | namespace 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 | |||
2066 | namespace 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 | |||
2444 | namespace 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 | |||
2553 | inline 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 | ||
31 | typedef 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 | ||
35 | typedef 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 | ||
73 | uint32_t tox_version_major(void) | ||
74 | { | ||
75 | return TOX_VERSION_MAJOR; | ||
76 | } | ||
77 | |||
78 | uint32_t tox_version_minor(void) | ||
79 | { | ||
80 | return TOX_VERSION_MINOR; | ||
81 | } | ||
82 | |||
83 | uint32_t tox_version_patch(void) | ||
84 | { | ||
85 | return TOX_VERSION_PATCH; | ||
86 | } | ||
87 | 76 | ||
88 | bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch) | 77 | bool 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 | ||
98 | void 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 | |||
108 | struct 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 | |||
122 | void tox_options_free(struct Tox_Options *options) | ||
123 | { | ||
124 | free(options); | ||
125 | } | ||
126 | |||
127 | Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error) | 83 | Tox *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 | ||
241 | void tox_kill(Tox *tox) | 201 | void 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 | ||
249 | size_t tox_get_savedata_size(const Tox *tox) | 212 | size_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 | ||
255 | void tox_get_savedata(const Tox *tox, uint8_t *data) | 218 | void 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 | ||
320 | bool tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key, | 269 | bool 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 | ||
377 | TOX_CONNECTION tox_self_get_connection_status(const Tox *tox) | 312 | TOX_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 | ||
393 | void tox_callback_self_connection_status(Tox *tox, tox_self_connection_status_cb *function, void *user_data) | 330 | void 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 | ||
399 | uint32_t tox_iteration_interval(const Tox *tox) | 336 | uint32_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 | ||
405 | void tox_iterate(Tox *tox) | 342 | void 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 | ||
412 | void tox_self_get_address(const Tox *tox, uint8_t *address) | 349 | void 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) | |||
420 | void tox_self_set_nospam(Tox *tox, uint32_t nospam) | 357 | void 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 | ||
426 | uint32_t tox_self_get_nospam(const Tox *tox) | 363 | uint32_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 | ||
432 | void tox_self_get_public_key(const Tox *tox, uint8_t *public_key) | 369 | void 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 | ||
440 | void tox_self_get_secret_key(const Tox *tox, uint8_t *secret_key) | 378 | void 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 | ||
448 | bool tox_self_set_name(Tox *tox, const uint8_t *name, size_t length, TOX_ERR_SET_INFO *error) | 387 | bool 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 | ||
468 | size_t tox_self_get_name_size(const Tox *tox) | 407 | size_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 | ||
482 | bool tox_self_set_status_message(Tox *tox, const uint8_t *status, size_t length, TOX_ERR_SET_INFO *error) | 421 | bool 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 | ||
500 | size_t tox_self_get_status_message_size(const Tox *tox) | 439 | size_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 | ||
506 | void tox_self_get_status_message(const Tox *tox, uint8_t *status) | 445 | void 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 | ||
514 | void tox_self_set_status(Tox *tox, TOX_USER_STATUS user_status) | 453 | void 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 | ||
520 | TOX_USER_STATUS tox_self_get_status(const Tox *tox) | 459 | TOX_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 | ||
526 | static void set_friend_error(int32_t ret, TOX_ERR_FRIEND_ADD *error) | 466 | static 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 | ||
677 | void tox_self_get_friend_list(const Tox *tox, uint32_t *list) | 616 | void 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 | ||
719 | void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *function, void *user_data) | 658 | void 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 | ||
725 | size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) | 664 | size_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 | ||
739 | bool tox_friend_get_status_message(const Tox *tox, uint32_t friend_number, uint8_t *message, | 678 | bool 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 | ||
760 | void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *function, void *user_data) | 699 | void 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 | ||
766 | TOX_USER_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) | 705 | TOX_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 | ||
781 | void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *function, void *user_data) | 720 | void 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 | ||
787 | TOX_CONNECTION tox_friend_get_connection_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) | 726 | TOX_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 | ||
802 | void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_status_cb *function, void *user_data) | 741 | void 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 | ||
808 | bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) | 747 | bool 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 | ||
822 | void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *function, void *user_data) | 761 | void 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 | ||
828 | bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool is_typing, TOX_ERR_SET_TYPING *error) | 767 | bool 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 | ||
889 | void tox_callback_friend_read_receipt(Tox *tox, tox_friend_read_receipt_cb *function, void *user_data) | 828 | void 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 | ||
895 | void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *function, void *user_data) | 834 | void 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 | ||
901 | void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *function, void *user_data) | 840 | void 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 | ||
907 | bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length) | 846 | bool 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 | ||
1008 | void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *function, void *user_data) | 947 | void 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 | ||
1014 | bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t *file_id, | 953 | bool 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 | ||
1128 | void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *function, void *user_data) | 1069 | void 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 | |||
1075 | void 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 | ||
1134 | void tox_callback_file_recv(Tox *tox, tox_file_recv_cb *function, void *user_data) | 1081 | void 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 | ||
1140 | void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *function, void *user_data) | 1087 | void 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 | |||
1095 | void 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 | |||
1103 | void 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 | |||
1109 | void 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 | |||
1115 | void 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 | |||
1121 | uint32_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 | |||
1135 | bool 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 | |||
1149 | uint32_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 | |||
1163 | size_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 | |||
1183 | bool 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 | |||
1203 | bool 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 | |||
1223 | bool 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 | |||
1247 | bool 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 | |||
1267 | uint32_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 | |||
1303 | bool 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 | |||
1337 | size_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 | |||
1356 | bool 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 | |||
1376 | bool 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 | |||
1400 | size_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 | |||
1406 | void 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 | |||
1413 | TOX_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 | ||
1146 | static void set_custom_packet_error(int ret, TOX_ERR_FRIEND_CUSTOM_PACKET *error) | 1428 | static 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 | ||
1206 | void tox_callback_friend_lossy_packet(Tox *tox, tox_friend_lossy_packet_cb *function, void *user_data) | 1488 | void 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 | ||
1212 | bool tox_friend_send_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, | 1494 | bool 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 | ||
1238 | void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb *function, void *user_data) | 1520 | void 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 | ||
1244 | void tox_self_get_dht_id(const Tox *tox, uint8_t *dht_id) | 1526 | void 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 | ||
1252 | uint16_t tox_self_get_udp_port(const Tox *tox, TOX_ERR_GET_PORT *error) | 1534 | uint16_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 | |||
168 | uint32_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 | |||
177 | uint32_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 | */ | ||
183 | uint32_t tox_version_major(void); | ||
184 | 184 | ||
185 | /** | 185 | uint32_t tox_version_patch(void); |
186 | * Return the minor version number of the library. | ||
187 | */ | ||
188 | uint32_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 |
193 | uint32_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 | ||
239 | uint32_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 | ||
246 | uint32_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 | |||
253 | uint32_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 | |||
265 | uint32_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 | ||
274 | uint32_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 | ||
283 | uint32_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 | ||
292 | uint32_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 | ||
301 | uint32_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 | ||
310 | uint32_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 | ||
317 | uint32_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 | ||
324 | uint32_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 | ||
333 | uint32_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 | */ |
315 | typedef enum TOX_MESSAGE_TYPE { | 373 | typedef 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. | 447 | typedef 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 | */ | ||
494 | typedef 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 | */ |
391 | struct Tox_Options { | 511 | struct 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 | ||
648 | bool tox_options_get_ipv6_enabled(const struct Tox_Options *options); | ||
649 | |||
650 | void tox_options_set_ipv6_enabled(struct Tox_Options *options, bool ipv6_enabled); | ||
651 | |||
652 | bool tox_options_get_udp_enabled(const struct Tox_Options *options); | ||
653 | |||
654 | void tox_options_set_udp_enabled(struct Tox_Options *options, bool udp_enabled); | ||
655 | |||
656 | bool tox_options_get_local_discovery_enabled(const struct Tox_Options *options); | ||
657 | |||
658 | void tox_options_set_local_discovery_enabled(struct Tox_Options *options, bool local_discovery_enabled); | ||
659 | |||
660 | TOX_PROXY_TYPE tox_options_get_proxy_type(const struct Tox_Options *options); | ||
661 | |||
662 | void tox_options_set_proxy_type(struct Tox_Options *options, TOX_PROXY_TYPE type); | ||
663 | |||
664 | const char *tox_options_get_proxy_host(const struct Tox_Options *options); | ||
665 | |||
666 | void tox_options_set_proxy_host(struct Tox_Options *options, const char *host); | ||
667 | |||
668 | uint16_t tox_options_get_proxy_port(const struct Tox_Options *options); | ||
669 | |||
670 | void tox_options_set_proxy_port(struct Tox_Options *options, uint16_t port); | ||
671 | |||
672 | uint16_t tox_options_get_start_port(const struct Tox_Options *options); | ||
673 | |||
674 | void tox_options_set_start_port(struct Tox_Options *options, uint16_t start_port); | ||
675 | |||
676 | uint16_t tox_options_get_end_port(const struct Tox_Options *options); | ||
677 | |||
678 | void tox_options_set_end_port(struct Tox_Options *options, uint16_t end_port); | ||
679 | |||
680 | uint16_t tox_options_get_tcp_port(const struct Tox_Options *options); | ||
681 | |||
682 | void tox_options_set_tcp_port(struct Tox_Options *options, uint16_t tcp_port); | ||
683 | |||
684 | bool tox_options_get_hole_punching_enabled(const struct Tox_Options *options); | ||
685 | |||
686 | void tox_options_set_hole_punching_enabled(struct Tox_Options *options, bool hole_punching_enabled); | ||
687 | |||
688 | TOX_SAVEDATA_TYPE tox_options_get_savedata_type(const struct Tox_Options *options); | ||
689 | |||
690 | void tox_options_set_savedata_type(struct Tox_Options *options, TOX_SAVEDATA_TYPE type); | ||
691 | |||
692 | const uint8_t *tox_options_get_savedata_data(const struct Tox_Options *options); | ||
693 | |||
694 | void tox_options_set_savedata_data(struct Tox_Options *options, const uint8_t *data, size_t length); | ||
695 | |||
696 | size_t tox_options_get_savedata_length(const struct Tox_Options *options); | ||
697 | |||
698 | void tox_options_set_savedata_length(struct Tox_Options *options, size_t length); | ||
699 | |||
700 | tox_log_cb *tox_options_get_log_callback(const struct Tox_Options *options); | ||
701 | |||
702 | void tox_options_set_log_callback(struct Tox_Options *options, tox_log_cb *callback); | ||
703 | |||
704 | void *tox_options_get_log_user_data(const struct Tox_Options *options); | ||
705 | |||
706 | void 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 | */ |
658 | void tox_get_savedata(const Tox *tox, uint8_t *savedata); | 870 | void 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 | */ |
760 | TOX_CONNECTION tox_self_get_connection_status(const Tox *tox); | 975 | TOX_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 | */ |
779 | void tox_callback_self_connection_status(Tox *tox, tox_self_connection_status_cb *callback, void *user_data); | 994 | void 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 | */ |
791 | void tox_iterate(Tox *tox); | 1006 | void tox_iterate(Tox *tox, void *user_data); |
792 | 1007 | ||
793 | 1008 | ||
794 | /******************************************************************************* | 1009 | /******************************************************************************* |
@@ -811,14 +1026,17 @@ void tox_iterate(Tox *tox); | |||
811 | void tox_self_get_address(const Tox *tox, uint8_t *address); | 1026 | void 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 | */ |
818 | void tox_self_set_nospam(Tox *tox, uint32_t nospam); | 1035 | void 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 | */ |
823 | uint32_t tox_self_get_nospam(const Tox *tox); | 1041 | uint32_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 | */ |
942 | void tox_self_get_status_message(const Tox *tox, uint8_t *status_message); | 1160 | void 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 | */ |
949 | void tox_self_set_status(Tox *tox, TOX_USER_STATUS status); | 1167 | void 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 | */ |
1151 | void tox_self_get_friend_list(const Tox *tox, uint32_t *friend_list); | 1369 | void 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 | */ |
1277 | void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *callback, void *user_data); | 1495 | void 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 | */ |
1317 | void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *callback, void *user_data); | 1535 | void 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 | */ |
1326 | TOX_USER_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); | 1547 | TOX_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 | */ |
1341 | void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *callback, void *user_data); | 1562 | void 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 | */ |
1355 | TOX_CONNECTION tox_friend_get_connection_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); | 1579 | TOX_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 | */ |
1376 | void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_status_cb *callback, void *user_data); | 1600 | void 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 | */ |
1387 | bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error); | 1614 | bool 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 | */ |
1403 | void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *callback, void *user_data); | 1630 | void 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 | */ |
1521 | void tox_callback_friend_read_receipt(Tox *tox, tox_friend_read_receipt_cb *callback, void *user_data); | 1748 | void 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 | */ |
1551 | void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *callback, void *user_data); | 1773 | void 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 | */ |
1561 | typedef void tox_friend_message_cb(Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type, const uint8_t *message, | 1780 | typedef 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 | */ |
1570 | void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *callback, void *user_data); | 1789 | void 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 | */ |
1738 | void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *callback, void *user_data); | 1957 | void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *callback); |
1739 | 1958 | ||
1740 | typedef enum TOX_ERR_FILE_SEEK { | 1959 | typedef 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 | */ |
2042 | void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *callback, void *user_data); | 2261 | void 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 | */ |
2080 | void tox_callback_file_recv(Tox *tox, tox_file_recv_cb *callback, void *user_data); | 2299 | void 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 | */ |
2108 | void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *callback, void *user_data); | 2327 | void 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 | */ | ||
2341 | typedef 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 | */ | ||
2366 | typedef 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 | */ | ||
2375 | void 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 | */ | ||
2384 | typedef 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 | */ | ||
2393 | void 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 | */ | ||
2401 | typedef 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 | */ | ||
2412 | void 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 | */ | ||
2421 | typedef 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 | */ | ||
2430 | void 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 | */ | ||
2436 | typedef 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 | */ | ||
2444 | void tox_callback_conference_peer_list_changed(Tox *tox, tox_conference_peer_list_changed_cb *callback); | ||
2445 | |||
2446 | typedef 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 | */ | ||
2468 | uint32_t tox_conference_new(Tox *tox, TOX_ERR_CONFERENCE_NEW *error); | ||
2469 | |||
2470 | typedef 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 | */ | ||
2492 | bool tox_conference_delete(Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_DELETE *error); | ||
2493 | |||
2494 | /** | ||
2495 | * Error codes for peer info queries. | ||
2496 | */ | ||
2497 | typedef 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 | */ | ||
2525 | uint32_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 | */ | ||
2530 | size_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 | */ | ||
2539 | bool 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 | */ | ||
2548 | bool 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 | */ | ||
2554 | bool 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 | |||
2557 | typedef 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 | */ | ||
2585 | bool tox_conference_invite(Tox *tox, uint32_t friend_number, uint32_t conference_number, | ||
2586 | TOX_ERR_CONFERENCE_INVITE *error); | ||
2587 | |||
2588 | typedef 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 | */ | ||
2637 | uint32_t tox_conference_join(Tox *tox, uint32_t friend_number, const uint8_t *cookie, size_t length, | ||
2638 | TOX_ERR_CONFERENCE_JOIN *error); | ||
2639 | |||
2640 | typedef 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 | */ | ||
2688 | bool 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 | |||
2691 | typedef 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 | */ | ||
2722 | size_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 | */ | ||
2737 | bool 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 | */ | ||
2747 | bool 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 | */ | ||
2754 | size_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 | */ | ||
2760 | void 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 | */ | ||
2766 | typedef 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 | |||
2781 | TOX_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 | */ |
2238 | void tox_callback_friend_lossy_packet(Tox *tox, tox_friend_lossy_packet_cb *callback, void *user_data); | 2894 | void 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 | */ |
2253 | void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb *callback, void *user_data); | 2909 | void 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 | */ |
2302 | uint16_t tox_self_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error); | 2958 | uint16_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) \ | ||
12 | uint32_t tox_##lowercase(void) \ | ||
13 | { \ | ||
14 | return TOX_##uppercase; \ | ||
15 | } | ||
16 | |||
17 | CONST_FUNCTION(version_major, VERSION_MAJOR) | ||
18 | CONST_FUNCTION(version_minor, VERSION_MINOR) | ||
19 | CONST_FUNCTION(version_patch, VERSION_PATCH) | ||
20 | CONST_FUNCTION(public_key_size, PUBLIC_KEY_SIZE) | ||
21 | CONST_FUNCTION(secret_key_size, SECRET_KEY_SIZE) | ||
22 | CONST_FUNCTION(nospam_size, NOSPAM_SIZE) | ||
23 | CONST_FUNCTION(address_size, ADDRESS_SIZE) | ||
24 | CONST_FUNCTION(max_name_length, MAX_NAME_LENGTH) | ||
25 | CONST_FUNCTION(max_status_message_length, MAX_STATUS_MESSAGE_LENGTH) | ||
26 | CONST_FUNCTION(max_friend_request_length, MAX_FRIEND_REQUEST_LENGTH) | ||
27 | CONST_FUNCTION(max_message_length, MAX_MESSAGE_LENGTH) | ||
28 | CONST_FUNCTION(max_custom_packet_size, MAX_CUSTOM_PACKET_SIZE) | ||
29 | CONST_FUNCTION(hash_length, HASH_LENGTH) | ||
30 | CONST_FUNCTION(file_id_length, FILE_ID_LENGTH) | ||
31 | CONST_FUNCTION(max_filename_length, MAX_FILENAME_LENGTH) | ||
32 | |||
33 | |||
34 | #define ACCESSORS(type, ns, name) \ | ||
35 | type tox_options_get_##ns##name(const struct Tox_Options *options) \ | ||
36 | { \ | ||
37 | return options->ns##name; \ | ||
38 | } \ | ||
39 | void tox_options_set_##ns##name(struct Tox_Options *options, type name) \ | ||
40 | { \ | ||
41 | options->ns##name = name; \ | ||
42 | } | ||
43 | |||
44 | ACCESSORS(bool,, ipv6_enabled) | ||
45 | ACCESSORS(bool,, udp_enabled) | ||
46 | ACCESSORS(TOX_PROXY_TYPE, proxy_, type) | ||
47 | ACCESSORS(const char *, proxy_, host) | ||
48 | ACCESSORS(uint16_t, proxy_, port) | ||
49 | ACCESSORS(uint16_t,, start_port) | ||
50 | ACCESSORS(uint16_t,, end_port) | ||
51 | ACCESSORS(uint16_t,, tcp_port) | ||
52 | ACCESSORS(bool,, hole_punching_enabled) | ||
53 | ACCESSORS(TOX_SAVEDATA_TYPE, savedata_, type) | ||
54 | ACCESSORS(size_t, savedata_, length) | ||
55 | ACCESSORS(tox_log_cb *, log_, callback) | ||
56 | ACCESSORS(void *, log_, user_data) | ||
57 | ACCESSORS(bool,, local_discovery_enabled) | ||
58 | |||
59 | const uint8_t *tox_options_get_savedata_data(const struct Tox_Options *options) | ||
60 | { | ||
61 | return options->savedata_data; | ||
62 | } | ||
63 | |||
64 | void 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 | |||
70 | void 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 | |||
83 | struct 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 | |||
97 | void 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 | */ | ||
8 | enum { | ||
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 | */ | ||
21 | void 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 | */ | ||
28 | void 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 | */ | ||
35 | void 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 | */ | ||
43 | void 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 | */ | ||
51 | typedef enum { | ||
52 | TOX_CHAT_CHANGE_PEER_ADD, | ||
53 | TOX_CHAT_CHANGE_PEER_DEL, | ||
54 | TOX_CHAT_CHANGE_PEER_NAME, | ||
55 | } TOX_CHAT_CHANGE; | ||
56 | |||
57 | void 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 | */ | ||
65 | int 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 | */ | ||
72 | int 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 | */ | ||
80 | int 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 | */ | ||
88 | int 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 | */ | ||
94 | int 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 | */ | ||
102 | int 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 | */ | ||
108 | int 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 | */ | ||
114 | int 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 | */ | ||
120 | int 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 | */ | ||
128 | int 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 | */ | ||
135 | unsigned 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 | */ | ||
140 | int 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 | */ | ||
152 | int 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. */ | ||
158 | uint32_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. */ | ||
165 | uint32_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 | */ | ||
172 | int 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 | */ | ||
9 | void 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 | */ | ||
20 | void 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 | */ | ||
31 | void 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 | */ | ||
43 | void 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 | */ | ||
55 | void 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 | */ | ||
66 | int 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 | */ | ||
77 | int 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 | */ | ||
89 | int 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 | */ | ||
101 | int 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 | */ | ||
111 | int 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 | */ | ||
123 | int 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 | */ | ||
133 | int 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 | */ | ||
143 | int 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 | */ | ||
153 | int 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 | */ | ||
165 | int 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 | */ | ||
176 | unsigned 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 | */ | ||
185 | int 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 | */ | ||
201 | int 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. */ | ||
211 | uint32_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. */ | ||
222 | uint32_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 | */ | ||
233 | int 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 */ |
38 | static uint64_t unix_time_value; | 44 | static uint64_t unix_time_value; |
39 | static uint64_t unix_base_time_value; | 45 | static uint64_t unix_base_time_value; |
40 | 46 | ||
41 | void 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 */ | ||
49 | void 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 | ||
49 | uint64_t unix_time() | 58 | uint64_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 | ||
66 | uint32_t id_copy(uint8_t *dest, const uint8_t *src) | 75 | uint32_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 | ||
72 | void host_to_net(uint8_t *num, uint16_t numbytes) | 81 | void 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 | ||
87 | uint16_t lendian_to_host16(uint16_t lendian) | 95 | uint16_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) | |||
96 | void host_to_lendian32(uint8_t *dest, uint32_t num) | 104 | void 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 */ |
117 | int load_state(load_state_callback_func load_state_callback, void *outer, | 125 | int 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 | ||
173 | int create_recursive_mutex(pthread_mutex_t *mutex) | 174 | int 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 | 198 | int32_t max_s32(int32_t a, int32_t b) | |
197 | struct RingBuffer { | ||
198 | uint16_t size; /* Max size */ | ||
199 | uint16_t start; | ||
200 | uint16_t end; | ||
201 | void **data; | ||
202 | }; | ||
203 | |||
204 | bool rb_full(const RingBuffer *b) | ||
205 | { | ||
206 | return (b->end + 1) % b->size == b->start; | ||
207 | } | ||
208 | bool rb_empty(const RingBuffer *b) | ||
209 | { | ||
210 | return b->end == b->start; | ||
211 | } | ||
212 | void *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 | } | ||
227 | bool 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 | } | ||
238 | RingBuffer *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 | } | ||
253 | void 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 | } |
260 | uint16_t rb_size(const RingBuffer *b) | ||
261 | { | ||
262 | if (rb_empty(b)) | ||
263 | return 0; | ||
264 | 202 | ||
265 | return | 203 | uint64_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 | } | ||
270 | uint16_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 | ||
36 | extern "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 | ||
35 | void unix_time_update(); | 42 | void unix_time_update(void); |
36 | uint64_t unix_time(); | 43 | uint64_t unix_time(void); |
37 | int is_timeout(uint64_t timestamp, uint64_t timeout); | 44 | int 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 */ |
54 | typedef int (*load_state_callback_func)(void *outer, const uint8_t *data, uint32_t len, uint16_t type); | 61 | typedef int (*load_state_callback_func)(void *outer, const uint8_t *data, uint32_t len, uint16_t type); |
55 | int load_state(load_state_callback_func load_state_callback, void *outer, | 62 | int 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 */ |
59 | int create_recursive_mutex(pthread_mutex_t *mutex); | 66 | int create_recursive_mutex(pthread_mutex_t *mutex); |
60 | 67 | ||
61 | /* Ring buffer */ | 68 | int32_t max_s32(int32_t a, int32_t b); |
62 | typedef struct RingBuffer RingBuffer; | 69 | uint64_t min_u64(uint64_t a, uint64_t b); |
63 | bool rb_full(const RingBuffer *b); | 70 | |
64 | bool rb_empty(const RingBuffer *b); | 71 | #ifdef __cplusplus |
65 | void *rb_write(RingBuffer *b, void *p); | 72 | } // extern "C" |
66 | bool rb_read(RingBuffer *b, void **p); | 73 | #endif |
67 | RingBuffer *rb_new(int size); | 74 | |
68 | void rb_kill(RingBuffer *b); | 75 | #endif /* UTIL_H */ |
69 | uint16_t rb_size(const RingBuffer *b); | ||
70 | uint16_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 | |||
7 | TEST(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 | |||
20 | TEST(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 | |||
32 | TEST(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 | |||
45 | TEST(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 | } | ||