diff options
50 files changed, 5123 insertions, 4104 deletions
diff --git a/auto_tests/Makefile.inc b/auto_tests/Makefile.inc index 1f0f6697..5e101f60 100644 --- a/auto_tests/Makefile.inc +++ b/auto_tests/Makefile.inc | |||
@@ -15,6 +15,7 @@ AUTOTEST_LDADD = \ | |||
15 | $(NACL_LDFLAGS) \ | 15 | $(NACL_LDFLAGS) \ |
16 | libtoxcore.la \ | 16 | libtoxcore.la \ |
17 | $(LIBSODIUM_LIBS) \ | 17 | $(LIBSODIUM_LIBS) \ |
18 | $(NACL_OBJECTS) \ | ||
18 | $(NACL_LIBS) \ | 19 | $(NACL_LIBS) \ |
19 | $(CHECK_LIBS) | 20 | $(CHECK_LIBS) |
20 | 21 | ||
diff --git a/configure.ac b/configure.ac index 8650e197..7456617a 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -427,6 +427,17 @@ AC_C_BIGENDIAN | |||
427 | # Checks for library functions. | 427 | # Checks for library functions. |
428 | AC_FUNC_FORK | 428 | AC_FUNC_FORK |
429 | AC_CHECK_FUNCS([gettimeofday memset socket strchr malloc]) | 429 | AC_CHECK_FUNCS([gettimeofday memset socket strchr malloc]) |
430 | if test "x$WIN32" != "xyes"; then | ||
431 | AC_CHECK_LIB(rt, clock_gettime, | ||
432 | [ | ||
433 | RT_LIBS="-lrt" | ||
434 | AC_SUBST(RT_LIBS) | ||
435 | ], | ||
436 | [ | ||
437 | AC_MSG_ERROR([required library rt was not found on your system]) | ||
438 | ] | ||
439 | ) | ||
440 | fi | ||
430 | 441 | ||
431 | if test "x$BUILD_AV" = "xyes"; then | 442 | if test "x$BUILD_AV" = "xyes"; then |
432 | AX_PTHREAD( | 443 | AX_PTHREAD( |
diff --git a/other/DHT_bootstrap.c b/other/DHT_bootstrap.c index 291d6589..462360c3 100644 --- a/other/DHT_bootstrap.c +++ b/other/DHT_bootstrap.c | |||
@@ -31,6 +31,12 @@ | |||
31 | #include "../toxcore/friend_requests.h" | 31 | #include "../toxcore/friend_requests.h" |
32 | #include "../toxcore/util.h" | 32 | #include "../toxcore/util.h" |
33 | 33 | ||
34 | #define TCP_RELAY_ENABLED | ||
35 | |||
36 | #ifdef TCP_RELAY_ENABLED | ||
37 | #include "../toxcore/TCP_server.h" | ||
38 | #endif | ||
39 | |||
34 | #include "../testing/misc_tools.c" | 40 | #include "../testing/misc_tools.c" |
35 | 41 | ||
36 | #ifdef DHT_NODE_EXTRA_PACKETS | 42 | #ifdef DHT_NODE_EXTRA_PACKETS |
@@ -69,11 +75,12 @@ void manage_keys(DHT *dht) | |||
69 | exit(1); | 75 | exit(1); |
70 | } | 76 | } |
71 | 77 | ||
72 | load_keys(dht->c, keys); | 78 | memcpy(dht->self_public_key, keys, crypto_box_PUBLICKEYBYTES); |
79 | memcpy(dht->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES); | ||
73 | printf("Keys loaded successfully.\n"); | 80 | printf("Keys loaded successfully.\n"); |
74 | } else { | 81 | } else { |
75 | new_keys(dht->c); | 82 | memcpy(keys, dht->self_public_key, crypto_box_PUBLICKEYBYTES); |
76 | save_keys(dht->c, keys); | 83 | memcpy(keys + crypto_box_PUBLICKEYBYTES, dht->self_secret_key, crypto_box_SECRETKEYBYTES); |
77 | keys_file = fopen("key", "w"); | 84 | keys_file = fopen("key", "w"); |
78 | 85 | ||
79 | if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file) != KEYS_SIZE) { | 86 | if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file) != KEYS_SIZE) { |
@@ -107,7 +114,7 @@ int main(int argc, char *argv[]) | |||
107 | IP ip; | 114 | IP ip; |
108 | ip_init(&ip, ipv6enabled); | 115 | ip_init(&ip, ipv6enabled); |
109 | 116 | ||
110 | DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT))); | 117 | DHT *dht = new_DHT(new_networking(ip, PORT)); |
111 | Onion *onion = new_onion(dht); | 118 | Onion *onion = new_onion(dht); |
112 | Onion_Announce *onion_a = new_onion_announce(dht); | 119 | Onion_Announce *onion_a = new_onion_announce(dht); |
113 | 120 | ||
@@ -123,27 +130,33 @@ int main(int argc, char *argv[]) | |||
123 | perror("Initialization"); | 130 | perror("Initialization"); |
124 | 131 | ||
125 | manage_keys(dht); | 132 | manage_keys(dht); |
126 | /* We want our DHT public key to be the same as our internal one since this is a bootstrap node */ | ||
127 | memcpy(dht->self_public_key, dht->c->self_public_key, crypto_box_PUBLICKEYBYTES); | ||
128 | memcpy(dht->self_secret_key, dht->c->self_secret_key, crypto_box_SECRETKEYBYTES); | ||
129 | printf("Public key: "); | 133 | printf("Public key: "); |
130 | uint32_t i; | 134 | uint32_t i; |
131 | 135 | ||
136 | #ifdef TCP_RELAY_ENABLED | ||
137 | #define NUM_PORTS 3 | ||
138 | uint16_t ports[NUM_PORTS] = {443, 3389, PORT}; | ||
139 | TCP_Server *tcp_s = new_TCP_server(ipv6enabled, NUM_PORTS, ports, dht->self_public_key, dht->self_secret_key, onion); | ||
140 | |||
141 | if (tcp_s == NULL) { | ||
142 | printf("TCP server failed to initialize.\n"); | ||
143 | exit(1); | ||
144 | } | ||
145 | |||
146 | #endif | ||
147 | |||
132 | FILE *file; | 148 | FILE *file; |
133 | file = fopen("PUBLIC_ID.txt", "w"); | 149 | file = fopen("PUBLIC_ID.txt", "w"); |
134 | 150 | ||
135 | for (i = 0; i < 32; i++) { | 151 | for (i = 0; i < 32; i++) { |
136 | if (dht->c->self_public_key[i] < 16) | 152 | printf("%02hhX", dht->self_public_key[i]); |
137 | printf("0"); | 153 | fprintf(file, "%02hhX", dht->self_public_key[i]); |
138 | |||
139 | printf("%hhX", dht->c->self_public_key[i]); | ||
140 | fprintf(file, "%hhX", dht->c->self_public_key[i]); | ||
141 | } | 154 | } |
142 | 155 | ||
143 | fclose(file); | 156 | fclose(file); |
144 | 157 | ||
145 | printf("\n"); | 158 | printf("\n"); |
146 | printf("Port: %u\n", ntohs(dht->c->lossless_udp->net->port)); | 159 | printf("Port: %u\n", ntohs(dht->net->port)); |
147 | 160 | ||
148 | if (argc > argvoffset + 3) { | 161 | if (argc > argvoffset + 3) { |
149 | printf("Trying to bootstrap into the network...\n"); | 162 | printf("Trying to bootstrap into the network...\n"); |
@@ -177,7 +190,10 @@ int main(int argc, char *argv[]) | |||
177 | last_LANdiscovery = unix_time(); | 190 | last_LANdiscovery = unix_time(); |
178 | } | 191 | } |
179 | 192 | ||
180 | networking_poll(dht->c->lossless_udp->net); | 193 | #ifdef TCP_RELAY_ENABLED |
194 | do_TCP_server(tcp_s); | ||
195 | #endif | ||
196 | networking_poll(dht->net); | ||
181 | 197 | ||
182 | c_sleep(1); | 198 | c_sleep(1); |
183 | } | 199 | } |
diff --git a/other/DHTnodes b/other/DHTnodes index 35509931..0abdbbd9 100644 --- a/other/DHTnodes +++ b/other/DHTnodes | |||
@@ -1,3 +1,3 @@ | |||
1 | As maintaining 2 seperate lists of the same information seemed redundant, this list has been phased out. | 1 | As maintaining 2 separate lists of the same information seemed redundant, this list has been phased out. |
2 | 2 | ||
3 | For a current DHT node list please visit http://wiki.tox.im/nodes | 3 | For a current DHT node list please visit http://wiki.tox.im/nodes |
diff --git a/testing/DHT_test.c b/testing/DHT_test.c index 3f8b58bd..2636ed02 100644 --- a/testing/DHT_test.c +++ b/testing/DHT_test.c | |||
@@ -187,9 +187,7 @@ int main(int argc, char *argv[]) | |||
187 | IP ip; | 187 | IP ip; |
188 | ip_init(&ip, ipv6enabled); | 188 | ip_init(&ip, ipv6enabled); |
189 | 189 | ||
190 | DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT))); | 190 | DHT *dht = new_DHT(new_networking(ip, PORT)); |
191 | |||
192 | new_keys(dht->c); | ||
193 | printf("OUR ID: "); | 191 | printf("OUR ID: "); |
194 | uint32_t i; | 192 | uint32_t i; |
195 | 193 | ||
@@ -245,7 +243,7 @@ int main(int argc, char *argv[]) | |||
245 | } | 243 | } |
246 | } | 244 | } |
247 | */ | 245 | */ |
248 | networking_poll(dht->c->lossless_udp->net); | 246 | networking_poll(dht->net); |
249 | 247 | ||
250 | print_clientlist(dht); | 248 | print_clientlist(dht); |
251 | print_friendlist(dht); | 249 | print_friendlist(dht); |
diff --git a/testing/Lossless_UDP_testclient.c b/testing/Lossless_UDP_testclient.c deleted file mode 100644 index 535509e0..00000000 --- a/testing/Lossless_UDP_testclient.c +++ /dev/null | |||
@@ -1,260 +0,0 @@ | |||
1 | /* Lossless_UDP testclient | ||
2 | * A program that connects and sends a file using our lossless UDP algorithm. | ||
3 | * NOTE: this program simulates a 33% packet loss. | ||
4 | * | ||
5 | * Best used in combination with Lossless_UDP_testserver | ||
6 | * | ||
7 | * Compile with: gcc -O2 -Wall -lsodium -o testclient ../toxcore/network.c ../toxcore/Lossless_UDP.c ../toxcore/util.c Lossless_UDP_testclient.c | ||
8 | * | ||
9 | * Command line arguments are the ip and port to connect and send the file to. | ||
10 | * EX: ./testclient --ipv4 127.0.0.1 33445 filename.txt | ||
11 | * | ||
12 | * Copyright (C) 2013 Tox project All Rights Reserved. | ||
13 | * | ||
14 | * This file is part of Tox. | ||
15 | * | ||
16 | * Tox is free software: you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation, either version 3 of the License, or | ||
19 | * (at your option) any later version. | ||
20 | * | ||
21 | * Tox is distributed in the hope that it will be useful, | ||
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
24 | * GNU General Public License for more details. | ||
25 | * | ||
26 | * You should have received a copy of the GNU General Public License | ||
27 | * along with Tox. If not, see <http://www.gnu.org/licenses/>. | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | #ifdef HAVE_CONFIG_H | ||
32 | #include "config.h" | ||
33 | #endif | ||
34 | |||
35 | #include "../toxcore/network.h" | ||
36 | #include "../toxcore/Lossless_UDP.h" | ||
37 | #include "../toxcore/util.h" | ||
38 | #include "misc_tools.c" | ||
39 | |||
40 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) | ||
41 | |||
42 | #define c_sleep(x) Sleep(1*x) | ||
43 | |||
44 | #else | ||
45 | #include <unistd.h> | ||
46 | #include <arpa/inet.h> | ||
47 | #define c_sleep(x) usleep(1000*x) | ||
48 | |||
49 | #endif | ||
50 | |||
51 | #define PORT 33446 | ||
52 | |||
53 | void printpacket(uint8_t *data, uint32_t length, IP_Port ip_port) | ||
54 | { | ||
55 | uint32_t i; | ||
56 | printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length); | ||
57 | printf("--------------------BEGIN-----------------------------\n"); | ||
58 | |||
59 | for (i = 0; i < length; i++) { | ||
60 | if (data[i] < 16) | ||
61 | printf("0"); | ||
62 | |||
63 | printf("%hhX", data[i]); | ||
64 | } | ||
65 | |||
66 | printf("\n--------------------END-----------------------------\n\n\n"); | ||
67 | } | ||
68 | |||
69 | void printip(IP_Port ip_port) | ||
70 | { | ||
71 | printf("\nIP: %s Port: %u", ip_ntoa(&ip_port.ip), ntohs(ip_port.port)); | ||
72 | } | ||
73 | /* | ||
74 | void printpackets(Data test) | ||
75 | { | ||
76 | int i; | ||
77 | if(test.size == 0) | ||
78 | return; | ||
79 | printf("SIZE: %u\n", test.size); | ||
80 | for(i =0; i < test.size; i++) | ||
81 | { | ||
82 | printf("%hhX", test.data[i]); | ||
83 | } | ||
84 | printf("\n"); | ||
85 | } | ||
86 | |||
87 | void printconnection(int connection_id) | ||
88 | { | ||
89 | printf("--------------------BEGIN---------------------\n"); | ||
90 | IP_Port ip_port = connections[connection_id].ip_port; | ||
91 | printf("IP: %u.%u.%u.%u Port: %u\n",ip_port.ip.c[0],ip_port.ip.c[1],ip_port.ip.c[2],ip_port.ip.c[3],ntohs(ip_port.port)); | ||
92 | printf("status: %u, inbound: %u, SYNC_rate: %u\n", connections[connection_id].status, | ||
93 | connections[connection_id].inbound, connections[connection_id].SYNC_rate); | ||
94 | printf("data rate: %u, last sync: %llu, last sent: %llu, last recv: %llu \n", connections[connection_id].data_rate, | ||
95 | connections[connection_id].last_SYNC, connections[connection_id].last_sent, connections[connection_id].last_recv); | ||
96 | int i; | ||
97 | for(i =0; i < MAX_QUEUE_NUM; i++) | ||
98 | { | ||
99 | printf(" %u ",i); | ||
100 | printpackets(connections[connection_id].sendbuffer[i]); | ||
101 | } | ||
102 | for(i =0; i < MAX_QUEUE_NUM; i++) | ||
103 | { | ||
104 | printf(" %u ",i); | ||
105 | printpackets(connections[connection_id].recvbuffer[i]); | ||
106 | } | ||
107 | Data sendbuffer[MAX_QUEUE_NUM]; | ||
108 | Data recvbuffer[MAX_QUEUE_NUM]; | ||
109 | printf("recv_num: %u, orecv_num: %u, sent_packetnum %u, osent_packetnum: %u, successful_sent: %u, successful_read: %u\n", | ||
110 | connections[connection_id].recv_packetnum, | ||
111 | connections[connection_id].orecv_packetnum, connections[connection_id].sent_packetnum, connections[connection_id].osent_packetnum, | ||
112 | connections[connection_id].successful_sent, | ||
113 | connections[connection_id].successful_read); | ||
114 | |||
115 | printf("req packets: \n"); | ||
116 | for(i = 0; i < BUFFER_PACKET_NUM; i++) | ||
117 | { | ||
118 | printf(" %u ", connections[connection_id].req_packets[i]); | ||
119 | } | ||
120 | printf("\nNumber: %u recv_counter: %u, send_counter: %u\n", connections[connection_id].num_req_paquets, | ||
121 | connections[connection_id].recv_counter, connections[connection_id].send_counter); | ||
122 | |||
123 | printf("--------------------END---------------------\n"); | ||
124 | |||
125 | } | ||
126 | */ | ||
127 | |||
128 | /*( receive packets and send them to the packethandler */ | ||
129 | /*run doLossless_UDP(); */ | ||
130 | //void Lossless_UDP() | ||
131 | //{ | ||
132 | /* IP_Port ip_port; | ||
133 | uint8_t data[MAX_UDP_PACKET_SIZE]; | ||
134 | uint32_t length; | ||
135 | while (receivepacket(&ip_port, data, &length) != -1) { | ||
136 | printf("packet with length: %u\n", length); */ | ||
137 | /* if(rand() % 3 != 1)//add packet loss | ||
138 | { */ | ||
139 | /* | ||
140 | if (LosslessUDP_handlepacket(data, length, ip_port)) | ||
141 | printpacket(data, length, ip_port); | ||
142 | else | ||
143 | printf("Received handled packet with length: %u\n", length); //printconnection(0); */ | ||
144 | |||
145 | /* } */ | ||
146 | /* }*/ | ||
147 | |||
148 | //networking_poll(); | ||
149 | |||
150 | //doLossless_UDP(); | ||
151 | |||
152 | //} | ||
153 | |||
154 | int main(int argc, char *argv[]) | ||
155 | { | ||
156 | /* let user override default by cmdline */ | ||
157 | uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */ | ||
158 | int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled); | ||
159 | |||
160 | if (argvoffset < 0) | ||
161 | exit(1); | ||
162 | |||
163 | if (argc < argvoffset + 4) { | ||
164 | printf("Usage: %s [--ipv4|--ipv6] ip port filename\n", argv[0]); | ||
165 | exit(0); | ||
166 | } | ||
167 | |||
168 | uint8_t buffer[MAX_DATA_SIZE]; | ||
169 | int read; | ||
170 | |||
171 | FILE *file = fopen(argv[argvoffset + 3], "rb"); | ||
172 | |||
173 | if (file == NULL) { | ||
174 | printf("Failed to open file \"%s\".\n", argv[argvoffset + 3]); | ||
175 | return 1; | ||
176 | } | ||
177 | |||
178 | |||
179 | /* initialize networking */ | ||
180 | /* bind to ip 0.0.0.0:PORT */ | ||
181 | IP ip; | ||
182 | ip_init(&ip, ipv6enabled); | ||
183 | |||
184 | Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT)); | ||
185 | perror("Initialization"); | ||
186 | |||
187 | IP_Port serverip; | ||
188 | ip_init(&serverip.ip, ipv6enabled); | ||
189 | |||
190 | if (!addr_resolve(argv[argvoffset + 1], &serverip.ip, NULL)) { | ||
191 | printf("Failed to convert \"%s\" into an IP address.\n", argv[argvoffset + 1]); | ||
192 | return 1; | ||
193 | } | ||
194 | |||
195 | serverip.port = htons(atoi(argv[argvoffset + 2])); | ||
196 | printip(serverip); | ||
197 | |||
198 | int connection = new_connection(ludp, serverip); | ||
199 | uint64_t timer = current_time(); | ||
200 | |||
201 | while (1) { | ||
202 | /* printconnection(connection); */ | ||
203 | networking_poll(ludp->net); | ||
204 | do_lossless_udp(ludp); | ||
205 | |||
206 | if (is_connected(ludp, connection) == LUDP_ESTABLISHED) { | ||
207 | printf("Connecting took: %llu us\n", (unsigned long long)(current_time() - timer)); | ||
208 | break; | ||
209 | } | ||
210 | |||
211 | if (is_connected(ludp, connection) == LUDP_NO_CONNECTION) { | ||
212 | printf("Connection timeout after: %llu us\n", (unsigned long long)(current_time() - timer)); | ||
213 | return 1; | ||
214 | } | ||
215 | |||
216 | c_sleep(1); | ||
217 | } | ||
218 | |||
219 | timer = current_time(); | ||
220 | unsigned long long bytes_sent = 0; | ||
221 | |||
222 | /*read first part of file */ | ||
223 | read = fread(buffer, 1, MAX_DATA_SIZE, file); | ||
224 | |||
225 | while (1) { | ||
226 | /* printconnection(connection); */ | ||
227 | networking_poll(ludp->net); | ||
228 | do_lossless_udp(ludp); | ||
229 | |||
230 | if (is_connected(ludp, connection) == LUDP_ESTABLISHED) { | ||
231 | |||
232 | while (write_packet(ludp, connection, buffer, read)) { | ||
233 | bytes_sent += read; | ||
234 | /* printf("Wrote data.\n"); */ | ||
235 | read = fread(buffer, 1, MAX_DATA_SIZE, file); | ||
236 | |||
237 | } | ||
238 | |||
239 | /* printf("%u\n", sendqueue(connection)); */ | ||
240 | if (sendqueue(ludp, connection) == 0) { | ||
241 | if (read == 0) { | ||
242 | unsigned long long us = (unsigned long long)(current_time() - timer); | ||
243 | printf("Sent file successfully in: %llu us = %llu seconds. Average speed: %llu KB/s\n", us, us / 1000000UL, | ||
244 | bytes_sent / (us / 1024UL)); | ||
245 | //printf("Total bytes sent: %llu B, Total data sent: %llu B, overhead: %llu B\n", total_bytes_sent, bytes_sent, total_bytes_sent-bytes_sent); | ||
246 | break; | ||
247 | } | ||
248 | } | ||
249 | } else { | ||
250 | printf("%u Client Connecting Lost after: %llu us\n", is_connected(ludp, connection), | ||
251 | (unsigned long long)(current_time() - timer)); | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | } | ||
256 | |||
257 | c_sleep(25); | ||
258 | |||
259 | return 0; | ||
260 | } | ||
diff --git a/testing/Lossless_UDP_testserver.c b/testing/Lossless_UDP_testserver.c deleted file mode 100644 index dd4612f5..00000000 --- a/testing/Lossless_UDP_testserver.c +++ /dev/null | |||
@@ -1,237 +0,0 @@ | |||
1 | /* Lossless_UDP testserver | ||
2 | * A program that waits for a lossless UDP connection and then saves all the data received to a file. | ||
3 | * NOTE: this program simulates a 33% packet loss. | ||
4 | * | ||
5 | * Best used in combination with Lossless_UDP_testclient | ||
6 | * | ||
7 | * Compile with: gcc -O2 -Wall -lsodium -o testserver ../toxcore/network.c ../toxcore/Lossless_UDP.c ../toxcore/util.c Lossless_UDP_testserver.c | ||
8 | * | ||
9 | * Command line argument is the name of the file to save what we receive to. | ||
10 | * EX: ./testserver filename1.txt | ||
11 | * | ||
12 | * Copyright (C) 2013 Tox project All Rights Reserved. | ||
13 | * | ||
14 | * This file is part of Tox. | ||
15 | * | ||
16 | * Tox is free software: you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation, either version 3 of the License, or | ||
19 | * (at your option) any later version. | ||
20 | * | ||
21 | * Tox is distributed in the hope that it will be useful, | ||
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
24 | * GNU General Public License for more details. | ||
25 | * | ||
26 | * You should have received a copy of the GNU General Public License | ||
27 | * along with Tox. If not, see <http://www.gnu.org/licenses/>. | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | #ifdef HAVE_CONFIG_H | ||
32 | #include "config.h" | ||
33 | #endif | ||
34 | |||
35 | #include "../toxcore/network.h" | ||
36 | #include "../toxcore/Lossless_UDP.h" | ||
37 | #include "../toxcore/util.h" | ||
38 | #include "misc_tools.c" | ||
39 | |||
40 | //Sleep function (x = milliseconds) | ||
41 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) | ||
42 | |||
43 | #define c_sleep(x) Sleep(1*x) | ||
44 | |||
45 | #else | ||
46 | #include <unistd.h> | ||
47 | #include <arpa/inet.h> | ||
48 | #define c_sleep(x) usleep(1000*x) | ||
49 | |||
50 | #endif | ||
51 | |||
52 | #define PORT 33445 | ||
53 | |||
54 | void printpacket(uint8_t *data, uint32_t length, IP_Port ip_port) | ||
55 | { | ||
56 | uint32_t i; | ||
57 | printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length); | ||
58 | printf("--------------------BEGIN-----------------------------\n"); | ||
59 | |||
60 | for (i = 0; i < length; i++) { | ||
61 | if (data[i] < 16) | ||
62 | printf("0"); | ||
63 | |||
64 | printf("%hhX", data[i]); | ||
65 | } | ||
66 | |||
67 | printf("\n--------------------END-----------------------------\n\n\n"); | ||
68 | } | ||
69 | |||
70 | /* | ||
71 | void printpackets(Data test) | ||
72 | { | ||
73 | int i; | ||
74 | if(test.size == 0) | ||
75 | return; | ||
76 | printf("SIZE: %u\n", test.size); | ||
77 | for(i =0; i < test.size; i++) | ||
78 | { | ||
79 | printf("%hhX", test.data[i]); | ||
80 | } | ||
81 | printf("\n"); | ||
82 | } | ||
83 | |||
84 | void printconnection(int connection_id) | ||
85 | { | ||
86 | printf("--------------------BEGIN---------------------\n"); | ||
87 | IP_Port ip_port = connections[connection_id].ip_port; | ||
88 | printf("IP: %u.%u.%u.%u Port: %u\n",ip_port.ip.c[0],ip_port.ip.c[1],ip_port.ip.c[2],ip_port.ip.c[3],ntohs(ip_port.port)); | ||
89 | printf("status: %u, inbound: %u, SYNC_rate: %u\n", connections[connection_id].status, | ||
90 | connections[connection_id].inbound, connections[connection_id].SYNC_rate); | ||
91 | printf("data rate: %u, last sync: %llu, last sent: %llu, last recv: %llu \n", connections[connection_id].data_rate, | ||
92 | connections[connection_id].last_SYNC, connections[connection_id].last_sent, connections[connection_id].last_recv); | ||
93 | int i; | ||
94 | for(i =0; i < MAX_QUEUE_NUM; i++) | ||
95 | { | ||
96 | printf(" %u ",i); | ||
97 | printpackets(connections[connection_id].sendbuffer[i]); | ||
98 | } | ||
99 | for(i =0; i < MAX_QUEUE_NUM; i++) | ||
100 | { | ||
101 | printf(" %u ",i); | ||
102 | printpackets(connections[connection_id].recvbuffer[i]); | ||
103 | } | ||
104 | Data sendbuffer[MAX_QUEUE_NUM]; | ||
105 | Data recvbuffer[MAX_QUEUE_NUM]; | ||
106 | printf("recv_num: %u, orecv_num: %u, sent_packetnum %u, osent_packetnum: %u, successful_sent: %u, successful_read: %u\n", | ||
107 | connections[connection_id].recv_packetnum, | ||
108 | connections[connection_id].orecv_packetnum, connections[connection_id].sent_packetnum, connections[connection_id].osent_packetnum, | ||
109 | connections[connection_id].successful_sent, | ||
110 | connections[connection_id].successful_read); | ||
111 | |||
112 | printf("req packets: \n"); | ||
113 | for(i = 0; i < BUFFER_PACKET_NUM; i++) | ||
114 | { | ||
115 | printf(" %u ", connections[connection_id].req_packets[i]); | ||
116 | } | ||
117 | printf("\nNumber: %u recv_counter: %u, send_counter: %u\n", connections[connection_id].num_req_paquets, | ||
118 | connections[connection_id].recv_counter, connections[connection_id].send_counter); | ||
119 | |||
120 | printf("--------------------END---------------------\n"); | ||
121 | |||
122 | } | ||
123 | */ | ||
124 | |||
125 | /* receive packets and send them to the packethandler | ||
126 | * run doLossless_UDP(); */ | ||
127 | //void Lossless_UDP() | ||
128 | //{ | ||
129 | // IP_Port ip_port; | ||
130 | // uint8_t data[MAX_UDP_PACKET_SIZE]; | ||
131 | // uint32_t length; | ||
132 | // while (receivepacket(&ip_port, data, &length) != -1) { | ||
133 | //if(rand() % 3 != 1)//add packet loss | ||
134 | //{ | ||
135 | // if (LosslessUDP_handlepacket(data, length, ip_port)) { | ||
136 | // printpacket(data, length, ip_port); | ||
137 | // } else { | ||
138 | //printconnection(0); | ||
139 | // printf("Received handled packet with length: %u\n", length); | ||
140 | // } | ||
141 | //} | ||
142 | // } | ||
143 | |||
144 | // networking_poll(); | ||
145 | |||
146 | //doLossless_UDP(); | ||
147 | //} | ||
148 | |||
149 | |||
150 | int main(int argc, char *argv[]) | ||
151 | { | ||
152 | /* let user override default by cmdline */ | ||
153 | uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */ | ||
154 | int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled); | ||
155 | |||
156 | if (argvoffset < 0) | ||
157 | exit(1); | ||
158 | |||
159 | if (argc < argvoffset + 2) { | ||
160 | printf("Usage: %s [--ipv4|--ipv6] filename\n", argv[0]); | ||
161 | exit(0); | ||
162 | } | ||
163 | |||
164 | uint8_t buffer[MAX_DATA_SIZE]; | ||
165 | int read; | ||
166 | |||
167 | FILE *file = fopen(argv[argvoffset + 1], "wb"); | ||
168 | |||
169 | if (file == NULL) { | ||
170 | printf("Failed to open file \"%s\".\n", argv[argvoffset + 1]); | ||
171 | return 1; | ||
172 | } | ||
173 | |||
174 | |||
175 | //initialize networking | ||
176 | //bind to ip 0.0.0.0:PORT | ||
177 | IP ip; | ||
178 | ip_init(&ip, ipv6enabled); | ||
179 | |||
180 | Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT)); | ||
181 | perror("Initialization"); | ||
182 | |||
183 | int connection; | ||
184 | uint64_t timer = current_time(); | ||
185 | |||
186 | while (1) { | ||
187 | networking_poll(ludp->net); | ||
188 | do_lossless_udp(ludp); | ||
189 | connection = incoming_connection(ludp, 0); | ||
190 | |||
191 | if (connection != -1) { | ||
192 | if (is_connected(ludp, connection) == LUDP_NOT_CONFIRMED) { | ||
193 | printf("Received the connection.\n"); | ||
194 | |||
195 | } | ||
196 | |||
197 | break; | ||
198 | } | ||
199 | |||
200 | c_sleep(1); | ||
201 | } | ||
202 | |||
203 | timer = current_time(); | ||
204 | |||
205 | while (1) { | ||
206 | //printconnection(0); | ||
207 | networking_poll(ludp->net); | ||
208 | |||
209 | if (is_connected(ludp, connection) >= LUDP_NOT_CONFIRMED) { | ||
210 | confirm_connection(ludp, connection); | ||
211 | |||
212 | while (1) { | ||
213 | read = read_packet(ludp, connection, buffer); | ||
214 | |||
215 | if (read != 0) { | ||
216 | // printf("Received data.\n"); | ||
217 | if (!fwrite(buffer, read, 1, file)) | ||
218 | printf("file write error\n"); | ||
219 | } else { | ||
220 | break; | ||
221 | } | ||
222 | } | ||
223 | } | ||
224 | |||
225 | do_lossless_udp(ludp); | ||
226 | |||
227 | if (is_connected(ludp, connection) == LUDP_TIMED_OUT) { | ||
228 | printf("Server Connecting Lost after: %llu us\n", (unsigned long long)(current_time() - timer)); | ||
229 | fclose(file); | ||
230 | return 1; | ||
231 | } | ||
232 | |||
233 | c_sleep(25); | ||
234 | } | ||
235 | |||
236 | return 0; | ||
237 | } | ||
diff --git a/testing/Makefile.inc b/testing/Makefile.inc index 812a5be1..b3912033 100644 --- a/testing/Makefile.inc +++ b/testing/Makefile.inc | |||
@@ -22,8 +22,6 @@ endif | |||
22 | if BUILD_TESTING | 22 | if BUILD_TESTING |
23 | 23 | ||
24 | noinst_PROGRAMS += DHT_test \ | 24 | noinst_PROGRAMS += DHT_test \ |
25 | Lossless_UDP_testclient \ | ||
26 | Lossless_UDP_testserver \ | ||
27 | Messenger_test \ | 25 | Messenger_test \ |
28 | crypto_speed_test | 26 | crypto_speed_test |
29 | 27 | ||
@@ -41,40 +39,6 @@ DHT_test_LDADD = $(LIBSODIUM_LDFLAGS) \ | |||
41 | $(WINSOCK2_LIBS) | 39 | $(WINSOCK2_LIBS) |
42 | 40 | ||
43 | 41 | ||
44 | Lossless_UDP_testclient_SOURCES = \ | ||
45 | ../testing/Lossless_UDP_testclient.c | ||
46 | |||
47 | Lossless_UDP_testclient_CFLAGS = \ | ||
48 | $(LIBSODIUM_CFLAGS) \ | ||
49 | $(NACL_CFLAGS) | ||
50 | |||
51 | Lossless_UDP_testclient_LDADD = \ | ||
52 | $(LIBSODIUM_LDFLAGS) \ | ||
53 | $(NACL_LDFLAGS) \ | ||
54 | libtoxcore.la \ | ||
55 | $(LIBSODIUM_LIBS) \ | ||
56 | $(NACL_OBJECTS) \ | ||
57 | $(NACL_LIBS) \ | ||
58 | $(WINSOCK2_LIBS) | ||
59 | |||
60 | |||
61 | Lossless_UDP_testserver_SOURCES = \ | ||
62 | ../testing/Lossless_UDP_testserver.c | ||
63 | |||
64 | Lossless_UDP_testserver_CFLAGS = \ | ||
65 | $(LIBSODIUM_CFLAGS) \ | ||
66 | $(NACL_CFLAGS) | ||
67 | |||
68 | Lossless_UDP_testserver_LDADD = \ | ||
69 | $(LIBSODIUM_LDFLAGS) \ | ||
70 | $(NACL_LDFLAGS) \ | ||
71 | libtoxcore.la \ | ||
72 | $(LIBSODIUM_LIBS) \ | ||
73 | $(NACL_OBJECTS) \ | ||
74 | $(NACL_LIBS) \ | ||
75 | $(WINSOCK2_LIBS) | ||
76 | |||
77 | |||
78 | Messenger_test_SOURCES = \ | 42 | Messenger_test_SOURCES = \ |
79 | ../testing/Messenger_test.c | 43 | ../testing/Messenger_test.c |
80 | 44 | ||
diff --git a/testing/crypto_speed_test.c b/testing/crypto_speed_test.c index 60ff1937..3e81a46b 100644 --- a/testing/crypto_speed_test.c +++ b/testing/crypto_speed_test.c | |||
@@ -97,8 +97,8 @@ int main(int argc, char *argv[]) | |||
97 | starttime = get_time(); | 97 | starttime = get_time(); |
98 | 98 | ||
99 | for (trialno = 0; trialno < numtrials; trialno++) { | 99 | for (trialno = 0; trialno < numtrials; trialno++) { |
100 | encrypt_data_fast(k1, n, m, sizeof(m), c); | 100 | encrypt_data_symmetric(k1, n, m, sizeof(m), c); |
101 | decrypt_data_fast(k2, n, c, sizeof(c), m); | 101 | decrypt_data_symmetric(k2, n, c, sizeof(c), m); |
102 | } | 102 | } |
103 | 103 | ||
104 | endtime = get_time(); | 104 | endtime = get_time(); |
diff --git a/toxav/Makefile.inc b/toxav/Makefile.inc index 060a760c..2d48d210 100644 --- a/toxav/Makefile.inc +++ b/toxav/Makefile.inc | |||
@@ -18,15 +18,18 @@ libtoxav_la_SOURCES = ../toxav/event.h \ | |||
18 | 18 | ||
19 | libtoxav_la_CFLAGS = -I../toxcore \ | 19 | libtoxav_la_CFLAGS = -I../toxcore \ |
20 | -I../toxav \ | 20 | -I../toxav \ |
21 | $(LIBSODIUM_CFLAGS) \ | ||
21 | $(NACL_CFLAGS) \ | 22 | $(NACL_CFLAGS) \ |
22 | $(AV_CFLAGS) \ | 23 | $(AV_CFLAGS) \ |
23 | $(PTHREAD_CFLAGS) | 24 | $(PTHREAD_CFLAGS) |
24 | 25 | ||
25 | libtoxav_la_LDFLAGS = $(TOXAV_LT_LDFLAGS) \ | 26 | libtoxav_la_LDFLAGS = $(TOXAV_LT_LDFLAGS) \ |
27 | $(LIBSODIUM_LDFLAGS) \ | ||
26 | $(NACL_LDFLAGS) \ | 28 | $(NACL_LDFLAGS) \ |
27 | $(EXTRA_LT_LDFLAGS) | 29 | $(EXTRA_LT_LDFLAGS) |
28 | 30 | ||
29 | libtoxav_la_LIBADD = libtoxcore.la \ | 31 | libtoxav_la_LIBADD = libtoxcore.la \ |
32 | $(LIBSODIUM_LIBS) \ | ||
30 | $(NACL_LIBS) \ | 33 | $(NACL_LIBS) \ |
31 | $(PTHREAD_LIBS) \ | 34 | $(PTHREAD_LIBS) \ |
32 | $(AV_LIBS) | 35 | $(AV_LIBS) |
diff --git a/toxav/event.c b/toxav/event.c index ffda35ec..35af98bb 100644 --- a/toxav/event.c +++ b/toxav/event.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #endif /* HAVE_CONFIG_H */ | 27 | #endif /* HAVE_CONFIG_H */ |
28 | 28 | ||
29 | #include <stdlib.h> | 29 | #include <stdlib.h> |
30 | #include "../toxcore/network.h" /* current_time_monotonic() */ | ||
30 | #include "event.h" | 31 | #include "event.h" |
31 | 32 | ||
32 | #define _GNU_SOURCE | 33 | #define _GNU_SOURCE |
@@ -199,7 +200,7 @@ void *event_poll( void *arg ) | |||
199 | 200 | ||
200 | if ( _event_handler->timed_events ) { | 201 | if ( _event_handler->timed_events ) { |
201 | 202 | ||
202 | uint32_t _time = ((uint32_t)(current_time() / 1000)); | 203 | uint32_t _time = ((uint32_t)current_time_monotonic()); |
203 | 204 | ||
204 | if ( _event_handler->timed_events[0].timeout < _time ) { | 205 | if ( _event_handler->timed_events[0].timeout < _time ) { |
205 | 206 | ||
@@ -249,7 +250,7 @@ int throw_timer_event ( void * (func)(void *), void *arg, unsigned timeout) | |||
249 | 250 | ||
250 | size_t _counter = event_handler.timed_events_count; | 251 | size_t _counter = event_handler.timed_events_count; |
251 | 252 | ||
252 | event_handler.timed_events[_counter - 1].timeout = timeout + ((uint32_t)(current_time() / 1000)); | 253 | event_handler.timed_events[_counter - 1].timeout = timeout + ((uint32_t)current_time_monotonic()); |
253 | event_handler.timed_events[_counter - 1].id = _unique_id; | 254 | event_handler.timed_events[_counter - 1].id = _unique_id; |
254 | ++_unique_id; | 255 | ++_unique_id; |
255 | 256 | ||
@@ -330,7 +331,7 @@ int reset_timer_event ( int id, uint32_t timeout ) | |||
330 | /* Find it and change */ | 331 | /* Find it and change */ |
331 | for ( ; _i; _i-- ) { | 332 | for ( ; _i; _i-- ) { |
332 | if ( _it->id == id ) { | 333 | if ( _it->id == id ) { |
333 | _it->timeout = timeout + ((uint32_t)(current_time() / 1000)); | 334 | _it->timeout = timeout + ((uint32_t)current_time_monotonic()); |
334 | break; | 335 | break; |
335 | } | 336 | } |
336 | 337 | ||
diff --git a/toxav/media.h b/toxav/media.h index a1193aae..8dc495ed 100644 --- a/toxav/media.h +++ b/toxav/media.h | |||
@@ -36,7 +36,7 @@ | |||
36 | #define VIDEO_CODEC_ENCODER_INTERFACE (vpx_codec_vp8_cx()) | 36 | #define VIDEO_CODEC_ENCODER_INTERFACE (vpx_codec_vp8_cx()) |
37 | 37 | ||
38 | /* Audio encoding/decoding */ | 38 | /* Audio encoding/decoding */ |
39 | #include <opus/opus.h> | 39 | #include <opus.h> |
40 | 40 | ||
41 | typedef enum _Capabilities | 41 | typedef enum _Capabilities |
42 | { | 42 | { |
diff --git a/toxav/msi.c b/toxav/msi.c index c2d50302..aab13471 100755 --- a/toxav/msi.c +++ b/toxav/msi.c | |||
@@ -28,8 +28,6 @@ | |||
28 | 28 | ||
29 | #include "../toxcore/logger.h" | 29 | #include "../toxcore/logger.h" |
30 | 30 | ||
31 | /*#define _BSD_SOURCE*/ | ||
32 | |||
33 | #include "msi.h" | 31 | #include "msi.h" |
34 | #include "event.h" | 32 | #include "event.h" |
35 | 33 | ||
@@ -219,7 +217,7 @@ static inline__ const uint8_t *stringify_response ( MSIResponse response ) | |||
219 | * @param msg Container. | 217 | * @param msg Container. |
220 | * @param data The data. | 218 | * @param data The data. |
221 | * @return int | 219 | * @return int |
222 | * @retval -1 Error occured. | 220 | * @retval -1 Error occurred. |
223 | * @retval 0 Success. | 221 | * @retval 0 Success. |
224 | */ | 222 | */ |
225 | int parse_raw_data ( MSIMessage *msg, const uint8_t *data, uint16_t length ) | 223 | int parse_raw_data ( MSIMessage *msg, const uint8_t *data, uint16_t length ) |
@@ -354,7 +352,7 @@ void free_message ( MSIMessage *msg ) | |||
354 | * @param type Request or response. | 352 | * @param type Request or response. |
355 | * @param type_id Type of request/response. | 353 | * @param type_id Type of request/response. |
356 | * @return MSIMessage* Created message. | 354 | * @return MSIMessage* Created message. |
357 | * @retval NULL Error occured. | 355 | * @retval NULL Error occurred. |
358 | */ | 356 | */ |
359 | MSIMessage *msi_new_message ( uint8_t type, const uint8_t *type_id ) | 357 | MSIMessage *msi_new_message ( uint8_t type, const uint8_t *type_id ) |
360 | { | 358 | { |
@@ -387,7 +385,7 @@ MSIMessage *msi_new_message ( uint8_t type, const uint8_t *type_id ) | |||
387 | * | 385 | * |
388 | * @param data The data. | 386 | * @param data The data. |
389 | * @return MSIMessage* Parsed message. | 387 | * @return MSIMessage* Parsed message. |
390 | * @retval NULL Error occured. | 388 | * @retval NULL Error occurred. |
391 | */ | 389 | */ |
392 | MSIMessage *parse_message ( const uint8_t *data, uint16_t length ) | 390 | MSIMessage *parse_message ( const uint8_t *data, uint16_t length ) |
393 | { | 391 | { |
@@ -495,7 +493,7 @@ uint8_t *append_header_to_string ( | |||
495 | 493 | ||
496 | *dest = field_byte; /* Set the first byte */ | 494 | *dest = field_byte; /* Set the first byte */ |
497 | 495 | ||
498 | uint8_t *_getback_byte = dest + 1; /* remeber the byte we were on */ | 496 | uint8_t *_getback_byte = dest + 1; /* remember the byte we were on */ |
499 | dest += 3; /* swith to 4th byte where field value starts */ | 497 | dest += 3; /* swith to 4th byte where field value starts */ |
500 | 498 | ||
501 | /* Now set the field value and calculate it's length */ | 499 | /* Now set the field value and calculate it's length */ |
@@ -685,7 +683,7 @@ static inline__ const uint8_t *stringify_error_code ( MSICallError error_code ) | |||
685 | * @param msg The message. | 683 | * @param msg The message. |
686 | * @param to Where to. | 684 | * @param to Where to. |
687 | * @return int | 685 | * @return int |
688 | * @retval -1 Error occured. | 686 | * @retval -1 Error occurred. |
689 | * @retval 0 Success. | 687 | * @retval 0 Success. |
690 | */ | 688 | */ |
691 | int send_message ( MSISession *session, MSICall* call, MSIMessage *msg, uint32_t to ) | 689 | int send_message ( MSISession *session, MSICall* call, MSIMessage *msg, uint32_t to ) |
@@ -838,7 +836,7 @@ int handle_error ( MSISession *session, MSICall* call, MSICallError errid, uint3 | |||
838 | * @param msg The message. | 836 | * @param msg The message. |
839 | * @return int | 837 | * @return int |
840 | * @retval -1 No error. | 838 | * @retval -1 No error. |
841 | * @retval 0 Error occured and response sent. | 839 | * @retval 0 Error occurred and response sent. |
842 | */ | 840 | */ |
843 | int has_call_error ( MSISession *session, MSICall* call, MSIMessage *msg ) | 841 | int has_call_error ( MSISession *session, MSICall* call, MSIMessage *msg ) |
844 | { | 842 | { |
@@ -951,7 +949,7 @@ MSICall *init_call ( MSISession *session, int peers, int ringing_timeout ) | |||
951 | * | 949 | * |
952 | * @param session Control session. | 950 | * @param session Control session. |
953 | * @return int | 951 | * @return int |
954 | * @retval -1 Error occured. | 952 | * @retval -1 Error occurred. |
955 | * @retval 0 Success. | 953 | * @retval 0 Success. |
956 | */ | 954 | */ |
957 | int terminate_call ( MSISession *session, MSICall *call ) | 955 | int terminate_call ( MSISession *session, MSICall *call ) |
@@ -1031,7 +1029,7 @@ int handle_recv_invite ( MSISession *session, MSICall* call, MSIMessage *msg ) | |||
1031 | * B calls A. Who has advantage is set bey calculating | 1029 | * B calls A. Who has advantage is set bey calculating |
1032 | * 'bigger' Call id and then that call id is being used in | 1030 | * 'bigger' Call id and then that call id is being used in |
1033 | * future. User with 'bigger' Call id has the advantage | 1031 | * future. User with 'bigger' Call id has the advantage |
1034 | * as in he will wait the reponse from the other. | 1032 | * as in he will wait the response from the other. |
1035 | */ | 1033 | */ |
1036 | 1034 | ||
1037 | if ( call_id_bigger (call->id, msg->callid.header_value) == 1 ) { /* Peer has advantage */ | 1035 | if ( call_id_bigger (call->id, msg->callid.header_value) == 1 ) { /* Peer has advantage */ |
@@ -1408,7 +1406,7 @@ void msi_register_callback ( MSICallback callback, MSICallbackID id, void* userd | |||
1408 | * @param messenger Tox* object. | 1406 | * @param messenger Tox* object. |
1409 | * @param max_calls Amount of calls possible | 1407 | * @param max_calls Amount of calls possible |
1410 | * @return MSISession* The created session. | 1408 | * @return MSISession* The created session. |
1411 | * @retval NULL Error occured. | 1409 | * @retval NULL Error occurred. |
1412 | */ | 1410 | */ |
1413 | MSISession *msi_init_session ( Messenger* messenger, int32_t max_calls ) | 1411 | MSISession *msi_init_session ( Messenger* messenger, int32_t max_calls ) |
1414 | { | 1412 | { |
@@ -1530,7 +1528,7 @@ int msi_invite ( MSISession* session, int32_t* call_index, MSICallType call_type | |||
1530 | * @param session Control session. | 1528 | * @param session Control session. |
1531 | * @param call_id To which call is this action handled. | 1529 | * @param call_id To which call is this action handled. |
1532 | * @return int | 1530 | * @return int |
1533 | * @retval -1 Error occured. | 1531 | * @retval -1 Error occurred. |
1534 | * @retval 0 Success. | 1532 | * @retval 0 Success. |
1535 | */ | 1533 | */ |
1536 | int msi_hangup ( MSISession* session, int32_t call_index ) | 1534 | int msi_hangup ( MSISession* session, int32_t call_index ) |
diff --git a/toxav/msi.h b/toxav/msi.h index 2a7c5ba8..e9e1b4d7 100755 --- a/toxav/msi.h +++ b/toxav/msi.h | |||
@@ -84,7 +84,7 @@ typedef struct _MSICall { /* Call info structure */ | |||
84 | int ringing_timer_id; /* Timer id for ringing timeout */ | 84 | int ringing_timer_id; /* Timer id for ringing timeout */ |
85 | 85 | ||
86 | pthread_mutex_t mutex; /* It's to be assumed that call will have | 86 | pthread_mutex_t mutex; /* It's to be assumed that call will have |
87 | * seperate thread so add mutex | 87 | * separate thread so add mutex |
88 | */ | 88 | */ |
89 | uint32_t *peers; | 89 | uint32_t *peers; |
90 | uint16_t peer_count; | 90 | uint16_t peer_count; |
@@ -156,7 +156,7 @@ void msi_register_callback(MSICallback callback, MSICallbackID id, void* userdat | |||
156 | * @param messenger Tox* object. | 156 | * @param messenger Tox* object. |
157 | * @param max_calls Amount of calls possible | 157 | * @param max_calls Amount of calls possible |
158 | * @return MSISession* The created session. | 158 | * @return MSISession* The created session. |
159 | * @retval NULL Error occured. | 159 | * @retval NULL Error occurred. |
160 | */ | 160 | */ |
161 | MSISession *msi_init_session ( Messenger *messenger, int32_t max_calls ); | 161 | MSISession *msi_init_session ( Messenger *messenger, int32_t max_calls ); |
162 | 162 | ||
@@ -189,7 +189,7 @@ int msi_invite ( MSISession *session, int32_t* call_index, MSICallType call_type | |||
189 | * @param session Control session. | 189 | * @param session Control session. |
190 | * @param call_index To which call is this action handled. | 190 | * @param call_index To which call is this action handled. |
191 | * @return int | 191 | * @return int |
192 | * @retval -1 Error occured. | 192 | * @retval -1 Error occurred. |
193 | * @retval 0 Success. | 193 | * @retval 0 Success. |
194 | */ | 194 | */ |
195 | int msi_hangup ( MSISession *session, int32_t call_index ); | 195 | int msi_hangup ( MSISession *session, int32_t call_index ); |
diff --git a/toxav/rtp.c b/toxav/rtp.c index 8b2768f1..cdaabd3a 100755 --- a/toxav/rtp.c +++ b/toxav/rtp.c | |||
@@ -170,8 +170,8 @@ inline__ void increase_nonce(uint8_t *nonce, uint16_t target) | |||
170 | uint16_t _nonce_counter; | 170 | uint16_t _nonce_counter; |
171 | 171 | ||
172 | uint8_t _reverse_bytes[2]; | 172 | uint8_t _reverse_bytes[2]; |
173 | _reverse_bytes[0] = nonce[crypto_secretbox_NONCEBYTES - 1]; | 173 | _reverse_bytes[0] = nonce[crypto_box_NONCEBYTES - 1]; |
174 | _reverse_bytes[1] = nonce[crypto_secretbox_NONCEBYTES - 2]; | 174 | _reverse_bytes[1] = nonce[crypto_box_NONCEBYTES - 2]; |
175 | 175 | ||
176 | bytes_to_U16(&_nonce_counter, _reverse_bytes ); | 176 | bytes_to_U16(&_nonce_counter, _reverse_bytes ); |
177 | 177 | ||
@@ -179,8 +179,8 @@ inline__ void increase_nonce(uint8_t *nonce, uint16_t target) | |||
179 | if (_nonce_counter > UINT16_MAX - target ) { /* 2 bytes are not long enough */ | 179 | if (_nonce_counter > UINT16_MAX - target ) { /* 2 bytes are not long enough */ |
180 | uint8_t _it = 3; | 180 | uint8_t _it = 3; |
181 | 181 | ||
182 | while ( _it <= crypto_secretbox_NONCEBYTES ) _it += ++nonce[crypto_secretbox_NONCEBYTES - _it] ? | 182 | while ( _it <= crypto_box_NONCEBYTES ) _it += ++nonce[crypto_box_NONCEBYTES - _it] ? |
183 | crypto_secretbox_NONCEBYTES : 1; | 183 | crypto_box_NONCEBYTES : 1; |
184 | 184 | ||
185 | _nonce_counter = _nonce_counter - (UINT16_MAX - target ); /* Assign the rest of it */ | 185 | _nonce_counter = _nonce_counter - (UINT16_MAX - target ); /* Assign the rest of it */ |
186 | } else { /* Increase nonce */ | 186 | } else { /* Increase nonce */ |
@@ -191,8 +191,8 @@ inline__ void increase_nonce(uint8_t *nonce, uint16_t target) | |||
191 | /* Assign the last bytes */ | 191 | /* Assign the last bytes */ |
192 | 192 | ||
193 | U16_to_bytes( _reverse_bytes, _nonce_counter); | 193 | U16_to_bytes( _reverse_bytes, _nonce_counter); |
194 | nonce [crypto_secretbox_NONCEBYTES - 1] = _reverse_bytes[0]; | 194 | nonce [crypto_box_NONCEBYTES - 1] = _reverse_bytes[0]; |
195 | nonce [crypto_secretbox_NONCEBYTES - 2] = _reverse_bytes[1]; | 195 | nonce [crypto_box_NONCEBYTES - 2] = _reverse_bytes[1]; |
196 | 196 | ||
197 | } | 197 | } |
198 | 198 | ||
@@ -416,7 +416,7 @@ RTPHeader *build_header ( RTPSession *session ) | |||
416 | ADD_SETTING_PAYLOAD ( _retu, session->payload_type ); | 416 | ADD_SETTING_PAYLOAD ( _retu, session->payload_type ); |
417 | 417 | ||
418 | _retu->sequnum = session->sequnum; | 418 | _retu->sequnum = session->sequnum; |
419 | _retu->timestamp = ((uint32_t)(current_time() / 1000)); /* micro to milli */ | 419 | _retu->timestamp = current_time_monotonic(); /* milliseconds */ |
420 | _retu->ssrc = session->ssrc; | 420 | _retu->ssrc = session->ssrc; |
421 | 421 | ||
422 | int i; | 422 | int i; |
@@ -505,7 +505,7 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l | |||
505 | RTPSession *_session = object; | 505 | RTPSession *_session = object; |
506 | RTPMessage *_msg; | 506 | RTPMessage *_msg; |
507 | 507 | ||
508 | if ( !_session || length < 13 + crypto_secretbox_MACBYTES) { /* 12 is the minimum length for rtp + desc. byte */ | 508 | if ( !_session || length < 13 + crypto_box_MACBYTES) { /* 12 is the minimum length for rtp + desc. byte */ |
509 | LOGGER_WARNING("No session or invalid length of received buffer!"); | 509 | LOGGER_WARNING("No session or invalid length of received buffer!"); |
510 | return -1; | 510 | return -1; |
511 | } | 511 | } |
@@ -521,12 +521,13 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l | |||
521 | bytes_to_U16(&_sequnum, data + 1); | 521 | bytes_to_U16(&_sequnum, data + 1); |
522 | 522 | ||
523 | /* Clculate the right nonce */ | 523 | /* Clculate the right nonce */ |
524 | uint8_t _calculated[crypto_secretbox_NONCEBYTES]; | 524 | uint8_t _calculated[crypto_box_NONCEBYTES]; |
525 | memcpy(_calculated, _session->decrypt_nonce, crypto_secretbox_NONCEBYTES); | 525 | memcpy(_calculated, _session->decrypt_nonce, crypto_box_NONCEBYTES); |
526 | increase_nonce ( _calculated, _sequnum ); | 526 | increase_nonce ( _calculated, _sequnum ); |
527 | 527 | ||
528 | /* Decrypt message */ | 528 | /* Decrypt message */ |
529 | int _decrypted_length = decrypt_data_symmetric((uint8_t *)_session->decrypt_key, _calculated, data + 3, length - 3, _plain ); | 529 | int _decrypted_length = decrypt_data_symmetric( |
530 | (uint8_t *)_session->decrypt_key, _calculated, data + 3, length - 3, _plain ); | ||
530 | 531 | ||
531 | /* This packet is either not encrypted properly or late | 532 | /* This packet is either not encrypted properly or late |
532 | */ | 533 | */ |
@@ -557,8 +558,8 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l | |||
557 | } | 558 | } |
558 | 559 | ||
559 | /* A new cycle setting. */ | 560 | /* A new cycle setting. */ |
560 | memcpy(_session->nonce_cycle, _session->decrypt_nonce, crypto_secretbox_NONCEBYTES); | 561 | memcpy(_session->nonce_cycle, _session->decrypt_nonce, crypto_box_NONCEBYTES); |
561 | memcpy(_session->decrypt_nonce, _calculated, crypto_secretbox_NONCEBYTES); | 562 | memcpy(_session->decrypt_nonce, _calculated, crypto_box_NONCEBYTES); |
562 | } | 563 | } |
563 | } | 564 | } |
564 | 565 | ||
@@ -774,8 +775,8 @@ int rtp_send_msg ( RTPSession *session, Messenger *messenger, const uint8_t *dat | |||
774 | _send_data[0] = session->prefix; | 775 | _send_data[0] = session->prefix; |
775 | 776 | ||
776 | /* Generate the right nonce */ | 777 | /* Generate the right nonce */ |
777 | uint8_t _calculated[crypto_secretbox_NONCEBYTES]; | 778 | uint8_t _calculated[crypto_box_NONCEBYTES]; |
778 | memcpy(_calculated, session->encrypt_nonce, crypto_secretbox_NONCEBYTES); | 779 | memcpy(_calculated, session->encrypt_nonce, crypto_box_NONCEBYTES); |
779 | increase_nonce ( _calculated, msg->header->sequnum ); | 780 | increase_nonce ( _calculated, msg->header->sequnum ); |
780 | 781 | ||
781 | /* Need to skip 2 bytes that are for sequnum */ | 782 | /* Need to skip 2 bytes that are for sequnum */ |
@@ -798,7 +799,7 @@ int rtp_send_msg ( RTPSession *session, Messenger *messenger, const uint8_t *dat | |||
798 | /* Set sequ number */ | 799 | /* Set sequ number */ |
799 | if ( session->sequnum >= MAX_SEQU_NUM ) { | 800 | if ( session->sequnum >= MAX_SEQU_NUM ) { |
800 | session->sequnum = 0; | 801 | session->sequnum = 0; |
801 | memcpy(session->encrypt_nonce, _calculated, crypto_secretbox_NONCEBYTES); | 802 | memcpy(session->encrypt_nonce, _calculated, crypto_box_NONCEBYTES); |
802 | } else { | 803 | } else { |
803 | session->sequnum++; | 804 | session->sequnum++; |
804 | } | 805 | } |
@@ -888,16 +889,16 @@ RTPSession *rtp_init_session ( int payload_type, | |||
888 | _retu->decrypt_key = decrypt_key; | 889 | _retu->decrypt_key = decrypt_key; |
889 | 890 | ||
890 | /* Need to allocate new memory */ | 891 | /* Need to allocate new memory */ |
891 | _retu->encrypt_nonce = calloc ( crypto_secretbox_NONCEBYTES, sizeof (uint8_t) ); | 892 | _retu->encrypt_nonce = calloc ( crypto_box_NONCEBYTES, sizeof (uint8_t) ); |
892 | assert(_retu->encrypt_nonce); | 893 | assert(_retu->encrypt_nonce); |
893 | _retu->decrypt_nonce = calloc ( crypto_secretbox_NONCEBYTES, sizeof (uint8_t) ); | 894 | _retu->decrypt_nonce = calloc ( crypto_box_NONCEBYTES, sizeof (uint8_t) ); |
894 | assert(_retu->decrypt_nonce); | 895 | assert(_retu->decrypt_nonce); |
895 | _retu->nonce_cycle = calloc ( crypto_secretbox_NONCEBYTES, sizeof (uint8_t) ); | 896 | _retu->nonce_cycle = calloc ( crypto_box_NONCEBYTES, sizeof (uint8_t) ); |
896 | assert(_retu->nonce_cycle); | 897 | assert(_retu->nonce_cycle); |
897 | 898 | ||
898 | memcpy(_retu->encrypt_nonce, encrypt_nonce, crypto_secretbox_NONCEBYTES); | 899 | memcpy(_retu->encrypt_nonce, encrypt_nonce, crypto_box_NONCEBYTES); |
899 | memcpy(_retu->decrypt_nonce, decrypt_nonce, crypto_secretbox_NONCEBYTES); | 900 | memcpy(_retu->decrypt_nonce, decrypt_nonce, crypto_box_NONCEBYTES); |
900 | memcpy(_retu->nonce_cycle , decrypt_nonce, crypto_secretbox_NONCEBYTES); | 901 | memcpy(_retu->nonce_cycle , decrypt_nonce, crypto_box_NONCEBYTES); |
901 | 902 | ||
902 | _retu->csrc = calloc(1, sizeof (uint32_t)); | 903 | _retu->csrc = calloc(1, sizeof (uint32_t)); |
903 | assert(_retu->csrc); | 904 | assert(_retu->csrc); |
diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 870e6ca2..7534387a 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c | |||
@@ -165,15 +165,15 @@ void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, uint8_t *secr | |||
165 | } | 165 | } |
166 | } | 166 | } |
167 | 167 | ||
168 | /* Copy shared_key to decrypt DHT packet from client_id into shared_key | 168 | /* Copy shared_key to encrypt/decrypt DHT packet from client_id into shared_key |
169 | * for packets that we recieve. | 169 | * for packets that we receive. |
170 | */ | 170 | */ |
171 | void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, uint8_t *client_id) | 171 | void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, uint8_t *client_id) |
172 | { | 172 | { |
173 | return get_shared_key(&dht->shared_keys_recv, shared_key, dht->self_secret_key, client_id); | 173 | return get_shared_key(&dht->shared_keys_recv, shared_key, dht->self_secret_key, client_id); |
174 | } | 174 | } |
175 | 175 | ||
176 | /* Copy shared_key to decrypt DHT packet from client_id into shared_key | 176 | /* Copy shared_key to encrypt/decrypt DHT packet from client_id into shared_key |
177 | * for packets that we send. | 177 | * for packets that we send. |
178 | */ | 178 | */ |
179 | void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, uint8_t *client_id) | 179 | void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, uint8_t *client_id) |
@@ -181,6 +181,155 @@ void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, uint8_t *client_id) | |||
181 | return get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, client_id); | 181 | return get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, client_id); |
182 | } | 182 | } |
183 | 183 | ||
184 | void to_net_family(IP *ip) | ||
185 | { | ||
186 | if (ip->family == AF_INET) | ||
187 | ip->family = TOX_AF_INET; | ||
188 | else if (ip->family == AF_INET6) | ||
189 | ip->family = TOX_AF_INET6; | ||
190 | } | ||
191 | |||
192 | void to_host_family(IP *ip) | ||
193 | { | ||
194 | if (ip->family == TOX_AF_INET) | ||
195 | ip->family = AF_INET; | ||
196 | else if (ip->family == TOX_AF_INET6) | ||
197 | ip->family = AF_INET6; | ||
198 | } | ||
199 | |||
200 | /* Pack number of nodes into data of maxlength length. | ||
201 | * | ||
202 | * return length of packed nodes on success. | ||
203 | * return -1 on failure. | ||
204 | */ | ||
205 | int pack_nodes(uint8_t *data, uint16_t length, Node_format *nodes, uint16_t number) | ||
206 | { | ||
207 | uint32_t i, packed_length = 0; | ||
208 | |||
209 | for (i = 0; i < number; ++i) { | ||
210 | int ipv6 = -1; | ||
211 | uint8_t net_family; | ||
212 | |||
213 | if (nodes[i].ip_port.ip.family == AF_INET) { | ||
214 | ipv6 = 0; | ||
215 | net_family = TOX_AF_INET; | ||
216 | } else if (nodes[i].ip_port.ip.family == TCP_INET) { | ||
217 | ipv6 = 0; | ||
218 | net_family = TOX_TCP_INET; | ||
219 | } else if (nodes[i].ip_port.ip.family == AF_INET6) { | ||
220 | ipv6 = 1; | ||
221 | net_family = TOX_AF_INET6; | ||
222 | } else if (nodes[i].ip_port.ip.family == TCP_INET6) { | ||
223 | ipv6 = 1; | ||
224 | net_family = TOX_TCP_INET6; | ||
225 | } else { | ||
226 | return -1; | ||
227 | } | ||
228 | |||
229 | if (ipv6 == 0) { | ||
230 | uint32_t size = 1 + sizeof(IP4) + sizeof(uint16_t) + CLIENT_ID_SIZE; | ||
231 | |||
232 | if (packed_length + size > length) | ||
233 | return -1; | ||
234 | |||
235 | data[packed_length] = net_family; | ||
236 | memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip4, sizeof(IP4)); | ||
237 | memcpy(data + packed_length + 1 + sizeof(IP4), &nodes[i].ip_port.port, sizeof(uint16_t)); | ||
238 | memcpy(data + packed_length + 1 + sizeof(IP4) + sizeof(uint16_t), nodes[i].client_id, CLIENT_ID_SIZE); | ||
239 | packed_length += size; | ||
240 | } else if (ipv6 == 1) { | ||
241 | uint32_t size = 1 + sizeof(IP6) + sizeof(uint16_t) + CLIENT_ID_SIZE; | ||
242 | |||
243 | if (packed_length + size > length) | ||
244 | return -1; | ||
245 | |||
246 | data[packed_length] = net_family; | ||
247 | memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip6, sizeof(IP6)); | ||
248 | memcpy(data + packed_length + 1 + sizeof(IP6), &nodes[i].ip_port.port, sizeof(uint16_t)); | ||
249 | memcpy(data + packed_length + 1 + sizeof(IP6) + sizeof(uint16_t), nodes[i].client_id, CLIENT_ID_SIZE); | ||
250 | packed_length += size; | ||
251 | } else { | ||
252 | return -1; | ||
253 | } | ||
254 | } | ||
255 | |||
256 | return packed_length; | ||
257 | } | ||
258 | |||
259 | /* Unpack data of length into nodes of size max_num_nodes. | ||
260 | * Put the length of the data processed in processed_data_len. | ||
261 | * tcp_enabled sets if TCP nodes are expected (true) or not (false). | ||
262 | * | ||
263 | * return number of unpacked nodes on success. | ||
264 | * return -1 on failure. | ||
265 | */ | ||
266 | int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, uint8_t *data, | ||
267 | uint16_t length, uint8_t tcp_enabled) | ||
268 | { | ||
269 | uint32_t num = 0, len_processed = 0; | ||
270 | |||
271 | while (num < max_num_nodes && len_processed < length) { | ||
272 | int ipv6 = -1; | ||
273 | uint8_t host_family; | ||
274 | |||
275 | if (data[len_processed] == TOX_AF_INET) { | ||
276 | ipv6 = 0; | ||
277 | host_family = AF_INET; | ||
278 | } else if (data[len_processed] == TOX_TCP_INET) { | ||
279 | if (!tcp_enabled) | ||
280 | return -1; | ||
281 | |||
282 | ipv6 = 0; | ||
283 | host_family = TCP_INET; | ||
284 | } else if (data[len_processed] == TOX_AF_INET6) { | ||
285 | ipv6 = 1; | ||
286 | host_family = AF_INET6; | ||
287 | } else if (data[len_processed] == TOX_TCP_INET6) { | ||
288 | if (!tcp_enabled) | ||
289 | return -1; | ||
290 | |||
291 | ipv6 = 1; | ||
292 | host_family = TCP_INET6; | ||
293 | } else { | ||
294 | return -1; | ||
295 | } | ||
296 | |||
297 | if (ipv6 == 0) { | ||
298 | uint32_t size = 1 + sizeof(IP4) + sizeof(uint16_t) + CLIENT_ID_SIZE; | ||
299 | |||
300 | if (len_processed + size > length) | ||
301 | return -1; | ||
302 | |||
303 | nodes[num].ip_port.ip.family = host_family; | ||
304 | memcpy(&nodes[num].ip_port.ip.ip4, data + len_processed + 1, sizeof(IP4)); | ||
305 | memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + sizeof(IP4), sizeof(uint16_t)); | ||
306 | memcpy(nodes[num].client_id, data + len_processed + 1 + sizeof(IP4) + sizeof(uint16_t), CLIENT_ID_SIZE); | ||
307 | len_processed += size; | ||
308 | ++num; | ||
309 | } else if (ipv6 == 1) { | ||
310 | uint32_t size = 1 + sizeof(IP6) + sizeof(uint16_t) + CLIENT_ID_SIZE; | ||
311 | |||
312 | if (len_processed + size > length) | ||
313 | return -1; | ||
314 | |||
315 | nodes[num].ip_port.ip.family = host_family; | ||
316 | memcpy(&nodes[num].ip_port.ip.ip6, data + len_processed + 1, sizeof(IP6)); | ||
317 | memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + sizeof(IP6), sizeof(uint16_t)); | ||
318 | memcpy(nodes[num].client_id, data + len_processed + 1 + sizeof(IP6) + sizeof(uint16_t), CLIENT_ID_SIZE); | ||
319 | len_processed += size; | ||
320 | ++num; | ||
321 | } else { | ||
322 | return -1; | ||
323 | } | ||
324 | } | ||
325 | |||
326 | if (processed_data_len) | ||
327 | *processed_data_len = len_processed; | ||
328 | |||
329 | return num; | ||
330 | } | ||
331 | |||
332 | |||
184 | 333 | ||
185 | /* Check if client with client_id is already in list of length length. | 334 | /* Check if client with client_id is already in list of length length. |
186 | * If it is then set its corresponding timestamp to current time. | 335 | * If it is then set its corresponding timestamp to current time. |
@@ -266,7 +415,7 @@ static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t | |||
266 | /* Check if client with client_id is already in node format list of length length. | 415 | /* Check if client with client_id is already in node format list of length length. |
267 | * | 416 | * |
268 | * return 1 if true. | 417 | * return 1 if true. |
269 | * return 2 if false. | 418 | * return 0 if false. |
270 | */ | 419 | */ |
271 | static int client_in_nodelist(Node_format *list, uint32_t length, uint8_t *client_id) | 420 | static int client_in_nodelist(Node_format *list, uint32_t length, uint8_t *client_id) |
272 | { | 421 | { |
@@ -310,15 +459,15 @@ static uint8_t hardening_correct(Hardening *h) | |||
310 | /* | 459 | /* |
311 | * helper for get_close_nodes(). argument list is a monster :D | 460 | * helper for get_close_nodes(). argument list is a monster :D |
312 | */ | 461 | */ |
313 | static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nodes_list, | 462 | static void get_close_nodes_inner(uint8_t *client_id, Node_format *nodes_list, |
314 | sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length, | 463 | sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length, |
315 | uint32_t *num_nodes_ptr, uint8_t is_LAN, uint8_t want_good) | 464 | uint32_t *num_nodes_ptr, uint8_t is_LAN, uint8_t want_good) |
316 | { | 465 | { |
317 | if ((sa_family != AF_INET) && (sa_family != AF_INET6)) | 466 | if ((sa_family != AF_INET) && (sa_family != AF_INET6) && (sa_family != 0)) |
318 | return; | 467 | return; |
319 | 468 | ||
320 | uint32_t num_nodes = *num_nodes_ptr; | 469 | uint32_t num_nodes = *num_nodes_ptr; |
321 | int ipv46x, j, closest; | 470 | int j, closest; |
322 | uint32_t i; | 471 | uint32_t i; |
323 | 472 | ||
324 | for (i = 0; i < client_list_length; i++) { | 473 | for (i = 0; i < client_list_length; i++) { |
@@ -330,39 +479,22 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod | |||
330 | 479 | ||
331 | IPPTsPng *ipptp = NULL; | 480 | IPPTsPng *ipptp = NULL; |
332 | 481 | ||
333 | if (sa_family == AF_INET) | 482 | if (sa_family == AF_INET) { |
334 | ipptp = &client->assoc4; | 483 | ipptp = &client->assoc4; |
335 | else | 484 | } else if (sa_family == AF_INET6) { |
336 | ipptp = &client->assoc6; | 485 | ipptp = &client->assoc6; |
486 | } else { | ||
487 | if (client->assoc4.timestamp >= client->assoc6.timestamp) { | ||
488 | ipptp = &client->assoc4; | ||
489 | } else { | ||
490 | ipptp = &client->assoc6; | ||
491 | } | ||
492 | } | ||
337 | 493 | ||
338 | /* node not in a good condition? */ | 494 | /* node not in a good condition? */ |
339 | if (is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT)) | 495 | if (is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT)) |
340 | continue; | 496 | continue; |
341 | 497 | ||
342 | IP *client_ip = &ipptp->ip_port.ip; | ||
343 | |||
344 | /* | ||
345 | * Careful: AF_INET isn't seen as AF_INET on dual-stack sockets for | ||
346 | * our connections, instead we have to look if it is an embedded | ||
347 | * IPv4-in-IPv6 here and convert it down in sendnodes(). | ||
348 | */ | ||
349 | sa_family_t ip_treat_as_family = client_ip->family; | ||
350 | |||
351 | if ((dht->net->family == AF_INET6) && | ||
352 | (client_ip->family == AF_INET6)) { | ||
353 | /* socket is AF_INET6, address claims AF_INET6: | ||
354 | * check for embedded IPv4-in-IPv6 (shouldn't happen anymore, | ||
355 | * all storing functions should already convert down to IPv4) */ | ||
356 | if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6.in6_addr)) | ||
357 | ip_treat_as_family = AF_INET; | ||
358 | } | ||
359 | |||
360 | ipv46x = !(sa_family == ip_treat_as_family); | ||
361 | |||
362 | /* node address of the wrong family? */ | ||
363 | if (ipv46x) | ||
364 | continue; | ||
365 | |||
366 | /* don't send LAN ips to non LAN peers */ | 498 | /* don't send LAN ips to non LAN peers */ |
367 | if (LAN_ip(ipptp->ip_port.ip) == 0 && !is_LAN) | 499 | if (LAN_ip(ipptp->ip_port.ip) == 0 && !is_LAN) |
368 | continue; | 500 | continue; |
@@ -416,7 +548,7 @@ static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *n | |||
416 | uint8_t is_LAN, uint8_t want_good) | 548 | uint8_t is_LAN, uint8_t want_good) |
417 | { | 549 | { |
418 | uint32_t num_nodes = 0, i; | 550 | uint32_t num_nodes = 0, i; |
419 | get_close_nodes_inner(dht, client_id, nodes_list, sa_family, | 551 | get_close_nodes_inner(client_id, nodes_list, sa_family, |
420 | dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, want_good); | 552 | dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, want_good); |
421 | 553 | ||
422 | /*TODO uncomment this when hardening is added to close friend clients | 554 | /*TODO uncomment this when hardening is added to close friend clients |
@@ -426,7 +558,7 @@ static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *n | |||
426 | &num_nodes, is_LAN, want_good); | 558 | &num_nodes, is_LAN, want_good); |
427 | */ | 559 | */ |
428 | for (i = 0; i < dht->num_friends; ++i) | 560 | for (i = 0; i < dht->num_friends; ++i) |
429 | get_close_nodes_inner(dht, client_id, nodes_list, sa_family, | 561 | get_close_nodes_inner(client_id, nodes_list, sa_family, |
430 | dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, | 562 | dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, |
431 | &num_nodes, is_LAN, 0); | 563 | &num_nodes, is_LAN, 0); |
432 | 564 | ||
@@ -444,6 +576,7 @@ int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_fa | |||
444 | return get_somewhat_close_nodes(dht, client_id, nodes_list, sa_family, is_LAN, want_good); | 576 | return get_somewhat_close_nodes(dht, client_id, nodes_list, sa_family, is_LAN, want_good); |
445 | 577 | ||
446 | #ifdef ENABLE_ASSOC_DHT | 578 | #ifdef ENABLE_ASSOC_DHT |
579 | //TODO: assoc, sa_family 0 (don't care if ipv4 or ipv6) support. | ||
447 | Client_data *result[MAX_SENT_NODES]; | 580 | Client_data *result[MAX_SENT_NODES]; |
448 | 581 | ||
449 | Assoc_close_entries request; | 582 | Assoc_close_entries request; |
@@ -581,7 +714,7 @@ static int replace_possible_bad( Client_data *list, | |||
581 | 714 | ||
582 | sort_list(list, length, comp_client_id); | 715 | sort_list(list, length, comp_client_id); |
583 | 716 | ||
584 | /* TODO: decide if the folowing lines should stay commented or not. | 717 | /* TODO: decide if the following lines should stay commented or not. |
585 | if (id_closest(comp_client_id, list[0].client_id, client_id) == 1) | 718 | if (id_closest(comp_client_id, list[0].client_id, client_id) == 1) |
586 | return 0;*/ | 719 | return 0;*/ |
587 | 720 | ||
@@ -823,7 +956,7 @@ end: | |||
823 | return 0; | 956 | return 0; |
824 | } | 957 | } |
825 | 958 | ||
826 | #define NODES_ENCRYPTED_MESSAGE_LENGTH (crypto_secretbox_NONCEBYTES + sizeof(uint64_t) + sizeof(Node_format) + sizeof(Node_format) + crypto_secretbox_MACBYTES) | 959 | #define NODES_ENCRYPTED_MESSAGE_LENGTH (crypto_box_NONCEBYTES + sizeof(uint64_t) + sizeof(Node_format) + sizeof(Node_format) + crypto_box_MACBYTES) |
827 | 960 | ||
828 | /* Send a getnodes request. | 961 | /* Send a getnodes request. |
829 | sendback_node is the node that it will send back the response to (set to NULL to disable this) */ | 962 | sendback_node is the node that it will send back the response to (set to NULL to disable this) */ |
@@ -842,23 +975,23 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli | |||
842 | 975 | ||
843 | uint64_t temp_time = unix_time(); | 976 | uint64_t temp_time = unix_time(); |
844 | memcpy(plain_message, &temp_time, sizeof(temp_time)); | 977 | memcpy(plain_message, &temp_time, sizeof(temp_time)); |
845 | Node_format reciever; | 978 | Node_format receiver; |
846 | memcpy(reciever.client_id, public_key, CLIENT_ID_SIZE); | 979 | memcpy(receiver.client_id, public_key, CLIENT_ID_SIZE); |
847 | reciever.ip_port = ip_port; | 980 | receiver.ip_port = ip_port; |
848 | memcpy(plain_message + sizeof(temp_time), &reciever, sizeof(reciever)); | 981 | memcpy(plain_message + sizeof(temp_time), &receiver, sizeof(receiver)); |
849 | 982 | ||
850 | if (sendback_node != NULL) | 983 | if (sendback_node != NULL) |
851 | memcpy(plain_message + sizeof(temp_time) + sizeof(reciever), sendback_node, sizeof(Node_format)); | 984 | memcpy(plain_message + sizeof(temp_time) + sizeof(receiver), sendback_node, sizeof(Node_format)); |
852 | else | 985 | else |
853 | memset(plain_message + sizeof(temp_time) + sizeof(reciever), 0, sizeof(Node_format)); | 986 | memset(plain_message + sizeof(temp_time) + sizeof(receiver), 0, sizeof(Node_format)); |
854 | 987 | ||
855 | int len_m = encrypt_data_symmetric(dht->secret_symmetric_key, | 988 | int len_m = encrypt_data_symmetric(dht->secret_symmetric_key, |
856 | nonce, | 989 | nonce, |
857 | plain_message, | 990 | plain_message, |
858 | sizeof(temp_time) + sizeof(reciever) + sizeof(Node_format), | 991 | sizeof(temp_time) + sizeof(receiver) + sizeof(Node_format), |
859 | encrypted_message + crypto_secretbox_NONCEBYTES); | 992 | encrypted_message + crypto_box_NONCEBYTES); |
860 | 993 | ||
861 | if (len_m != NODES_ENCRYPTED_MESSAGE_LENGTH - crypto_secretbox_NONCEBYTES) | 994 | if (len_m != NODES_ENCRYPTED_MESSAGE_LENGTH - crypto_box_NONCEBYTES) |
862 | return -1; | 995 | return -1; |
863 | 996 | ||
864 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; | 997 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; |
@@ -871,11 +1004,11 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli | |||
871 | 1004 | ||
872 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; | 1005 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; |
873 | DHT_get_shared_key_sent(dht, shared_key, public_key); | 1006 | DHT_get_shared_key_sent(dht, shared_key, public_key); |
874 | int len = encrypt_data_fast( shared_key, | 1007 | int len = encrypt_data_symmetric( shared_key, |
875 | nonce, | 1008 | nonce, |
876 | plain, | 1009 | plain, |
877 | CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH, | 1010 | CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH, |
878 | encrypt ); | 1011 | encrypt ); |
879 | 1012 | ||
880 | if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES) | 1013 | if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES) |
881 | return -1; | 1014 | return -1; |
@@ -888,132 +1021,46 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli | |||
888 | return sendpacket(dht->net, ip_port, data, sizeof(data)); | 1021 | return sendpacket(dht->net, ip_port, data, sizeof(data)); |
889 | } | 1022 | } |
890 | 1023 | ||
891 | /* Send a send nodes response. */ | 1024 | /* Send a send nodes response: message for IPv6 nodes */ |
892 | /* because of BINARY compatibility, the Node_format MUST BE Node4_format, | 1025 | static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *sendback_data, |
893 | * IPv6 nodes are sent in a different message | 1026 | uint16_t length, uint8_t *shared_encryption_key) |
894 | * encrypted_data must be of size NODES_ENCRYPTED_MESSAGE_LENGTH */ | ||
895 | static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data, | ||
896 | uint8_t *shared_encryption_key) | ||
897 | { | 1027 | { |
898 | /* Check if packet is going to be sent to ourself. */ | 1028 | /* Check if packet is going to be sent to ourself. */ |
899 | if (id_equal(public_key, dht->self_public_key)) | 1029 | if (id_equal(public_key, dht->self_public_key)) |
900 | return -1; | 1030 | return -1; |
901 | 1031 | ||
902 | size_t Node4_format_size = sizeof(Node4_format); | 1032 | if (length > NODES_ENCRYPTED_MESSAGE_LENGTH || length == 0) |
903 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES | ||
904 | + Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; | ||
905 | |||
906 | Node_format nodes_list[MAX_SENT_NODES]; | ||
907 | uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET, LAN_ip(ip_port.ip) == 0, 1); | ||
908 | |||
909 | if (num_nodes == 0) | ||
910 | return 0; | ||
911 | |||
912 | uint8_t plain[Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH]; | ||
913 | uint8_t encrypt[Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; | ||
914 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
915 | new_nonce(nonce); | ||
916 | |||
917 | Node4_format *nodes4_list = (Node4_format *)(plain); | ||
918 | uint32_t i, num_nodes_ok = 0; | ||
919 | |||
920 | for (i = 0; i < num_nodes; i++) { | ||
921 | memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE); | ||
922 | nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port; | ||
923 | |||
924 | IP *node_ip = &nodes_list[i].ip_port.ip; | ||
925 | |||
926 | if ((node_ip->family == AF_INET6) && IN6_IS_ADDR_V4MAPPED(&node_ip->ip6.in6_addr)) | ||
927 | /* embedded IPv4-in-IPv6 address: return it in regular sendnodes packet */ | ||
928 | nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip6.uint32[3]; | ||
929 | else if (node_ip->family == AF_INET) | ||
930 | nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip4.uint32; | ||
931 | else /* shouldn't happen */ | ||
932 | continue; | ||
933 | |||
934 | num_nodes_ok++; | ||
935 | } | ||
936 | |||
937 | if (num_nodes_ok < num_nodes) { | ||
938 | /* shouldn't happen */ | ||
939 | num_nodes = num_nodes_ok; | ||
940 | } | ||
941 | |||
942 | memcpy(plain + num_nodes * Node4_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH); | ||
943 | int len = encrypt_data_fast( shared_encryption_key, | ||
944 | nonce, | ||
945 | plain, | ||
946 | num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH, | ||
947 | encrypt ); | ||
948 | |||
949 | if ((unsigned int)len != num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + | ||
950 | crypto_box_MACBYTES) | ||
951 | return -1; | ||
952 | |||
953 | data[0] = NET_PACKET_SEND_NODES; | ||
954 | memcpy(data + 1, dht->self_public_key, CLIENT_ID_SIZE); | ||
955 | memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); | ||
956 | memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); | ||
957 | |||
958 | return sendpacket(dht->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); | ||
959 | } | ||
960 | |||
961 | void to_net_family(IP *ip) | ||
962 | { | ||
963 | ip->padding[0] = 0; | ||
964 | ip->padding[1] = 0; | ||
965 | ip->padding[2] = 0; | ||
966 | |||
967 | if (ip->family == AF_INET) | ||
968 | ip->family = TOX_AF_INET; | ||
969 | else if (ip->family == AF_INET6) | ||
970 | ip->family = TOX_AF_INET6; | ||
971 | } | ||
972 | |||
973 | void to_host_family(IP *ip) | ||
974 | { | ||
975 | if (ip->family == TOX_AF_INET) | ||
976 | ip->family = AF_INET; | ||
977 | else if (ip->family == TOX_AF_INET6) | ||
978 | ip->family = AF_INET6; | ||
979 | } | ||
980 | /* Send a send nodes response: message for IPv6 nodes */ | ||
981 | static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data, | ||
982 | uint8_t *shared_encryption_key) | ||
983 | { | ||
984 | /* Check if packet is going to be sent to ourself. */ | ||
985 | if (id_equal(public_key, dht->self_public_key)) | ||
986 | return -1; | 1033 | return -1; |
987 | 1034 | ||
988 | size_t Node_format_size = sizeof(Node_format); | 1035 | size_t Node_format_size = sizeof(Node_format); |
989 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES | 1036 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES |
990 | + Node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; | 1037 | + Node_format_size * MAX_SENT_NODES + length + crypto_box_MACBYTES]; |
991 | 1038 | ||
992 | Node_format nodes_list[MAX_SENT_NODES]; | 1039 | Node_format nodes_list[MAX_SENT_NODES]; |
993 | uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET6, LAN_ip(ip_port.ip) == 0, 1); | 1040 | uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, 0, LAN_ip(ip_port.ip) == 0, 1); |
994 | 1041 | ||
995 | if (num_nodes == 0) | 1042 | if (num_nodes == 0) |
996 | return 0; | 1043 | return 0; |
997 | 1044 | ||
998 | uint8_t plain[Node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH]; | 1045 | uint8_t plain[1 + Node_format_size * MAX_SENT_NODES + length]; |
999 | uint8_t encrypt[Node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; | 1046 | uint8_t encrypt[sizeof(plain) + crypto_box_MACBYTES]; |
1000 | uint8_t nonce[crypto_box_NONCEBYTES]; | 1047 | uint8_t nonce[crypto_box_NONCEBYTES]; |
1001 | new_nonce(nonce); | 1048 | new_nonce(nonce); |
1002 | 1049 | ||
1003 | uint32_t i; | 1050 | int nodes_length = pack_nodes(plain + 1, Node_format_size * MAX_SENT_NODES, nodes_list, num_nodes); |
1004 | 1051 | ||
1005 | for (i = 0; i < num_nodes; ++i) | 1052 | if (nodes_length <= 0) |
1006 | to_net_family(&nodes_list[i].ip_port.ip); | 1053 | return -1; |
1007 | 1054 | ||
1008 | memcpy(plain, nodes_list, num_nodes * Node_format_size); | 1055 | plain[0] = num_nodes; |
1009 | memcpy(plain + num_nodes * Node_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH); | 1056 | memcpy(plain + 1 + nodes_length, sendback_data, length); |
1010 | int len = encrypt_data_fast( shared_encryption_key, | 1057 | int len = encrypt_data_symmetric( shared_encryption_key, |
1011 | nonce, | 1058 | nonce, |
1012 | plain, | 1059 | plain, |
1013 | num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH, | 1060 | 1 + nodes_length + length, |
1014 | encrypt ); | 1061 | encrypt ); |
1015 | 1062 | ||
1016 | if ((unsigned int)len != num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES) | 1063 | if (len != 1 + nodes_length + length + crypto_box_MACBYTES) |
1017 | return -1; | 1064 | return -1; |
1018 | 1065 | ||
1019 | data[0] = NET_PACKET_SEND_NODES_IPV6; | 1066 | data[0] = NET_PACKET_SEND_NODES_IPV6; |
@@ -1026,35 +1073,38 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_ | |||
1026 | 1073 | ||
1027 | static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 1074 | static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) |
1028 | { | 1075 | { |
1029 | DHT *dht = object; | 1076 | uint32_t cmp_len = 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + CLIENT_ID_SIZE + crypto_box_MACBYTES; |
1077 | |||
1078 | if (length <= cmp_len) | ||
1079 | return 1; | ||
1030 | 1080 | ||
1031 | if (length != ( 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + | 1081 | if (length > cmp_len + NODES_ENCRYPTED_MESSAGE_LENGTH) |
1032 | crypto_box_MACBYTES )) | ||
1033 | return 1; | 1082 | return 1; |
1034 | 1083 | ||
1084 | uint16_t sendback_data_length = length - cmp_len; | ||
1085 | |||
1086 | DHT *dht = object; | ||
1087 | |||
1035 | /* Check if packet is from ourself. */ | 1088 | /* Check if packet is from ourself. */ |
1036 | if (id_equal(packet + 1, dht->self_public_key)) | 1089 | if (id_equal(packet + 1, dht->self_public_key)) |
1037 | return 1; | 1090 | return 1; |
1038 | 1091 | ||
1039 | uint8_t plain[CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH]; | 1092 | uint8_t plain[CLIENT_ID_SIZE + sendback_data_length]; |
1040 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; | 1093 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; |
1041 | 1094 | ||
1042 | DHT_get_shared_key_recv(dht, shared_key, packet + 1); | 1095 | DHT_get_shared_key_recv(dht, shared_key, packet + 1); |
1043 | int len = decrypt_data_fast( shared_key, | 1096 | int len = decrypt_data_symmetric( shared_key, |
1044 | packet + 1 + CLIENT_ID_SIZE, | 1097 | packet + 1 + CLIENT_ID_SIZE, |
1045 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, | 1098 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, |
1046 | CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, | 1099 | CLIENT_ID_SIZE + sendback_data_length + crypto_box_MACBYTES, |
1047 | plain ); | 1100 | plain ); |
1048 | 1101 | ||
1049 | if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH) | 1102 | if (len != CLIENT_ID_SIZE + sendback_data_length) |
1050 | return 1; | 1103 | return 1; |
1051 | 1104 | ||
1052 | sendnodes(dht, source, packet + 1, plain, plain + CLIENT_ID_SIZE, shared_key); | 1105 | sendnodes_ipv6(dht, source, packet + 1, plain, plain + CLIENT_ID_SIZE, sendback_data_length, shared_key); |
1053 | sendnodes_ipv6(dht, source, packet + 1, plain, | ||
1054 | plain + CLIENT_ID_SIZE, shared_key); /* TODO: prevent possible amplification attacks */ | ||
1055 | 1106 | ||
1056 | add_to_ping(dht->ping, packet + 1, source); | 1107 | add_to_ping(dht->ping, packet + 1, source); |
1057 | //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */ | ||
1058 | 1108 | ||
1059 | return 0; | 1109 | return 0; |
1060 | } | 1110 | } |
@@ -1066,8 +1116,8 @@ static uint8_t sent_getnode_to_node(DHT *dht, uint8_t *client_id, IP_Port node_i | |||
1066 | { | 1116 | { |
1067 | uint8_t plain_message[NODES_ENCRYPTED_MESSAGE_LENGTH]; | 1117 | uint8_t plain_message[NODES_ENCRYPTED_MESSAGE_LENGTH]; |
1068 | 1118 | ||
1069 | if (decrypt_data_symmetric(dht->secret_symmetric_key, encrypted_data, encrypted_data + crypto_secretbox_NONCEBYTES, | 1119 | if (decrypt_data_symmetric(dht->secret_symmetric_key, encrypted_data, encrypted_data + crypto_box_NONCEBYTES, |
1070 | NODES_ENCRYPTED_MESSAGE_LENGTH - crypto_secretbox_NONCEBYTES, | 1120 | NODES_ENCRYPTED_MESSAGE_LENGTH - crypto_box_NONCEBYTES, |
1071 | plain_message) != sizeof(uint64_t) + sizeof(Node_format) * 2) | 1121 | plain_message) != sizeof(uint64_t) + sizeof(Node_format) * 2) |
1072 | return 0; | 1122 | return 0; |
1073 | 1123 | ||
@@ -1089,124 +1139,87 @@ static uint8_t sent_getnode_to_node(DHT *dht, uint8_t *client_id, IP_Port node_i | |||
1089 | } | 1139 | } |
1090 | 1140 | ||
1091 | /* Function is needed in following functions. */ | 1141 | /* Function is needed in following functions. */ |
1092 | static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, Node_format *list, | 1142 | static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, uint8_t *nodes_data, |
1093 | uint16_t num_nodes); | 1143 | uint16_t nodes_data_length); |
1094 | 1144 | ||
1095 | static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, uint32_t length, | 1145 | static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, uint32_t length, |
1096 | size_t node_format_size, uint8_t *plain, uint16_t plain_length, uint32_t *num_nodes_out, Node_format *sendback_node) | 1146 | Node_format *plain_nodes, uint16_t size_plain_nodes, uint32_t *num_nodes_out) |
1097 | { | 1147 | { |
1098 | if (plain_length != MAX_SENT_NODES * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH) | ||
1099 | return 1; | ||
1100 | |||
1101 | DHT *dht = object; | 1148 | DHT *dht = object; |
1102 | uint32_t cid_size = 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES; | 1149 | uint32_t cid_size = 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + 1 + NODES_ENCRYPTED_MESSAGE_LENGTH + |
1150 | crypto_box_MACBYTES; | ||
1103 | 1151 | ||
1104 | if (length <= cid_size) /* too short */ | 1152 | if (length <= cid_size) /* too short */ |
1105 | return 1; | 1153 | return 1; |
1106 | 1154 | ||
1107 | uint32_t data_size = length - cid_size; | 1155 | uint32_t data_size = length - cid_size; |
1108 | 1156 | ||
1109 | if ((data_size % node_format_size) != 0) /* invalid length */ | 1157 | if (data_size == 0) |
1110 | return 1; | 1158 | return 1; |
1111 | 1159 | ||
1112 | uint32_t num_nodes = data_size / node_format_size; | 1160 | if (data_size > sizeof(Node_format) * MAX_SENT_NODES) /* invalid length */ |
1113 | |||
1114 | if (num_nodes > MAX_SENT_NODES) /* too long */ | ||
1115 | return 1; | 1161 | return 1; |
1116 | 1162 | ||
1163 | uint8_t plain[1 + data_size + NODES_ENCRYPTED_MESSAGE_LENGTH]; | ||
1117 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; | 1164 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; |
1118 | DHT_get_shared_key_sent(dht, shared_key, packet + 1); | 1165 | DHT_get_shared_key_sent(dht, shared_key, packet + 1); |
1119 | int len = decrypt_data_fast( | 1166 | int len = decrypt_data_symmetric( |
1120 | shared_key, | 1167 | shared_key, |
1121 | packet + 1 + CLIENT_ID_SIZE, | 1168 | packet + 1 + CLIENT_ID_SIZE, |
1122 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, | 1169 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, |
1123 | num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, | 1170 | 1 + data_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, |
1124 | plain); | 1171 | plain); |
1125 | 1172 | ||
1126 | if ((unsigned int)len != num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH) | 1173 | if ((unsigned int)len != sizeof(plain)) |
1127 | return 1; | 1174 | return 1; |
1128 | 1175 | ||
1129 | if (!sent_getnode_to_node(dht, packet + 1, source, plain + num_nodes * node_format_size, sendback_node)) | 1176 | if (plain[0] > size_plain_nodes || plain[0] == 0) |
1130 | return 1; | 1177 | return 1; |
1131 | 1178 | ||
1132 | /* store the address the *request* was sent to */ | ||
1133 | addto_lists(dht, source, packet + 1); | ||
1134 | |||
1135 | *num_nodes_out = num_nodes; | ||
1136 | |||
1137 | return 0; | ||
1138 | } | ||
1139 | |||
1140 | static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) | ||
1141 | { | ||
1142 | DHT *dht = object; | ||
1143 | size_t node4_format_size = sizeof(Node4_format); | ||
1144 | uint8_t plain[node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH]; | ||
1145 | uint32_t num_nodes; | ||
1146 | |||
1147 | Node_format sendback_node; | 1179 | Node_format sendback_node; |
1148 | 1180 | ||
1149 | if (handle_sendnodes_core(object, source, packet, length, node4_format_size, plain, sizeof(plain), &num_nodes, | 1181 | if (!sent_getnode_to_node(dht, packet + 1, source, plain + 1 + data_size, &sendback_node)) |
1150 | &sendback_node)) | ||
1151 | return 1; | 1182 | return 1; |
1152 | 1183 | ||
1153 | if (num_nodes == 0) | 1184 | uint16_t length_nodes = 0; |
1154 | return 0; | 1185 | int num_nodes = unpack_nodes(plain_nodes, plain[0], &length_nodes, plain + 1, data_size, 0); |
1155 | |||
1156 | Node4_format *nodes4_list = (Node4_format *)(plain); | ||
1157 | |||
1158 | uint64_t time_now = unix_time(); | ||
1159 | IPPTs ippts; | ||
1160 | ippts.ip_port.ip.family = AF_INET; | ||
1161 | ippts.timestamp = time_now; | ||
1162 | |||
1163 | uint32_t i; | ||
1164 | 1186 | ||
1165 | Node_format nodes_list[MAX_SENT_NODES]; | 1187 | if (length_nodes != data_size) |
1188 | return 1; | ||
1166 | 1189 | ||
1167 | for (i = 0; i < num_nodes; i++) | 1190 | if (num_nodes != plain[0]) |
1168 | if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != (uint32_t)~0)) { | 1191 | return 1; |
1169 | ippts.ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32; | ||
1170 | ippts.ip_port.port = nodes4_list[i].ip_port.port; | ||
1171 | 1192 | ||
1172 | send_ping_request(dht->ping, ippts.ip_port, nodes4_list[i].client_id); | 1193 | if (num_nodes <= 0) |
1173 | returnedip_ports(dht, ippts.ip_port, nodes4_list[i].client_id, packet + 1); | 1194 | return 1; |
1174 | 1195 | ||
1175 | memcpy(nodes_list[i].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE); | 1196 | /* store the address the *request* was sent to */ |
1176 | ipport_copy(&nodes_list[i].ip_port, &ippts.ip_port); | 1197 | addto_lists(dht, source, packet + 1); |
1177 | 1198 | ||
1178 | } | 1199 | *num_nodes_out = num_nodes; |
1179 | 1200 | ||
1180 | send_hardening_getnode_res(dht, &sendback_node, packet + 1, nodes_list, num_nodes); | 1201 | send_hardening_getnode_res(dht, &sendback_node, packet + 1, plain + 1, data_size); |
1181 | return 0; | 1202 | return 0; |
1182 | } | 1203 | } |
1183 | 1204 | ||
1184 | static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 1205 | static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length) |
1185 | { | 1206 | { |
1186 | DHT *dht = object; | 1207 | DHT *dht = object; |
1187 | size_t node_format_size = sizeof(Node_format); | 1208 | Node_format plain_nodes[MAX_SENT_NODES]; |
1188 | uint8_t plain[node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH]; | ||
1189 | uint32_t num_nodes; | 1209 | uint32_t num_nodes; |
1190 | 1210 | ||
1191 | Node_format sendback_node; | 1211 | if (handle_sendnodes_core(object, source, packet, length, plain_nodes, MAX_SENT_NODES, &num_nodes)) |
1192 | |||
1193 | if (handle_sendnodes_core(object, source, packet, length, node_format_size, plain, sizeof(plain), &num_nodes, | ||
1194 | &sendback_node)) | ||
1195 | return 1; | 1212 | return 1; |
1196 | 1213 | ||
1197 | if (num_nodes == 0) | 1214 | if (num_nodes == 0) |
1198 | return 0; | 1215 | return 0; |
1199 | 1216 | ||
1200 | Node_format *nodes_list = (Node_format *)(plain); | ||
1201 | uint32_t i; | 1217 | uint32_t i; |
1202 | send_hardening_getnode_res(dht, &sendback_node, packet + 1, nodes_list, num_nodes); | ||
1203 | 1218 | ||
1204 | for (i = 0; i < num_nodes; i++) { | 1219 | for (i = 0; i < num_nodes; i++) { |
1205 | to_host_family(&nodes_list[i].ip_port.ip); | 1220 | if (ipport_isset(&plain_nodes[i].ip_port)) { |
1206 | 1221 | send_ping_request(dht->ping, plain_nodes[i].ip_port, plain_nodes[i].client_id); | |
1207 | if (ipport_isset(&nodes_list[i].ip_port)) { | 1222 | returnedip_ports(dht, plain_nodes[i].ip_port, plain_nodes[i].client_id, packet + 1); |
1208 | send_ping_request(dht->ping, nodes_list[i].ip_port, nodes_list[i].client_id); | ||
1209 | returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); | ||
1210 | } | 1223 | } |
1211 | } | 1224 | } |
1212 | 1225 | ||
@@ -1595,7 +1608,7 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) | |||
1595 | /* Send the following packet to everyone who tells us they are connected to friend_id. | 1608 | /* Send the following packet to everyone who tells us they are connected to friend_id. |
1596 | * | 1609 | * |
1597 | * return ip for friend. | 1610 | * return ip for friend. |
1598 | * return number of nodes the packet was sent to. (Only works if more than (MAX_FRIEND_CLIENTS / 2). | 1611 | * return number of nodes the packet was sent to. (Only works if more than (MAX_FRIEND_CLIENTS / 4). |
1599 | */ | 1612 | */ |
1600 | int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t length) | 1613 | int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t length) |
1601 | { | 1614 | { |
@@ -1724,7 +1737,7 @@ int friend_ips(DHT *dht, IP_Port *ip_portlist, uint8_t *friend_id) | |||
1724 | static int send_NATping(DHT *dht, uint8_t *public_key, uint64_t ping_id, uint8_t type) | 1737 | static int send_NATping(DHT *dht, uint8_t *public_key, uint64_t ping_id, uint8_t type) |
1725 | { | 1738 | { |
1726 | uint8_t data[sizeof(uint64_t) + 1]; | 1739 | uint8_t data[sizeof(uint64_t) + 1]; |
1727 | uint8_t packet[MAX_DATA_SIZE]; | 1740 | uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; |
1728 | 1741 | ||
1729 | int num = 0; | 1742 | int num = 0; |
1730 | 1743 | ||
@@ -1935,7 +1948,7 @@ static int send_hardening_req(DHT *dht, Node_format *sendto, uint8_t type, uint8 | |||
1935 | if (length > HARDREQ_DATA_SIZE - 1) | 1948 | if (length > HARDREQ_DATA_SIZE - 1) |
1936 | return -1; | 1949 | return -1; |
1937 | 1950 | ||
1938 | uint8_t packet[MAX_DATA_SIZE]; | 1951 | uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; |
1939 | uint8_t data[HARDREQ_DATA_SIZE] = {0}; | 1952 | uint8_t data[HARDREQ_DATA_SIZE] = {0}; |
1940 | data[0] = type; | 1953 | data[0] = type; |
1941 | memcpy(data + 1, contents, length); | 1954 | memcpy(data + 1, contents, length); |
@@ -1958,17 +1971,17 @@ static int send_hardening_getnode_req(DHT *dht, Node_format *dest, Node_format * | |||
1958 | } | 1971 | } |
1959 | 1972 | ||
1960 | /* Send a get node hardening response */ | 1973 | /* Send a get node hardening response */ |
1961 | static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, Node_format *list, | 1974 | static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, uint8_t *nodes_data, |
1962 | uint16_t num_nodes) | 1975 | uint16_t nodes_data_length) |
1963 | { | 1976 | { |
1964 | if (!ip_isset(&sendto->ip_port.ip)) | 1977 | if (!ip_isset(&sendto->ip_port.ip)) |
1965 | return -1; | 1978 | return -1; |
1966 | 1979 | ||
1967 | uint8_t packet[MAX_DATA_SIZE]; | 1980 | uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; |
1968 | uint8_t data[1 + CLIENT_ID_SIZE + num_nodes * sizeof(Node_format)]; | 1981 | uint8_t data[1 + CLIENT_ID_SIZE + nodes_data_length]; |
1969 | data[0] = CHECK_TYPE_GETNODE_RES; | 1982 | data[0] = CHECK_TYPE_GETNODE_RES; |
1970 | memcpy(data + 1, queried_client_id, CLIENT_ID_SIZE); | 1983 | memcpy(data + 1, queried_client_id, CLIENT_ID_SIZE); |
1971 | memcpy(data + 1 + CLIENT_ID_SIZE, list, num_nodes * sizeof(Node_format)); | 1984 | memcpy(data + 1 + CLIENT_ID_SIZE, nodes_data, nodes_data_length); |
1972 | int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->client_id, data, | 1985 | int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->client_id, data, |
1973 | sizeof(data), CRYPTO_PACKET_HARDENING); | 1986 | sizeof(data), CRYPTO_PACKET_HARDENING); |
1974 | 1987 | ||
@@ -2056,28 +2069,22 @@ static int handle_hardening(void *object, IP_Port source, uint8_t *source_pubkey | |||
2056 | if (length <= CLIENT_ID_SIZE + 1) | 2069 | if (length <= CLIENT_ID_SIZE + 1) |
2057 | return 1; | 2070 | return 1; |
2058 | 2071 | ||
2059 | if ((length - 1 - CLIENT_ID_SIZE) % sizeof(Node_format) != 0) | 2072 | if (length > 1 + CLIENT_ID_SIZE + sizeof(Node_format) * MAX_SENT_NODES) |
2060 | return 1; | 2073 | return 1; |
2061 | 2074 | ||
2062 | uint16_t num = (length - 1 - CLIENT_ID_SIZE) / sizeof(Node_format); | 2075 | uint16_t length_nodes = length - 1 - CLIENT_ID_SIZE; |
2076 | Node_format nodes[MAX_SENT_NODES]; | ||
2077 | int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, packet + 1 + CLIENT_ID_SIZE, length_nodes, 0); | ||
2063 | 2078 | ||
2064 | /* TODO: MAX_SENT_NODES nodes should be returned at all times | 2079 | /* TODO: MAX_SENT_NODES nodes should be returned at all times |
2065 | (right now we have a small network size so it could cause problems for testing and etc..) */ | 2080 | (right now we have a small network size so it could cause problems for testing and etc..) */ |
2066 | if (num > MAX_SENT_NODES || num == 0) | 2081 | if (num_nodes <= 0) |
2067 | return 1; | 2082 | return 1; |
2068 | 2083 | ||
2069 | Node_format nodes[num]; | ||
2070 | memcpy(nodes, packet + 1 + CLIENT_ID_SIZE, sizeof(Node_format)*num); | ||
2071 | uint32_t i; | ||
2072 | |||
2073 | for (i = 0; i < num; ++i) | ||
2074 | to_host_family(&nodes[i].ip_port.ip); | ||
2075 | |||
2076 | /* NOTE: This should work for now but should be changed to something better. */ | 2084 | /* NOTE: This should work for now but should be changed to something better. */ |
2077 | if (have_nodes_closelist(dht, nodes, num) < (uint32_t)((num + 2) / 2)) | 2085 | if (have_nodes_closelist(dht, nodes, num_nodes) < (uint32_t)((num_nodes + 2) / 2)) |
2078 | return 1; | 2086 | return 1; |
2079 | 2087 | ||
2080 | |||
2081 | IPPTsPng *temp = get_closelist_IPPTsPng(dht, packet + 1, nodes[0].ip_port.ip.family); | 2088 | IPPTsPng *temp = get_closelist_IPPTsPng(dht, packet + 1, nodes[0].ip_port.ip.family); |
2082 | 2089 | ||
2083 | if (temp == NULL) | 2090 | if (temp == NULL) |
@@ -2204,6 +2211,8 @@ static int random_node_fromlist(Client_data *list, uint16_t list_size, Node_form | |||
2204 | * return the number of nodes. | 2211 | * return the number of nodes. |
2205 | * | 2212 | * |
2206 | * NOTE:this is used to pick nodes for paths. | 2213 | * NOTE:this is used to pick nodes for paths. |
2214 | * | ||
2215 | * TODO: remove the LAN stuff from this. | ||
2207 | */ | 2216 | */ |
2208 | uint16_t random_nodes_path(DHT *dht, Node_format *nodes, uint16_t max_num) | 2217 | uint16_t random_nodes_path(DHT *dht, Node_format *nodes, uint16_t max_num) |
2209 | { | 2218 | { |
@@ -2287,12 +2296,54 @@ void do_hardening(DHT *dht) | |||
2287 | 2296 | ||
2288 | /*----------------------------------------------------------------------------------*/ | 2297 | /*----------------------------------------------------------------------------------*/ |
2289 | 2298 | ||
2290 | DHT *new_DHT(Net_Crypto *c) | 2299 | void cryptopacket_registerhandler(DHT *dht, uint8_t byte, cryptopacket_handler_callback cb, void *object) |
2300 | { | ||
2301 | dht->cryptopackethandlers[byte].function = cb; | ||
2302 | dht->cryptopackethandlers[byte].object = object; | ||
2303 | } | ||
2304 | |||
2305 | static int cryptopacket_handle(void *object, IP_Port source, uint8_t *packet, uint32_t length) | ||
2306 | { | ||
2307 | DHT *dht = object; | ||
2308 | |||
2309 | if (packet[0] == NET_PACKET_CRYPTO) { | ||
2310 | if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + crypto_box_MACBYTES || | ||
2311 | length > MAX_CRYPTO_REQUEST_SIZE + crypto_box_MACBYTES) | ||
2312 | return 1; | ||
2313 | |||
2314 | if (memcmp(packet + 1, dht->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { // Check if request is for us. | ||
2315 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; | ||
2316 | uint8_t data[MAX_CRYPTO_REQUEST_SIZE]; | ||
2317 | uint8_t number; | ||
2318 | int len = handle_request(dht->self_public_key, dht->self_secret_key, public_key, data, &number, packet, length); | ||
2319 | |||
2320 | if (len == -1 || len == 0) | ||
2321 | return 1; | ||
2322 | |||
2323 | if (!dht->cryptopackethandlers[number].function) return 1; | ||
2324 | |||
2325 | return dht->cryptopackethandlers[number].function(dht->cryptopackethandlers[number].object, source, public_key, | ||
2326 | data, len); | ||
2327 | |||
2328 | } else { /* If request is not for us, try routing it. */ | ||
2329 | int retval = route_packet(dht, packet + 1, packet, length); | ||
2330 | |||
2331 | if ((unsigned int)retval == length) | ||
2332 | return 0; | ||
2333 | } | ||
2334 | } | ||
2335 | |||
2336 | return 1; | ||
2337 | } | ||
2338 | |||
2339 | /*----------------------------------------------------------------------------------*/ | ||
2340 | |||
2341 | DHT *new_DHT(Networking_Core *net) | ||
2291 | { | 2342 | { |
2292 | /* init time */ | 2343 | /* init time */ |
2293 | unix_time_update(); | 2344 | unix_time_update(); |
2294 | 2345 | ||
2295 | if (c == NULL) | 2346 | if (net == NULL) |
2296 | return NULL; | 2347 | return NULL; |
2297 | 2348 | ||
2298 | DHT *dht = calloc(1, sizeof(DHT)); | 2349 | DHT *dht = calloc(1, sizeof(DHT)); |
@@ -2300,8 +2351,7 @@ DHT *new_DHT(Net_Crypto *c) | |||
2300 | if (dht == NULL) | 2351 | if (dht == NULL) |
2301 | return NULL; | 2352 | return NULL; |
2302 | 2353 | ||
2303 | dht->c = c; | 2354 | dht->net = net; |
2304 | dht->net = c->lossless_udp->net; | ||
2305 | dht->ping = new_ping(dht); | 2355 | dht->ping = new_ping(dht); |
2306 | 2356 | ||
2307 | if (dht->ping == NULL) { | 2357 | if (dht->ping == NULL) { |
@@ -2310,11 +2360,10 @@ DHT *new_DHT(Net_Crypto *c) | |||
2310 | } | 2360 | } |
2311 | 2361 | ||
2312 | networking_registerhandler(dht->net, NET_PACKET_GET_NODES, &handle_getnodes, dht); | 2362 | networking_registerhandler(dht->net, NET_PACKET_GET_NODES, &handle_getnodes, dht); |
2313 | networking_registerhandler(dht->net, NET_PACKET_SEND_NODES, &handle_sendnodes, dht); | ||
2314 | networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht); | 2363 | networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht); |
2315 | init_cryptopackets(dht); | 2364 | networking_registerhandler(dht->net, NET_PACKET_CRYPTO, &cryptopacket_handle, dht); |
2316 | cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht); | 2365 | cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht); |
2317 | cryptopacket_registerhandler(c, CRYPTO_PACKET_HARDENING, &handle_hardening, dht); | 2366 | cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, &handle_hardening, dht); |
2318 | 2367 | ||
2319 | new_symmetric_key(dht->secret_symmetric_key); | 2368 | new_symmetric_key(dht->secret_symmetric_key); |
2320 | crypto_box_keypair(dht->self_public_key, dht->self_secret_key); | 2369 | crypto_box_keypair(dht->self_public_key, dht->self_secret_key); |
@@ -2361,8 +2410,8 @@ void kill_DHT(DHT *dht) | |||
2361 | networking_registerhandler(dht->net, NET_PACKET_GET_NODES, NULL, NULL); | 2410 | networking_registerhandler(dht->net, NET_PACKET_GET_NODES, NULL, NULL); |
2362 | networking_registerhandler(dht->net, NET_PACKET_SEND_NODES, NULL, NULL); | 2411 | networking_registerhandler(dht->net, NET_PACKET_SEND_NODES, NULL, NULL); |
2363 | networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, NULL, NULL); | 2412 | networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, NULL, NULL); |
2364 | cryptopacket_registerhandler(dht->c, CRYPTO_PACKET_NAT_PING, NULL, NULL); | 2413 | cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, NULL, NULL); |
2365 | cryptopacket_registerhandler(dht->c, CRYPTO_PACKET_HARDENING, NULL, NULL); | 2414 | cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, NULL, NULL); |
2366 | kill_ping(dht->ping); | 2415 | kill_ping(dht->ping); |
2367 | free(dht->friends_list); | 2416 | free(dht->friends_list); |
2368 | free(dht); | 2417 | free(dht); |
diff --git a/toxcore/DHT.h b/toxcore/DHT.h index 3d2722f8..41fe99c9 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h | |||
@@ -24,7 +24,8 @@ | |||
24 | #ifndef DHT_H | 24 | #ifndef DHT_H |
25 | #define DHT_H | 25 | #define DHT_H |
26 | 26 | ||
27 | #include "net_crypto.h" | 27 | #include "crypto_core.h" |
28 | #include "network.h" | ||
28 | 29 | ||
29 | /* Size of the client_id in bytes. */ | 30 | /* Size of the client_id in bytes. */ |
30 | #define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES | 31 | #define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES |
@@ -36,7 +37,7 @@ | |||
36 | #define LCLIENT_LIST 32 | 37 | #define LCLIENT_LIST 32 |
37 | 38 | ||
38 | /* The max number of nodes to send with send nodes. */ | 39 | /* The max number of nodes to send with send nodes. */ |
39 | #define MAX_SENT_NODES 8 | 40 | #define MAX_SENT_NODES 4 |
40 | 41 | ||
41 | /* Ping timeout in seconds */ | 42 | /* Ping timeout in seconds */ |
42 | #define PING_TIMEOUT 3 | 43 | #define PING_TIMEOUT 3 |
@@ -52,6 +53,8 @@ | |||
52 | /* Redefinitions of variables for safe transfer over wire. */ | 53 | /* Redefinitions of variables for safe transfer over wire. */ |
53 | #define TOX_AF_INET 2 | 54 | #define TOX_AF_INET 2 |
54 | #define TOX_AF_INET6 10 | 55 | #define TOX_AF_INET6 10 |
56 | #define TOX_TCP_INET 130 | ||
57 | #define TOX_TCP_INET6 138 | ||
55 | 58 | ||
56 | /* The number of "fake" friends to add (for optimization purposes and so our paths for the onion part are more random) */ | 59 | /* The number of "fake" friends to add (for optimization purposes and so our paths for the onion part are more random) */ |
57 | #define DHT_FAKE_FRIEND_NUMBER 4 | 60 | #define DHT_FAKE_FRIEND_NUMBER 4 |
@@ -128,16 +131,30 @@ typedef struct { | |||
128 | NAT nat; | 131 | NAT nat; |
129 | } DHT_Friend; | 132 | } DHT_Friend; |
130 | 133 | ||
131 | /* this must be kept even if IP_Port is expanded: wire compatibility */ | 134 | typedef struct __attribute__ ((__packed__)) |
132 | typedef struct { | 135 | { |
133 | uint8_t client_id[CLIENT_ID_SIZE]; | ||
134 | IP4_Port ip_port; | ||
135 | } Node4_format; | ||
136 | |||
137 | typedef struct { | ||
138 | uint8_t client_id[CLIENT_ID_SIZE]; | 136 | uint8_t client_id[CLIENT_ID_SIZE]; |
139 | IP_Port ip_port; | 137 | IP_Port ip_port; |
140 | } Node_format; | 138 | } |
139 | Node_format; | ||
140 | |||
141 | /* Pack number of nodes into data of maxlength length. | ||
142 | * | ||
143 | * return length of packed nodes on success. | ||
144 | * return -1 on failure. | ||
145 | */ | ||
146 | int pack_nodes(uint8_t *data, uint16_t length, Node_format *nodes, uint16_t number); | ||
147 | |||
148 | /* Unpack data of length into nodes of size max_num_nodes. | ||
149 | * Put the length of the data processed in processed_data_len. | ||
150 | * tcp_enabled sets if TCP nodes are expected (true) or not (false). | ||
151 | * | ||
152 | * return number of unpacked nodes on success. | ||
153 | * return -1 on failure. | ||
154 | */ | ||
155 | int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, uint8_t *data, | ||
156 | uint16_t length, uint8_t tcp_enabled); | ||
157 | |||
141 | 158 | ||
142 | /*----------------------------------------------------------------------------------*/ | 159 | /*----------------------------------------------------------------------------------*/ |
143 | /* struct to store some shared keys so we don't have to regenerate them for each request. */ | 160 | /* struct to store some shared keys so we don't have to regenerate them for each request. */ |
@@ -155,8 +172,15 @@ typedef struct { | |||
155 | 172 | ||
156 | /*----------------------------------------------------------------------------------*/ | 173 | /*----------------------------------------------------------------------------------*/ |
157 | 174 | ||
175 | typedef int (*cryptopacket_handler_callback)(void *object, IP_Port ip_port, uint8_t *source_pubkey, uint8_t *data, | ||
176 | uint32_t len); | ||
177 | |||
178 | typedef struct { | ||
179 | cryptopacket_handler_callback function; | ||
180 | void *object; | ||
181 | } Cryptopacket_Handles; | ||
182 | |||
158 | typedef struct { | 183 | typedef struct { |
159 | Net_Crypto *c; | ||
160 | Networking_Core *net; | 184 | Networking_Core *net; |
161 | 185 | ||
162 | Client_data close_clientlist[LCLIENT_LIST]; | 186 | Client_data close_clientlist[LCLIENT_LIST]; |
@@ -164,7 +188,7 @@ typedef struct { | |||
164 | uint32_t close_bootstrap_times; | 188 | uint32_t close_bootstrap_times; |
165 | 189 | ||
166 | /* Note: this key should not be/is not used to transmit any sensitive materials */ | 190 | /* Note: this key should not be/is not used to transmit any sensitive materials */ |
167 | uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES]; | 191 | uint8_t secret_symmetric_key[crypto_box_KEYBYTES]; |
168 | /* DHT keypair */ | 192 | /* DHT keypair */ |
169 | uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; | 193 | uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; |
170 | uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; | 194 | uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; |
@@ -180,6 +204,8 @@ typedef struct { | |||
180 | struct Assoc *assoc; | 204 | struct Assoc *assoc; |
181 | #endif | 205 | #endif |
182 | uint64_t last_run; | 206 | uint64_t last_run; |
207 | |||
208 | Cryptopacket_Handles cryptopackethandlers[256]; | ||
183 | } DHT; | 209 | } DHT; |
184 | /*----------------------------------------------------------------------------------*/ | 210 | /*----------------------------------------------------------------------------------*/ |
185 | 211 | ||
@@ -191,12 +217,12 @@ typedef struct { | |||
191 | */ | 217 | */ |
192 | void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, uint8_t *secret_key, uint8_t *client_id); | 218 | void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, uint8_t *secret_key, uint8_t *client_id); |
193 | 219 | ||
194 | /* Copy shared_key to decrypt DHT packet from client_id into shared_key | 220 | /* Copy shared_key to encrypt/decrypt DHT packet from client_id into shared_key |
195 | * for packets that we recieve. | 221 | * for packets that we receive. |
196 | */ | 222 | */ |
197 | void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, uint8_t *client_id); | 223 | void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, uint8_t *client_id); |
198 | 224 | ||
199 | /* Copy shared_key to decrypt DHT packet from client_id into shared_key | 225 | /* Copy shared_key to encrypt/decrypt DHT packet from client_id into shared_key |
200 | * for packets that we send. | 226 | * for packets that we send. |
201 | */ | 227 | */ |
202 | void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, uint8_t *client_id); | 228 | void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, uint8_t *client_id); |
@@ -251,7 +277,7 @@ int id_closest(uint8_t *id, uint8_t *id1, uint8_t *id2); | |||
251 | /* Get the (maximum MAX_SENT_NODES) closest nodes to client_id we know | 277 | /* Get the (maximum MAX_SENT_NODES) closest nodes to client_id we know |
252 | * and put them in nodes_list (must be MAX_SENT_NODES big). | 278 | * and put them in nodes_list (must be MAX_SENT_NODES big). |
253 | * | 279 | * |
254 | * sa_family = family (IPv4 or IPv6)? | 280 | * sa_family = family (IPv4 or IPv6) (0 if we don't care)? |
255 | * is_LAN = return some LAN ips (true or false) | 281 | * is_LAN = return some LAN ips (true or false) |
256 | * want_good = do we want tested nodes or not? (TODO) | 282 | * want_good = do we want tested nodes or not? (TODO) |
257 | * | 283 | * |
@@ -315,6 +341,10 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length) | |||
315 | */ | 341 | */ |
316 | int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t length); | 342 | int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t length); |
317 | 343 | ||
344 | /* Function to handle crypto packets. | ||
345 | */ | ||
346 | void cryptopacket_registerhandler(DHT *dht, uint8_t byte, cryptopacket_handler_callback cb, void *object); | ||
347 | |||
318 | /* NAT PUNCHING FUNCTIONS */ | 348 | /* NAT PUNCHING FUNCTIONS */ |
319 | 349 | ||
320 | /* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist. | 350 | /* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist. |
@@ -341,7 +371,7 @@ void DHT_save(DHT *dht, uint8_t *data); | |||
341 | int DHT_load(DHT *dht, uint8_t *data, uint32_t length); | 371 | int DHT_load(DHT *dht, uint8_t *data, uint32_t length); |
342 | 372 | ||
343 | /* Initialize DHT. */ | 373 | /* Initialize DHT. */ |
344 | DHT *new_DHT(Net_Crypto *c); | 374 | DHT *new_DHT(Networking_Core *net); |
345 | 375 | ||
346 | void kill_DHT(DHT *dht); | 376 | void kill_DHT(DHT *dht); |
347 | 377 | ||
diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c index bed14754..9d1f055e 100644 --- a/toxcore/LAN_discovery.c +++ b/toxcore/LAN_discovery.c | |||
@@ -78,8 +78,10 @@ static void fetch_broadcast_info(uint16_t port) | |||
78 | 78 | ||
79 | struct sockaddr_in *sock4 = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr; | 79 | struct sockaddr_in *sock4 = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr; |
80 | 80 | ||
81 | if (broadcast_count >= MAX_INTERFACES) | 81 | if (broadcast_count >= MAX_INTERFACES) { |
82 | close(sock); | ||
82 | return; | 83 | return; |
84 | } | ||
83 | 85 | ||
84 | IP_Port *ip_port = &broadcast_ip_port[broadcast_count]; | 86 | IP_Port *ip_port = &broadcast_ip_port[broadcast_count]; |
85 | ip_port->ip.family = AF_INET; | 87 | ip_port->ip.family = AF_INET; |
diff --git a/toxcore/Lossless_UDP.c b/toxcore/Lossless_UDP.c deleted file mode 100644 index c0db8a10..00000000 --- a/toxcore/Lossless_UDP.c +++ /dev/null | |||
@@ -1,1168 +0,0 @@ | |||
1 | /* Lossless_UDP.c | ||
2 | * | ||
3 | * An implementation of the Lossless_UDP protocol as seen in http://wiki.tox.im/index.php/Lossless_UDP | ||
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 | /* | ||
25 | * TODO: clean this file a bit. | ||
26 | * There are a couple of useless variables to get rid of. | ||
27 | */ | ||
28 | |||
29 | #ifdef HAVE_CONFIG_H | ||
30 | #include "config.h" | ||
31 | #endif | ||
32 | |||
33 | #include "Lossless_UDP.h" | ||
34 | |||
35 | #define LUDP_CONNECTION_OUTBOUND 0 | ||
36 | #define LUDP_CONNECTION_INBOUND_HANDLED 1 | ||
37 | #define LUDP_CONNECTION_INBOUND 2 | ||
38 | |||
39 | /* Functions */ | ||
40 | |||
41 | /* | ||
42 | * Get connection id from IP_Port. | ||
43 | * | ||
44 | * return -1 if there are no connections like we are looking for. | ||
45 | * return id if it found it. | ||
46 | */ | ||
47 | int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port) | ||
48 | { | ||
49 | tox_array_for_each(&ludp->connections, Connection, tmp) { | ||
50 | if (tmp->status != LUDP_NO_CONNECTION && ipport_equal(&tmp->ip_port, &ip_port)) { | ||
51 | return tmp_i; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | return -1; | ||
56 | } | ||
57 | |||
58 | /* Resize a queue | ||
59 | * return length of queue on success. | ||
60 | * return ~0 on failure. | ||
61 | */ | ||
62 | uint32_t resize_queue(Data **buffer, uint32_t length, uint32_t new_length, uint32_t min_packetnum, | ||
63 | uint32_t max_packetnum) | ||
64 | { | ||
65 | if (MAX_QUEUE_NUM < new_length) | ||
66 | new_length = MAX_QUEUE_NUM; | ||
67 | |||
68 | if (max_packetnum - min_packetnum > new_length) | ||
69 | return ~0; | ||
70 | |||
71 | if (length == new_length) | ||
72 | return new_length; | ||
73 | |||
74 | Data *temp = calloc(1, sizeof(Data) * new_length); | ||
75 | |||
76 | if (temp == NULL) | ||
77 | return ~0; | ||
78 | |||
79 | if (*buffer == NULL) { | ||
80 | *buffer = temp; | ||
81 | return new_length; | ||
82 | } | ||
83 | |||
84 | uint32_t i; | ||
85 | |||
86 | for (i = min_packetnum; i != max_packetnum; ++i) | ||
87 | memcpy(temp + (i % new_length), *buffer + (i % length), sizeof(Data)); | ||
88 | |||
89 | free(*buffer); | ||
90 | *buffer = temp; | ||
91 | return new_length; | ||
92 | } | ||
93 | |||
94 | |||
95 | |||
96 | /* | ||
97 | * Generate a handshake_id which depends on the ip_port. | ||
98 | * This function will always give one unique handshake_id per ip_port. | ||
99 | * | ||
100 | * TODO: make this better | ||
101 | */ | ||
102 | |||
103 | static uint32_t randtable_initget(Lossless_UDP *ludp, uint32_t index, uint8_t value) | ||
104 | { | ||
105 | if (ludp->randtable[index][value] == 0) | ||
106 | ludp->randtable[index][value] = random_int(); | ||
107 | |||
108 | return ludp->randtable[index][value]; | ||
109 | } | ||
110 | |||
111 | static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source) | ||
112 | { | ||
113 | uint32_t id = 0, i = 0; | ||
114 | |||
115 | uint8_t *uint8; | ||
116 | uint8 = (uint8_t *)&source.port; | ||
117 | id ^= randtable_initget(ludp, i, *uint8); | ||
118 | i++, uint8++; | ||
119 | id ^= randtable_initget(ludp, i, *uint8); | ||
120 | i++; | ||
121 | |||
122 | if (source.ip.family == AF_INET) { | ||
123 | int k; | ||
124 | |||
125 | for (k = 0; k < 4; k++) { | ||
126 | id ^= randtable_initget(ludp, i++, source.ip.ip4.uint8[k]); | ||
127 | } | ||
128 | } | ||
129 | |||
130 | if (source.ip.family == AF_INET6) { | ||
131 | int k; | ||
132 | |||
133 | for (k = 0; k < 16; k++) { | ||
134 | id ^= randtable_initget(ludp, i++, source.ip.ip6.uint8[k]); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | /* id can't be zero. */ | ||
139 | if (id == 0) | ||
140 | id = 1; | ||
141 | |||
142 | return id; | ||
143 | } | ||
144 | |||
145 | /* | ||
146 | * Change the handshake id associated with that ip_port. | ||
147 | * | ||
148 | * TODO: Make this better | ||
149 | */ | ||
150 | static void change_handshake(Lossless_UDP *ludp, IP_Port source) | ||
151 | { | ||
152 | uint8_t rand; | ||
153 | |||
154 | if (source.ip.family == AF_INET) { | ||
155 | rand = random_int() % 4; | ||
156 | } else if (source.ip.family == AF_INET6) { | ||
157 | rand = random_int() % 16; | ||
158 | } else { | ||
159 | return; | ||
160 | } | ||
161 | |||
162 | /* Forced to be more robust against strange definitions of sa_family_t */ | ||
163 | ludp->randtable[2 + rand][((uint8_t *)&source.ip.ip6)[rand]] = random_int(); | ||
164 | } | ||
165 | |||
166 | /* | ||
167 | * Initialize a new connection to ip_port | ||
168 | * | ||
169 | * return an integer corresponding to the connection id. | ||
170 | * return -1 if it could not initialize the connectiont | ||
171 | * If there already was an existing connection to that ip_port return its number. | ||
172 | */ | ||
173 | int new_connection(Lossless_UDP *ludp, IP_Port ip_port) | ||
174 | { | ||
175 | int connection_id = getconnection_id(ludp, ip_port); | ||
176 | |||
177 | if (connection_id != -1) { | ||
178 | confirm_connection(ludp, connection_id); | ||
179 | return connection_id; | ||
180 | } | ||
181 | |||
182 | tox_array_for_each(&ludp->connections, Connection, tmp) { | ||
183 | if (tmp->status == LUDP_NO_CONNECTION) { | ||
184 | connection_id = tmp_i; | ||
185 | break; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | if (connection_id == -1) { | ||
190 | if (tox_array_push_ptr(&ludp->connections, 0) == 0) | ||
191 | return -1; | ||
192 | |||
193 | connection_id = ludp->connections.len - 1; | ||
194 | } | ||
195 | |||
196 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
197 | |||
198 | memset(connection, 0, sizeof(Connection)); | ||
199 | |||
200 | uint32_t handshake_id1 = handshake_id(ludp, ip_port); | ||
201 | /* Add randomness to timeout to prevent connections getting stuck in a loop. */ | ||
202 | uint8_t timeout = CONNECTION_TIMEOUT + rand() % CONNECTION_TIMEOUT; | ||
203 | |||
204 | *connection = (Connection) { | ||
205 | .ip_port = ip_port, | ||
206 | .status = LUDP_HANDSHAKE_SENDING, | ||
207 | .inbound = LUDP_CONNECTION_OUTBOUND, | ||
208 | .handshake_id1 = handshake_id1, | ||
209 | .sent_packetnum = handshake_id1, | ||
210 | .sendbuff_packetnum = handshake_id1, | ||
211 | .successful_sent = handshake_id1, | ||
212 | .SYNC_rate = SYNC_RATE, | ||
213 | .data_rate = DATA_SYNC_RATE, | ||
214 | .last_recvSYNC = current_time(), | ||
215 | .last_sent = current_time(), | ||
216 | .killat = ~0, | ||
217 | .send_counter = 0, | ||
218 | .timeout = timeout, | ||
219 | .confirmed = 1 | ||
220 | }; | ||
221 | connection->sendbuffer_length = resize_queue(&connection->sendbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0); | ||
222 | connection->recvbuffer_length = resize_queue(&connection->recvbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0); | ||
223 | |||
224 | if (connection->sendbuffer_length == (uint32_t)~0 || connection->recvbuffer_length == (uint32_t)~0) { | ||
225 | free(connection->sendbuffer); | ||
226 | free(connection->recvbuffer); | ||
227 | memset(connection, 0, sizeof(Connection)); | ||
228 | return -1; | ||
229 | } | ||
230 | |||
231 | return connection_id; | ||
232 | } | ||
233 | |||
234 | /* | ||
235 | * Initialize a new inbound connection from ip_port. | ||
236 | * | ||
237 | * return an integer corresponding to the connection id. | ||
238 | * return -1 if it could not initialize the connection. | ||
239 | */ | ||
240 | static int new_inconnection(Lossless_UDP *ludp, IP_Port ip_port) | ||
241 | { | ||
242 | if (getconnection_id(ludp, ip_port) != -1) | ||
243 | return -1; /* TODO: return existing connection instead? */ | ||
244 | |||
245 | int connection_id = -1; | ||
246 | tox_array_for_each(&ludp->connections, Connection, tmp) { | ||
247 | if (tmp->status == LUDP_NO_CONNECTION) { | ||
248 | connection_id = tmp_i; | ||
249 | break; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | if (connection_id == -1) { | ||
254 | if (tox_array_push_ptr(&ludp->connections, 0) == 0) | ||
255 | return -1; | ||
256 | |||
257 | connection_id = ludp->connections.len - 1; | ||
258 | } | ||
259 | |||
260 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
261 | memset(connection, 0, sizeof(Connection)); | ||
262 | /* Add randomness to timeout to prevent connections getting stuck in a loop. */ | ||
263 | uint8_t timeout = CONNECTION_TIMEOUT + rand() % CONNECTION_TIMEOUT; | ||
264 | |||
265 | *connection = (Connection) { | ||
266 | .ip_port = ip_port, | ||
267 | .status = LUDP_NOT_CONFIRMED, | ||
268 | .inbound = LUDP_CONNECTION_INBOUND, | ||
269 | .SYNC_rate = SYNC_RATE, | ||
270 | .data_rate = DATA_SYNC_RATE, | ||
271 | .last_recvSYNC = current_time(), | ||
272 | .last_sent = current_time(), | ||
273 | .send_counter = 127, | ||
274 | |||
275 | .timeout = timeout, | ||
276 | |||
277 | /* If this connection isn't handled within the timeout kill it. */ | ||
278 | .killat = current_time() + 1000000ULL * timeout, | ||
279 | .confirmed = 0 | ||
280 | }; | ||
281 | connection->sendbuffer_length = resize_queue(&connection->sendbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0); | ||
282 | connection->recvbuffer_length = resize_queue(&connection->recvbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0); | ||
283 | |||
284 | if (connection->sendbuffer_length == (uint32_t)~0 || connection->recvbuffer_length == (uint32_t)~0) { | ||
285 | free(connection->sendbuffer); | ||
286 | free(connection->recvbuffer); | ||
287 | memset(connection, 0, sizeof(Connection)); | ||
288 | return -1; | ||
289 | } | ||
290 | |||
291 | return connection_id; | ||
292 | } | ||
293 | |||
294 | /* | ||
295 | * return an integer corresponding to the next connection in our incoming connection list with at least numpackets in the recieve queue. | ||
296 | * return -1 if there are no new incoming connections in the list. | ||
297 | */ | ||
298 | int incoming_connection(Lossless_UDP *ludp, uint32_t numpackets) | ||
299 | { | ||
300 | tox_array_for_each(&ludp->connections, Connection, tmp) { | ||
301 | if (tmp->inbound == LUDP_CONNECTION_INBOUND && tmp->recv_packetnum - tmp->successful_read >= numpackets) { | ||
302 | tmp->inbound = LUDP_CONNECTION_INBOUND_HANDLED; | ||
303 | return tmp_i; | ||
304 | } | ||
305 | } | ||
306 | return -1; | ||
307 | } | ||
308 | /* Try to free some memory from the connections array. */ | ||
309 | static void free_connections(Lossless_UDP *ludp) | ||
310 | { | ||
311 | uint32_t i; | ||
312 | |||
313 | for (i = ludp->connections.len; i != 0; --i) { | ||
314 | Connection *connection = &tox_array_get(&ludp->connections, i - 1, Connection); | ||
315 | |||
316 | if (connection->status != LUDP_NO_CONNECTION) | ||
317 | break; | ||
318 | } | ||
319 | |||
320 | if (ludp->connections.len == i) | ||
321 | return; | ||
322 | |||
323 | return tox_array_pop(&ludp->connections, ludp->connections.len - i); | ||
324 | } | ||
325 | /* return -1 if it could not kill the connection. | ||
326 | * return 0 if killed successfully. | ||
327 | */ | ||
328 | int kill_connection(Lossless_UDP *ludp, int connection_id) | ||
329 | { | ||
330 | if ((unsigned int)connection_id < ludp->connections.len) { | ||
331 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
332 | |||
333 | if (connection->status != LUDP_NO_CONNECTION) { | ||
334 | connection->status = LUDP_NO_CONNECTION; | ||
335 | change_handshake(ludp, connection->ip_port); | ||
336 | free(connection->sendbuffer); | ||
337 | free(connection->recvbuffer); | ||
338 | memset(connection, 0, sizeof(Connection)); | ||
339 | free_connections(ludp); | ||
340 | return 0; | ||
341 | } | ||
342 | } | ||
343 | |||
344 | return -1; | ||
345 | } | ||
346 | |||
347 | /* | ||
348 | * timeout connection in seconds. | ||
349 | * | ||
350 | * return -1 if it can not kill the connection. | ||
351 | * return 0 if it will kill it. | ||
352 | */ | ||
353 | int timeout_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds) | ||
354 | { | ||
355 | if ((unsigned int)connection_id < ludp->connections.len) { | ||
356 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
357 | |||
358 | if (connection->status != LUDP_NO_CONNECTION) { | ||
359 | connection->killat = current_time() + 1000000ULL * seconds; | ||
360 | return 0; | ||
361 | } | ||
362 | } | ||
363 | |||
364 | return -1; | ||
365 | } | ||
366 | |||
367 | /* | ||
368 | * Check if connection is connected: | ||
369 | * | ||
370 | * return LUDP_NO_CONNECTION if not. | ||
371 | * return LUDP_HANDSHAKE_SENDING if attempting handshake. | ||
372 | * return LUDP_NOT_CONFIRMED if handshake is done. | ||
373 | * return LUDP_ESTABLISHED if fully connected. | ||
374 | * return LUDP_TIMED_OUT if timed out and waiting to be killed. | ||
375 | */ | ||
376 | int is_connected(Lossless_UDP *ludp, int connection_id) | ||
377 | { | ||
378 | if ((unsigned int)connection_id < ludp->connections.len) | ||
379 | return tox_array_get(&ludp->connections, connection_id, Connection).status; | ||
380 | |||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | /* Check if connection is confirmed. | ||
385 | * | ||
386 | * returns 1 if yes. | ||
387 | * returns 0 if no/failure. | ||
388 | */ | ||
389 | int connection_confirmed(Lossless_UDP *ludp, int connection_id) | ||
390 | { | ||
391 | if ((unsigned int)connection_id >= ludp->connections.len) | ||
392 | return 0; | ||
393 | |||
394 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
395 | |||
396 | if (connection->status == LUDP_NO_CONNECTION) | ||
397 | return 0; | ||
398 | |||
399 | if (connection->confirmed == 1) | ||
400 | return 1; | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | /* Confirm an incoming connection. | ||
406 | * Also disable the auto kill timeout on incomming connections. | ||
407 | * | ||
408 | * return 0 on success | ||
409 | * return -1 on failure. | ||
410 | */ | ||
411 | int confirm_connection(Lossless_UDP *ludp, int connection_id) | ||
412 | { | ||
413 | if ((unsigned int)connection_id >= ludp->connections.len) | ||
414 | return -1; | ||
415 | |||
416 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
417 | |||
418 | if (connection->status == LUDP_NO_CONNECTION) | ||
419 | return -1; | ||
420 | |||
421 | connection->killat = ~0; | ||
422 | connection->confirmed = 1; | ||
423 | connection->inbound = LUDP_CONNECTION_OUTBOUND; | ||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | /* return the ip_port of the corresponding connection. */ | ||
428 | IP_Port connection_ip(Lossless_UDP *ludp, int connection_id) | ||
429 | { | ||
430 | if ((unsigned int)connection_id < ludp->connections.len) | ||
431 | return tox_array_get(&ludp->connections, connection_id, Connection).ip_port; | ||
432 | |||
433 | IP_Port zero; | ||
434 | ip_reset(&zero.ip); | ||
435 | zero.port = 0; | ||
436 | return zero; | ||
437 | } | ||
438 | |||
439 | /* return the number of packets in the queue waiting to be successfully sent. */ | ||
440 | uint32_t sendqueue(Lossless_UDP *ludp, int connection_id) | ||
441 | { | ||
442 | if ((unsigned int)connection_id >= ludp->connections.len) | ||
443 | return 0; | ||
444 | |||
445 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
446 | |||
447 | if (connection->status == LUDP_NO_CONNECTION) | ||
448 | return 0; | ||
449 | |||
450 | return connection->sendbuff_packetnum - connection->successful_sent; | ||
451 | } | ||
452 | |||
453 | /* return number of packets in all queues waiting to be successfully sent. */ | ||
454 | uint32_t sendqueue_total(Lossless_UDP *ludp) | ||
455 | { | ||
456 | uint32_t i, total = 0; | ||
457 | |||
458 | for (i = 0; i < ludp->connections.len; i++) { | ||
459 | Connection *connection = &tox_array_get(&ludp->connections, i, Connection); | ||
460 | |||
461 | if (connection->status != 0) | ||
462 | total += connection->sendbuff_packetnum - connection->successful_sent; | ||
463 | } | ||
464 | |||
465 | return total; | ||
466 | } | ||
467 | |||
468 | /* return the number of packets in the queue waiting to be successfully read with read_packet(...). */ | ||
469 | uint32_t recvqueue(Lossless_UDP *ludp, int connection_id) | ||
470 | { | ||
471 | if ((unsigned int)connection_id >= ludp->connections.len) | ||
472 | return 0; | ||
473 | |||
474 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
475 | |||
476 | if (connection->status == LUDP_NO_CONNECTION) | ||
477 | return 0; | ||
478 | |||
479 | return connection->recv_packetnum - connection->successful_read; | ||
480 | } | ||
481 | |||
482 | /* return the id of the next packet in the queue. | ||
483 | * return ~0 if no packet in queue. | ||
484 | */ | ||
485 | uint8_t id_packet(Lossless_UDP *ludp, int connection_id) | ||
486 | { | ||
487 | if (recvqueue(ludp, connection_id) == 0) | ||
488 | return ~0; | ||
489 | |||
490 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
491 | |||
492 | if (connection->status != LUDP_NO_CONNECTION) | ||
493 | return connection->recvbuffer[connection->successful_read % connection->recvbuffer_length].data[0]; | ||
494 | |||
495 | return ~0; | ||
496 | } | ||
497 | |||
498 | /* return 0 if there is no received data in the buffer. | ||
499 | * return length of received packet if successful. | ||
500 | */ | ||
501 | int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data) | ||
502 | { | ||
503 | if (recvqueue(ludp, connection_id) == 0) | ||
504 | return 0; | ||
505 | |||
506 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
507 | |||
508 | if (connection->status == LUDP_NO_CONNECTION) | ||
509 | return 0; | ||
510 | |||
511 | uint16_t index = connection->successful_read % connection->recvbuffer_length; | ||
512 | uint16_t size = connection->recvbuffer[index].size; | ||
513 | memcpy(data, connection->recvbuffer[index].data, size); | ||
514 | ++connection->successful_read; | ||
515 | connection->recvbuffer[index].size = 0; | ||
516 | return size; | ||
517 | } | ||
518 | |||
519 | /* Like read_packet() but does leaves the queue as is. | ||
520 | * return 0 if there is no received data in the buffer. | ||
521 | * return length of received packet if successful. | ||
522 | */ | ||
523 | int read_packet_silent(Lossless_UDP *ludp, int connection_id, uint8_t *data) | ||
524 | { | ||
525 | if (recvqueue(ludp, connection_id) == 0) | ||
526 | return 0; | ||
527 | |||
528 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
529 | |||
530 | if (connection->status == LUDP_NO_CONNECTION) | ||
531 | return 0; | ||
532 | |||
533 | uint16_t index = connection->successful_read % connection->recvbuffer_length; | ||
534 | uint16_t size = connection->recvbuffer[index].size; | ||
535 | memcpy(data, connection->recvbuffer[index].data, size); | ||
536 | return size; | ||
537 | } | ||
538 | /* Discard the next packet to be read from the queue | ||
539 | * return 0 if success. | ||
540 | * return -1 if failure. | ||
541 | */ | ||
542 | int discard_packet(Lossless_UDP *ludp, int connection_id) | ||
543 | { | ||
544 | if (recvqueue(ludp, connection_id) == 0) | ||
545 | return -1; | ||
546 | |||
547 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
548 | uint16_t index = connection->successful_read % connection->recvbuffer_length; | ||
549 | ++connection->successful_read; | ||
550 | connection->recvbuffer[index].size = 0; | ||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | #define MAX_SYNC_RATE 20 | ||
555 | #define MIN_SLOTS 16 | ||
556 | /* returns the number of packet slots left in the sendbuffer. | ||
557 | * return 0 if failure. | ||
558 | */ | ||
559 | uint32_t num_free_sendqueue_slots(Lossless_UDP *ludp, int connection_id) | ||
560 | { | ||
561 | if ((unsigned int)connection_id >= ludp->connections.len) | ||
562 | return 0; | ||
563 | |||
564 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
565 | uint32_t max_slots = (connection->data_rate / MAX_SYNC_RATE) * 1.5; | ||
566 | |||
567 | if (max_slots > MAX_QUEUE_NUM) | ||
568 | max_slots = MAX_QUEUE_NUM; | ||
569 | |||
570 | if (max_slots < MIN_SLOTS) | ||
571 | max_slots = MIN_SLOTS; | ||
572 | |||
573 | if (sendqueue(ludp, connection_id) > max_slots) | ||
574 | return 0; | ||
575 | |||
576 | return max_slots - sendqueue(ludp, connection_id); | ||
577 | } | ||
578 | |||
579 | |||
580 | /* return 0 if data could not be put in packet queue. | ||
581 | * return 1 if data was put into the queue. | ||
582 | */ | ||
583 | int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t length) | ||
584 | { | ||
585 | if ((unsigned int)connection_id >= ludp->connections.len) | ||
586 | return 0; | ||
587 | |||
588 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
589 | |||
590 | if (connection->status == LUDP_NO_CONNECTION) | ||
591 | return 0; | ||
592 | |||
593 | if (length > MAX_DATA_SIZE || length == 0 || sendqueue(ludp, connection_id) >= MAX_QUEUE_NUM) | ||
594 | return 0; | ||
595 | |||
596 | if (num_free_sendqueue_slots(ludp, connection_id) == 0) | ||
597 | return 0; | ||
598 | |||
599 | if (sendqueue(ludp, connection_id) >= connection->sendbuffer_length && connection->sendbuffer_length != 0) { | ||
600 | uint32_t newlen = connection->sendbuffer_length = resize_queue(&connection->sendbuffer, connection->sendbuffer_length, | ||
601 | connection->sendbuffer_length * 2, connection->successful_sent, connection->sendbuff_packetnum); | ||
602 | |||
603 | if (newlen == (uint32_t)~0) | ||
604 | return 0; | ||
605 | |||
606 | connection->sendbuffer_length = newlen; | ||
607 | return write_packet(ludp, connection_id, data, length); | ||
608 | } | ||
609 | |||
610 | uint32_t index = connection->sendbuff_packetnum % connection->sendbuffer_length; | ||
611 | memcpy(connection->sendbuffer[index].data, data, length); | ||
612 | connection->sendbuffer[index].size = length; | ||
613 | connection->sendbuff_packetnum++; | ||
614 | return 1; | ||
615 | } | ||
616 | |||
617 | /* Put the packet numbers the we are missing in requested and return the number. */ | ||
618 | static uint32_t missing_packets(Lossless_UDP *ludp, int connection_id, uint32_t *requested) | ||
619 | { | ||
620 | if ((unsigned int)connection_id >= ludp->connections.len) | ||
621 | return 0; | ||
622 | |||
623 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
624 | |||
625 | /* Don't request packets if the buffer is full. */ | ||
626 | if (recvqueue(ludp, connection_id) >= (connection->recvbuffer_length - 1)) | ||
627 | return 0; | ||
628 | |||
629 | uint32_t number = 0; | ||
630 | uint32_t i; | ||
631 | uint32_t temp; | ||
632 | |||
633 | for (i = connection->recv_packetnum; | ||
634 | i != connection->osent_packetnum; | ||
635 | i++) { | ||
636 | if (connection->recvbuffer[i % connection->recvbuffer_length].size == 0) { | ||
637 | temp = htonl(i); | ||
638 | memcpy(requested + number, &temp, 4); | ||
639 | ++number; | ||
640 | } | ||
641 | |||
642 | if (number >= MAX_REQUESTED_PACKETS) | ||
643 | return number; | ||
644 | } | ||
645 | |||
646 | if (number == 0) | ||
647 | connection->recv_packetnum = connection->osent_packetnum; | ||
648 | |||
649 | return number; | ||
650 | } | ||
651 | |||
652 | /* | ||
653 | * BEGIN Packet sending functions. | ||
654 | * One per packet type. | ||
655 | * See http://wiki.tox.im/index.php/Lossless_UDP for more information. | ||
656 | */ | ||
657 | |||
658 | static int send_handshake(Lossless_UDP *ludp, IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2) | ||
659 | { | ||
660 | uint8_t packet[1 + 4 + 4]; | ||
661 | uint32_t temp; | ||
662 | |||
663 | packet[0] = NET_PACKET_HANDSHAKE; | ||
664 | temp = htonl(handshake_id1); | ||
665 | memcpy(packet + 1, &temp, 4); | ||
666 | temp = htonl(handshake_id2); | ||
667 | memcpy(packet + 5, &temp, 4); | ||
668 | |||
669 | return sendpacket(ludp->net, ip_port, packet, sizeof(packet)); | ||
670 | } | ||
671 | |||
672 | static int send_SYNC(Lossless_UDP *ludp, int connection_id) | ||
673 | { | ||
674 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
675 | uint8_t packet[(MAX_REQUESTED_PACKETS * 4 + 4 + 4 + 2)]; | ||
676 | uint16_t index = 0; | ||
677 | |||
678 | IP_Port ip_port = connection->ip_port; | ||
679 | uint8_t counter = connection->send_counter; | ||
680 | uint32_t recv_packetnum = htonl(connection->recv_packetnum); | ||
681 | uint32_t sent_packetnum = htonl(connection->sent_packetnum); | ||
682 | |||
683 | uint32_t requested[MAX_REQUESTED_PACKETS]; | ||
684 | uint32_t number = missing_packets(ludp, connection_id, requested); | ||
685 | |||
686 | packet[0] = NET_PACKET_SYNC; | ||
687 | index += 1; | ||
688 | memcpy(packet + index, &counter, 1); | ||
689 | index += 1; | ||
690 | memcpy(packet + index, &recv_packetnum, 4); | ||
691 | index += 4; | ||
692 | memcpy(packet + index, &sent_packetnum, 4); | ||
693 | index += 4; | ||
694 | memcpy(packet + index, requested, 4 * number); | ||
695 | |||
696 | return sendpacket(ludp->net, ip_port, packet, (number * 4 + 4 + 4 + 2)); | ||
697 | |||
698 | } | ||
699 | |||
700 | static int send_data_packet(Lossless_UDP *ludp, int connection_id, uint32_t packet_num) | ||
701 | { | ||
702 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
703 | |||
704 | uint32_t index = packet_num % connection->sendbuffer_length; | ||
705 | uint32_t temp; | ||
706 | uint8_t packet[1 + 4 + MAX_DATA_SIZE]; | ||
707 | packet[0] = NET_PACKET_DATA; | ||
708 | temp = htonl(packet_num); | ||
709 | memcpy(packet + 1, &temp, 4); | ||
710 | memcpy(packet + 5, connection->sendbuffer[index].data, connection->sendbuffer[index].size); | ||
711 | return sendpacket(ludp->net, connection->ip_port, packet, 1 + 4 + connection->sendbuffer[index].size); | ||
712 | } | ||
713 | |||
714 | /* Sends 1 data packet. */ | ||
715 | static int send_DATA(Lossless_UDP *ludp, int connection_id) | ||
716 | { | ||
717 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
718 | int ret; | ||
719 | uint32_t buffer[MAX_REQUESTED_PACKETS]; | ||
720 | |||
721 | if (connection->num_req_paquets > 0) { | ||
722 | ret = send_data_packet(ludp, connection_id, connection->req_packets[0]); | ||
723 | connection->num_req_paquets--; | ||
724 | memcpy(buffer, connection->req_packets + 1, connection->num_req_paquets * 4); | ||
725 | memcpy(connection->req_packets, buffer, connection->num_req_paquets * 4); | ||
726 | return ret; | ||
727 | } | ||
728 | |||
729 | if (connection->sendbuff_packetnum != connection->sent_packetnum) { | ||
730 | ret = send_data_packet(ludp, connection_id, connection->sent_packetnum); | ||
731 | connection->sent_packetnum++; | ||
732 | return ret; | ||
733 | } | ||
734 | |||
735 | return 0; | ||
736 | } | ||
737 | |||
738 | /* | ||
739 | * END of packet sending functions. | ||
740 | * | ||
741 | * | ||
742 | * BEGIN Packet handling functions. | ||
743 | * One to handle each type of packets we receive. | ||
744 | */ | ||
745 | |||
746 | |||
747 | /* return 0 if handled correctly. | ||
748 | * return 1 if packet is bad. | ||
749 | */ | ||
750 | static int handle_handshake(void *object, IP_Port source, uint8_t *packet, uint32_t length) | ||
751 | { | ||
752 | Lossless_UDP *ludp = object; | ||
753 | |||
754 | if (length != (1 + 4 + 4)) | ||
755 | return 1; | ||
756 | |||
757 | uint32_t temp; | ||
758 | uint32_t handshake_id1, handshake_id2; | ||
759 | int connection_id = getconnection_id(ludp, source); | ||
760 | |||
761 | memcpy(&temp, packet + 1, 4); | ||
762 | handshake_id1 = ntohl(temp); | ||
763 | memcpy(&temp, packet + 5, 4); | ||
764 | handshake_id2 = ntohl(temp); | ||
765 | |||
766 | |||
767 | if (handshake_id2 == 0 && is_connected(ludp, connection_id) != LUDP_ESTABLISHED && | ||
768 | is_connected(ludp, connection_id) != LUDP_TIMED_OUT) { | ||
769 | send_handshake(ludp, source, handshake_id(ludp, source), handshake_id1); | ||
770 | return 0; | ||
771 | } | ||
772 | |||
773 | if (is_connected(ludp, connection_id) != LUDP_HANDSHAKE_SENDING) | ||
774 | return 1; | ||
775 | |||
776 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
777 | |||
778 | /* if handshake_id2 is what we sent previously as handshake_id1 */ | ||
779 | if (handshake_id2 == connection->handshake_id1) { | ||
780 | connection->status = LUDP_NOT_CONFIRMED; | ||
781 | /* NOTE: Is this necessary? | ||
782 | connection->handshake_id2 = handshake_id1; */ | ||
783 | connection->orecv_packetnum = handshake_id2; | ||
784 | connection->osent_packetnum = handshake_id1; | ||
785 | connection->recv_packetnum = handshake_id1; | ||
786 | connection->successful_read = handshake_id1; | ||
787 | } | ||
788 | |||
789 | return 0; | ||
790 | } | ||
791 | |||
792 | /* return 1 if sync packet is valid. | ||
793 | * return 0 if not. | ||
794 | */ | ||
795 | static int SYNC_valid(uint32_t length) | ||
796 | { | ||
797 | if (length < 4 + 4 + 2) | ||
798 | return 0; | ||
799 | |||
800 | if (length > (MAX_REQUESTED_PACKETS * 4 + 4 + 4 + 2) || | ||
801 | ((length - 4 - 4 - 2) % 4) != 0) | ||
802 | return 0; | ||
803 | |||
804 | return 1; | ||
805 | } | ||
806 | |||
807 | /* case 1 in handle_SYNC: */ | ||
808 | static int handle_SYNC1(Lossless_UDP *ludp, IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnum) | ||
809 | { | ||
810 | if (handshake_id(ludp, source) == recv_packetnum) { | ||
811 | int connection_id = new_inconnection(ludp, source); | ||
812 | |||
813 | if (connection_id != -1) { | ||
814 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
815 | connection->orecv_packetnum = recv_packetnum; | ||
816 | connection->sent_packetnum = recv_packetnum; | ||
817 | connection->sendbuff_packetnum = recv_packetnum; | ||
818 | connection->successful_sent = recv_packetnum; | ||
819 | connection->osent_packetnum = sent_packetnum; | ||
820 | connection->recv_packetnum = sent_packetnum; | ||
821 | connection->successful_read = sent_packetnum; | ||
822 | |||
823 | return connection_id; | ||
824 | } | ||
825 | } | ||
826 | |||
827 | return -1; | ||
828 | } | ||
829 | |||
830 | /* case 2 in handle_SYNC: */ | ||
831 | static int handle_SYNC2(Lossless_UDP *ludp, int connection_id, uint8_t counter, uint32_t recv_packetnum, | ||
832 | uint32_t sent_packetnum) | ||
833 | { | ||
834 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
835 | |||
836 | if (recv_packetnum == connection->orecv_packetnum && sent_packetnum == connection->osent_packetnum) { | ||
837 | connection->status = LUDP_ESTABLISHED; | ||
838 | connection->recv_counter = counter; | ||
839 | ++connection->send_counter; | ||
840 | send_SYNC(ludp, connection_id); | ||
841 | return 0; | ||
842 | } | ||
843 | |||
844 | return 1; | ||
845 | } | ||
846 | |||
847 | /* | ||
848 | * Automatically adjusts send rates of data packets for optimal transmission. | ||
849 | * | ||
850 | * TODO: Improve this. | ||
851 | */ | ||
852 | static void adjust_datasendspeed(Connection *connection, uint32_t req_packets) | ||
853 | { | ||
854 | /* if there are no packets in send buffer */ | ||
855 | if (connection->sendbuff_packetnum - connection->successful_sent == 0) { | ||
856 | connection->data_rate -= connection->data_rate / 8; | ||
857 | |||
858 | if (connection->data_rate < DATA_SYNC_RATE) | ||
859 | connection->data_rate = DATA_SYNC_RATE; | ||
860 | |||
861 | return; | ||
862 | } | ||
863 | |||
864 | if (req_packets <= (connection->data_rate / connection->SYNC_rate) / 4 || req_packets <= 10) { | ||
865 | connection->data_rate += (connection->data_rate / 4) + 1; | ||
866 | |||
867 | if (connection->data_rate > connection->sendbuffer_length * connection->SYNC_rate) | ||
868 | connection->data_rate = connection->sendbuffer_length * connection->SYNC_rate; | ||
869 | } else { | ||
870 | connection->data_rate -= connection->data_rate / 8; | ||
871 | } | ||
872 | } | ||
873 | |||
874 | |||
875 | /* case 3 in handle_SYNC: */ | ||
876 | static int handle_SYNC3(Lossless_UDP *ludp, int connection_id, uint8_t counter, uint32_t recv_packetnum, | ||
877 | uint32_t sent_packetnum, | ||
878 | uint32_t *req_packets, | ||
879 | uint16_t number) | ||
880 | { | ||
881 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
882 | |||
883 | uint8_t comp_counter = (counter - connection->recv_counter); | ||
884 | uint32_t i, temp; | ||
885 | /* uint32_t comp_1 = (recv_packetnum - connection->successful_sent); | ||
886 | uint32_t comp_2 = (sent_packetnum - connection->successful_read); */ | ||
887 | uint32_t comp_1 = (recv_packetnum - connection->orecv_packetnum); | ||
888 | uint32_t comp_2 = (sent_packetnum - connection->osent_packetnum); | ||
889 | |||
890 | /* Packet valid. */ | ||
891 | if (comp_1 <= connection->sendbuffer_length && | ||
892 | comp_2 <= MAX_QUEUE_NUM && | ||
893 | comp_counter != 0 && comp_counter < 8) { | ||
894 | connection->orecv_packetnum = recv_packetnum; | ||
895 | connection->osent_packetnum = sent_packetnum; | ||
896 | connection->successful_sent = recv_packetnum; | ||
897 | connection->last_recvSYNC = current_time(); | ||
898 | |||
899 | connection->recv_counter = counter; | ||
900 | |||
901 | ++connection->send_counter; | ||
902 | |||
903 | for (i = 0; i < number; ++i) { | ||
904 | temp = ntohl(req_packets[i]); | ||
905 | memcpy(connection->req_packets + i, &temp, sizeof(uint32_t)); | ||
906 | } | ||
907 | |||
908 | connection->num_req_paquets = number; | ||
909 | adjust_datasendspeed(connection, number); | ||
910 | return 0; | ||
911 | } | ||
912 | |||
913 | return 1; | ||
914 | } | ||
915 | |||
916 | static int handle_SYNC(void *object, IP_Port source, uint8_t *packet, uint32_t length) | ||
917 | { | ||
918 | Lossless_UDP *ludp = object; | ||
919 | |||
920 | if (!SYNC_valid(length)) | ||
921 | return 1; | ||
922 | |||
923 | uint8_t counter; | ||
924 | uint32_t temp; | ||
925 | uint32_t recv_packetnum, sent_packetnum; | ||
926 | uint16_t number = (length - 4 - 4 - 2) / 4; | ||
927 | uint32_t req_packets[number]; | ||
928 | |||
929 | memcpy(&counter, packet + 1, 1); | ||
930 | memcpy(&temp, packet + 2, 4); | ||
931 | recv_packetnum = ntohl(temp); | ||
932 | memcpy(&temp, packet + 6, 4); | ||
933 | sent_packetnum = ntohl(temp); | ||
934 | |||
935 | if (number != 0) | ||
936 | memcpy(req_packets, packet + 10, 4 * number); | ||
937 | |||
938 | int connection_id = getconnection_id(ludp, source); | ||
939 | |||
940 | if (connection_id == -1) | ||
941 | return handle_SYNC1(ludp, source, recv_packetnum, sent_packetnum); | ||
942 | |||
943 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
944 | |||
945 | if (connection->status == LUDP_NOT_CONFIRMED) | ||
946 | return handle_SYNC2(ludp, connection_id, counter, | ||
947 | recv_packetnum, sent_packetnum); | ||
948 | |||
949 | if (connection->status == LUDP_ESTABLISHED) | ||
950 | return handle_SYNC3(ludp, connection_id, counter, recv_packetnum, | ||
951 | sent_packetnum, req_packets, number); | ||
952 | |||
953 | return 0; | ||
954 | } | ||
955 | |||
956 | /* | ||
957 | * Add a packet to the received buffer and set the recv_packetnum of the | ||
958 | * connection to its proper value. | ||
959 | * | ||
960 | * return 1 if data was too big. | ||
961 | * return 0 if not. | ||
962 | */ | ||
963 | static int add_recv(Lossless_UDP *ludp, int connection_id, uint32_t data_num, uint8_t *data, uint16_t size) | ||
964 | { | ||
965 | if (size > MAX_DATA_SIZE) | ||
966 | return 1; | ||
967 | |||
968 | Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); | ||
969 | uint32_t i; | ||
970 | uint32_t test = data_num - connection->recv_packetnum; | ||
971 | |||
972 | if (test > MAX_QUEUE_NUM) | ||
973 | return 0; | ||
974 | |||
975 | if (test > connection->recvbuffer_length) { | ||
976 | if (connection->confirmed == 0) | ||
977 | return 0; | ||
978 | |||
979 | uint32_t len = resize_queue(&connection->recvbuffer, connection->recvbuffer_length, test * 2, | ||
980 | connection->successful_read, connection->successful_read + connection->recvbuffer_length); | ||
981 | |||
982 | if (len == (uint32_t)~0) | ||
983 | return 0; | ||
984 | |||
985 | connection->recvbuffer_length = len; | ||
986 | } | ||
987 | |||
988 | uint32_t maxnum = connection->successful_read + connection->recvbuffer_length; | ||
989 | uint32_t sent_packet = data_num - connection->osent_packetnum; | ||
990 | |||
991 | for (i = connection->recv_packetnum; i != maxnum; ++i) { | ||
992 | if (i == data_num) { | ||
993 | memcpy(connection->recvbuffer[data_num % connection->recvbuffer_length].data, data, size); | ||
994 | |||
995 | connection->recvbuffer[data_num % connection->recvbuffer_length].size = size; | ||
996 | connection->last_recvdata = current_time(); | ||
997 | |||
998 | if (sent_packet < connection->recvbuffer_length) | ||
999 | connection->osent_packetnum = data_num; | ||
1000 | |||
1001 | break; | ||
1002 | } | ||
1003 | } | ||
1004 | |||
1005 | for (i = connection->recv_packetnum; i != maxnum; ++i) { | ||
1006 | if (connection->recvbuffer[i % connection->recvbuffer_length].size != 0) | ||
1007 | connection->recv_packetnum = i; | ||
1008 | else | ||
1009 | break; | ||
1010 | } | ||
1011 | |||
1012 | return 0; | ||
1013 | } | ||
1014 | |||
1015 | static int handle_data(void *object, IP_Port source, uint8_t *packet, uint32_t length) | ||
1016 | { | ||
1017 | Lossless_UDP *ludp = object; | ||
1018 | int connection_id = getconnection_id(ludp, source); | ||
1019 | |||
1020 | /* Drop the data packet if connection is not connected. */ | ||
1021 | if (connection_id == -1) | ||
1022 | return 1; | ||
1023 | |||
1024 | if (tox_array_get(&ludp->connections, connection_id, Connection).status != LUDP_ESTABLISHED) | ||
1025 | return 1; | ||
1026 | |||
1027 | if (length > 1 + 4 + MAX_DATA_SIZE || length < 1 + 4 + 1) | ||
1028 | return 1; | ||
1029 | |||
1030 | uint32_t temp; | ||
1031 | uint32_t number; | ||
1032 | uint16_t size = length - 1 - 4; | ||
1033 | |||
1034 | memcpy(&temp, packet + 1, 4); | ||
1035 | number = ntohl(temp); | ||
1036 | |||
1037 | return add_recv(ludp, connection_id, number, packet + 5, size); | ||
1038 | } | ||
1039 | |||
1040 | /* | ||
1041 | * END of packet handling functions. | ||
1042 | */ | ||
1043 | |||
1044 | Lossless_UDP *new_lossless_udp(Networking_Core *net) | ||
1045 | { | ||
1046 | if (net == NULL) | ||
1047 | return NULL; | ||
1048 | |||
1049 | Lossless_UDP *temp = calloc(1, sizeof(Lossless_UDP)); | ||
1050 | |||
1051 | if (temp == NULL) | ||
1052 | return NULL; | ||
1053 | |||
1054 | tox_array_init(&temp->connections, sizeof(Connection)); | ||
1055 | |||
1056 | temp->net = net; | ||
1057 | networking_registerhandler(net, NET_PACKET_HANDSHAKE, &handle_handshake, temp); | ||
1058 | networking_registerhandler(net, NET_PACKET_SYNC, &handle_SYNC, temp); | ||
1059 | networking_registerhandler(net, NET_PACKET_DATA, &handle_data, temp); | ||
1060 | return temp; | ||
1061 | } | ||
1062 | |||
1063 | /* | ||
1064 | * Send handshake requests. | ||
1065 | * Handshake packets are sent at the same rate as SYNC packets. | ||
1066 | */ | ||
1067 | static void do_new(Lossless_UDP *ludp) | ||
1068 | { | ||
1069 | uint64_t temp_time = current_time(); | ||
1070 | |||
1071 | tox_array_for_each(&ludp->connections, Connection, tmp) { | ||
1072 | if (tmp->status == LUDP_HANDSHAKE_SENDING && (tmp->last_sent + (1000000ULL / tmp->SYNC_rate)) <= temp_time) { | ||
1073 | send_handshake(ludp, tmp->ip_port, tmp->handshake_id1, 0); | ||
1074 | tmp->last_sent = temp_time; | ||
1075 | } | ||
1076 | |||
1077 | /* kill all timed out connections */ | ||
1078 | if (tmp->status != LUDP_NO_CONNECTION && (tmp->last_recvSYNC + tmp->timeout * 1000000ULL) < temp_time | ||
1079 | && tmp->status != LUDP_TIMED_OUT) { | ||
1080 | tmp->status = LUDP_TIMED_OUT; | ||
1081 | /* kill_connection(i); */ | ||
1082 | } | ||
1083 | |||
1084 | if (tmp->status != LUDP_NO_CONNECTION && tmp->killat < temp_time) | ||
1085 | tmp->status = LUDP_TIMED_OUT; | ||
1086 | |||
1087 | if (tmp->inbound == LUDP_CONNECTION_INBOUND && tmp->status == LUDP_TIMED_OUT) | ||
1088 | kill_connection(ludp, tmp_i); | ||
1089 | } | ||
1090 | } | ||
1091 | |||
1092 | static void do_SYNC(Lossless_UDP *ludp) | ||
1093 | { | ||
1094 | uint64_t temp_time = current_time(); | ||
1095 | |||
1096 | tox_array_for_each(&ludp->connections, Connection, tmp) { | ||
1097 | if (tmp->status == LUDP_NOT_CONFIRMED || tmp->status == LUDP_ESTABLISHED) | ||
1098 | if ((tmp->last_SYNC + (1000000ULL / tmp->SYNC_rate)) <= temp_time) { | ||
1099 | send_SYNC(ludp, tmp_i); | ||
1100 | tmp->last_SYNC = temp_time; | ||
1101 | } | ||
1102 | } | ||
1103 | } | ||
1104 | |||
1105 | static void do_data(Lossless_UDP *ludp) | ||
1106 | { | ||
1107 | uint64_t j; | ||
1108 | uint64_t temp_time = current_time(); | ||
1109 | |||
1110 | tox_array_for_each(&ludp->connections, Connection, tmp) { | ||
1111 | if (tmp->status == LUDP_ESTABLISHED && sendqueue(ludp, tmp_i) != 0 && | ||
1112 | (tmp->last_sent + (1000000ULL / tmp->data_rate)) <= temp_time) { | ||
1113 | for (j = tmp->last_sent; j < temp_time; j += (1000000ULL / tmp->data_rate)) | ||
1114 | if (send_DATA(ludp, tmp_i) <= 0) | ||
1115 | break; | ||
1116 | |||
1117 | tmp->last_sent = temp_time; | ||
1118 | |||
1119 | } | ||
1120 | } | ||
1121 | } | ||
1122 | |||
1123 | |||
1124 | |||
1125 | /* | ||
1126 | * Automatically adjusts send rates of packets for optimal transmission. | ||
1127 | * | ||
1128 | * TODO: Flow control. | ||
1129 | */ | ||
1130 | static void adjust_rates(Lossless_UDP *ludp) | ||
1131 | { | ||
1132 | uint64_t temp_time = current_time(); | ||
1133 | |||
1134 | tox_array_for_each(&ludp->connections, Connection, tmp) { | ||
1135 | if (tmp->status == LUDP_HANDSHAKE_SENDING || tmp->status == LUDP_NOT_CONFIRMED) | ||
1136 | tmp->SYNC_rate = MAX_SYNC_RATE; | ||
1137 | |||
1138 | if (tmp->status == LUDP_ESTABLISHED) { | ||
1139 | if (sendqueue(ludp, tmp_i) != 0) { | ||
1140 | tmp->SYNC_rate = MAX_SYNC_RATE; | ||
1141 | } else if (tmp->last_recvdata + 200000ULL > temp_time) { /* 200 ms */ | ||
1142 | tmp->SYNC_rate = MAX_SYNC_RATE; | ||
1143 | } else { | ||
1144 | tmp->SYNC_rate = SYNC_RATE; | ||
1145 | } | ||
1146 | } | ||
1147 | } | ||
1148 | } | ||
1149 | |||
1150 | /* Call this function a couple times per second. It is the main loop. */ | ||
1151 | void do_lossless_udp(Lossless_UDP *ludp) | ||
1152 | { | ||
1153 | do_new(ludp); | ||
1154 | do_SYNC(ludp); | ||
1155 | do_data(ludp); | ||
1156 | adjust_rates(ludp); | ||
1157 | } | ||
1158 | |||
1159 | void kill_lossless_udp(Lossless_UDP *ludp) | ||
1160 | { | ||
1161 | uint32_t i; | ||
1162 | |||
1163 | for (i = 0; i < ludp->connections.len; ++i) | ||
1164 | kill_connection(ludp, i); | ||
1165 | |||
1166 | tox_array_delete(&ludp->connections); | ||
1167 | free(ludp); | ||
1168 | } | ||
diff --git a/toxcore/Lossless_UDP.h b/toxcore/Lossless_UDP.h deleted file mode 100644 index b23d602a..00000000 --- a/toxcore/Lossless_UDP.h +++ /dev/null | |||
@@ -1,261 +0,0 @@ | |||
1 | /* Lossless_UDP.h | ||
2 | * | ||
3 | * An implementation of the Lossless_UDP protocol as seen in http://wiki.tox.im/index.php/Lossless_UDP | ||
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 LOSSLESS_UDP_H | ||
25 | #define LOSSLESS_UDP_H | ||
26 | |||
27 | #include "network.h" | ||
28 | #include "misc_tools.h" | ||
29 | |||
30 | |||
31 | /* Maximum length of the data in the data packets. */ | ||
32 | #define MAX_DATA_SIZE 1024 | ||
33 | |||
34 | /* Maximum data packets in sent and receive queues. */ | ||
35 | #define MAX_QUEUE_NUM 1024 | ||
36 | #define DEFAULT_QUEUE_NUM 4 | ||
37 | |||
38 | /* Maximum number of data packets in the buffer. */ | ||
39 | #define MAX_REQUESTED_PACKETS 256 | ||
40 | |||
41 | /* Timeout per connection is randomly set between CONNECTION_TIMEOUT and 2*CONNECTION_TIMEOUT. */ | ||
42 | #define CONNECTION_TIMEOUT 5 | ||
43 | |||
44 | /* Initial amount of sync/handshake packets to send per second. */ | ||
45 | #define SYNC_RATE 2 | ||
46 | |||
47 | /* Initial send rate of data. */ | ||
48 | #define DATA_SYNC_RATE 30 | ||
49 | |||
50 | typedef struct { | ||
51 | uint8_t data[MAX_DATA_SIZE]; | ||
52 | uint16_t size; | ||
53 | } Data; | ||
54 | |||
55 | #define LUDP_NO_CONNECTION 0 | ||
56 | #define LUDP_HANDSHAKE_SENDING 1 | ||
57 | #define LUDP_NOT_CONFIRMED 2 | ||
58 | #define LUDP_ESTABLISHED 3 | ||
59 | #define LUDP_TIMED_OUT 4 | ||
60 | |||
61 | typedef struct { | ||
62 | IP_Port ip_port; | ||
63 | |||
64 | /* | ||
65 | * return LUDP_NO_CONNECTION if connection is dead. | ||
66 | * return LUDP_HANDSHAKE_SENDING if attempting handshake. | ||
67 | * return LUDP_NOT_CONFIRMED if handshake is done (we start sending SYNC packets). | ||
68 | * return LUDP_ESTABLISHED if we are sending SYNC packets and can send data. | ||
69 | * return LUDP_TIMED_OUT if the connection has timed out. | ||
70 | */ | ||
71 | uint8_t status; | ||
72 | |||
73 | /* | ||
74 | * return 0 if connection was not initiated by someone else. | ||
75 | * return 1 if incoming_connection() has returned. | ||
76 | * return 2 if it has not. | ||
77 | */ | ||
78 | uint8_t inbound; | ||
79 | |||
80 | uint16_t SYNC_rate; /* Current SYNC packet send rate packets per second. */ | ||
81 | uint32_t data_rate; /* Current data packet send rate packets per second. */ | ||
82 | |||
83 | uint64_t last_SYNC; /* Time our last SYNC packet was sent. */ | ||
84 | uint64_t last_sent; /* Time our last data or handshake packet was sent. */ | ||
85 | uint64_t last_recvSYNC; /* Time we last received a SYNC packet from the other. */ | ||
86 | uint64_t last_recvdata; /* Time we last received a DATA packet from the other. */ | ||
87 | uint64_t killat; /* Time to kill the connection. */ | ||
88 | |||
89 | Data *sendbuffer; /* packet send buffer. */ | ||
90 | uint32_t sendbuffer_length; | ||
91 | Data *recvbuffer; /* packet receive buffer. */ | ||
92 | uint32_t recvbuffer_length; | ||
93 | uint32_t handshake_id1; | ||
94 | uint32_t handshake_id2; | ||
95 | |||
96 | /* Number of data packets received (also used as handshake_id1). */ | ||
97 | uint32_t recv_packetnum; | ||
98 | |||
99 | /* Number of packets received by the other peer. */ | ||
100 | uint32_t orecv_packetnum; | ||
101 | |||
102 | /* Number of data packets sent. */ | ||
103 | uint32_t sent_packetnum; | ||
104 | |||
105 | /* Number of packets sent by the other peer. */ | ||
106 | uint32_t osent_packetnum; | ||
107 | |||
108 | /* Number of latest packet written onto the sendbuffer. */ | ||
109 | uint32_t sendbuff_packetnum; | ||
110 | |||
111 | /* We know all packets before that number were successfully sent. */ | ||
112 | uint32_t successful_sent; | ||
113 | |||
114 | /* Packet number of last packet read with the read_packet function. */ | ||
115 | uint32_t successful_read; | ||
116 | |||
117 | /* List of currently requested packet numbers(by the other person). */ | ||
118 | uint32_t req_packets[MAX_REQUESTED_PACKETS]; | ||
119 | |||
120 | /* Total number of currently requested packets(by the other person). */ | ||
121 | uint16_t num_req_paquets; | ||
122 | |||
123 | uint8_t recv_counter; | ||
124 | uint8_t send_counter; | ||
125 | uint8_t timeout; /* connection timeout in seconds. */ | ||
126 | |||
127 | /* Is the connection confirmed or not? 1 if yes, 0 if no */ | ||
128 | uint8_t confirmed; | ||
129 | } Connection; | ||
130 | |||
131 | typedef struct { | ||
132 | Networking_Core *net; | ||
133 | |||
134 | tox_array connections; | ||
135 | |||
136 | /* Table of random numbers used in handshake_id. */ | ||
137 | /* IPv6 (16) + port (2)*/ | ||
138 | uint32_t randtable[18][256]; | ||
139 | } Lossless_UDP; | ||
140 | |||
141 | /* | ||
142 | * Initialize a new connection to ip_port. | ||
143 | * | ||
144 | * return an integer corresponding to the connection id. | ||
145 | * return -1 if it could not initialize the connection. | ||
146 | * return number if there already was an existing connection to that ip_port. | ||
147 | */ | ||
148 | int new_connection(Lossless_UDP *ludp, IP_Port ip_port); | ||
149 | |||
150 | /* | ||
151 | * Get connection id from IP_Port. | ||
152 | * | ||
153 | * return -1 if there are no connections like we are looking for. | ||
154 | * return id if it found it . | ||
155 | */ | ||
156 | int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port); | ||
157 | |||
158 | /* | ||
159 | * return an integer corresponding to the next connection in our incoming connection list with at least numpackets in the recieve queue. | ||
160 | * return -1 if there are no new incoming connections in the list. | ||
161 | */ | ||
162 | int incoming_connection(Lossless_UDP *ludp, uint32_t numpackets); | ||
163 | |||
164 | /* return -1 if it could not kill the connection. | ||
165 | * return 0 if killed successfully. | ||
166 | */ | ||
167 | int kill_connection(Lossless_UDP *ludp, int connection_id); | ||
168 | |||
169 | /* | ||
170 | * timeout connection in seconds seconds. | ||
171 | * | ||
172 | * return -1 if it can not kill the connection. | ||
173 | * return 0 if it will kill it. | ||
174 | */ | ||
175 | int timeout_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds); | ||
176 | |||
177 | |||
178 | /* Check if connection is confirmed. | ||
179 | * | ||
180 | * returns 1 if yes. | ||
181 | * returns 0 if no. | ||
182 | */ | ||
183 | int connection_confirmed(Lossless_UDP *ludp, int connection_id); | ||
184 | |||
185 | /* Confirm an incoming connection. | ||
186 | * Also disables the auto kill timeout on incomming connections. | ||
187 | * | ||
188 | * return 0 on success | ||
189 | * return -1 on failure. | ||
190 | */ | ||
191 | int confirm_connection(Lossless_UDP *ludp, int connection_id); | ||
192 | |||
193 | /* returns the ip_port of the corresponding connection. | ||
194 | * return 0 if there is no such connection. | ||
195 | */ | ||
196 | IP_Port connection_ip(Lossless_UDP *ludp, int connection_id); | ||
197 | |||
198 | /* returns the id of the next packet in the queue. | ||
199 | * return -1 if no packet in queue. | ||
200 | */ | ||
201 | uint8_t id_packet(Lossless_UDP *ludp, int connection_id); | ||
202 | |||
203 | /* return 0 if there is no received data in the buffer. | ||
204 | * return length of received packet if successful. | ||
205 | */ | ||
206 | int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data); | ||
207 | |||
208 | /* Like read_packet() but does leaves the queue as is. | ||
209 | * return 0 if there is no received data in the buffer. | ||
210 | * return length of received packet if successful. | ||
211 | */ | ||
212 | int read_packet_silent(Lossless_UDP *ludp, int connection_id, uint8_t *data); | ||
213 | |||
214 | /* Discard the next packet to be read from the queue | ||
215 | * return 0 if success. | ||
216 | * return -1 if failure. | ||
217 | */ | ||
218 | int discard_packet(Lossless_UDP *ludp, int connection_id); | ||
219 | |||
220 | /* returns the number of packet slots left in the sendbuffer. | ||
221 | * return 0 if failure. | ||
222 | */ | ||
223 | uint32_t num_free_sendqueue_slots(Lossless_UDP *ludp, int connection_id); | ||
224 | |||
225 | /* return 0 if data could not be put in packet queue. | ||
226 | * return 1 if data was put into the queue. | ||
227 | */ | ||
228 | int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t length); | ||
229 | |||
230 | /* return number of packets in the queue waiting to be successfully sent. */ | ||
231 | uint32_t sendqueue(Lossless_UDP *ludp, int connection_id); | ||
232 | |||
233 | /* return number of packets in all queues waiting to be successfully sent. */ | ||
234 | uint32_t sendqueue_total(Lossless_UDP *ludp); | ||
235 | |||
236 | /* | ||
237 | * return number of packets in the queue waiting to be successfully | ||
238 | * read with read_packet(...). | ||
239 | */ | ||
240 | uint32_t recvqueue(Lossless_UDP *ludp, int connection_id); | ||
241 | |||
242 | /* Check if connection is connected: | ||
243 | * | ||
244 | * return LUDP_NO_CONNECTION if not. | ||
245 | * return LUDP_HANDSHAKE_SENDING if attempting handshake. | ||
246 | * return LUDP_NOT_CONFIRMED if handshake is done. | ||
247 | * return LUDP_ESTABLISHED if fully connected. | ||
248 | * return LUDP_TIMED_OUT if timed out and wating to be killed. | ||
249 | */ | ||
250 | int is_connected(Lossless_UDP *ludp, int connection_id); | ||
251 | |||
252 | /* Call this function a couple times per second. It is the main loop. */ | ||
253 | void do_lossless_udp(Lossless_UDP *ludp); | ||
254 | |||
255 | /* This function sets up LosslessUDP packet handling. */ | ||
256 | Lossless_UDP *new_lossless_udp(Networking_Core *net); | ||
257 | |||
258 | void kill_lossless_udp(Lossless_UDP *ludp); | ||
259 | |||
260 | |||
261 | #endif | ||
diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc index 5f9ab0d7..0760952a 100644 --- a/toxcore/Makefile.inc +++ b/toxcore/Makefile.inc | |||
@@ -9,8 +9,10 @@ libtoxcore_la_SOURCES = ../toxcore/DHT.h \ | |||
9 | ../toxcore/DHT.c \ | 9 | ../toxcore/DHT.c \ |
10 | ../toxcore/network.h \ | 10 | ../toxcore/network.h \ |
11 | ../toxcore/network.c \ | 11 | ../toxcore/network.c \ |
12 | ../toxcore/Lossless_UDP.h \ | 12 | ../toxcore/crypto_core.h \ |
13 | ../toxcore/Lossless_UDP.c \ | 13 | ../toxcore/crypto_core.c \ |
14 | ../toxcore/ping_array.h \ | ||
15 | ../toxcore/ping_array.c \ | ||
14 | ../toxcore/net_crypto.h \ | 16 | ../toxcore/net_crypto.h \ |
15 | ../toxcore/net_crypto.c \ | 17 | ../toxcore/net_crypto.c \ |
16 | ../toxcore/friend_requests.h \ | 18 | ../toxcore/friend_requests.h \ |
@@ -52,6 +54,7 @@ libtoxcore_la_LDFLAGS = $(TOXCORE_LT_LDFLAGS) \ | |||
52 | $(EXTRA_LT_LDFLAGS) \ | 54 | $(EXTRA_LT_LDFLAGS) \ |
53 | $(LIBSODIUM_LDFLAGS) \ | 55 | $(LIBSODIUM_LDFLAGS) \ |
54 | $(NACL_LDFLAGS) \ | 56 | $(NACL_LDFLAGS) \ |
57 | $(RT_LIBS) \ | ||
55 | $(WINSOCK2_LIBS) | 58 | $(WINSOCK2_LIBS) |
56 | 59 | ||
57 | libtoxcore_la_LIBADD = $(LIBSODIUM_LIBS) \ | 60 | libtoxcore_la_LIBADD = $(LIBSODIUM_LIBS) \ |
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index f5ed14b1..28c8845a 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c | |||
@@ -38,6 +38,8 @@ | |||
38 | static void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status); | 38 | static void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status); |
39 | static int write_cryptpacket_id(Messenger *m, int32_t friendnumber, uint8_t packet_id, uint8_t *data, uint32_t length); | 39 | static int write_cryptpacket_id(Messenger *m, int32_t friendnumber, uint8_t packet_id, uint8_t *data, uint32_t length); |
40 | 40 | ||
41 | static IP_Port get_friend_ipport(Messenger *m, int32_t friendnumber); | ||
42 | |||
41 | // friend_not_valid determines if the friendnumber passed is valid in the Messenger object | 43 | // friend_not_valid determines if the friendnumber passed is valid in the Messenger object |
42 | static uint8_t friend_not_valid(Messenger *m, int32_t friendnumber) | 44 | static uint8_t friend_not_valid(Messenger *m, int32_t friendnumber) |
43 | { | 45 | { |
@@ -194,6 +196,21 @@ void getaddress(Messenger *m, uint8_t *address) | |||
194 | memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(nospam), &checksum, sizeof(checksum)); | 196 | memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(nospam), &checksum, sizeof(checksum)); |
195 | } | 197 | } |
196 | 198 | ||
199 | /* callback for recv TCP relay nodes. */ | ||
200 | static int tcp_relay_node_callback(void *object, uint32_t number, IP_Port ip_port, uint8_t *public_key) | ||
201 | { | ||
202 | Messenger *m = object; | ||
203 | |||
204 | if (friend_not_valid(m, number)) | ||
205 | return -1; | ||
206 | |||
207 | if (m->friendlist[number].crypt_connection_id != -1) { | ||
208 | return add_tcp_relay_peer(m->net_crypto, m->friendlist[number].crypt_connection_id, ip_port, public_key); | ||
209 | } else { | ||
210 | return add_tcp_relay(m->net_crypto, ip_port, public_key); | ||
211 | } | ||
212 | } | ||
213 | |||
197 | /* | 214 | /* |
198 | * Add a friend. | 215 | * Add a friend. |
199 | * Set the data that will be sent along with friend request. | 216 | * Set the data that will be sent along with friend request. |
@@ -213,9 +230,7 @@ void getaddress(Messenger *m, uint8_t *address) | |||
213 | */ | 230 | */ |
214 | int32_t m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length) | 231 | int32_t m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length) |
215 | { | 232 | { |
216 | if (length >= (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES | 233 | if (length > MAX_FRIEND_REQUEST_DATA_SIZE) |
217 | - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES | ||
218 | + crypto_box_ZEROBYTES)) | ||
219 | return FAERR_TOOLONG; | 234 | return FAERR_TOOLONG; |
220 | 235 | ||
221 | uint8_t client_id[crypto_box_PUBLICKEYBYTES]; | 236 | uint8_t client_id[crypto_box_PUBLICKEYBYTES]; |
@@ -278,6 +293,7 @@ int32_t m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t leng | |||
278 | m->friendlist[i].message_id = 0; | 293 | m->friendlist[i].message_id = 0; |
279 | m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */ | 294 | m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */ |
280 | memcpy(&(m->friendlist[i].friendrequest_nospam), address + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t)); | 295 | memcpy(&(m->friendlist[i].friendrequest_nospam), address + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t)); |
296 | recv_tcp_relay_handler(m->onion_c, onion_friendnum, &tcp_relay_node_callback, m, i); | ||
281 | 297 | ||
282 | if (m->numfriends == i) | 298 | if (m->numfriends == i) |
283 | ++m->numfriends; | 299 | ++m->numfriends; |
@@ -323,6 +339,7 @@ int32_t m_addfriend_norequest(Messenger *m, uint8_t *client_id) | |||
323 | m->friendlist[i].is_typing = 0; | 339 | m->friendlist[i].is_typing = 0; |
324 | m->friendlist[i].message_id = 0; | 340 | m->friendlist[i].message_id = 0; |
325 | m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */ | 341 | m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */ |
342 | recv_tcp_relay_handler(m->onion_c, onion_friendnum, &tcp_relay_node_callback, m, i); | ||
326 | 343 | ||
327 | if (m->numfriends == i) | 344 | if (m->numfriends == i) |
328 | ++m->numfriends; | 345 | ++m->numfriends; |
@@ -407,10 +424,10 @@ uint32_t m_sendmessage(Messenger *m, int32_t friendnumber, uint8_t *message, uin | |||
407 | 424 | ||
408 | uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid, uint8_t *message, uint32_t length) | 425 | uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid, uint8_t *message, uint32_t length) |
409 | { | 426 | { |
410 | if (length >= (MAX_DATA_SIZE - sizeof(theid))) | 427 | if (length >= (MAX_CRYPTO_DATA_SIZE - sizeof(theid))) |
411 | return 0; | 428 | return 0; |
412 | 429 | ||
413 | uint8_t temp[MAX_DATA_SIZE]; | 430 | uint8_t temp[MAX_CRYPTO_DATA_SIZE]; |
414 | theid = htonl(theid); | 431 | theid = htonl(theid); |
415 | memcpy(temp, &theid, sizeof(theid)); | 432 | memcpy(temp, &theid, sizeof(theid)); |
416 | memcpy(temp + sizeof(theid), message, length); | 433 | memcpy(temp + sizeof(theid), message, length); |
@@ -441,10 +458,10 @@ uint32_t m_sendaction(Messenger *m, int32_t friendnumber, uint8_t *action, uint3 | |||
441 | 458 | ||
442 | uint32_t m_sendaction_withid(Messenger *m, int32_t friendnumber, uint32_t theid, uint8_t *action, uint32_t length) | 459 | uint32_t m_sendaction_withid(Messenger *m, int32_t friendnumber, uint32_t theid, uint8_t *action, uint32_t length) |
443 | { | 460 | { |
444 | if (length >= (MAX_DATA_SIZE - sizeof(theid))) | 461 | if (length >= (MAX_CRYPTO_DATA_SIZE - sizeof(theid))) |
445 | return 0; | 462 | return 0; |
446 | 463 | ||
447 | uint8_t temp[MAX_DATA_SIZE]; | 464 | uint8_t temp[MAX_CRYPTO_DATA_SIZE]; |
448 | theid = htonl(theid); | 465 | theid = htonl(theid); |
449 | memcpy(temp, &theid, sizeof(theid)); | 466 | memcpy(temp, &theid, sizeof(theid)); |
450 | memcpy(temp + sizeof(theid), action, length); | 467 | memcpy(temp + sizeof(theid), action, length); |
@@ -690,7 +707,7 @@ static int send_user_istyping(Messenger *m, int32_t friendnumber, uint8_t is_typ | |||
690 | 707 | ||
691 | static int send_ping(Messenger *m, int32_t friendnumber) | 708 | static int send_ping(Messenger *m, int32_t friendnumber) |
692 | { | 709 | { |
693 | int ret = write_cryptpacket_id(m, friendnumber, PACKET_ID_PING, 0, 0); | 710 | int ret = write_cryptpacket_id(m, friendnumber, PACKET_ID_ALIVE, 0, 0); |
694 | 711 | ||
695 | if (ret == 1) | 712 | if (ret == 1) |
696 | m->friendlist[friendnumber].ping_lastsent = unix_time(); | 713 | m->friendlist[friendnumber].ping_lastsent = unix_time(); |
@@ -841,7 +858,7 @@ int write_cryptpacket_id(Messenger *m, int32_t friendnumber, uint8_t packet_id, | |||
841 | if (friend_not_valid(m, friendnumber)) | 858 | if (friend_not_valid(m, friendnumber)) |
842 | return 0; | 859 | return 0; |
843 | 860 | ||
844 | if (length >= MAX_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE) | 861 | if (length >= MAX_CRYPTO_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE) |
845 | return 0; | 862 | return 0; |
846 | 863 | ||
847 | uint8_t packet[length + 1]; | 864 | uint8_t packet[length + 1]; |
@@ -850,7 +867,7 @@ int write_cryptpacket_id(Messenger *m, int32_t friendnumber, uint8_t packet_id, | |||
850 | if (length != 0) | 867 | if (length != 0) |
851 | memcpy(packet + 1, data, length); | 868 | memcpy(packet + 1, data, length); |
852 | 869 | ||
853 | return write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, packet, length + 1); | 870 | return write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, packet, length + 1) != -1; |
854 | } | 871 | } |
855 | 872 | ||
856 | /**********GROUP CHATS************/ | 873 | /**********GROUP CHATS************/ |
@@ -876,7 +893,7 @@ static uint8_t groupnumber_not_valid(Messenger *m, int groupnumber) | |||
876 | /* returns valid ip port of connected friend on success | 893 | /* returns valid ip port of connected friend on success |
877 | * returns zeroed out IP_Port on failure | 894 | * returns zeroed out IP_Port on failure |
878 | */ | 895 | */ |
879 | IP_Port get_friend_ipport(Messenger *m, int32_t friendnumber) | 896 | static IP_Port get_friend_ipport(Messenger *m, int32_t friendnumber) |
880 | { | 897 | { |
881 | IP_Port zero; | 898 | IP_Port zero; |
882 | memset(&zero, 0, sizeof(zero)); | 899 | memset(&zero, 0, sizeof(zero)); |
@@ -886,10 +903,15 @@ IP_Port get_friend_ipport(Messenger *m, int32_t friendnumber) | |||
886 | 903 | ||
887 | int crypt_id = m->friendlist[friendnumber].crypt_connection_id; | 904 | int crypt_id = m->friendlist[friendnumber].crypt_connection_id; |
888 | 905 | ||
889 | if (is_cryptoconnected(m->net_crypto, crypt_id) != CRYPTO_CONN_ESTABLISHED) | 906 | uint8_t direct_connected; |
907 | |||
908 | if (crypto_connection_status(m->net_crypto, crypt_id, &direct_connected) != CRYPTO_CONN_ESTABLISHED) | ||
890 | return zero; | 909 | return zero; |
891 | 910 | ||
892 | return connection_ip(m->net_crypto->lossless_udp, m->net_crypto->crypto_connections[crypt_id].number); | 911 | if (direct_connected == 0) |
912 | return zero; | ||
913 | |||
914 | return m->net_crypto->crypto_connections[crypt_id].ip_port; | ||
893 | } | 915 | } |
894 | 916 | ||
895 | /* returns the group number of the chat with public key group_public_key. | 917 | /* returns the group number of the chat with public key group_public_key. |
@@ -1396,7 +1418,7 @@ int new_filesender(Messenger *m, int32_t friendnumber, uint64_t filesize, uint8_ | |||
1396 | int file_control(Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id, | 1418 | int file_control(Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id, |
1397 | uint8_t *data, uint16_t length) | 1419 | uint8_t *data, uint16_t length) |
1398 | { | 1420 | { |
1399 | if (length > MAX_DATA_SIZE - 3) | 1421 | if (length > MAX_CRYPTO_DATA_SIZE - 3) |
1400 | return -1; | 1422 | return -1; |
1401 | 1423 | ||
1402 | if (friend_not_valid(m, friendnumber)) | 1424 | if (friend_not_valid(m, friendnumber)) |
@@ -1413,7 +1435,7 @@ int file_control(Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8 | |||
1413 | if (send_receive > 1) | 1435 | if (send_receive > 1) |
1414 | return -1; | 1436 | return -1; |
1415 | 1437 | ||
1416 | uint8_t packet[MAX_DATA_SIZE]; | 1438 | uint8_t packet[MAX_CRYPTO_DATA_SIZE]; |
1417 | packet[0] = send_receive; | 1439 | packet[0] = send_receive; |
1418 | packet[1] = filenumber; | 1440 | packet[1] = filenumber; |
1419 | packet[2] = message_id; | 1441 | packet[2] = message_id; |
@@ -1483,7 +1505,7 @@ int file_control(Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8 | |||
1483 | */ | 1505 | */ |
1484 | int file_data(Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length) | 1506 | int file_data(Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length) |
1485 | { | 1507 | { |
1486 | if (length > MAX_DATA_SIZE - 1) | 1508 | if (length > MAX_CRYPTO_DATA_SIZE - 1) |
1487 | return -1; | 1509 | return -1; |
1488 | 1510 | ||
1489 | if (friend_not_valid(m, friendnumber)) | 1511 | if (friend_not_valid(m, friendnumber)) |
@@ -1496,7 +1518,7 @@ int file_data(Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t *d | |||
1496 | if (crypto_num_free_sendqueue_slots(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id) < MIN_SLOTS_FREE) | 1518 | if (crypto_num_free_sendqueue_slots(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id) < MIN_SLOTS_FREE) |
1497 | return -1; | 1519 | return -1; |
1498 | 1520 | ||
1499 | uint8_t packet[MAX_DATA_SIZE]; | 1521 | uint8_t packet[MAX_CRYPTO_DATA_SIZE]; |
1500 | packet[0] = filenumber; | 1522 | packet[0] = filenumber; |
1501 | memcpy(packet + 1, data, length); | 1523 | memcpy(packet + 1, data, length); |
1502 | 1524 | ||
@@ -1739,6 +1761,30 @@ static void LANdiscovery(Messenger *m) | |||
1739 | } | 1761 | } |
1740 | } | 1762 | } |
1741 | 1763 | ||
1764 | static int handle_status(void *object, int i, uint8_t status); | ||
1765 | static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len); | ||
1766 | |||
1767 | static int handle_new_connections(void *object, New_Connection *n_c) | ||
1768 | { | ||
1769 | Messenger *m = object; | ||
1770 | int friend_id = getfriend_id(m, n_c->public_key); | ||
1771 | |||
1772 | if (friend_id != -1) { | ||
1773 | if (m->friendlist[friend_id].crypt_connection_id != -1) | ||
1774 | return -1; | ||
1775 | |||
1776 | int id = accept_crypto_connection(m->net_crypto, n_c); | ||
1777 | connection_status_handler(m->net_crypto, id, &handle_status, m, friend_id); | ||
1778 | connection_data_handler(m->net_crypto, id, &handle_packet, m, friend_id); | ||
1779 | m->friendlist[friend_id].crypt_connection_id = id; | ||
1780 | set_friend_status(m, friend_id, FRIEND_CONFIRMED); | ||
1781 | return 0; | ||
1782 | } | ||
1783 | |||
1784 | return -1; | ||
1785 | } | ||
1786 | |||
1787 | |||
1742 | /* Run this at startup. */ | 1788 | /* Run this at startup. */ |
1743 | Messenger *new_messenger(uint8_t ipv6enabled) | 1789 | Messenger *new_messenger(uint8_t ipv6enabled) |
1744 | { | 1790 | { |
@@ -1756,26 +1802,28 @@ Messenger *new_messenger(uint8_t ipv6enabled) | |||
1756 | return NULL; | 1802 | return NULL; |
1757 | } | 1803 | } |
1758 | 1804 | ||
1759 | m->net_crypto = new_net_crypto(m->net); | 1805 | m->dht = new_DHT(m->net); |
1760 | 1806 | ||
1761 | if (m->net_crypto == NULL) { | 1807 | if (m->dht == NULL) { |
1762 | kill_networking(m->net); | 1808 | kill_networking(m->net); |
1763 | free(m); | 1809 | free(m); |
1764 | return NULL; | 1810 | return NULL; |
1765 | } | 1811 | } |
1766 | 1812 | ||
1767 | m->dht = new_DHT(m->net_crypto); | 1813 | m->net_crypto = new_net_crypto(m->dht); |
1768 | 1814 | ||
1769 | if (m->dht == NULL) { | 1815 | if (m->net_crypto == NULL) { |
1770 | kill_net_crypto(m->net_crypto); | ||
1771 | kill_networking(m->net); | 1816 | kill_networking(m->net); |
1817 | kill_DHT(m->dht); | ||
1772 | free(m); | 1818 | free(m); |
1773 | return NULL; | 1819 | return NULL; |
1774 | } | 1820 | } |
1775 | 1821 | ||
1822 | new_connection_handler(m->net_crypto, &handle_new_connections, m); | ||
1823 | |||
1776 | m->onion = new_onion(m->dht); | 1824 | m->onion = new_onion(m->dht); |
1777 | m->onion_a = new_onion_announce(m->dht); | 1825 | m->onion_a = new_onion_announce(m->dht); |
1778 | m->onion_c = new_onion_client(m->dht); | 1826 | m->onion_c = new_onion_client(m->net_crypto); |
1779 | 1827 | ||
1780 | if (!(m->onion && m->onion_a && m->onion_c)) { | 1828 | if (!(m->onion && m->onion_a && m->onion_c)) { |
1781 | kill_onion(m->onion); | 1829 | kill_onion(m->onion); |
@@ -1814,9 +1862,15 @@ void kill_messenger(Messenger *m) | |||
1814 | kill_onion(m->onion); | 1862 | kill_onion(m->onion); |
1815 | kill_onion_announce(m->onion_a); | 1863 | kill_onion_announce(m->onion_a); |
1816 | kill_onion_client(m->onion_c); | 1864 | kill_onion_client(m->onion_c); |
1817 | kill_DHT(m->dht); | ||
1818 | kill_net_crypto(m->net_crypto); | 1865 | kill_net_crypto(m->net_crypto); |
1866 | kill_DHT(m->dht); | ||
1819 | kill_networking(m->net); | 1867 | kill_networking(m->net); |
1868 | |||
1869 | for (i = 0; i < m->numfriends; ++i) { | ||
1870 | if (m->friendlist[i].statusmessage) | ||
1871 | free(m->friendlist[i].statusmessage); | ||
1872 | } | ||
1873 | |||
1820 | free(m->friendlist); | 1874 | free(m->friendlist); |
1821 | free(m); | 1875 | free(m); |
1822 | } | 1876 | } |
@@ -1839,379 +1893,395 @@ static void check_friend_request_timed_out(Messenger *m, uint32_t i, uint64_t t) | |||
1839 | } | 1893 | } |
1840 | } | 1894 | } |
1841 | 1895 | ||
1842 | /* TODO: Make this function not suck. */ | 1896 | static int handle_status(void *object, int i, uint8_t status) |
1843 | void do_friends(Messenger *m) | ||
1844 | { | 1897 | { |
1845 | uint32_t i; | ||
1846 | int len; | ||
1847 | uint8_t temp[MAX_DATA_SIZE]; | ||
1848 | uint64_t temp_time = unix_time(); | 1898 | uint64_t temp_time = unix_time(); |
1899 | Messenger *m = object; | ||
1849 | 1900 | ||
1850 | for (i = 0; i < m->numfriends; ++i) { | 1901 | if (status) { /* Went online. */ |
1851 | if (m->friendlist[i].status == FRIEND_ADDED) { | 1902 | set_friend_status(m, i, FRIEND_ONLINE); |
1852 | int fr = send_friendrequest(m->onion_c, m->friendlist[i].client_id, m->friendlist[i].friendrequest_nospam, | 1903 | m->friendlist[i].name_sent = 0; |
1853 | m->friendlist[i].info, | 1904 | m->friendlist[i].userstatus_sent = 0; |
1854 | m->friendlist[i].info_size); | 1905 | m->friendlist[i].statusmessage_sent = 0; |
1906 | m->friendlist[i].ping_lastrecv = temp_time; | ||
1907 | } else { /* Went offline. */ | ||
1908 | m->friendlist[i].crypt_connection_id = -1; | ||
1855 | 1909 | ||
1856 | if (fr >= 0) { | 1910 | if (m->friendlist[i].status == FRIEND_ONLINE) { |
1857 | set_friend_status(m, i, FRIEND_REQUESTED); | 1911 | set_friend_status(m, i, FRIEND_CONFIRMED); |
1858 | m->friendlist[i].friendrequest_lastsent = temp_time; | ||
1859 | } | ||
1860 | } | 1912 | } |
1913 | } | ||
1861 | 1914 | ||
1862 | if (m->friendlist[i].status == FRIEND_REQUESTED | 1915 | return 0; |
1863 | || m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online. */ | 1916 | } |
1864 | if (m->friendlist[i].status == FRIEND_REQUESTED) { | ||
1865 | /* If we didn't connect to friend after successfully sending him a friend request the request is deemed | ||
1866 | * unsuccessful so we set the status back to FRIEND_ADDED and try again. | ||
1867 | */ | ||
1868 | check_friend_request_timed_out(m, i, temp_time); | ||
1869 | } | ||
1870 | 1917 | ||
1871 | IP_Port friendip; | 1918 | static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) |
1872 | int friendok = onion_getfriendip(m->onion_c, m->friendlist[i].onion_friendnum, &friendip); | 1919 | { |
1920 | if (len == 0) | ||
1921 | return -1; | ||
1873 | 1922 | ||
1874 | switch (is_cryptoconnected(m->net_crypto, m->friendlist[i].crypt_connection_id)) { | 1923 | Messenger *m = object; |
1875 | case CRYPTO_CONN_NO_CONNECTION: | 1924 | uint64_t temp_time = unix_time(); |
1876 | if (friendok == 1) | 1925 | uint8_t packet_id = temp[0]; |
1877 | m->friendlist[i].crypt_connection_id = crypto_connect(m->net_crypto, m->friendlist[i].client_id, friendip); | 1926 | uint8_t *data = temp + 1; |
1927 | uint32_t data_length = len - 1; | ||
1878 | 1928 | ||
1879 | break; | 1929 | if (m->friendlist[i].status != FRIEND_ONLINE) |
1930 | return -1; | ||
1880 | 1931 | ||
1881 | case CRYPTO_CONN_ESTABLISHED: /* Connection is established. */ | 1932 | switch (packet_id) { |
1882 | set_friend_status(m, i, FRIEND_ONLINE); | 1933 | case PACKET_ID_ALIVE: { |
1883 | m->friendlist[i].name_sent = 0; | 1934 | m->friendlist[i].ping_lastrecv = temp_time; |
1884 | m->friendlist[i].userstatus_sent = 0; | 1935 | break; |
1885 | m->friendlist[i].statusmessage_sent = 0; | 1936 | } |
1886 | m->friendlist[i].ping_lastrecv = temp_time; | ||
1887 | break; | ||
1888 | 1937 | ||
1889 | case CRYPTO_CONN_TIMED_OUT: | 1938 | case PACKET_ID_NICKNAME: { |
1890 | crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); | 1939 | if (data_length > MAX_NAME_LENGTH || data_length == 0) |
1891 | m->friendlist[i].crypt_connection_id = -1; | 1940 | break; |
1892 | break; | ||
1893 | 1941 | ||
1894 | default: | 1942 | /* Make sure the NULL terminator is present. */ |
1895 | break; | 1943 | uint8_t data_terminated[data_length + 1]; |
1896 | } | 1944 | memcpy(data_terminated, data, data_length); |
1945 | data_terminated[data_length] = 0; | ||
1946 | |||
1947 | /* inform of namechange before we overwrite the old name */ | ||
1948 | if (m->friend_namechange) | ||
1949 | m->friend_namechange(m, i, data_terminated, data_length, m->friend_namechange_userdata); | ||
1950 | |||
1951 | memcpy(m->friendlist[i].name, data_terminated, data_length); | ||
1952 | m->friendlist[i].name_length = data_length; | ||
1953 | |||
1954 | break; | ||
1897 | } | 1955 | } |
1898 | 1956 | ||
1899 | while (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */ | 1957 | case PACKET_ID_STATUSMESSAGE: { |
1900 | if (m->friendlist[i].name_sent == 0) { | 1958 | if (data_length == 0 || data_length > MAX_STATUSMESSAGE_LENGTH) |
1901 | if (m_sendname(m, i, m->name, m->name_length)) | 1959 | break; |
1902 | m->friendlist[i].name_sent = 1; | ||
1903 | } | ||
1904 | 1960 | ||
1905 | if (m->friendlist[i].statusmessage_sent == 0) { | 1961 | /* Make sure the NULL terminator is present. */ |
1906 | if (send_statusmessage(m, i, m->statusmessage, m->statusmessage_length)) | 1962 | uint8_t data_terminated[data_length + 1]; |
1907 | m->friendlist[i].statusmessage_sent = 1; | 1963 | memcpy(data_terminated, data, data_length); |
1908 | } | 1964 | data_terminated[data_length] = 0; |
1909 | 1965 | ||
1910 | if (m->friendlist[i].userstatus_sent == 0) { | 1966 | if (m->friend_statusmessagechange) |
1911 | if (send_userstatus(m, i, m->userstatus)) | 1967 | m->friend_statusmessagechange(m, i, data_terminated, data_length, |
1912 | m->friendlist[i].userstatus_sent = 1; | 1968 | m->friend_statuschange_userdata); |
1913 | } | ||
1914 | 1969 | ||
1915 | if (m->friendlist[i].user_istyping_sent == 0) { | 1970 | set_friend_statusmessage(m, i, data_terminated, data_length); |
1916 | if (send_user_istyping(m, i, m->friendlist[i].user_istyping)) | 1971 | break; |
1917 | m->friendlist[i].user_istyping_sent = 1; | 1972 | } |
1918 | } | ||
1919 | 1973 | ||
1920 | if (m->friendlist[i].ping_lastsent + FRIEND_PING_INTERVAL < temp_time) { | 1974 | case PACKET_ID_USERSTATUS: { |
1921 | send_ping(m, i); | 1975 | if (data_length != 1) |
1922 | } | 1976 | break; |
1923 | 1977 | ||
1924 | len = read_cryptpacket(m->net_crypto, m->friendlist[i].crypt_connection_id, temp); | 1978 | USERSTATUS status = data[0]; |
1925 | 1979 | ||
1926 | if (len > 0) { | 1980 | if (status >= USERSTATUS_INVALID) |
1927 | uint8_t packet_id = temp[0]; | 1981 | break; |
1928 | uint8_t *data = temp + 1; | ||
1929 | uint32_t data_length = len - 1; | ||
1930 | 1982 | ||
1931 | switch (packet_id) { | 1983 | if (m->friend_userstatuschange) |
1932 | case PACKET_ID_PING: { | 1984 | m->friend_userstatuschange(m, i, status, m->friend_userstatuschange_userdata); |
1933 | m->friendlist[i].ping_lastrecv = temp_time; | ||
1934 | break; | ||
1935 | } | ||
1936 | 1985 | ||
1937 | case PACKET_ID_NICKNAME: { | 1986 | set_friend_userstatus(m, i, status); |
1938 | if (data_length > MAX_NAME_LENGTH || data_length == 0) | 1987 | break; |
1939 | break; | 1988 | } |
1940 | 1989 | ||
1941 | /* Make sure the NULL terminator is present. */ | 1990 | case PACKET_ID_TYPING: { |
1942 | uint8_t data_terminated[data_length + 1]; | 1991 | if (data_length != 1) |
1943 | memcpy(data_terminated, data, data_length); | 1992 | break; |
1944 | data_terminated[data_length] = 0; | ||
1945 | 1993 | ||
1946 | /* inform of namechange before we overwrite the old name */ | 1994 | uint8_t typing = data[0]; |
1947 | if (m->friend_namechange) | ||
1948 | m->friend_namechange(m, i, data_terminated, data_length, m->friend_namechange_userdata); | ||
1949 | 1995 | ||
1950 | memcpy(m->friendlist[i].name, data_terminated, data_length); | 1996 | set_friend_typing(m, i, typing); |
1951 | m->friendlist[i].name_length = data_length; | ||
1952 | 1997 | ||
1953 | break; | 1998 | if (m->friend_typingchange) |
1954 | } | 1999 | m->friend_typingchange(m, i, typing, m->friend_typingchange_userdata); |
1955 | 2000 | ||
1956 | case PACKET_ID_STATUSMESSAGE: { | 2001 | break; |
1957 | if (data_length == 0 || data_length > MAX_STATUSMESSAGE_LENGTH) | 2002 | } |
1958 | break; | ||
1959 | 2003 | ||
1960 | /* Make sure the NULL terminator is present. */ | 2004 | case PACKET_ID_MESSAGE: { |
1961 | uint8_t data_terminated[data_length + 1]; | 2005 | uint8_t *message_id = data; |
1962 | memcpy(data_terminated, data, data_length); | 2006 | uint8_t message_id_length = 4; |
1963 | data_terminated[data_length] = 0; | ||
1964 | 2007 | ||
1965 | if (m->friend_statusmessagechange) | 2008 | if (data_length <= message_id_length) |
1966 | m->friend_statusmessagechange(m, i, data_terminated, data_length, | 2009 | break; |
1967 | m->friend_statuschange_userdata); | ||
1968 | 2010 | ||
1969 | set_friend_statusmessage(m, i, data_terminated, data_length); | 2011 | uint8_t *message = data + message_id_length; |
1970 | break; | 2012 | uint16_t message_length = data_length - message_id_length; |
1971 | } | ||
1972 | 2013 | ||
1973 | case PACKET_ID_USERSTATUS: { | 2014 | /* Make sure the NULL terminator is present. */ |
1974 | if (data_length != 1) | 2015 | uint8_t message_terminated[message_length + 1]; |
1975 | break; | 2016 | memcpy(message_terminated, message, message_length); |
2017 | message_terminated[message_length] = 0; | ||
1976 | 2018 | ||
1977 | USERSTATUS status = data[0]; | 2019 | if (m->friendlist[i].receives_read_receipts) { |
2020 | write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length); | ||
2021 | } | ||
1978 | 2022 | ||
1979 | if (status >= USERSTATUS_INVALID) | 2023 | if (m->friend_message) |
1980 | break; | 2024 | (*m->friend_message)(m, i, message_terminated, message_length, m->friend_message_userdata); |
1981 | 2025 | ||
1982 | if (m->friend_userstatuschange) | 2026 | break; |
1983 | m->friend_userstatuschange(m, i, status, m->friend_userstatuschange_userdata); | 2027 | } |
1984 | 2028 | ||
1985 | set_friend_userstatus(m, i, status); | 2029 | case PACKET_ID_ACTION: { |
1986 | break; | 2030 | uint8_t *message_id = data; |
1987 | } | 2031 | uint8_t message_id_length = 4; |
1988 | 2032 | ||
1989 | case PACKET_ID_TYPING: { | 2033 | if (data_length <= message_id_length) |
1990 | if (data_length != 1) | 2034 | break; |
1991 | break; | ||
1992 | 2035 | ||
1993 | uint8_t typing = data[0]; | 2036 | uint8_t *action = data + message_id_length; |
2037 | uint16_t action_length = data_length - message_id_length; | ||
1994 | 2038 | ||
1995 | set_friend_typing(m, i, typing); | 2039 | /* Make sure the NULL terminator is present. */ |
2040 | uint8_t action_terminated[action_length + 1]; | ||
2041 | memcpy(action_terminated, action, action_length); | ||
2042 | action_terminated[action_length] = 0; | ||
1996 | 2043 | ||
1997 | if (m->friend_typingchange) | 2044 | if (m->friendlist[i].receives_read_receipts) { |
1998 | m->friend_typingchange(m, i, typing, m->friend_typingchange_userdata); | 2045 | write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length); |
2046 | } | ||
1999 | 2047 | ||
2000 | break; | 2048 | if (m->friend_action) |
2001 | } | 2049 | (*m->friend_action)(m, i, action_terminated, action_length, m->friend_action_userdata); |
2002 | 2050 | ||
2003 | case PACKET_ID_MESSAGE: { | 2051 | break; |
2004 | uint8_t *message_id = data; | 2052 | } |
2005 | uint8_t message_id_length = 4; | ||
2006 | 2053 | ||
2007 | if (data_length <= message_id_length) | 2054 | case PACKET_ID_RECEIPT: { |
2008 | break; | 2055 | uint32_t msgid; |
2009 | 2056 | ||
2010 | uint8_t *message = data + message_id_length; | 2057 | if (data_length < sizeof(msgid)) |
2011 | uint16_t message_length = data_length - message_id_length; | 2058 | break; |
2012 | 2059 | ||
2013 | /* Make sure the NULL terminator is present. */ | 2060 | memcpy(&msgid, data, sizeof(msgid)); |
2014 | uint8_t message_terminated[message_length + 1]; | 2061 | msgid = ntohl(msgid); |
2015 | memcpy(message_terminated, message, message_length); | ||
2016 | message_terminated[message_length] = 0; | ||
2017 | 2062 | ||
2018 | if (m->friendlist[i].receives_read_receipts) { | 2063 | if (m->read_receipt) |
2019 | write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length); | 2064 | (*m->read_receipt)(m, i, msgid, m->read_receipt_userdata); |
2020 | } | ||
2021 | 2065 | ||
2022 | if (m->friend_message) | 2066 | break; |
2023 | (*m->friend_message)(m, i, message_terminated, message_length, m->friend_message_userdata); | 2067 | } |
2024 | 2068 | ||
2025 | break; | 2069 | case PACKET_ID_INVITE_GROUPCHAT: { |
2026 | } | 2070 | if (data_length != crypto_box_PUBLICKEYBYTES) |
2071 | break; | ||
2027 | 2072 | ||
2028 | case PACKET_ID_ACTION: { | 2073 | if (m->group_invite) |
2029 | uint8_t *message_id = data; | 2074 | (*m->group_invite)(m, i, data, m->group_invite_userdata); |
2030 | uint8_t message_id_length = 4; | ||
2031 | 2075 | ||
2032 | if (data_length <= message_id_length) | 2076 | break; |
2033 | break; | 2077 | } |
2034 | 2078 | ||
2035 | uint8_t *action = data + message_id_length; | 2079 | case PACKET_ID_JOIN_GROUPCHAT: { |
2036 | uint16_t action_length = data_length - message_id_length; | 2080 | if (data_length != crypto_box_PUBLICKEYBYTES * 2) |
2081 | break; | ||
2037 | 2082 | ||
2038 | /* Make sure the NULL terminator is present. */ | 2083 | int groupnum = group_num(m, data); |
2039 | uint8_t action_terminated[action_length + 1]; | ||
2040 | memcpy(action_terminated, action, action_length); | ||
2041 | action_terminated[action_length] = 0; | ||
2042 | 2084 | ||
2043 | if (m->friendlist[i].receives_read_receipts) { | 2085 | if (groupnum == -1) |
2044 | write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length); | 2086 | break; |
2045 | } | ||
2046 | 2087 | ||
2047 | if (m->friend_action) | 2088 | if (!group_invited(m, i, groupnum)) |
2048 | (*m->friend_action)(m, i, action_terminated, action_length, m->friend_action_userdata); | 2089 | break; |
2049 | 2090 | ||
2050 | break; | 2091 | group_newpeer(m->chats[groupnum], data + crypto_box_PUBLICKEYBYTES); |
2051 | } | 2092 | /* This is just there to speedup joining. */ |
2093 | chat_bootstrap(m->chats[groupnum], get_friend_ipport(m, i), data + crypto_box_PUBLICKEYBYTES); | ||
2094 | break; | ||
2095 | } | ||
2052 | 2096 | ||
2053 | case PACKET_ID_RECEIPT: { | 2097 | case PACKET_ID_FILE_SENDREQUEST: { |
2054 | uint32_t msgid; | 2098 | if (data_length < 1 + sizeof(uint64_t) + 1) |
2099 | break; | ||
2055 | 2100 | ||
2056 | if (data_length < sizeof(msgid)) | 2101 | uint8_t filenumber = data[0]; |
2057 | break; | 2102 | uint64_t filesize; |
2103 | net_to_host(data + 1, sizeof(filesize)); | ||
2104 | memcpy(&filesize, data + 1, sizeof(filesize)); | ||
2105 | m->friendlist[i].file_receiving[filenumber].status = FILESTATUS_NOT_ACCEPTED; | ||
2106 | m->friendlist[i].file_receiving[filenumber].size = filesize; | ||
2107 | m->friendlist[i].file_receiving[filenumber].transferred = 0; | ||
2058 | 2108 | ||
2059 | memcpy(&msgid, data, sizeof(msgid)); | 2109 | /* Force NULL terminate file name. */ |
2060 | msgid = ntohl(msgid); | 2110 | uint8_t filename_terminated[data_length - 1 - sizeof(uint64_t) + 1]; |
2111 | memcpy(filename_terminated, data + 1 + sizeof(uint64_t), data_length - 1 - sizeof(uint64_t)); | ||
2112 | filename_terminated[data_length - 1 - sizeof(uint64_t)] = 0; | ||
2061 | 2113 | ||
2062 | if (m->read_receipt) | 2114 | if (m->file_sendrequest) |
2063 | (*m->read_receipt)(m, i, msgid, m->read_receipt_userdata); | 2115 | (*m->file_sendrequest)(m, i, filenumber, filesize, filename_terminated, data_length - 1 - sizeof(uint64_t), |
2116 | m->file_sendrequest_userdata); | ||
2064 | 2117 | ||
2065 | break; | 2118 | break; |
2066 | } | 2119 | } |
2067 | 2120 | ||
2068 | case PACKET_ID_INVITE_GROUPCHAT: { | 2121 | case PACKET_ID_FILE_CONTROL: { |
2069 | if (data_length != crypto_box_PUBLICKEYBYTES) | 2122 | if (data_length < 3) |
2070 | break; | 2123 | break; |
2071 | 2124 | ||
2072 | if (m->group_invite) | 2125 | uint8_t send_receive = data[0]; |
2073 | (*m->group_invite)(m, i, data, m->group_invite_userdata); | 2126 | uint8_t filenumber = data[1]; |
2127 | uint8_t control_type = data[2]; | ||
2074 | 2128 | ||
2075 | break; | 2129 | if (handle_filecontrol(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3) == -1) |
2076 | } | 2130 | break; |
2077 | 2131 | ||
2078 | case PACKET_ID_JOIN_GROUPCHAT: { | 2132 | if (m->file_filecontrol) |
2079 | if (data_length != crypto_box_PUBLICKEYBYTES * 2) | 2133 | (*m->file_filecontrol)(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3, |
2080 | break; | 2134 | m->file_filecontrol_userdata); |
2081 | 2135 | ||
2082 | int groupnum = group_num(m, data); | 2136 | break; |
2137 | } | ||
2083 | 2138 | ||
2084 | if (groupnum == -1) | 2139 | case PACKET_ID_FILE_DATA: { |
2085 | break; | 2140 | if (data_length < 2) |
2141 | break; | ||
2086 | 2142 | ||
2087 | if (!group_invited(m, i, groupnum)) | 2143 | uint8_t filenumber = data[0]; |
2088 | break; | ||
2089 | 2144 | ||
2090 | group_newpeer(m->chats[groupnum], data + crypto_box_PUBLICKEYBYTES); | 2145 | if (m->friendlist[i].file_receiving[filenumber].status == FILESTATUS_NONE) |
2091 | /* This is just there to speedup joining. */ | 2146 | break; |
2092 | chat_bootstrap(m->chats[groupnum], get_friend_ipport(m, i), data + crypto_box_PUBLICKEYBYTES); | ||
2093 | break; | ||
2094 | } | ||
2095 | 2147 | ||
2096 | case PACKET_ID_FILE_SENDREQUEST: { | 2148 | m->friendlist[i].file_receiving[filenumber].transferred += (data_length - 1); |
2097 | if (data_length < 1 + sizeof(uint64_t) + 1) | ||
2098 | break; | ||
2099 | 2149 | ||
2100 | uint8_t filenumber = data[0]; | 2150 | if (m->file_filedata) |
2101 | uint64_t filesize; | 2151 | (*m->file_filedata)(m, i, filenumber, data + 1, data_length - 1, m->file_filedata_userdata); |
2102 | net_to_host(data + 1, sizeof(filesize)); | ||
2103 | memcpy(&filesize, data + 1, sizeof(filesize)); | ||
2104 | m->friendlist[i].file_receiving[filenumber].status = FILESTATUS_NOT_ACCEPTED; | ||
2105 | m->friendlist[i].file_receiving[filenumber].size = filesize; | ||
2106 | m->friendlist[i].file_receiving[filenumber].transferred = 0; | ||
2107 | 2152 | ||
2108 | /* Force NULL terminate file name. */ | 2153 | break; |
2109 | uint8_t filename_terminated[data_length - 1 - sizeof(uint64_t) + 1]; | 2154 | } |
2110 | memcpy(filename_terminated, data + 1 + sizeof(uint64_t), data_length - 1 - sizeof(uint64_t)); | ||
2111 | filename_terminated[data_length - 1 - sizeof(uint64_t)] = 0; | ||
2112 | 2155 | ||
2113 | if (m->file_sendrequest) | 2156 | case PACKET_ID_MSI: { |
2114 | (*m->file_sendrequest)(m, i, filenumber, filesize, filename_terminated, data_length - 1 - sizeof(uint64_t), | 2157 | if (data_length == 0) |
2115 | m->file_sendrequest_userdata); | 2158 | break; |
2116 | 2159 | ||
2117 | break; | 2160 | if (m->msi_packet) |
2118 | } | 2161 | (*m->msi_packet)(m, i, data, data_length, m->msi_packet_userdata); |
2162 | } | ||
2119 | 2163 | ||
2120 | case PACKET_ID_FILE_CONTROL: { | 2164 | default: { |
2121 | if (data_length < 3) | 2165 | break; |
2122 | break; | 2166 | } |
2167 | } | ||
2123 | 2168 | ||
2124 | uint8_t send_receive = data[0]; | 2169 | return 0; |
2125 | uint8_t filenumber = data[1]; | 2170 | } |
2126 | uint8_t control_type = data[2]; | ||
2127 | 2171 | ||
2128 | if (handle_filecontrol(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3) == -1) | 2172 | static int friend_new_connection(Messenger *m, int32_t friendnumber, uint8_t *real_public_key) |
2129 | break; | 2173 | { |
2174 | if (friend_not_valid(m, friendnumber)) | ||
2175 | return -1; | ||
2130 | 2176 | ||
2131 | if (m->file_filecontrol) | 2177 | if (m->friendlist[friendnumber].crypt_connection_id != -1) { |
2132 | (*m->file_filecontrol)(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3, | 2178 | return -1; |
2133 | m->file_filecontrol_userdata); | 2179 | } |
2134 | 2180 | ||
2135 | break; | 2181 | int id = new_crypto_connection(m->net_crypto, real_public_key); |
2136 | } | ||
2137 | 2182 | ||
2138 | case PACKET_ID_FILE_DATA: { | 2183 | if (id == -1) |
2139 | if (data_length < 2) | 2184 | return -1; |
2140 | break; | ||
2141 | 2185 | ||
2142 | uint8_t filenumber = data[0]; | 2186 | m->friendlist[friendnumber].crypt_connection_id = id; |
2187 | connection_status_handler(m->net_crypto, id, &handle_status, m, friendnumber); | ||
2188 | connection_data_handler(m->net_crypto, id, &handle_packet, m, friendnumber); | ||
2189 | return 0; | ||
2143 | 2190 | ||
2144 | if (m->friendlist[i].file_receiving[filenumber].status == FILESTATUS_NONE) | 2191 | } |
2145 | break; | ||
2146 | 2192 | ||
2147 | m->friendlist[i].file_receiving[filenumber].transferred += (data_length - 1); | 2193 | /* TODO: Make this function not suck. */ |
2194 | void do_friends(Messenger *m) | ||
2195 | { | ||
2196 | uint32_t i; | ||
2197 | uint64_t temp_time = unix_time(); | ||
2148 | 2198 | ||
2149 | if (m->file_filedata) | 2199 | for (i = 0; i < m->numfriends; ++i) { |
2150 | (*m->file_filedata)(m, i, filenumber, data + 1, data_length - 1, m->file_filedata_userdata); | 2200 | if (m->friendlist[i].status == FRIEND_ADDED) { |
2201 | int fr = send_friendrequest(m->onion_c, m->friendlist[i].client_id, m->friendlist[i].friendrequest_nospam, | ||
2202 | m->friendlist[i].info, | ||
2203 | m->friendlist[i].info_size); | ||
2151 | 2204 | ||
2152 | break; | 2205 | if (fr >= 0) { |
2153 | } | 2206 | set_friend_status(m, i, FRIEND_REQUESTED); |
2207 | m->friendlist[i].friendrequest_lastsent = temp_time; | ||
2208 | } | ||
2209 | } | ||
2210 | |||
2211 | if (m->friendlist[i].status == FRIEND_REQUESTED | ||
2212 | || m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online. */ | ||
2213 | if (m->friendlist[i].status == FRIEND_REQUESTED) { | ||
2214 | /* If we didn't connect to friend after successfully sending him a friend request the request is deemed | ||
2215 | * unsuccessful so we set the status back to FRIEND_ADDED and try again. | ||
2216 | */ | ||
2217 | check_friend_request_timed_out(m, i, temp_time); | ||
2218 | } | ||
2154 | 2219 | ||
2155 | case PACKET_ID_MSI: { | 2220 | friend_new_connection(m, i, m->friendlist[i].client_id); |
2156 | if (data_length == 0) | 2221 | } |
2157 | break; | ||
2158 | 2222 | ||
2159 | if (m->msi_packet) | 2223 | if (m->friendlist[i].crypt_connection_id != -1) { |
2160 | (*m->msi_packet)(m, i, data, data_length, m->msi_packet_userdata); | 2224 | uint8_t dht_public_key1[crypto_box_PUBLICKEYBYTES]; |
2161 | } | 2225 | uint64_t timestamp1 = onion_getfriend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key1); |
2226 | uint8_t dht_public_key2[crypto_box_PUBLICKEYBYTES]; | ||
2227 | uint64_t timestamp2 = get_connection_dht_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key2); | ||
2162 | 2228 | ||
2163 | default: { | 2229 | if (timestamp1 > timestamp2) { |
2164 | break; | 2230 | set_connection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key1, timestamp1); |
2165 | } | 2231 | } else if (timestamp1 < timestamp2) { |
2166 | } | 2232 | onion_set_friend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key2, timestamp2); |
2167 | } else { | 2233 | } |
2168 | if (is_cryptoconnected(m->net_crypto, | ||
2169 | m->friendlist[i].crypt_connection_id) == CRYPTO_CONN_TIMED_OUT) { /* If the connection timed out, kill it. */ | ||
2170 | crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); | ||
2171 | m->friendlist[i].crypt_connection_id = -1; | ||
2172 | set_friend_status(m, i, FRIEND_CONFIRMED); | ||
2173 | } | ||
2174 | 2234 | ||
2175 | if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) { | 2235 | uint8_t direct_connected; |
2176 | /* If we stopped recieving ping packets, kill it. */ | 2236 | unsigned int status = crypto_connection_status(m->net_crypto, m->friendlist[i].crypt_connection_id, &direct_connected); |
2177 | crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); | ||
2178 | m->friendlist[i].crypt_connection_id = -1; | ||
2179 | set_friend_status(m, i, FRIEND_CONFIRMED); | ||
2180 | } | ||
2181 | 2237 | ||
2182 | break; | 2238 | if (direct_connected == 0 || status == CRYPTO_CONN_COOKIE_REQUESTING) { |
2239 | IP_Port friendip; | ||
2240 | |||
2241 | if (onion_getfriendip(m->onion_c, m->friendlist[i].onion_friendnum, &friendip) == 1) { | ||
2242 | set_direct_ip_port(m->net_crypto, m->friendlist[i].crypt_connection_id, friendip); | ||
2243 | } | ||
2183 | } | 2244 | } |
2184 | } | 2245 | } |
2185 | } | ||
2186 | } | ||
2187 | 2246 | ||
2188 | void do_inbound(Messenger *m) | 2247 | if (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */ |
2189 | { | 2248 | if (m->friendlist[i].name_sent == 0) { |
2190 | uint8_t secret_nonce[crypto_box_NONCEBYTES]; | 2249 | if (m_sendname(m, i, m->name, m->name_length)) |
2191 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; | 2250 | m->friendlist[i].name_sent = 1; |
2192 | uint8_t session_key[crypto_box_PUBLICKEYBYTES]; | 2251 | } |
2193 | int inconnection = crypto_inbound(m->net_crypto, public_key, secret_nonce, session_key); | ||
2194 | 2252 | ||
2195 | if (inconnection != -1) { | 2253 | if (m->friendlist[i].statusmessage_sent == 0) { |
2196 | int friend_id = getfriend_id(m, public_key); | 2254 | if (send_statusmessage(m, i, m->statusmessage, m->statusmessage_length)) |
2255 | m->friendlist[i].statusmessage_sent = 1; | ||
2256 | } | ||
2197 | 2257 | ||
2198 | if (friend_id != -1) { | 2258 | if (m->friendlist[i].userstatus_sent == 0) { |
2199 | if (m_get_friend_connectionstatus(m, friend_id) == 1) { | 2259 | if (send_userstatus(m, i, m->userstatus)) |
2200 | kill_connection(m->net_crypto->lossless_udp, inconnection); | 2260 | m->friendlist[i].userstatus_sent = 1; |
2201 | return; | 2261 | } |
2262 | |||
2263 | if (m->friendlist[i].user_istyping_sent == 0) { | ||
2264 | if (send_user_istyping(m, i, m->friendlist[i].user_istyping)) | ||
2265 | m->friendlist[i].user_istyping_sent = 1; | ||
2202 | } | 2266 | } |
2203 | 2267 | ||
2204 | crypto_kill(m->net_crypto, m->friendlist[friend_id].crypt_connection_id); | 2268 | if (m->friendlist[i].ping_lastsent + FRIEND_PING_INTERVAL < temp_time) { |
2205 | m->friendlist[friend_id].crypt_connection_id = | 2269 | send_ping(m, i); |
2206 | accept_crypto_inbound(m->net_crypto, inconnection, public_key, secret_nonce, session_key); | 2270 | } |
2207 | 2271 | ||
2208 | set_friend_status(m, friend_id, FRIEND_CONFIRMED); | 2272 | if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) { |
2209 | } else { | 2273 | /* If we stopped receiving ping packets, kill it. */ |
2210 | kill_connection(m->net_crypto->lossless_udp, inconnection); | 2274 | crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); |
2275 | m->friendlist[i].crypt_connection_id = -1; | ||
2276 | set_friend_status(m, i, FRIEND_CONFIRMED); | ||
2277 | } | ||
2211 | } | 2278 | } |
2212 | } | 2279 | } |
2213 | } | 2280 | } |
2214 | 2281 | ||
2282 | |||
2283 | |||
2284 | |||
2215 | #ifdef LOGGING | 2285 | #ifdef LOGGING |
2216 | #define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60UL | 2286 | #define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60UL |
2217 | static time_t lastdump = 0; | 2287 | static time_t lastdump = 0; |
@@ -2239,7 +2309,6 @@ void do_messenger(Messenger *m) | |||
2239 | do_net_crypto(m->net_crypto); | 2309 | do_net_crypto(m->net_crypto); |
2240 | do_onion_client(m->onion_c); | 2310 | do_onion_client(m->onion_c); |
2241 | do_friends(m); | 2311 | do_friends(m); |
2242 | do_inbound(m); | ||
2243 | do_allgroupchats(m); | 2312 | do_allgroupchats(m); |
2244 | LANdiscovery(m); | 2313 | LANdiscovery(m); |
2245 | 2314 | ||
@@ -2369,7 +2438,9 @@ size_t wait_data_size() | |||
2369 | 2438 | ||
2370 | int wait_prepare_messenger(Messenger *m, uint8_t *data) | 2439 | int wait_prepare_messenger(Messenger *m, uint8_t *data) |
2371 | { | 2440 | { |
2372 | return networking_wait_prepare(m->net, sendqueue_total(m->net_crypto->lossless_udp), data); | 2441 | //TODO |
2442 | //return networking_wait_prepare(m->net, sendqueue_total(m->net_crypto->lossless_udp), data); | ||
2443 | return networking_wait_prepare(m->net, 1024, data); | ||
2373 | } | 2444 | } |
2374 | 2445 | ||
2375 | int wait_execute_messenger(uint8_t *data, long seconds, long microseconds) | 2446 | int wait_execute_messenger(uint8_t *data, long seconds, long microseconds) |
@@ -2394,11 +2465,14 @@ int wait_cleanup_messenger(Messenger *m, uint8_t *data) | |||
2394 | #define MESSENGER_STATE_TYPE_NAME 4 | 2465 | #define MESSENGER_STATE_TYPE_NAME 4 |
2395 | #define MESSENGER_STATE_TYPE_STATUSMESSAGE 5 | 2466 | #define MESSENGER_STATE_TYPE_STATUSMESSAGE 5 |
2396 | #define MESSENGER_STATE_TYPE_STATUS 6 | 2467 | #define MESSENGER_STATE_TYPE_STATUS 6 |
2468 | #define MESSENGER_STATE_TYPE_TCP_RELAY 10 | ||
2397 | 2469 | ||
2470 | #define SAVED_FRIEND_REQUEST_SIZE 1024 | ||
2471 | #define NUM_SAVED_TCP_RELAYS 8 | ||
2398 | struct SAVED_FRIEND { | 2472 | struct SAVED_FRIEND { |
2399 | uint8_t status; | 2473 | uint8_t status; |
2400 | uint8_t client_id[CLIENT_ID_SIZE]; | 2474 | uint8_t client_id[CLIENT_ID_SIZE]; |
2401 | uint8_t info[MAX_DATA_SIZE]; // the data that is sent during the friend requests we do. | 2475 | uint8_t info[SAVED_FRIEND_REQUEST_SIZE]; // the data that is sent during the friend requests we do. |
2402 | uint16_t info_size; // Length of the info. | 2476 | uint16_t info_size; // Length of the info. |
2403 | uint8_t name[MAX_NAME_LENGTH]; | 2477 | uint8_t name[MAX_NAME_LENGTH]; |
2404 | uint16_t name_length; | 2478 | uint16_t name_length; |
@@ -2414,7 +2488,7 @@ struct SAVED_FRIEND { | |||
2414 | struct SAVED_FRIEND_OLD { | 2488 | struct SAVED_FRIEND_OLD { |
2415 | uint8_t status; | 2489 | uint8_t status; |
2416 | uint8_t client_id[CLIENT_ID_SIZE]; | 2490 | uint8_t client_id[CLIENT_ID_SIZE]; |
2417 | uint8_t info[MAX_DATA_SIZE]; | 2491 | uint8_t info[1024]; |
2418 | uint16_t info_size; | 2492 | uint16_t info_size; |
2419 | uint8_t name[MAX_NAME_LENGTH]; | 2493 | uint8_t name[MAX_NAME_LENGTH]; |
2420 | uint16_t name_length; | 2494 | uint16_t name_length; |
@@ -2442,7 +2516,12 @@ static uint32_t friends_list_save(Messenger *m, uint8_t *data) | |||
2442 | memcpy(temp.client_id, m->friendlist[i].client_id, CLIENT_ID_SIZE); | 2516 | memcpy(temp.client_id, m->friendlist[i].client_id, CLIENT_ID_SIZE); |
2443 | 2517 | ||
2444 | if (temp.status < 3) { | 2518 | if (temp.status < 3) { |
2445 | memcpy(temp.info, m->friendlist[i].info, m->friendlist[i].info_size); | 2519 | if (m->friendlist[i].info_size > SAVED_FRIEND_REQUEST_SIZE) { |
2520 | memcpy(temp.info, m->friendlist[i].info, SAVED_FRIEND_REQUEST_SIZE); | ||
2521 | } else { | ||
2522 | memcpy(temp.info, m->friendlist[i].info, m->friendlist[i].info_size); | ||
2523 | } | ||
2524 | |||
2446 | temp.info_size = htons(m->friendlist[i].info_size); | 2525 | temp.info_size = htons(m->friendlist[i].info_size); |
2447 | temp.friendrequest_nospam = m->friendlist[i].friendrequest_nospam; | 2526 | temp.friendrequest_nospam = m->friendlist[i].friendrequest_nospam; |
2448 | } else { | 2527 | } else { |
@@ -2524,6 +2603,7 @@ uint32_t messenger_size(Messenger *m) | |||
2524 | + sizesubhead + m->name_length // Own nickname. | 2603 | + sizesubhead + m->name_length // Own nickname. |
2525 | + sizesubhead + m->statusmessage_length // status message | 2604 | + sizesubhead + m->statusmessage_length // status message |
2526 | + sizesubhead + 1 // status | 2605 | + sizesubhead + 1 // status |
2606 | + sizesubhead + NUM_SAVED_TCP_RELAYS * sizeof(Node_format) //TCP relays | ||
2527 | ; | 2607 | ; |
2528 | } | 2608 | } |
2529 | 2609 | ||
@@ -2588,74 +2668,15 @@ void messenger_save(Messenger *m, uint8_t *data) | |||
2588 | data = z_state_save_subheader(data, len, type); | 2668 | data = z_state_save_subheader(data, len, type); |
2589 | *data = m->userstatus; | 2669 | *data = m->userstatus; |
2590 | data += len; | 2670 | data += len; |
2591 | } | ||
2592 | |||
2593 | static int messenger_load_state_callback_old(void *outer, uint8_t *data, uint32_t length, uint16_t type) | ||
2594 | { | ||
2595 | Messenger *m = outer; | ||
2596 | |||
2597 | switch (type) { | ||
2598 | case MESSENGER_STATE_TYPE_NOSPAMKEYS: | ||
2599 | if (length == crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t)) { | ||
2600 | set_nospam(&(m->fr), *(uint32_t *)data); | ||
2601 | load_keys(m->net_crypto, &data[sizeof(uint32_t)]); | ||
2602 | #ifdef ENABLE_ASSOC_DHT | ||
2603 | |||
2604 | if (m->dht->assoc) | ||
2605 | Assoc_self_client_id_changed(m->dht->assoc, m->net_crypto->self_public_key); | ||
2606 | 2671 | ||
2607 | #endif | 2672 | Node_format relays[NUM_SAVED_TCP_RELAYS]; |
2608 | } else | 2673 | len = sizeof(relays); |
2609 | return -1; /* critical */ | 2674 | type = MESSENGER_STATE_TYPE_TCP_RELAY; |
2610 | 2675 | data = z_state_save_subheader(data, len, type); | |
2611 | break; | 2676 | memset(relays, 0, len); |
2612 | 2677 | copy_connected_tcp_relays(m->net_crypto, relays, NUM_SAVED_TCP_RELAYS); | |
2613 | case MESSENGER_STATE_TYPE_DHT: | 2678 | memcpy(data, relays, len); |
2614 | DHT_load(m->dht, data, length); | 2679 | data += len; |
2615 | break; | ||
2616 | |||
2617 | case MESSENGER_STATE_TYPE_FRIENDS: | ||
2618 | if (!(length % sizeof(Friend))) { | ||
2619 | uint16_t num = length / sizeof(Friend); | ||
2620 | Friend *friends = (Friend *)data; | ||
2621 | uint32_t i; | ||
2622 | |||
2623 | for (i = 0; i < num; ++i) { | ||
2624 | if (friends[i].status >= 3) { | ||
2625 | int fnum = m_addfriend_norequest(m, friends[i].client_id); | ||
2626 | setfriendname(m, fnum, friends[i].name, friends[i].name_length); | ||
2627 | /* set_friend_statusmessage(fnum, temp[i].statusmessage, temp[i].statusmessage_length); */ | ||
2628 | } else if (friends[i].status != 0) { | ||
2629 | /* TODO: This is not a good way to do this. */ | ||
2630 | uint8_t address[FRIEND_ADDRESS_SIZE]; | ||
2631 | id_copy(address, friends[i].client_id); | ||
2632 | memcpy(address + crypto_box_PUBLICKEYBYTES, &(friends[i].friendrequest_nospam), sizeof(uint32_t)); | ||
2633 | uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); | ||
2634 | memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), &checksum, sizeof(checksum)); | ||
2635 | m_addfriend(m, address, friends[i].info, friends[i].info_size); | ||
2636 | } | ||
2637 | } | ||
2638 | } | ||
2639 | |||
2640 | break; | ||
2641 | |||
2642 | case MESSENGER_STATE_TYPE_NAME: | ||
2643 | if ((length > 0) && (length < MAX_NAME_LENGTH)) { | ||
2644 | setname(m, data, length); | ||
2645 | } | ||
2646 | |||
2647 | break; | ||
2648 | |||
2649 | #ifdef DEBUG | ||
2650 | |||
2651 | default: | ||
2652 | fprintf(stderr, "Load state: contains unrecognized part (len %u, type %u)\n", | ||
2653 | length, type); | ||
2654 | break; | ||
2655 | #endif | ||
2656 | } | ||
2657 | |||
2658 | return 0; | ||
2659 | } | 2680 | } |
2660 | 2681 | ||
2661 | static int messenger_load_state_callback(void *outer, uint8_t *data, uint32_t length, uint16_t type) | 2682 | static int messenger_load_state_callback(void *outer, uint8_t *data, uint32_t length, uint16_t type) |
@@ -2706,6 +2727,22 @@ static int messenger_load_state_callback(void *outer, uint8_t *data, uint32_t le | |||
2706 | } | 2727 | } |
2707 | 2728 | ||
2708 | break; | 2729 | break; |
2730 | |||
2731 | case MESSENGER_STATE_TYPE_TCP_RELAY: { | ||
2732 | Node_format relays[NUM_SAVED_TCP_RELAYS]; | ||
2733 | |||
2734 | if (length != sizeof(relays)) { | ||
2735 | return -1; | ||
2736 | } | ||
2737 | |||
2738 | memcpy(relays, data, length); | ||
2739 | uint32_t i; | ||
2740 | |||
2741 | for (i = 0; i < NUM_SAVED_TCP_RELAYS; ++i) { | ||
2742 | add_tcp_relay(m->net_crypto, relays[i].ip_port, relays[i].client_id); | ||
2743 | } | ||
2744 | } | ||
2745 | break; | ||
2709 | #ifdef DEBUG | 2746 | #ifdef DEBUG |
2710 | 2747 | ||
2711 | default: | 2748 | default: |
@@ -2721,93 +2758,21 @@ static int messenger_load_state_callback(void *outer, uint8_t *data, uint32_t le | |||
2721 | /* Load the messenger from data of size length. */ | 2758 | /* Load the messenger from data of size length. */ |
2722 | int messenger_load(Messenger *m, uint8_t *data, uint32_t length) | 2759 | int messenger_load(Messenger *m, uint8_t *data, uint32_t length) |
2723 | { | 2760 | { |
2724 | uint32_t cookie_len = 2 * sizeof(uint32_t); | 2761 | uint32_t data32[2]; |
2762 | uint32_t cookie_len = sizeof(data32); | ||
2725 | 2763 | ||
2726 | if (length < cookie_len) | 2764 | if (length < cookie_len) |
2727 | return -1; | 2765 | return -1; |
2728 | 2766 | ||
2729 | uint32_t *data32 = (uint32_t *)data; | 2767 | memcpy(data32, data, sizeof(data32)); |
2730 | 2768 | ||
2731 | if (!data32[0] && (data32[1] == MESSENGER_STATE_COOKIE_GLOBAL)) | 2769 | if (!data32[0] && (data32[1] == MESSENGER_STATE_COOKIE_GLOBAL)) |
2732 | return load_state(messenger_load_state_callback, m, data + cookie_len, | 2770 | return load_state(messenger_load_state_callback, m, data + cookie_len, |
2733 | length - cookie_len, MESSENGER_STATE_COOKIE_TYPE); | 2771 | length - cookie_len, MESSENGER_STATE_COOKIE_TYPE); |
2734 | 2772 | else | |
2735 | else if (!data32[0] && (data32[1] == MESSENGER_STATE_COOKIE_GLOBAL_OLD)) | ||
2736 | return load_state(messenger_load_state_callback_old, m, data + cookie_len, | ||
2737 | length - cookie_len, MESSENGER_STATE_COOKIE_TYPE); | ||
2738 | else /* old state file */ | ||
2739 | return -1; | 2773 | return -1; |
2740 | } | 2774 | } |
2741 | 2775 | ||
2742 | /* return the size of data to pass to messenger_save_encrypted(...) | ||
2743 | * | ||
2744 | */ | ||
2745 | uint32_t messenger_size_encrypted(Messenger *m) | ||
2746 | { | ||
2747 | return messenger_size(m) + crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES; | ||
2748 | } | ||
2749 | |||
2750 | /* Save the messenger, encrypting the data with key of length key_length | ||
2751 | * | ||
2752 | * return 0 on success. | ||
2753 | * return -1 on failure. | ||
2754 | */ | ||
2755 | int messenger_save_encrypted(Messenger *m, uint8_t *data, uint8_t *key, uint16_t key_length) | ||
2756 | { | ||
2757 | uint32_t m_size = messenger_size(m); | ||
2758 | uint8_t *plain_messenger = malloc(m_size); | ||
2759 | |||
2760 | if (plain_messenger == NULL) | ||
2761 | return -1; | ||
2762 | |||
2763 | messenger_save(m, plain_messenger); | ||
2764 | |||
2765 | /* Hash the key with SHA256 to get a 32byte key. */ | ||
2766 | uint8_t hash[crypto_hash_sha256_BYTES]; | ||
2767 | crypto_hash_sha256(hash, key, key_length); | ||
2768 | random_nonce(data); | ||
2769 | encrypt_data_symmetric(hash, data, plain_messenger, m_size, data + crypto_secretbox_NONCEBYTES); | ||
2770 | |||
2771 | memset(plain_messenger, 0, m_size); | ||
2772 | free(plain_messenger); | ||
2773 | memset(hash, 0, crypto_hash_sha256_BYTES); | ||
2774 | return 0; | ||
2775 | } | ||
2776 | |||
2777 | /* Load the messenger from data of size length encrypted with key of key_length. | ||
2778 | * | ||
2779 | * return 0 on success. | ||
2780 | * return -1 on failure. | ||
2781 | */ | ||
2782 | int messenger_load_encrypted(Messenger *m, uint8_t *data, uint32_t length, uint8_t *key, uint16_t key_length) | ||
2783 | { | ||
2784 | if (length <= crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES) | ||
2785 | return -1; | ||
2786 | |||
2787 | uint8_t *plain_messenger = malloc(length); | ||
2788 | |||
2789 | if (plain_messenger == NULL) | ||
2790 | return -1; | ||
2791 | |||
2792 | /* Hash the key with SHA256 to get a 32byte key. */ | ||
2793 | uint8_t hash[crypto_hash_sha256_BYTES]; | ||
2794 | crypto_hash_sha256(hash, key, key_length); | ||
2795 | int len = decrypt_data_symmetric(hash, data, data + crypto_secretbox_NONCEBYTES, length - crypto_secretbox_NONCEBYTES, | ||
2796 | plain_messenger); | ||
2797 | int ret; | ||
2798 | |||
2799 | if ((uint32_t)len == length - crypto_secretbox_NONCEBYTES - crypto_secretbox_MACBYTES) { | ||
2800 | ret = messenger_load(m, plain_messenger, length - crypto_secretbox_NONCEBYTES - crypto_secretbox_MACBYTES); | ||
2801 | } else { | ||
2802 | ret = -1; | ||
2803 | } | ||
2804 | |||
2805 | memset(plain_messenger, 0, length); | ||
2806 | free(plain_messenger); | ||
2807 | memset(hash, 0, crypto_hash_sha256_BYTES); | ||
2808 | return ret; | ||
2809 | } | ||
2810 | |||
2811 | /* Return the number of friends in the instance m. | 2776 | /* Return the number of friends in the instance m. |
2812 | * You should use this to determine how much memory to allocate | 2777 | * You should use this to determine how much memory to allocate |
2813 | * for copy_friendlist. */ | 2778 | * for copy_friendlist. */ |
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index c29b6594..b72a0831 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h | |||
@@ -34,18 +34,20 @@ | |||
34 | #include "onion_client.h" | 34 | #include "onion_client.h" |
35 | 35 | ||
36 | #define MAX_NAME_LENGTH 128 | 36 | #define MAX_NAME_LENGTH 128 |
37 | /* TODO: this must depend on other variable. */ | ||
37 | #define MAX_STATUSMESSAGE_LENGTH 1007 | 38 | #define MAX_STATUSMESSAGE_LENGTH 1007 |
38 | 39 | ||
39 | #define FRIEND_ADDRESS_SIZE (crypto_box_PUBLICKEYBYTES + sizeof(uint32_t) + sizeof(uint16_t)) | 40 | #define FRIEND_ADDRESS_SIZE (crypto_box_PUBLICKEYBYTES + sizeof(uint32_t) + sizeof(uint16_t)) |
40 | 41 | ||
41 | #define PACKET_ID_PING 0 | 42 | /* NOTE: Packet ids below 16 must never be used. */ |
43 | #define PACKET_ID_ALIVE 16 | ||
42 | #define PACKET_ID_NICKNAME 48 | 44 | #define PACKET_ID_NICKNAME 48 |
43 | #define PACKET_ID_STATUSMESSAGE 49 | 45 | #define PACKET_ID_STATUSMESSAGE 49 |
44 | #define PACKET_ID_USERSTATUS 50 | 46 | #define PACKET_ID_USERSTATUS 50 |
45 | #define PACKET_ID_TYPING 51 | 47 | #define PACKET_ID_TYPING 51 |
46 | #define PACKET_ID_RECEIPT 65 | 48 | #define PACKET_ID_RECEIPT 63 |
47 | #define PACKET_ID_MESSAGE 64 | 49 | #define PACKET_ID_MESSAGE 64 |
48 | #define PACKET_ID_ACTION 63 | 50 | #define PACKET_ID_ACTION 65 |
49 | #define PACKET_ID_MSI 69 | 51 | #define PACKET_ID_MSI 69 |
50 | #define PACKET_ID_FILE_SENDREQUEST 80 | 52 | #define PACKET_ID_FILE_SENDREQUEST 80 |
51 | #define PACKET_ID_FILE_CONTROL 81 | 53 | #define PACKET_ID_FILE_CONTROL 81 |
@@ -80,17 +82,13 @@ enum { | |||
80 | FAERR_NOMEM = -8 | 82 | FAERR_NOMEM = -8 |
81 | }; | 83 | }; |
82 | 84 | ||
83 | /* Don't assume MAX_STATUSMESSAGE_LENGTH will stay at 128, it may be increased | ||
84 | * to an absurdly large number later. | ||
85 | */ | ||
86 | |||
87 | /* Default start timeout in seconds between friend requests. */ | 85 | /* Default start timeout in seconds between friend requests. */ |
88 | #define FRIENDREQUEST_TIMEOUT 5; | 86 | #define FRIENDREQUEST_TIMEOUT 5; |
89 | 87 | ||
90 | /* Interval between the sending of ping packets. */ | 88 | /* Interval between the sending of ping packets. */ |
91 | #define FRIEND_PING_INTERVAL 5 | 89 | #define FRIEND_PING_INTERVAL 5 |
92 | 90 | ||
93 | /* If no packets are recieved from friend in this time interval, kill the connection. */ | 91 | /* If no packets are received from friend in this time interval, kill the connection. */ |
94 | #define FRIEND_CONNECTION_TIMEOUT (FRIEND_PING_INTERVAL * 2) | 92 | #define FRIEND_CONNECTION_TIMEOUT (FRIEND_PING_INTERVAL * 2) |
95 | 93 | ||
96 | /* USERSTATUS - | 94 | /* USERSTATUS - |
@@ -137,7 +135,7 @@ typedef struct { | |||
137 | uint64_t friendrequest_lastsent; // Time at which the last friend request was sent. | 135 | uint64_t friendrequest_lastsent; // Time at which the last friend request was sent. |
138 | uint32_t friendrequest_timeout; // The timeout between successful friendrequest sending attempts. | 136 | uint32_t friendrequest_timeout; // The timeout between successful friendrequest sending attempts. |
139 | uint8_t status; // 0 if no friend, 1 if added, 2 if friend request sent, 3 if confirmed friend, 4 if online. | 137 | uint8_t status; // 0 if no friend, 1 if added, 2 if friend request sent, 3 if confirmed friend, 4 if online. |
140 | uint8_t info[MAX_DATA_SIZE]; // the data that is sent during the friend requests we do. | 138 | uint8_t info[MAX_FRIEND_REQUEST_DATA_SIZE]; // the data that is sent during the friend requests we do. |
141 | uint8_t name[MAX_NAME_LENGTH]; | 139 | uint8_t name[MAX_NAME_LENGTH]; |
142 | uint16_t name_length; | 140 | uint16_t name_length; |
143 | uint8_t name_sent; // 0 if we didn't send our name to this friend 1 if we have. | 141 | uint8_t name_sent; // 0 if we didn't send our name to this friend 1 if we have. |
@@ -354,7 +352,7 @@ int setname(Messenger *m, uint8_t *name, uint16_t length); | |||
354 | 352 | ||
355 | /* | 353 | /* |
356 | * Get your nickname. | 354 | * Get your nickname. |
357 | * m - The messanger context to use. | 355 | * m - The messenger context to use. |
358 | * name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes. | 356 | * name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes. |
359 | * | 357 | * |
360 | * return length of the name. | 358 | * return length of the name. |
@@ -376,11 +374,6 @@ int getname(Messenger *m, int32_t friendnumber, uint8_t *name); | |||
376 | int m_get_name_size(Messenger *m, int32_t friendnumber); | 374 | int m_get_name_size(Messenger *m, int32_t friendnumber); |
377 | int m_get_self_name_size(Messenger *m); | 375 | int m_get_self_name_size(Messenger *m); |
378 | 376 | ||
379 | /* returns valid ip port of connected friend on success | ||
380 | * returns zeroed out IP_Port on failure | ||
381 | */ | ||
382 | IP_Port get_friend_ipport(Messenger *m, int32_t friendnumber); | ||
383 | |||
384 | /* Set our user status. | 377 | /* Set our user status. |
385 | * You are responsible for freeing status after. | 378 | * You are responsible for freeing status after. |
386 | * | 379 | * |
@@ -739,24 +732,6 @@ void messenger_save(Messenger *m, uint8_t *data); | |||
739 | /* Load the messenger from data of size length. */ | 732 | /* Load the messenger from data of size length. */ |
740 | int messenger_load(Messenger *m, uint8_t *data, uint32_t length); | 733 | int messenger_load(Messenger *m, uint8_t *data, uint32_t length); |
741 | 734 | ||
742 | /* return the size of data to pass to messenger_save_encrypted(...) | ||
743 | */ | ||
744 | uint32_t messenger_size_encrypted(Messenger *m); | ||
745 | |||
746 | /* Save the messenger, encrypting the data with key of length key_length | ||
747 | * | ||
748 | * return 0 on success. | ||
749 | * return -1 on failure. | ||
750 | */ | ||
751 | int messenger_save_encrypted(Messenger *m, uint8_t *data, uint8_t *key, uint16_t key_length); | ||
752 | |||
753 | /* Load the messenger from data of size length encrypted with key of key_length. | ||
754 | * | ||
755 | * return 0 on success. | ||
756 | * return -1 on failure. | ||
757 | */ | ||
758 | int messenger_load_encrypted(Messenger *m, uint8_t *data, uint32_t length, uint8_t *key, uint16_t key_length); | ||
759 | |||
760 | /* Return the number of friends in the instance m. | 735 | /* Return the number of friends in the instance m. |
761 | * You should use this to determine how much memory to allocate | 736 | * You should use this to determine how much memory to allocate |
762 | * for copy_friendlist. */ | 737 | * for copy_friendlist. */ |
diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 437429b9..e4845852 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c | |||
@@ -20,6 +20,9 @@ | |||
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #ifdef HAVE_CONFIG_H | ||
24 | #include "config.h" | ||
25 | #endif | ||
23 | 26 | ||
24 | #include "TCP_client.h" | 27 | #include "TCP_client.h" |
25 | 28 | ||
@@ -71,8 +74,8 @@ static int generate_handshake(TCP_Client_Connection *TCP_conn, uint8_t *self_pub | |||
71 | memcpy(plain + crypto_box_PUBLICKEYBYTES, TCP_conn->sent_nonce, crypto_box_NONCEBYTES); | 74 | memcpy(plain + crypto_box_PUBLICKEYBYTES, TCP_conn->sent_nonce, crypto_box_NONCEBYTES); |
72 | memcpy(TCP_conn->last_packet, self_public_key, crypto_box_PUBLICKEYBYTES); | 75 | memcpy(TCP_conn->last_packet, self_public_key, crypto_box_PUBLICKEYBYTES); |
73 | new_nonce(TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES); | 76 | new_nonce(TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES); |
74 | int len = encrypt_data_fast(TCP_conn->shared_key, TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES, plain, | 77 | int len = encrypt_data_symmetric(TCP_conn->shared_key, TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES, plain, |
75 | sizeof(plain), TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); | 78 | sizeof(plain), TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); |
76 | 79 | ||
77 | if (len != sizeof(plain) + crypto_box_MACBYTES) | 80 | if (len != sizeof(plain) + crypto_box_MACBYTES) |
78 | return -1; | 81 | return -1; |
@@ -90,8 +93,8 @@ static int generate_handshake(TCP_Client_Connection *TCP_conn, uint8_t *self_pub | |||
90 | static int handle_handshake(TCP_Client_Connection *TCP_conn, uint8_t *data) | 93 | static int handle_handshake(TCP_Client_Connection *TCP_conn, uint8_t *data) |
91 | { | 94 | { |
92 | uint8_t plain[crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES]; | 95 | uint8_t plain[crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES]; |
93 | int len = decrypt_data_fast(TCP_conn->shared_key, data, data + crypto_box_NONCEBYTES, | 96 | int len = decrypt_data_symmetric(TCP_conn->shared_key, data, data + crypto_box_NONCEBYTES, |
94 | TCP_SERVER_HANDSHAKE_SIZE - crypto_box_NONCEBYTES, plain); | 97 | TCP_SERVER_HANDSHAKE_SIZE - crypto_box_NONCEBYTES, plain); |
95 | 98 | ||
96 | if (len != sizeof(plain)) | 99 | if (len != sizeof(plain)) |
97 | return -1; | 100 | return -1; |
@@ -130,6 +133,206 @@ static int send_pending_data(TCP_Client_Connection *con) | |||
130 | return -1; | 133 | return -1; |
131 | } | 134 | } |
132 | 135 | ||
136 | /* return 1 on success. | ||
137 | * return 0 if could not send packet. | ||
138 | * return -1 on failure (connection must be killed). | ||
139 | */ | ||
140 | static int write_packet_TCP_secure_connection(TCP_Client_Connection *con, uint8_t *data, uint16_t length) | ||
141 | { | ||
142 | if (length + crypto_box_MACBYTES > MAX_PACKET_SIZE) | ||
143 | return -1; | ||
144 | |||
145 | if (send_pending_data(con) == -1) | ||
146 | return 0; | ||
147 | |||
148 | uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES]; | ||
149 | |||
150 | uint16_t c_length = htons(length + crypto_box_MACBYTES); | ||
151 | memcpy(packet, &c_length, sizeof(uint16_t)); | ||
152 | int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); | ||
153 | |||
154 | if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) | ||
155 | return -1; | ||
156 | |||
157 | increment_nonce(con->sent_nonce); | ||
158 | |||
159 | len = send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL); | ||
160 | |||
161 | if ((unsigned int)len == sizeof(packet)) | ||
162 | return 1; | ||
163 | |||
164 | if (len <= 0) | ||
165 | return 0; | ||
166 | |||
167 | memcpy(con->last_packet, packet, length); | ||
168 | con->last_packet_length = sizeof(packet); | ||
169 | con->last_packet_sent = len; | ||
170 | return 1; | ||
171 | } | ||
172 | |||
173 | /* return 1 on success. | ||
174 | * return 0 if could not send packet. | ||
175 | * return -1 on failure (connection must be killed). | ||
176 | */ | ||
177 | int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key) | ||
178 | { | ||
179 | uint8_t packet[1 + crypto_box_PUBLICKEYBYTES]; | ||
180 | packet[0] = TCP_PACKET_ROUTING_REQUEST; | ||
181 | memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); | ||
182 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | ||
183 | } | ||
184 | |||
185 | void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id, | ||
186 | uint8_t *public_key), void *object) | ||
187 | { | ||
188 | con->response_callback = response_callback; | ||
189 | con->response_callback_object = object; | ||
190 | } | ||
191 | |||
192 | void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(void *object, uint32_t number, | ||
193 | uint8_t connection_id, uint8_t status), void *object) | ||
194 | { | ||
195 | con->status_callback = status_callback; | ||
196 | con->status_callback_object = object; | ||
197 | } | ||
198 | |||
199 | /* return 1 on success. | ||
200 | * return 0 if could not send packet. | ||
201 | * return -1 on failure. | ||
202 | */ | ||
203 | int send_data(TCP_Client_Connection *con, uint8_t con_id, uint8_t *data, uint16_t length) | ||
204 | { | ||
205 | if (con_id >= NUM_CLIENT_CONNECTIONS) | ||
206 | return -1; | ||
207 | |||
208 | if (con->connections[con_id].status != 2) | ||
209 | return -1; | ||
210 | |||
211 | uint8_t packet[1 + length]; | ||
212 | packet[0] = con_id + NUM_RESERVED_PORTS; | ||
213 | memcpy(packet + 1, data, length); | ||
214 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | ||
215 | } | ||
216 | |||
217 | /* return 1 on success. | ||
218 | * return 0 if could not send packet. | ||
219 | * return -1 on failure. | ||
220 | */ | ||
221 | int send_oob_packet(TCP_Client_Connection *con, uint8_t *public_key, uint8_t *data, uint16_t length) | ||
222 | { | ||
223 | if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) | ||
224 | return -1; | ||
225 | |||
226 | uint8_t packet[1 + crypto_box_PUBLICKEYBYTES + length]; | ||
227 | packet[0] = TCP_PACKET_OOB_SEND; | ||
228 | memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); | ||
229 | memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, data, length); | ||
230 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | ||
231 | } | ||
232 | |||
233 | |||
234 | /* Set the number that will be used as an argument in the callbacks related to con_id. | ||
235 | * | ||
236 | * When not set by this function, the number is ~0. | ||
237 | * | ||
238 | * return 0 on success. | ||
239 | * return -1 on failure. | ||
240 | */ | ||
241 | int set_tcp_connection_number(TCP_Client_Connection *con, uint8_t con_id, uint32_t number) | ||
242 | { | ||
243 | if (con_id >= NUM_CLIENT_CONNECTIONS) | ||
244 | return -1; | ||
245 | |||
246 | if (con->connections[con_id].status == 0) | ||
247 | return -1; | ||
248 | |||
249 | con->connections[con_id].number = number; | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number, | ||
254 | uint8_t connection_id, uint8_t *data, uint16_t length), void *object) | ||
255 | { | ||
256 | con->data_callback = data_callback; | ||
257 | con->data_callback_object = object; | ||
258 | } | ||
259 | |||
260 | void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, uint8_t *public_key, | ||
261 | uint8_t *data, uint16_t length), void *object) | ||
262 | { | ||
263 | con->oob_data_callback = oob_data_callback; | ||
264 | con->oob_data_callback_object = object; | ||
265 | } | ||
266 | |||
267 | /* return 1 on success. | ||
268 | * return 0 if could not send packet. | ||
269 | * return -1 on failure (connection must be killed). | ||
270 | */ | ||
271 | static int send_disconnect_notification(TCP_Client_Connection *con, uint8_t id) | ||
272 | { | ||
273 | uint8_t packet[1 + 1]; | ||
274 | packet[0] = TCP_PACKET_DISCONNECT_NOTIFICATION; | ||
275 | packet[1] = id; | ||
276 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | ||
277 | } | ||
278 | |||
279 | /* return 1 on success. | ||
280 | * return 0 if could not send packet. | ||
281 | * return -1 on failure (connection must be killed). | ||
282 | */ | ||
283 | static int send_ping_request(TCP_Client_Connection *con, uint64_t ping_id) | ||
284 | { | ||
285 | uint8_t packet[1 + sizeof(uint64_t)]; | ||
286 | packet[0] = TCP_PACKET_PING; | ||
287 | memcpy(packet + 1, &ping_id, sizeof(uint64_t)); | ||
288 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | ||
289 | } | ||
290 | |||
291 | /* return 1 on success. | ||
292 | * return 0 if could not send packet. | ||
293 | * return -1 on failure (connection must be killed). | ||
294 | */ | ||
295 | static int send_ping_response(TCP_Client_Connection *con, uint64_t ping_id) | ||
296 | { | ||
297 | uint8_t packet[1 + sizeof(uint64_t)]; | ||
298 | packet[0] = TCP_PACKET_PONG; | ||
299 | memcpy(packet + 1, &ping_id, sizeof(uint64_t)); | ||
300 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | ||
301 | } | ||
302 | |||
303 | /* return 1 on success. | ||
304 | * return 0 if could not send packet. | ||
305 | * return -1 on failure (connection must be killed). | ||
306 | */ | ||
307 | int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id) | ||
308 | { | ||
309 | if (con_id >= NUM_CLIENT_CONNECTIONS) | ||
310 | return -1; | ||
311 | |||
312 | con->connections[con_id].status = 0; | ||
313 | con->connections[con_id].number = 0; | ||
314 | return send_disconnect_notification(con, con_id + NUM_RESERVED_PORTS); | ||
315 | } | ||
316 | |||
317 | /* return 1 on success. | ||
318 | * return 0 if could not send packet. | ||
319 | * return -1 on failure (connection must be killed). | ||
320 | */ | ||
321 | int send_onion_request(TCP_Client_Connection *con, uint8_t *data, uint16_t length) | ||
322 | { | ||
323 | uint8_t packet[1 + length]; | ||
324 | packet[0] = TCP_PACKET_ONION_REQUEST; | ||
325 | memcpy(packet + 1, data, length); | ||
326 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | ||
327 | } | ||
328 | |||
329 | void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, uint8_t *data, | ||
330 | uint16_t length), void *object) | ||
331 | { | ||
332 | con->onion_callback = onion_callback; | ||
333 | con->onion_callback_object = object; | ||
334 | } | ||
335 | |||
133 | /* Create new TCP connection to ip_port/public_key | 336 | /* Create new TCP connection to ip_port/public_key |
134 | */ | 337 | */ |
135 | TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, uint8_t *public_key, uint8_t *self_public_key, | 338 | TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, uint8_t *public_key, uint8_t *self_public_key, |
@@ -149,6 +352,11 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, uint8_t *public_key, | |||
149 | return NULL; | 352 | return NULL; |
150 | } | 353 | } |
151 | 354 | ||
355 | if (!set_socket_nosigpipe(sock)) { | ||
356 | kill_sock(sock); | ||
357 | return 0; | ||
358 | } | ||
359 | |||
152 | if (!(set_socket_nonblock(sock) && connect_sock_to(sock, ip_port))) { | 360 | if (!(set_socket_nonblock(sock) && connect_sock_to(sock, ip_port))) { |
153 | kill_sock(sock); | 361 | kill_sock(sock); |
154 | return NULL; | 362 | return NULL; |
@@ -164,6 +372,7 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, uint8_t *public_key, | |||
164 | temp->status = TCP_CLIENT_CONNECTING; | 372 | temp->status = TCP_CLIENT_CONNECTING; |
165 | temp->sock = sock; | 373 | temp->sock = sock; |
166 | memcpy(temp->public_key, public_key, crypto_box_PUBLICKEYBYTES); | 374 | memcpy(temp->public_key, public_key, crypto_box_PUBLICKEYBYTES); |
375 | temp->ip_port = ip_port; | ||
167 | 376 | ||
168 | if (generate_handshake(temp, self_public_key, self_secret_key) == -1) { | 377 | if (generate_handshake(temp, self_public_key, self_secret_key) == -1) { |
169 | kill_sock(sock); | 378 | kill_sock(sock); |
@@ -176,8 +385,181 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, uint8_t *public_key, | |||
176 | return temp; | 385 | return temp; |
177 | } | 386 | } |
178 | 387 | ||
179 | static int do_confirmed_TCP(TCP_Client_Connection *TCP_connection) | 388 | /* return 0 on success |
389 | * return -1 on failure | ||
390 | */ | ||
391 | static int handle_TCP_packet(TCP_Client_Connection *conn, uint8_t *data, uint16_t length) | ||
180 | { | 392 | { |
393 | if (length <= 1) | ||
394 | return -1; | ||
395 | |||
396 | switch (data[0]) { | ||
397 | case TCP_PACKET_ROUTING_RESPONSE: { | ||
398 | if (length != 1 + 1 + crypto_box_PUBLICKEYBYTES) | ||
399 | return -1; | ||
400 | |||
401 | if (data[1] < NUM_RESERVED_PORTS) | ||
402 | return 0; | ||
403 | |||
404 | uint8_t con_id = data[1] - NUM_RESERVED_PORTS; | ||
405 | |||
406 | if (conn->connections[con_id].status != 0) | ||
407 | return 0; | ||
408 | |||
409 | conn->connections[con_id].status = 1; | ||
410 | conn->connections[con_id].number = ~0; | ||
411 | memcpy(conn->connections[con_id].public_key, data + 2, crypto_box_PUBLICKEYBYTES); | ||
412 | |||
413 | if (conn->response_callback) | ||
414 | conn->response_callback(conn->response_callback_object, con_id, conn->connections[con_id].public_key); | ||
415 | |||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | case TCP_PACKET_CONNECTION_NOTIFICATION: { | ||
420 | if (length != 1 + 1) | ||
421 | return -1; | ||
422 | |||
423 | if (data[1] < NUM_RESERVED_PORTS) | ||
424 | return -1; | ||
425 | |||
426 | uint8_t con_id = data[1] - NUM_RESERVED_PORTS; | ||
427 | |||
428 | if (conn->connections[con_id].status != 1) | ||
429 | return -1; | ||
430 | |||
431 | conn->connections[con_id].status = 2; | ||
432 | |||
433 | if (conn->status_callback) | ||
434 | conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id, | ||
435 | conn->connections[con_id].status); | ||
436 | |||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | case TCP_PACKET_DISCONNECT_NOTIFICATION: { | ||
441 | if (length != 1 + 1) | ||
442 | return -1; | ||
443 | |||
444 | if (data[1] < NUM_RESERVED_PORTS) | ||
445 | return -1; | ||
446 | |||
447 | uint8_t con_id = data[1] - NUM_RESERVED_PORTS; | ||
448 | |||
449 | if (conn->connections[con_id].status == 0) | ||
450 | return 0; | ||
451 | |||
452 | if (conn->connections[con_id].status != 2) | ||
453 | return -1; | ||
454 | |||
455 | conn->connections[con_id].status = 1; | ||
456 | |||
457 | if (conn->status_callback) | ||
458 | conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id, | ||
459 | conn->connections[con_id].status); | ||
460 | |||
461 | return 0; | ||
462 | } | ||
463 | |||
464 | case TCP_PACKET_PING: { | ||
465 | if (length != 1 + sizeof(uint64_t)) | ||
466 | return -1; | ||
467 | |||
468 | uint64_t ping_id; | ||
469 | memcpy(&ping_id, data + 1, sizeof(uint64_t)); | ||
470 | send_ping_response(conn, ping_id); | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | case TCP_PACKET_PONG: { | ||
475 | if (length != 1 + sizeof(uint64_t)) | ||
476 | return -1; | ||
477 | |||
478 | uint64_t ping_id; | ||
479 | memcpy(&ping_id, data + 1, sizeof(uint64_t)); | ||
480 | |||
481 | if (ping_id) { | ||
482 | if (ping_id == conn->ping_id) { | ||
483 | conn->ping_id = 0; | ||
484 | } | ||
485 | |||
486 | return 0; | ||
487 | } else { | ||
488 | return -1; | ||
489 | } | ||
490 | } | ||
491 | |||
492 | case TCP_PACKET_OOB_RECV: { | ||
493 | if (length <= 1 + crypto_box_PUBLICKEYBYTES) | ||
494 | return -1; | ||
495 | |||
496 | if (conn->oob_data_callback) | ||
497 | conn->oob_data_callback(conn->oob_data_callback_object, data + 1, data + 1 + crypto_box_PUBLICKEYBYTES, | ||
498 | length - (1 + crypto_box_PUBLICKEYBYTES)); | ||
499 | |||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | case TCP_PACKET_ONION_RESPONSE: { | ||
504 | conn->onion_callback(conn->onion_callback_object, data + 1, length - 1); | ||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | default: { | ||
509 | if (data[0] < NUM_RESERVED_PORTS) | ||
510 | return -1; | ||
511 | |||
512 | uint8_t con_id = data[0] - NUM_RESERVED_PORTS; | ||
513 | |||
514 | if (conn->data_callback) | ||
515 | conn->data_callback(conn->data_callback_object, conn->connections[con_id].number, con_id, data + 1, length - 1); | ||
516 | } | ||
517 | } | ||
518 | |||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | static int do_confirmed_TCP(TCP_Client_Connection *conn) | ||
523 | { | ||
524 | send_pending_data(conn); | ||
525 | uint8_t packet[MAX_PACKET_SIZE]; | ||
526 | int len; | ||
527 | |||
528 | if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) { | ||
529 | uint64_t ping_id = random_64b(); | ||
530 | |||
531 | if (!ping_id) | ||
532 | ++ping_id; | ||
533 | |||
534 | int ret = send_ping_request(conn, ping_id); | ||
535 | |||
536 | if (ret == 1) { | ||
537 | conn->last_pinged = unix_time(); | ||
538 | conn->ping_id = ping_id; | ||
539 | } else { | ||
540 | if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY + TCP_PING_TIMEOUT)) { | ||
541 | conn->status = TCP_CLIENT_DISCONNECTED; | ||
542 | } | ||
543 | } | ||
544 | } | ||
545 | |||
546 | if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) { | ||
547 | conn->status = TCP_CLIENT_DISCONNECTED; | ||
548 | return 0; | ||
549 | } | ||
550 | |||
551 | while ((len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key, | ||
552 | conn->recv_nonce, packet, sizeof(packet)))) { | ||
553 | if (len == -1) { | ||
554 | conn->status = TCP_CLIENT_DISCONNECTED; | ||
555 | break; | ||
556 | } | ||
557 | |||
558 | if (handle_TCP_packet(conn, packet, len) == -1) { | ||
559 | conn->status = TCP_CLIENT_DISCONNECTED; | ||
560 | break; | ||
561 | } | ||
562 | } | ||
181 | 563 | ||
182 | return 0; | 564 | return 0; |
183 | } | 565 | } |
@@ -204,6 +586,7 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection) | |||
204 | 586 | ||
205 | if (sizeof(data) == len) { | 587 | if (sizeof(data) == len) { |
206 | if (handle_handshake(TCP_connection, data) == 0) { | 588 | if (handle_handshake(TCP_connection, data) == 0) { |
589 | TCP_connection->kill_at = ~0; | ||
207 | TCP_connection->status = TCP_CLIENT_CONFIRMED; | 590 | TCP_connection->status = TCP_CLIENT_CONFIRMED; |
208 | } else { | 591 | } else { |
209 | TCP_connection->kill_at = 0; | 592 | TCP_connection->kill_at = 0; |
@@ -225,7 +608,10 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection) | |||
225 | */ | 608 | */ |
226 | void kill_TCP_connection(TCP_Client_Connection *TCP_connection) | 609 | void kill_TCP_connection(TCP_Client_Connection *TCP_connection) |
227 | { | 610 | { |
611 | if (TCP_connection == NULL) | ||
612 | return; | ||
613 | |||
228 | kill_sock(TCP_connection->sock); | 614 | kill_sock(TCP_connection->sock); |
229 | memset(TCP_connection, 0, sizeof(TCP_Client_Connection)); | 615 | memset(TCP_connection, 0, sizeof(TCP_Client_Connection)); |
230 | free(TCP_connection); | 616 | free(TCP_connection); |
231 | } \ No newline at end of file | 617 | } |
diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h index eb2aa39c..afb95392 100644 --- a/toxcore/TCP_client.h +++ b/toxcore/TCP_client.h | |||
@@ -24,7 +24,7 @@ | |||
24 | #ifndef TCP_CLIENT_H | 24 | #ifndef TCP_CLIENT_H |
25 | #define TCP_CLIENT_H | 25 | #define TCP_CLIENT_H |
26 | 26 | ||
27 | #include "net_crypto.h" | 27 | #include "crypto_core.h" |
28 | #include "TCP_server.h" | 28 | #include "TCP_server.h" |
29 | 29 | ||
30 | #define TCP_CONNECTION_TIMEOUT 10 | 30 | #define TCP_CONNECTION_TIMEOUT 10 |
@@ -40,6 +40,7 @@ typedef struct { | |||
40 | uint8_t status; | 40 | uint8_t status; |
41 | sock_t sock; | 41 | sock_t sock; |
42 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* public key of the server */ | 42 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* public key of the server */ |
43 | IP_Port ip_port; /* The ip and port of the server */ | ||
43 | uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */ | 44 | uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */ |
44 | uint8_t sent_nonce[crypto_box_NONCEBYTES]; /* Nonce of sent packets. */ | 45 | uint8_t sent_nonce[crypto_box_NONCEBYTES]; /* Nonce of sent packets. */ |
45 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; | 46 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; |
@@ -55,6 +56,25 @@ typedef struct { | |||
55 | 56 | ||
56 | uint64_t last_pinged; | 57 | uint64_t last_pinged; |
57 | uint64_t ping_id; | 58 | uint64_t ping_id; |
59 | |||
60 | void *net_crypto_pointer; | ||
61 | uint32_t net_crypto_location; | ||
62 | struct { | ||
63 | uint8_t status; /* 0 if not used, 1 if other is offline, 2 if other is online. */ | ||
64 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; | ||
65 | uint32_t number; | ||
66 | } connections[NUM_CLIENT_CONNECTIONS]; | ||
67 | int (*response_callback)(void *object, uint8_t connection_id, uint8_t *public_key); | ||
68 | void *response_callback_object; | ||
69 | int (*status_callback)(void *object, uint32_t number, uint8_t connection_id, uint8_t status); | ||
70 | void *status_callback_object; | ||
71 | int (*data_callback)(void *object, uint32_t number, uint8_t connection_id, uint8_t *data, uint16_t length); | ||
72 | void *data_callback_object; | ||
73 | int (*oob_data_callback)(void *object, uint8_t *public_key, uint8_t *data, uint16_t length); | ||
74 | void *oob_data_callback_object; | ||
75 | |||
76 | int (*onion_callback)(void *object, uint8_t *data, uint16_t length); | ||
77 | void *onion_callback_object; | ||
58 | } TCP_Client_Connection; | 78 | } TCP_Client_Connection; |
59 | 79 | ||
60 | /* Create new TCP connection to ip_port/public_key | 80 | /* Create new TCP connection to ip_port/public_key |
@@ -70,9 +90,54 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection); | |||
70 | */ | 90 | */ |
71 | void kill_TCP_connection(TCP_Client_Connection *TCP_connection); | 91 | void kill_TCP_connection(TCP_Client_Connection *TCP_connection); |
72 | 92 | ||
73 | int get_TCP_connection_status(TCP_Client_Connection *TCP_connection); | 93 | /* return 1 on success. |
94 | * return 0 if could not send packet. | ||
95 | * return -1 on failure (connection must be killed). | ||
96 | */ | ||
97 | int send_onion_request(TCP_Client_Connection *con, uint8_t *data, uint16_t length); | ||
98 | void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, uint8_t *data, | ||
99 | uint16_t length), void *object); | ||
74 | 100 | ||
75 | int read_TCP_connection(TCP_Client_Connection *TCP_connection, uint8_t *data); | 101 | /* return 1 on success. |
102 | * return 0 if could not send packet. | ||
103 | * return -1 on failure (connection must be killed). | ||
104 | */ | ||
105 | int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key); | ||
106 | void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id, | ||
107 | uint8_t *public_key), void *object); | ||
108 | void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(void *object, uint32_t number, | ||
109 | uint8_t connection_id, uint8_t status), void *object); | ||
110 | |||
111 | /* return 1 on success. | ||
112 | * return 0 if could not send packet. | ||
113 | * return -1 on failure (connection must be killed). | ||
114 | */ | ||
115 | int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id); | ||
116 | |||
117 | /* Set the number that will be used as an argument in the callbacks related to con_id. | ||
118 | * | ||
119 | * When not set by this function, the number is ~0. | ||
120 | * | ||
121 | * return 0 on success. | ||
122 | * return -1 on failure. | ||
123 | */ | ||
124 | int set_tcp_connection_number(TCP_Client_Connection *con, uint8_t con_id, uint32_t number); | ||
125 | |||
126 | /* return 1 on success. | ||
127 | * return 0 if could not send packet. | ||
128 | * return -1 on failure. | ||
129 | */ | ||
130 | int send_data(TCP_Client_Connection *con, uint8_t con_id, uint8_t *data, uint16_t length); | ||
131 | void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number, | ||
132 | uint8_t connection_id, uint8_t *data, uint16_t length), void *object); | ||
133 | |||
134 | /* return 1 on success. | ||
135 | * return 0 if could not send packet. | ||
136 | * return -1 on failure. | ||
137 | */ | ||
138 | int send_oob_packet(TCP_Client_Connection *con, uint8_t *public_key, uint8_t *data, uint16_t length); | ||
139 | void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, uint8_t *public_key, | ||
140 | uint8_t *data, uint16_t length), void *object); | ||
76 | 141 | ||
77 | 142 | ||
78 | #endif | 143 | #endif |
diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 4eed1209..ceab5f10 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c | |||
@@ -20,6 +20,10 @@ | |||
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #ifdef HAVE_CONFIG_H | ||
24 | #include "config.h" | ||
25 | #endif | ||
26 | |||
23 | #include "TCP_server.h" | 27 | #include "TCP_server.h" |
24 | 28 | ||
25 | #if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32) | 29 | #if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32) |
@@ -69,17 +73,46 @@ static int realloc_connection(TCP_Server *TCP_server, uint32_t num) | |||
69 | return 0; | 73 | return 0; |
70 | } | 74 | } |
71 | 75 | ||
76 | if (num == TCP_server->size_accepted_connections) { | ||
77 | return 0; | ||
78 | } | ||
79 | |||
72 | TCP_Secure_Connection *new_connections = realloc(TCP_server->accepted_connection_array, | 80 | TCP_Secure_Connection *new_connections = realloc(TCP_server->accepted_connection_array, |
73 | num * sizeof(TCP_Secure_Connection)); | 81 | num * sizeof(TCP_Secure_Connection)); |
74 | 82 | ||
75 | if (new_connections == NULL) | 83 | if (new_connections == NULL) |
76 | return -1; | 84 | return -1; |
77 | 85 | ||
86 | if (num > TCP_server->size_accepted_connections) { | ||
87 | uint32_t old_size = TCP_server->size_accepted_connections; | ||
88 | uint32_t size_new_entries = (num - old_size) * sizeof(TCP_Secure_Connection); | ||
89 | memset(new_connections + old_size, 0, size_new_entries); | ||
90 | } | ||
91 | |||
78 | TCP_server->accepted_connection_array = new_connections; | 92 | TCP_server->accepted_connection_array = new_connections; |
79 | TCP_server->size_accepted_connections = num; | 93 | TCP_server->size_accepted_connections = num; |
80 | return 0; | 94 | return 0; |
81 | } | 95 | } |
82 | 96 | ||
97 | /* return index corresponding to connection with peer on success | ||
98 | * return -1 on failure. | ||
99 | */ | ||
100 | static int get_TCP_connection_index(TCP_Server *TCP_server, uint8_t *public_key) | ||
101 | { | ||
102 | //TODO optimize this function. | ||
103 | uint32_t i; | ||
104 | |||
105 | for (i = 0; i < TCP_server->size_accepted_connections; ++i) { | ||
106 | if (memcmp(TCP_server->accepted_connection_array[i].public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) | ||
107 | return i; | ||
108 | } | ||
109 | |||
110 | return -1; | ||
111 | } | ||
112 | |||
113 | |||
114 | static int kill_accepted(TCP_Server *TCP_server, int index); | ||
115 | |||
83 | /* Add accepted TCP connection to the list. | 116 | /* Add accepted TCP connection to the list. |
84 | * | 117 | * |
85 | * return index on success | 118 | * return index on success |
@@ -87,7 +120,12 @@ static int realloc_connection(TCP_Server *TCP_server, uint32_t num) | |||
87 | */ | 120 | */ |
88 | static int add_accepted(TCP_Server *TCP_server, TCP_Secure_Connection *con) | 121 | static int add_accepted(TCP_Server *TCP_server, TCP_Secure_Connection *con) |
89 | { | 122 | { |
90 | int index = -1; | 123 | int index = get_TCP_connection_index(TCP_server, con->public_key); |
124 | |||
125 | if (index != -1) { /* If an old connection to the same public key exists, kill it. */ | ||
126 | kill_accepted(TCP_server, index); | ||
127 | index = -1; | ||
128 | } | ||
91 | 129 | ||
92 | if (TCP_server->size_accepted_connections == TCP_server->num_accepted_connections) { | 130 | if (TCP_server->size_accepted_connections == TCP_server->num_accepted_connections) { |
93 | if (realloc_connection(TCP_server, TCP_server->size_accepted_connections + 4) == -1) | 131 | if (realloc_connection(TCP_server, TCP_server->size_accepted_connections + 4) == -1) |
@@ -141,22 +179,6 @@ static int del_accepted(TCP_Server *TCP_server, int index) | |||
141 | return 0; | 179 | return 0; |
142 | } | 180 | } |
143 | 181 | ||
144 | /* return index corresponding to connection with peer on success | ||
145 | * return -1 on failure. | ||
146 | */ | ||
147 | static int get_TCP_connection_index(TCP_Server *TCP_server, uint8_t *public_key) | ||
148 | { | ||
149 | //TODO optimize this function. | ||
150 | uint32_t i; | ||
151 | |||
152 | for (i = 0; i < TCP_server->size_accepted_connections; ++i) { | ||
153 | if (memcmp(TCP_server->accepted_connection_array[i].public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) | ||
154 | return i; | ||
155 | } | ||
156 | |||
157 | return -1; | ||
158 | } | ||
159 | |||
160 | /* Read the next two bytes in TCP stream then convert them to | 182 | /* Read the next two bytes in TCP stream then convert them to |
161 | * length (host byte order). | 183 | * length (host byte order). |
162 | * | 184 | * |
@@ -224,14 +246,15 @@ int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length) | |||
224 | return -1; | 246 | return -1; |
225 | } | 247 | } |
226 | 248 | ||
227 | /* return length of recieved packet on success. | 249 | /* return length of received packet on success. |
228 | * return 0 if could not read any packet. | 250 | * return 0 if could not read any packet. |
229 | * return -1 on failure (connection must be killed). | 251 | * return -1 on failure (connection must be killed). |
230 | */ | 252 | */ |
231 | static int read_packet_TCP_secure_connection(TCP_Secure_Connection *con, uint8_t *data, uint16_t max_len) | 253 | int read_packet_TCP_secure_connection(sock_t sock, uint16_t *next_packet_length, uint8_t *shared_key, |
254 | uint8_t *recv_nonce, uint8_t *data, uint16_t max_len) | ||
232 | { | 255 | { |
233 | if (con->next_packet_length == 0) { | 256 | if (*next_packet_length == 0) { |
234 | uint16_t len = read_TCP_length(con->sock); | 257 | uint16_t len = read_TCP_length(sock); |
235 | 258 | ||
236 | if (len == (uint16_t)~0) | 259 | if (len == (uint16_t)~0) |
237 | return -1; | 260 | return -1; |
@@ -239,26 +262,26 @@ static int read_packet_TCP_secure_connection(TCP_Secure_Connection *con, uint8_t | |||
239 | if (len == 0) | 262 | if (len == 0) |
240 | return 0; | 263 | return 0; |
241 | 264 | ||
242 | con->next_packet_length = len; | 265 | *next_packet_length = len; |
243 | } | 266 | } |
244 | 267 | ||
245 | if (max_len + crypto_box_MACBYTES < con->next_packet_length) | 268 | if (max_len + crypto_box_MACBYTES < *next_packet_length) |
246 | return -1; | 269 | return -1; |
247 | 270 | ||
248 | uint8_t data_encrypted[con->next_packet_length]; | 271 | uint8_t data_encrypted[*next_packet_length]; |
249 | int len_packet = read_TCP_packet(con->sock, data_encrypted, con->next_packet_length); | 272 | int len_packet = read_TCP_packet(sock, data_encrypted, *next_packet_length); |
250 | 273 | ||
251 | if (len_packet != con->next_packet_length) | 274 | if (len_packet != *next_packet_length) |
252 | return 0; | 275 | return 0; |
253 | 276 | ||
254 | con->next_packet_length = 0; | 277 | *next_packet_length = 0; |
255 | 278 | ||
256 | int len = decrypt_data_fast(con->shared_key, con->recv_nonce, data_encrypted, len_packet, data); | 279 | int len = decrypt_data_symmetric(shared_key, recv_nonce, data_encrypted, len_packet, data); |
257 | 280 | ||
258 | if (len + crypto_box_MACBYTES != len_packet) | 281 | if (len + crypto_box_MACBYTES != len_packet) |
259 | return -1; | 282 | return -1; |
260 | 283 | ||
261 | increment_nonce(con->recv_nonce); | 284 | increment_nonce(recv_nonce); |
262 | 285 | ||
263 | return len; | 286 | return len; |
264 | } | 287 | } |
@@ -308,7 +331,7 @@ static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, uint8_ | |||
308 | 331 | ||
309 | uint16_t c_length = htons(length + crypto_box_MACBYTES); | 332 | uint16_t c_length = htons(length + crypto_box_MACBYTES); |
310 | memcpy(packet, &c_length, sizeof(uint16_t)); | 333 | memcpy(packet, &c_length, sizeof(uint16_t)); |
311 | int len = encrypt_data_fast(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); | 334 | int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); |
312 | 335 | ||
313 | if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) | 336 | if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) |
314 | return -1; | 337 | return -1; |
@@ -337,6 +360,33 @@ static void kill_TCP_connection(TCP_Secure_Connection *con) | |||
337 | memset(con, 0, sizeof(TCP_Secure_Connection)); | 360 | memset(con, 0, sizeof(TCP_Secure_Connection)); |
338 | } | 361 | } |
339 | 362 | ||
363 | static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number); | ||
364 | |||
365 | /* Kill an accepted TCP_Secure_Connection | ||
366 | * | ||
367 | * return -1 on failure. | ||
368 | * return 0 on success. | ||
369 | */ | ||
370 | static int kill_accepted(TCP_Server *TCP_server, int index) | ||
371 | { | ||
372 | if ((uint32_t)index >= TCP_server->size_accepted_connections) | ||
373 | return -1; | ||
374 | |||
375 | uint32_t i; | ||
376 | |||
377 | for (i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) { | ||
378 | rm_connection_index(TCP_server, &TCP_server->accepted_connection_array[index], i); | ||
379 | } | ||
380 | |||
381 | sock_t sock = TCP_server->accepted_connection_array[index].sock; | ||
382 | |||
383 | if (del_accepted(TCP_server, index) != 0) | ||
384 | return -1; | ||
385 | |||
386 | kill_sock(sock); | ||
387 | return 0; | ||
388 | } | ||
389 | |||
340 | /* return 1 if everything went well. | 390 | /* return 1 if everything went well. |
341 | * return -1 if the connection must be killed. | 391 | * return -1 if the connection must be killed. |
342 | */ | 392 | */ |
@@ -351,8 +401,8 @@ static int handle_TCP_handshake(TCP_Secure_Connection *con, uint8_t *data, uint1 | |||
351 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; | 401 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; |
352 | encrypt_precompute(data, self_secret_key, shared_key); | 402 | encrypt_precompute(data, self_secret_key, shared_key); |
353 | uint8_t plain[TCP_HANDSHAKE_PLAIN_SIZE]; | 403 | uint8_t plain[TCP_HANDSHAKE_PLAIN_SIZE]; |
354 | int len = decrypt_data_fast(shared_key, data + crypto_box_PUBLICKEYBYTES, | 404 | int len = decrypt_data_symmetric(shared_key, data + crypto_box_PUBLICKEYBYTES, |
355 | data + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES, plain); | 405 | data + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES, plain); |
356 | 406 | ||
357 | if (len != TCP_HANDSHAKE_PLAIN_SIZE) | 407 | if (len != TCP_HANDSHAKE_PLAIN_SIZE) |
358 | return -1; | 408 | return -1; |
@@ -368,7 +418,8 @@ static int handle_TCP_handshake(TCP_Secure_Connection *con, uint8_t *data, uint1 | |||
368 | uint8_t response[TCP_SERVER_HANDSHAKE_SIZE]; | 418 | uint8_t response[TCP_SERVER_HANDSHAKE_SIZE]; |
369 | new_nonce(response); | 419 | new_nonce(response); |
370 | 420 | ||
371 | len = encrypt_data_fast(shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE, response + crypto_box_NONCEBYTES); | 421 | len = encrypt_data_symmetric(shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE, |
422 | response + crypto_box_NONCEBYTES); | ||
372 | 423 | ||
373 | if (len != TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES) | 424 | if (len != TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES) |
374 | return -1; | 425 | return -1; |
@@ -449,9 +500,16 @@ static int handle_TCP_routing_req(TCP_Server *TCP_server, uint32_t con_id, uint8 | |||
449 | } | 500 | } |
450 | 501 | ||
451 | for (i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) { | 502 | for (i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) { |
452 | if (con->connections[i].status == 0) { | 503 | if (con->connections[i].status != 0) { |
504 | if (memcmp(public_key, con->connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) { | ||
505 | if (send_routing_response(con, i + NUM_RESERVED_PORTS, public_key) == -1) { | ||
506 | return -1; | ||
507 | } else { | ||
508 | return 0; | ||
509 | } | ||
510 | } | ||
511 | } else if (index == (uint32_t)~0) { | ||
453 | index = i; | 512 | index = i; |
454 | break; | ||
455 | } | 513 | } |
456 | } | 514 | } |
457 | 515 | ||
@@ -502,7 +560,37 @@ static int handle_TCP_routing_req(TCP_Server *TCP_server, uint32_t con_id, uint8 | |||
502 | return 0; | 560 | return 0; |
503 | } | 561 | } |
504 | 562 | ||
505 | static int disconnect_conection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number) | 563 | /* return 0 on success. |
564 | * return -1 on failure (connection must be killed). | ||
565 | */ | ||
566 | static int handle_TCP_oob_send(TCP_Server *TCP_server, uint32_t con_id, uint8_t *public_key, uint8_t *data, | ||
567 | uint16_t length) | ||
568 | { | ||
569 | if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) | ||
570 | return -1; | ||
571 | |||
572 | TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[con_id]; | ||
573 | |||
574 | int other_index = get_TCP_connection_index(TCP_server, public_key); | ||
575 | |||
576 | if (other_index != -1) { | ||
577 | uint8_t resp_packet[1 + crypto_box_PUBLICKEYBYTES + length]; | ||
578 | resp_packet[0] = TCP_PACKET_OOB_RECV; | ||
579 | memcpy(resp_packet + 1, con->public_key, crypto_box_PUBLICKEYBYTES); | ||
580 | memcpy(resp_packet + 1 + crypto_box_PUBLICKEYBYTES, data, length); | ||
581 | write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[other_index], resp_packet, | ||
582 | sizeof(resp_packet)); | ||
583 | } | ||
584 | |||
585 | return 0; | ||
586 | } | ||
587 | |||
588 | /* Remove connection with con_number from the connections array of con. | ||
589 | * | ||
590 | * return -1 on failure. | ||
591 | * return 0 on success. | ||
592 | */ | ||
593 | static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number) | ||
506 | { | 594 | { |
507 | if (con_number >= NUM_CLIENT_CONNECTIONS) | 595 | if (con_number >= NUM_CLIENT_CONNECTIONS) |
508 | return -1; | 596 | return -1; |
@@ -526,8 +614,6 @@ static int disconnect_conection_index(TCP_Server *TCP_server, TCP_Secure_Connect | |||
526 | con->connections[con_number].index = 0; | 614 | con->connections[con_number].index = 0; |
527 | con->connections[con_number].other_id = 0; | 615 | con->connections[con_number].other_id = 0; |
528 | con->connections[con_number].status = 0; | 616 | con->connections[con_number].status = 0; |
529 | //TODO: return values? | ||
530 | send_disconnect_notification(con, con_number); | ||
531 | return 0; | 617 | return 0; |
532 | } else { | 618 | } else { |
533 | return -1; | 619 | return -1; |
@@ -586,7 +672,7 @@ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, uint8_t *d | |||
586 | if (length != 2) | 672 | if (length != 2) |
587 | return -1; | 673 | return -1; |
588 | 674 | ||
589 | return disconnect_conection_index(TCP_server, con, data[1] - NUM_RESERVED_PORTS); | 675 | return rm_connection_index(TCP_server, con, data[1] - NUM_RESERVED_PORTS); |
590 | } | 676 | } |
591 | 677 | ||
592 | case TCP_PACKET_PING: { | 678 | case TCP_PACKET_PING: { |
@@ -618,6 +704,14 @@ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, uint8_t *d | |||
618 | } | 704 | } |
619 | } | 705 | } |
620 | 706 | ||
707 | case TCP_PACKET_OOB_SEND: { | ||
708 | if (length <= 1 + crypto_box_PUBLICKEYBYTES) | ||
709 | return -1; | ||
710 | |||
711 | return handle_TCP_oob_send(TCP_server, con_id, data + 1, data + 1 + crypto_box_PUBLICKEYBYTES, | ||
712 | length - (1 + crypto_box_PUBLICKEYBYTES)); | ||
713 | } | ||
714 | |||
621 | case TCP_PACKET_ONION_REQUEST: { | 715 | case TCP_PACKET_ONION_REQUEST: { |
622 | if (TCP_server->onion) { | 716 | if (TCP_server->onion) { |
623 | if (length <= 1 + crypto_box_NONCEBYTES + ONION_SEND_BASE * 2) | 717 | if (length <= 1 + crypto_box_NONCEBYTES + ONION_SEND_BASE * 2) |
@@ -642,22 +736,22 @@ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, uint8_t *d | |||
642 | if (data[0] < NUM_RESERVED_PORTS) | 736 | if (data[0] < NUM_RESERVED_PORTS) |
643 | return -1; | 737 | return -1; |
644 | 738 | ||
645 | uint8_t con_id = data[0] - NUM_RESERVED_PORTS; | 739 | uint8_t c_id = data[0] - NUM_RESERVED_PORTS; |
646 | 740 | ||
647 | if (con_id >= NUM_CLIENT_CONNECTIONS) | 741 | if (c_id >= NUM_CLIENT_CONNECTIONS) |
648 | return -1; | 742 | return -1; |
649 | 743 | ||
650 | if (con->connections[con_id].status == 0) | 744 | if (con->connections[c_id].status == 0) |
651 | return -1; | 745 | return -1; |
652 | 746 | ||
653 | if (con->connections[con_id].status != 2) | 747 | if (con->connections[c_id].status != 2) |
654 | return 0; | 748 | return 0; |
655 | 749 | ||
656 | uint32_t index = con->connections[con_id].index; | 750 | uint32_t index = con->connections[c_id].index; |
657 | uint8_t other_con_id = con->connections[con_id].other_id + NUM_RESERVED_PORTS; | 751 | uint8_t other_c_id = con->connections[c_id].other_id + NUM_RESERVED_PORTS; |
658 | uint8_t new_data[length]; | 752 | uint8_t new_data[length]; |
659 | memcpy(new_data, data, length); | 753 | memcpy(new_data, data, length); |
660 | new_data[0] = other_con_id; | 754 | new_data[0] = other_c_id; |
661 | int ret = write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[index], new_data, length); | 755 | int ret = write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[index], new_data, length); |
662 | 756 | ||
663 | if (ret == -1) | 757 | if (ret == -1) |
@@ -678,11 +772,8 @@ static int confirm_TCP_connection(TCP_Server *TCP_server, TCP_Secure_Connection | |||
678 | if (index == -1) | 772 | if (index == -1) |
679 | return -1; | 773 | return -1; |
680 | 774 | ||
681 | TCP_Secure_Connection *conn = &TCP_server->accepted_connection_array[index]; | ||
682 | |||
683 | if (handle_TCP_packet(TCP_server, index, data, length) == -1) { | 775 | if (handle_TCP_packet(TCP_server, index, data, length) == -1) { |
684 | kill_TCP_connection(conn); | 776 | kill_accepted(TCP_server, index); |
685 | del_accepted(TCP_server, index); | ||
686 | } | 777 | } |
687 | 778 | ||
688 | return 0; | 779 | return 0; |
@@ -701,6 +792,11 @@ static int accept_connection(TCP_Server *TCP_server, sock_t sock) | |||
701 | return 0; | 792 | return 0; |
702 | } | 793 | } |
703 | 794 | ||
795 | if (!set_socket_nosigpipe(sock)) { | ||
796 | kill_sock(sock); | ||
797 | return 0; | ||
798 | } | ||
799 | |||
704 | TCP_Secure_Connection *conn = | 800 | TCP_Secure_Connection *conn = |
705 | &TCP_server->incomming_connection_queue[TCP_server->incomming_connection_queue_index % MAX_INCOMMING_CONNECTIONS]; | 801 | &TCP_server->incomming_connection_queue[TCP_server->incomming_connection_queue_index % MAX_INCOMMING_CONNECTIONS]; |
706 | 802 | ||
@@ -848,7 +944,8 @@ static void do_TCP_unconfirmed(TCP_Server *TCP_server) | |||
848 | continue; | 944 | continue; |
849 | 945 | ||
850 | uint8_t packet[MAX_PACKET_SIZE]; | 946 | uint8_t packet[MAX_PACKET_SIZE]; |
851 | int len = read_packet_TCP_secure_connection(conn, packet, sizeof(packet)); | 947 | int len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key, conn->recv_nonce, |
948 | packet, sizeof(packet)); | ||
852 | 949 | ||
853 | if (len == 0) { | 950 | if (len == 0) { |
854 | continue; | 951 | continue; |
@@ -889,12 +986,16 @@ static void do_TCP_confirmed(TCP_Server *TCP_server) | |||
889 | if (ret == 1) { | 986 | if (ret == 1) { |
890 | conn->last_pinged = unix_time(); | 987 | conn->last_pinged = unix_time(); |
891 | conn->ping_id = ping_id; | 988 | conn->ping_id = ping_id; |
989 | } else { | ||
990 | if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY + TCP_PING_TIMEOUT)) { | ||
991 | kill_accepted(TCP_server, i); | ||
992 | continue; | ||
993 | } | ||
892 | } | 994 | } |
893 | } | 995 | } |
894 | 996 | ||
895 | if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) { | 997 | if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) { |
896 | kill_TCP_connection(conn); | 998 | kill_accepted(TCP_server, i); |
897 | del_accepted(TCP_server, i); | ||
898 | continue; | 999 | continue; |
899 | } | 1000 | } |
900 | 1001 | ||
@@ -902,16 +1003,15 @@ static void do_TCP_confirmed(TCP_Server *TCP_server) | |||
902 | uint8_t packet[MAX_PACKET_SIZE]; | 1003 | uint8_t packet[MAX_PACKET_SIZE]; |
903 | int len; | 1004 | int len; |
904 | 1005 | ||
905 | while ((len = read_packet_TCP_secure_connection(conn, packet, sizeof(packet)))) { | 1006 | while ((len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key, |
1007 | conn->recv_nonce, packet, sizeof(packet)))) { | ||
906 | if (len == -1) { | 1008 | if (len == -1) { |
907 | kill_TCP_connection(conn); | 1009 | kill_accepted(TCP_server, i); |
908 | del_accepted(TCP_server, i); | ||
909 | break; | 1010 | break; |
910 | } | 1011 | } |
911 | 1012 | ||
912 | if (handle_TCP_packet(TCP_server, i, packet, len) == -1) { | 1013 | if (handle_TCP_packet(TCP_server, i, packet, len) == -1) { |
913 | kill_TCP_connection(conn); | 1014 | kill_accepted(TCP_server, i); |
914 | del_accepted(TCP_server, i); | ||
915 | break; | 1015 | break; |
916 | } | 1016 | } |
917 | } | 1017 | } |
diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h index 3ae0eba4..fc8c234b 100644 --- a/toxcore/TCP_server.h +++ b/toxcore/TCP_server.h | |||
@@ -23,10 +23,10 @@ | |||
23 | #ifndef TCP_SERVER_H | 23 | #ifndef TCP_SERVER_H |
24 | #define TCP_SERVER_H | 24 | #define TCP_SERVER_H |
25 | 25 | ||
26 | #include "net_crypto.h" | 26 | #include "crypto_core.h" |
27 | #include "onion.h" | 27 | #include "onion.h" |
28 | 28 | ||
29 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) | 29 | #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MACH__) |
30 | #define MSG_NOSIGNAL 0 | 30 | #define MSG_NOSIGNAL 0 |
31 | #endif | 31 | #endif |
32 | 32 | ||
@@ -39,6 +39,7 @@ | |||
39 | #define TCP_HANDSHAKE_PLAIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES) | 39 | #define TCP_HANDSHAKE_PLAIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES) |
40 | #define TCP_SERVER_HANDSHAKE_SIZE (crypto_box_NONCEBYTES + TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES) | 40 | #define TCP_SERVER_HANDSHAKE_SIZE (crypto_box_NONCEBYTES + TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES) |
41 | #define TCP_CLIENT_HANDSHAKE_SIZE (crypto_box_PUBLICKEYBYTES + TCP_SERVER_HANDSHAKE_SIZE) | 41 | #define TCP_CLIENT_HANDSHAKE_SIZE (crypto_box_PUBLICKEYBYTES + TCP_SERVER_HANDSHAKE_SIZE) |
42 | #define TCP_MAX_OOB_DATA_LENGTH 1024 | ||
42 | 43 | ||
43 | #define NUM_RESERVED_PORTS 16 | 44 | #define NUM_RESERVED_PORTS 16 |
44 | #define NUM_CLIENT_CONNECTIONS (256 - NUM_RESERVED_PORTS) | 45 | #define NUM_CLIENT_CONNECTIONS (256 - NUM_RESERVED_PORTS) |
@@ -49,16 +50,16 @@ | |||
49 | #define TCP_PACKET_DISCONNECT_NOTIFICATION 3 | 50 | #define TCP_PACKET_DISCONNECT_NOTIFICATION 3 |
50 | #define TCP_PACKET_PING 4 | 51 | #define TCP_PACKET_PING 4 |
51 | #define TCP_PACKET_PONG 5 | 52 | #define TCP_PACKET_PONG 5 |
53 | #define TCP_PACKET_OOB_SEND 6 | ||
54 | #define TCP_PACKET_OOB_RECV 7 | ||
52 | #define TCP_PACKET_ONION_REQUEST 8 | 55 | #define TCP_PACKET_ONION_REQUEST 8 |
53 | #define TCP_PACKET_ONION_RESPONSE 9 | 56 | #define TCP_PACKET_ONION_RESPONSE 9 |
54 | 57 | ||
55 | #define ARRAY_ENTRY_SIZE 6 | 58 | #define ARRAY_ENTRY_SIZE 6 |
56 | 59 | ||
57 | #define TCP_ONION_FAMILY (AF_INET6 + 1) | ||
58 | |||
59 | /* frequency to ping connected nodes and timeout in seconds */ | 60 | /* frequency to ping connected nodes and timeout in seconds */ |
60 | #define TCP_PING_FREQUENCY 30 | 61 | #define TCP_PING_FREQUENCY 30 |
61 | #define TCP_PING_TIMEOUT 20 | 62 | #define TCP_PING_TIMEOUT 10 |
62 | 63 | ||
63 | enum { | 64 | enum { |
64 | TCP_STATUS_NO_STATUS, | 65 | TCP_STATUS_NO_STATUS, |
@@ -140,4 +141,12 @@ uint16_t read_TCP_length(sock_t sock); | |||
140 | */ | 141 | */ |
141 | int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length); | 142 | int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length); |
142 | 143 | ||
144 | /* return length of received packet on success. | ||
145 | * return 0 if could not read any packet. | ||
146 | * return -1 on failure (connection must be killed). | ||
147 | */ | ||
148 | int read_packet_TCP_secure_connection(sock_t sock, uint16_t *next_packet_length, uint8_t *shared_key, | ||
149 | uint8_t *recv_nonce, uint8_t *data, uint16_t max_len); | ||
150 | |||
151 | |||
143 | #endif | 152 | #endif |
diff --git a/toxcore/assoc.c b/toxcore/assoc.c index c8f58c9c..ed1ec241 100644 --- a/toxcore/assoc.c +++ b/toxcore/assoc.c | |||
@@ -29,7 +29,7 @@ | |||
29 | * Candidates are kept in buckets of hash tables. The hash | 29 | * Candidates are kept in buckets of hash tables. The hash |
30 | * function is calculated from the client_id. Up to | 30 | * function is calculated from the client_id. Up to |
31 | * HASH_COLLIDE_COUNT alternative positions are tried if | 31 | * HASH_COLLIDE_COUNT alternative positions are tried if |
32 | * the inital position is already used by a different entry. | 32 | * the initial position is already used by a different entry. |
33 | * The collision function is multiplicative, not additive. | 33 | * The collision function is multiplicative, not additive. |
34 | * | 34 | * |
35 | * A new candidate can bump an existing candidate, if it is | 35 | * A new candidate can bump an existing candidate, if it is |
diff --git a/toxcore/crypto_core.c b/toxcore/crypto_core.c new file mode 100644 index 00000000..6e92f5b6 --- /dev/null +++ b/toxcore/crypto_core.c | |||
@@ -0,0 +1,262 @@ | |||
1 | /* net_crypto.c | ||
2 | * | ||
3 | * Functions for the core crypto. | ||
4 | * | ||
5 | * NOTE: This code has to be perfect. We don't mess around with encryption. | ||
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 | * | ||
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 | */ | ||
25 | |||
26 | #ifdef HAVE_CONFIG_H | ||
27 | #include "config.h" | ||
28 | #endif | ||
29 | |||
30 | #include "crypto_core.h" | ||
31 | |||
32 | |||
33 | /* Use this instead of memcmp; not vulnerable to timing attacks. | ||
34 | returns 0 if both mem locations of length are equal, | ||
35 | return -1 if they are not. */ | ||
36 | int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length) | ||
37 | { | ||
38 | if (length == 16) { | ||
39 | return crypto_verify_16(mem1, mem2); | ||
40 | } else if (length == 32) { | ||
41 | return crypto_verify_32(mem1, mem2); | ||
42 | } | ||
43 | |||
44 | unsigned int i, check = 0; | ||
45 | |||
46 | for (i = 0; i < length; ++i) { | ||
47 | check |= mem1[i] ^ mem2[i]; | ||
48 | } | ||
49 | |||
50 | return (1 & ((check - 1) >> 8)) - 1; | ||
51 | } | ||
52 | |||
53 | /* return a random number. | ||
54 | */ | ||
55 | uint32_t random_int(void) | ||
56 | { | ||
57 | uint32_t randnum; | ||
58 | randombytes((uint8_t *)&randnum , sizeof(randnum)); | ||
59 | return randnum; | ||
60 | } | ||
61 | |||
62 | uint64_t random_64b(void) | ||
63 | { | ||
64 | uint64_t randnum; | ||
65 | randombytes((uint8_t *)&randnum, sizeof(randnum)); | ||
66 | return randnum; | ||
67 | } | ||
68 | |||
69 | /* Precomputes the shared key from their public_key and our secret_key. | ||
70 | * This way we can avoid an expensive elliptic curve scalar multiply for each | ||
71 | * encrypt/decrypt operation. | ||
72 | * enc_key has to be crypto_box_BEFORENMBYTES bytes long. | ||
73 | */ | ||
74 | void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_key) | ||
75 | { | ||
76 | crypto_box_beforenm(enc_key, public_key, secret_key); | ||
77 | } | ||
78 | |||
79 | int encrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *plain, uint32_t length, uint8_t *encrypted) | ||
80 | { | ||
81 | if (length == 0) | ||
82 | return -1; | ||
83 | |||
84 | uint8_t temp_plain[length + crypto_box_ZEROBYTES]; | ||
85 | uint8_t temp_encrypted[length + crypto_box_MACBYTES + crypto_box_BOXZEROBYTES]; | ||
86 | |||
87 | memset(temp_plain, 0, crypto_box_ZEROBYTES); | ||
88 | memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); // Pad the message with 32 0 bytes. | ||
89 | |||
90 | if (crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, secret_key) != 0) | ||
91 | return -1; | ||
92 | |||
93 | /* Unpad the encrypted message. */ | ||
94 | memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES); | ||
95 | return length + crypto_box_MACBYTES; | ||
96 | } | ||
97 | |||
98 | int decrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *encrypted, uint32_t length, uint8_t *plain) | ||
99 | { | ||
100 | if (length <= crypto_box_BOXZEROBYTES) | ||
101 | return -1; | ||
102 | |||
103 | uint8_t temp_plain[length + crypto_box_ZEROBYTES]; | ||
104 | uint8_t temp_encrypted[length + crypto_box_BOXZEROBYTES]; | ||
105 | |||
106 | memset(temp_plain, 0, crypto_box_BOXZEROBYTES); | ||
107 | memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); // Pad the message with 16 0 bytes. | ||
108 | |||
109 | if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce, secret_key) != 0) | ||
110 | return -1; | ||
111 | |||
112 | memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES); | ||
113 | return length - crypto_box_MACBYTES; | ||
114 | } | ||
115 | |||
116 | int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | ||
117 | uint8_t *plain, uint32_t length, uint8_t *encrypted) | ||
118 | { | ||
119 | uint8_t k[crypto_box_BEFORENMBYTES]; | ||
120 | encrypt_precompute(public_key, secret_key, k); | ||
121 | return encrypt_data_symmetric(k, nonce, plain, length, encrypted); | ||
122 | } | ||
123 | |||
124 | int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | ||
125 | uint8_t *encrypted, uint32_t length, uint8_t *plain) | ||
126 | { | ||
127 | uint8_t k[crypto_box_BEFORENMBYTES]; | ||
128 | encrypt_precompute(public_key, secret_key, k); | ||
129 | return decrypt_data_symmetric(k, nonce, encrypted, length, plain); | ||
130 | } | ||
131 | |||
132 | |||
133 | /* Increment the given nonce by 1. */ | ||
134 | void increment_nonce(uint8_t *nonce) | ||
135 | { | ||
136 | uint32_t i; | ||
137 | |||
138 | for (i = crypto_box_NONCEBYTES; i != 0; --i) { | ||
139 | ++nonce[i - 1]; | ||
140 | |||
141 | if (nonce[i - 1] != 0) | ||
142 | break; | ||
143 | } | ||
144 | } | ||
145 | /* increment the given nonce by num */ | ||
146 | void increment_nonce_number(uint8_t *nonce, uint32_t num) | ||
147 | { | ||
148 | uint32_t num1, num2; | ||
149 | memcpy(&num1, nonce + (crypto_box_NONCEBYTES - sizeof(num1)), sizeof(num1)); | ||
150 | num1 = ntohl(num1); | ||
151 | num2 = num + num1; | ||
152 | |||
153 | if (num2 < num1) { | ||
154 | uint32_t i; | ||
155 | |||
156 | for (i = crypto_box_NONCEBYTES - sizeof(num1); i != 0; --i) { | ||
157 | ++nonce[i - 1]; | ||
158 | |||
159 | if (nonce[i - 1] != 0) | ||
160 | break; | ||
161 | } | ||
162 | } | ||
163 | |||
164 | num2 = htonl(num2); | ||
165 | memcpy(nonce + (crypto_box_NONCEBYTES - sizeof(num2)), &num2, sizeof(num2)); | ||
166 | } | ||
167 | |||
168 | /* Fill the given nonce with random bytes. */ | ||
169 | void random_nonce(uint8_t *nonce) | ||
170 | { | ||
171 | randombytes(nonce, crypto_box_NONCEBYTES); | ||
172 | } | ||
173 | |||
174 | /* Fill a key crypto_box_KEYBYTES big with random bytes */ | ||
175 | void new_symmetric_key(uint8_t *key) | ||
176 | { | ||
177 | randombytes(key, crypto_box_KEYBYTES); | ||
178 | } | ||
179 | |||
180 | static uint8_t base_nonce[crypto_box_NONCEBYTES]; | ||
181 | static uint8_t nonce_set = 0; | ||
182 | |||
183 | /* Gives a nonce guaranteed to be different from previous ones.*/ | ||
184 | void new_nonce(uint8_t *nonce) | ||
185 | { | ||
186 | if (nonce_set == 0) { | ||
187 | random_nonce(base_nonce); | ||
188 | nonce_set = 1; | ||
189 | } | ||
190 | |||
191 | increment_nonce(base_nonce); | ||
192 | memcpy(nonce, base_nonce, crypto_box_NONCEBYTES); | ||
193 | } | ||
194 | |||
195 | /* Create a request to peer. | ||
196 | * send_public_key and send_secret_key are the pub/secret keys of the sender. | ||
197 | * recv_public_key is public key of reciever. | ||
198 | * packet must be an array of MAX_CRYPTO_REQUEST_SIZE big. | ||
199 | * Data represents the data we send with the request with length being the length of the data. | ||
200 | * request_id is the id of the request (32 = friend request, 254 = ping request). | ||
201 | * | ||
202 | * return -1 on failure. | ||
203 | * return the length of the created packet on success. | ||
204 | */ | ||
205 | int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t *packet, uint8_t *recv_public_key, | ||
206 | uint8_t *data, uint32_t length, uint8_t request_id) | ||
207 | { | ||
208 | if (MAX_CRYPTO_REQUEST_SIZE < length + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + | ||
209 | crypto_box_MACBYTES) | ||
210 | return -1; | ||
211 | |||
212 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
213 | uint8_t temp[MAX_CRYPTO_REQUEST_SIZE]; | ||
214 | memcpy(temp + 1, data, length); | ||
215 | temp[0] = request_id; | ||
216 | new_nonce(nonce); | ||
217 | int len = encrypt_data(recv_public_key, send_secret_key, nonce, temp, length + 1, | ||
218 | 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + packet); | ||
219 | |||
220 | if (len == -1) | ||
221 | return -1; | ||
222 | |||
223 | packet[0] = NET_PACKET_CRYPTO; | ||
224 | memcpy(packet + 1, recv_public_key, crypto_box_PUBLICKEYBYTES); | ||
225 | memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, send_public_key, crypto_box_PUBLICKEYBYTES); | ||
226 | memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES * 2, nonce, crypto_box_NONCEBYTES); | ||
227 | |||
228 | return len + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES; | ||
229 | } | ||
230 | |||
231 | /* Puts the senders public key in the request in public_key, the data from the request | ||
232 | * in data if a friend or ping request was sent to us and returns the length of the data. | ||
233 | * packet is the request packet and length is its length. | ||
234 | * | ||
235 | * return -1 if not valid request. | ||
236 | */ | ||
237 | int handle_request(uint8_t *self_public_key, uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data, | ||
238 | uint8_t *request_id, uint8_t *packet, uint16_t length) | ||
239 | { | ||
240 | if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + crypto_box_MACBYTES && | ||
241 | length <= MAX_CRYPTO_REQUEST_SIZE) { | ||
242 | if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { | ||
243 | memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); | ||
244 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
245 | uint8_t temp[MAX_CRYPTO_REQUEST_SIZE]; | ||
246 | memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES); | ||
247 | int len1 = decrypt_data(public_key, self_secret_key, nonce, | ||
248 | packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES, | ||
249 | length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), temp); | ||
250 | |||
251 | if (len1 == -1 || len1 == 0) | ||
252 | return -1; | ||
253 | |||
254 | request_id[0] = temp[0]; | ||
255 | --len1; | ||
256 | memcpy(data, temp + 1, len1); | ||
257 | return len1; | ||
258 | } | ||
259 | } | ||
260 | |||
261 | return -1; | ||
262 | } | ||
diff --git a/toxcore/crypto_core.h b/toxcore/crypto_core.h new file mode 100644 index 00000000..6b69f917 --- /dev/null +++ b/toxcore/crypto_core.h | |||
@@ -0,0 +1,142 @@ | |||
1 | /* crypto_core.h | ||
2 | * | ||
3 | * Functions for the core crypto. | ||
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 | #ifndef CORE_CRYPTO_H | ||
24 | #define CORE_CRYPTO_H | ||
25 | |||
26 | #include "network.h" | ||
27 | |||
28 | #ifndef VANILLA_NACL | ||
29 | /* We use libsodium by default. */ | ||
30 | #include <sodium.h> | ||
31 | #else | ||
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 | #define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) | ||
39 | #endif | ||
40 | |||
41 | #define crypto_box_KEYBYTES (crypto_box_BEFORENMBYTES) | ||
42 | |||
43 | /* Use this instead of memcmp; not vulnerable to timing attacks. | ||
44 | returns 0 if both mem locations of length are equal, | ||
45 | return -1 if they are not. */ | ||
46 | int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length); | ||
47 | |||
48 | /* return a random number. | ||
49 | * | ||
50 | * random_int for a 32bin int. | ||
51 | * random_64b for a 64bit int. | ||
52 | */ | ||
53 | uint32_t random_int(void); | ||
54 | uint64_t random_64b(void); | ||
55 | |||
56 | |||
57 | /* Encrypts plain of length length to encrypted of length + 16 using the | ||
58 | * public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce. | ||
59 | * | ||
60 | * return -1 if there was a problem. | ||
61 | * return length of encrypted data if everything was fine. | ||
62 | */ | ||
63 | int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | ||
64 | uint8_t *plain, uint32_t length, uint8_t *encrypted); | ||
65 | |||
66 | |||
67 | /* Decrypts encrypted of length length to plain of length length - 16 using the | ||
68 | * public key(32 bytes) of the sender, the secret key of the receiver and a 24 byte nonce. | ||
69 | * | ||
70 | * return -1 if there was a problem (decryption failed). | ||
71 | * return length of plain data if everything was fine. | ||
72 | */ | ||
73 | int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | ||
74 | uint8_t *encrypted, uint32_t length, uint8_t *plain); | ||
75 | |||
76 | /* Fast encrypt/decrypt operations. Use if this is not a one-time communication. | ||
77 | encrypt_precompute does the shared-key generation once so it does not have | ||
78 | to be preformed on every encrypt/decrypt. */ | ||
79 | void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_key); | ||
80 | |||
81 | /* Encrypts plain of length length to encrypted of length + 16 using a | ||
82 | * secret key crypto_box_KEYBYTES big and a 24 byte nonce. | ||
83 | * | ||
84 | * return -1 if there was a problem. | ||
85 | * return length of encrypted data if everything was fine. | ||
86 | */ | ||
87 | int encrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *plain, uint32_t length, uint8_t *encrypted); | ||
88 | |||
89 | /* Decrypts encrypted of length length to plain of length length - 16 using a | ||
90 | * secret key crypto_box_KEYBYTES big and a 24 byte nonce. | ||
91 | * | ||
92 | * return -1 if there was a problem (decryption failed). | ||
93 | * return length of plain data if everything was fine. | ||
94 | */ | ||
95 | int decrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *encrypted, uint32_t length, uint8_t *plain); | ||
96 | |||
97 | /* Increment the given nonce by 1. */ | ||
98 | void increment_nonce(uint8_t *nonce); | ||
99 | |||
100 | /* increment the given nonce by num */ | ||
101 | void increment_nonce_number(uint8_t *nonce, uint32_t num); | ||
102 | |||
103 | /* Fill the given nonce with random bytes. */ | ||
104 | void random_nonce(uint8_t *nonce); | ||
105 | |||
106 | /* Fill a key crypto_box_KEYBYTES big with random bytes */ | ||
107 | void new_symmetric_key(uint8_t *key); | ||
108 | |||
109 | /*Gives a nonce guaranteed to be different from previous ones.*/ | ||
110 | void new_nonce(uint8_t *nonce); | ||
111 | |||
112 | #define MAX_CRYPTO_REQUEST_SIZE 1024 | ||
113 | |||
114 | #define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */ | ||
115 | #define CRYPTO_PACKET_HARDENING 48 /* Hardening crypto packet ID. */ | ||
116 | #define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID. */ | ||
117 | #define CRYPTO_PACKET_GROUP_CHAT_GET_NODES 48 /* Group chat get Nodes packet */ | ||
118 | #define CRYPTO_PACKET_GROUP_CHAT_SEND_NODES 49 /* Group chat send Nodes packet */ | ||
119 | #define CRYPTO_PACKET_GROUP_CHAT_BROADCAST 50 /* Group chat broadcast packet */ | ||
120 | |||
121 | /* Create a request to peer. | ||
122 | * send_public_key and send_secret_key are the pub/secret keys of the sender. | ||
123 | * recv_public_key is public key of reciever. | ||
124 | * packet must be an array of MAX_CRYPTO_REQUEST_SIZE big. | ||
125 | * Data represents the data we send with the request with length being the length of the data. | ||
126 | * request_id is the id of the request (32 = friend request, 254 = ping request). | ||
127 | * | ||
128 | * return -1 on failure. | ||
129 | * return the length of the created packet on success. | ||
130 | */ | ||
131 | int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t *packet, uint8_t *recv_public_key, | ||
132 | uint8_t *data, uint32_t length, uint8_t request_id); | ||
133 | |||
134 | /* puts the senders public key in the request in public_key, the data from the request | ||
135 | in data if a friend or ping request was sent to us and returns the length of the data. | ||
136 | packet is the request packet and length is its length | ||
137 | return -1 if not valid request. */ | ||
138 | int handle_request(uint8_t *self_public_key, uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data, | ||
139 | uint8_t *request_id, uint8_t *packet, uint16_t length); | ||
140 | |||
141 | |||
142 | #endif | ||
diff --git a/toxcore/friend_requests.c b/toxcore/friend_requests.c index 469ab02d..eb2a791c 100644 --- a/toxcore/friend_requests.c +++ b/toxcore/friend_requests.c | |||
@@ -37,10 +37,10 @@ | |||
37 | */ | 37 | */ |
38 | int send_friendrequest(Onion_Client *onion_c, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length) | 38 | int send_friendrequest(Onion_Client *onion_c, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length) |
39 | { | 39 | { |
40 | if (length + sizeof(nospam_num) > MAX_DATA_SIZE) | 40 | if (1 + sizeof(nospam_num) + length > ONION_CLIENT_MAX_DATA_SIZE || length == 0) |
41 | return -1; | 41 | return -1; |
42 | 42 | ||
43 | uint8_t temp[MAX_DATA_SIZE]; | 43 | uint8_t temp[1 + sizeof(nospam_num) + length]; |
44 | temp[0] = CRYPTO_PACKET_FRIEND_REQ; | 44 | temp[0] = CRYPTO_PACKET_FRIEND_REQ; |
45 | memcpy(temp + 1, &nospam_num, sizeof(nospam_num)); | 45 | memcpy(temp + 1, &nospam_num, sizeof(nospam_num)); |
46 | memcpy(temp + 1 + sizeof(nospam_num), data, length); | 46 | memcpy(temp + 1 + sizeof(nospam_num), data, length); |
@@ -50,7 +50,7 @@ int send_friendrequest(Onion_Client *onion_c, uint8_t *public_key, uint32_t nosp | |||
50 | if (friend_num == -1) | 50 | if (friend_num == -1) |
51 | return -1; | 51 | return -1; |
52 | 52 | ||
53 | int num = send_onion_data(onion_c, friend_num, temp, 1 + sizeof(nospam_num) + length); | 53 | int num = send_onion_data(onion_c, friend_num, temp, sizeof(temp)); |
54 | 54 | ||
55 | if (num <= 0) | 55 | if (num <= 0) |
56 | return -1; | 56 | return -1; |
@@ -135,20 +135,17 @@ int remove_request_received(Friend_Requests *fr, uint8_t *client_id) | |||
135 | 135 | ||
136 | static int friendreq_handlepacket(void *object, uint8_t *source_pubkey, uint8_t *packet, uint32_t length) | 136 | static int friendreq_handlepacket(void *object, uint8_t *source_pubkey, uint8_t *packet, uint32_t length) |
137 | { | 137 | { |
138 | if (length == 0) | 138 | Friend_Requests *fr = object; |
139 | |||
140 | if (length <= 1 + sizeof(fr->nospam) || length > ONION_CLIENT_MAX_DATA_SIZE) | ||
139 | return 1; | 141 | return 1; |
140 | 142 | ||
141 | ++packet; | 143 | ++packet; |
142 | --length; | 144 | --length; |
143 | 145 | ||
144 | Friend_Requests *fr = object; | ||
145 | |||
146 | if (fr->handle_friendrequest_isset == 0) | 146 | if (fr->handle_friendrequest_isset == 0) |
147 | return 1; | 147 | return 1; |
148 | 148 | ||
149 | if (length <= sizeof(fr->nospam)) | ||
150 | return 1; | ||
151 | |||
152 | if (request_received(fr, source_pubkey)) | 149 | if (request_received(fr, source_pubkey)) |
153 | return 1; | 150 | return 1; |
154 | 151 | ||
@@ -161,11 +158,12 @@ static int friendreq_handlepacket(void *object, uint8_t *source_pubkey, uint8_t | |||
161 | 158 | ||
162 | addto_receivedlist(fr, source_pubkey); | 159 | addto_receivedlist(fr, source_pubkey); |
163 | 160 | ||
164 | uint8_t message[length - 4 + 1]; | 161 | uint32_t message_len = length - sizeof(fr->nospam); |
165 | memcpy(message, packet + 4, length - 4); | 162 | uint8_t message[message_len + 1]; |
163 | memcpy(message, packet + sizeof(fr->nospam), message_len); | ||
166 | message[sizeof(message) - 1] = 0; /* Be sure the message is null terminated. */ | 164 | message[sizeof(message) - 1] = 0; /* Be sure the message is null terminated. */ |
167 | 165 | ||
168 | (*fr->handle_friendrequest)(fr->handle_friendrequest_object, source_pubkey, message, length - 4, | 166 | (*fr->handle_friendrequest)(fr->handle_friendrequest_object, source_pubkey, message, message_len, |
169 | fr->handle_friendrequest_userdata); | 167 | fr->handle_friendrequest_userdata); |
170 | return 0; | 168 | return 0; |
171 | } | 169 | } |
diff --git a/toxcore/friend_requests.h b/toxcore/friend_requests.h index eab359f0..429ffbad 100644 --- a/toxcore/friend_requests.h +++ b/toxcore/friend_requests.h | |||
@@ -25,8 +25,8 @@ | |||
25 | #define FRIEND_REQUESTS_H | 25 | #define FRIEND_REQUESTS_H |
26 | 26 | ||
27 | #include "onion_client.h" | 27 | #include "onion_client.h" |
28 | #include "net_crypto.h" | ||
29 | 28 | ||
29 | #define MAX_FRIEND_REQUEST_DATA_SIZE (ONION_CLIENT_MAX_DATA_SIZE - (1 + sizeof(uint32_t))) | ||
30 | 30 | ||
31 | typedef struct { | 31 | typedef struct { |
32 | uint32_t nospam; | 32 | uint32_t nospam; |
@@ -48,7 +48,8 @@ typedef struct { | |||
48 | } Friend_Requests; | 48 | } Friend_Requests; |
49 | 49 | ||
50 | /* Try to send a friendrequest to peer with public_key. | 50 | /* Try to send a friendrequest to peer with public_key. |
51 | * data is the data in the request and length is the length. | 51 | * data is the data in the request and length is the length. |
52 | * Maximum length of data is MAX_FRIEND_REQUEST_DATA_SIZE. | ||
52 | */ | 53 | */ |
53 | int send_friendrequest(Onion_Client *onion_c, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length); | 54 | int send_friendrequest(Onion_Client *onion_c, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length); |
54 | /* Set and get the nospam variable used to prevent one type of friend request spam. */ | 55 | /* Set and get the nospam variable used to prevent one type of friend request spam. */ |
diff --git a/toxcore/group_chats.c b/toxcore/group_chats.c index de39331e..fbe76d16 100644 --- a/toxcore/group_chats.c +++ b/toxcore/group_chats.c | |||
@@ -26,12 +26,13 @@ | |||
26 | #include "config.h" | 26 | #include "config.h" |
27 | #endif | 27 | #endif |
28 | 28 | ||
29 | #include "group_chats.h" | 29 | #include "DHT.h" |
30 | #include "assoc.h" | 30 | #include "assoc.h" |
31 | #include "group_chats.h" | ||
31 | #include "LAN_discovery.h" | 32 | #include "LAN_discovery.h" |
32 | #include "util.h" | 33 | #include "util.h" |
33 | 34 | ||
34 | #define GROUPCHAT_MAXDATA_LENGTH (MAX_DATA_SIZE - (1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES)) | 35 | #define GROUPCHAT_MAXDATA_LENGTH (MAX_CRYPTO_REQUEST_SIZE - (1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES)) |
35 | #define GROUPCHAT_MAXPLAINDATA_LENGTH (GROUPCHAT_MAXDATA_LENGTH - crypto_box_MACBYTES) | 36 | #define GROUPCHAT_MAXPLAINDATA_LENGTH (GROUPCHAT_MAXDATA_LENGTH - crypto_box_MACBYTES) |
36 | 37 | ||
37 | #define GROUP_MAX_SENDNODES (GROUP_CLOSE_CONNECTIONS * 2) | 38 | #define GROUP_MAX_SENDNODES (GROUP_CLOSE_CONNECTIONS * 2) |
@@ -180,7 +181,7 @@ static int send_groupchatpacket(Group_Chat *chat, IP_Port ip_port, uint8_t *publ | |||
180 | if (id_equal(chat->self_public_key, public_key)) | 181 | if (id_equal(chat->self_public_key, public_key)) |
181 | return -1; | 182 | return -1; |
182 | 183 | ||
183 | uint8_t packet[MAX_DATA_SIZE]; | 184 | uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; |
184 | int len = create_request(chat->self_public_key, chat->self_secret_key, packet, public_key, data, length, request_id); | 185 | int len = create_request(chat->self_public_key, chat->self_secret_key, packet, public_key, data, length, request_id); |
185 | packet[0] = NET_PACKET_GROUP_CHATS; | 186 | packet[0] = NET_PACKET_GROUP_CHATS; |
186 | 187 | ||
@@ -586,10 +587,10 @@ static int handle_data(Group_Chat *chat, uint8_t *data, uint32_t len) | |||
586 | 587 | ||
587 | static uint8_t send_data(Group_Chat *chat, uint8_t *data, uint32_t len, uint8_t message_id) | 588 | static uint8_t send_data(Group_Chat *chat, uint8_t *data, uint32_t len, uint8_t message_id) |
588 | { | 589 | { |
589 | if (len + GROUP_DATA_MIN_SIZE > MAX_DATA_SIZE) /*NOTE: not the real maximum len.*/ | 590 | if (len + GROUP_DATA_MIN_SIZE > MAX_CRYPTO_REQUEST_SIZE) /*NOTE: not the real maximum len.*/ |
590 | return 1; | 591 | return 1; |
591 | 592 | ||
592 | uint8_t packet[MAX_DATA_SIZE]; | 593 | uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; |
593 | ++chat->message_number; | 594 | ++chat->message_number; |
594 | 595 | ||
595 | if (chat->message_number == 0) | 596 | if (chat->message_number == 0) |
@@ -615,11 +616,11 @@ static uint8_t send_data(Group_Chat *chat, uint8_t *data, uint32_t len, uint8_t | |||
615 | 616 | ||
616 | int handle_groupchatpacket(Group_Chat *chat, IP_Port source, uint8_t *packet, uint32_t length) | 617 | int handle_groupchatpacket(Group_Chat *chat, IP_Port source, uint8_t *packet, uint32_t length) |
617 | { | 618 | { |
618 | if (length > MAX_DATA_SIZE) | 619 | if (length > MAX_CRYPTO_REQUEST_SIZE) |
619 | return 1; | 620 | return 1; |
620 | 621 | ||
621 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; | 622 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; |
622 | uint8_t data[MAX_DATA_SIZE]; | 623 | uint8_t data[MAX_CRYPTO_REQUEST_SIZE]; |
623 | uint8_t number; | 624 | uint8_t number; |
624 | int len = handle_request(chat->self_public_key, chat->self_secret_key, public_key, data, &number, packet, length); | 625 | int len = handle_request(chat->self_public_key, chat->self_secret_key, public_key, data, &number, packet, length); |
625 | 626 | ||
diff --git a/toxcore/group_chats.h b/toxcore/group_chats.h index f218fe42..d9da54a5 100644 --- a/toxcore/group_chats.h +++ b/toxcore/group_chats.h | |||
@@ -25,8 +25,6 @@ | |||
25 | #ifndef GROUP_CHATS_H | 25 | #ifndef GROUP_CHATS_H |
26 | #define GROUP_CHATS_H | 26 | #define GROUP_CHATS_H |
27 | 27 | ||
28 | #include "net_crypto.h" | ||
29 | |||
30 | #define MAX_NICK_BYTES 128 | 28 | #define MAX_NICK_BYTES 128 |
31 | 29 | ||
32 | typedef struct { | 30 | typedef struct { |
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 17d2e8ff..875c639f 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c | |||
@@ -35,439 +35,1159 @@ static uint8_t crypt_connection_id_not_valid(Net_Crypto *c, int crypt_connection | |||
35 | return (uint32_t)crypt_connection_id >= c->crypto_connections_length; | 35 | return (uint32_t)crypt_connection_id >= c->crypto_connections_length; |
36 | } | 36 | } |
37 | 37 | ||
38 | /* Use this instead of memcmp; not vulnerable to timing attacks. */ | 38 | /* return 0 if connection is dead. |
39 | uint8_t crypto_iszero(uint8_t *mem, uint32_t length) | 39 | * return 1 if connection is alive. |
40 | */ | ||
41 | static int is_alive(uint8_t status) | ||
40 | { | 42 | { |
41 | uint8_t check = 0; | 43 | if (status == CRYPTO_CONN_COOKIE_REQUESTING || |
42 | uint32_t i; | 44 | status == CRYPTO_CONN_HANDSHAKE_SENT || |
43 | 45 | status == CRYPTO_CONN_NOT_CONFIRMED || | |
44 | for (i = 0; i < length; ++i) { | 46 | status == CRYPTO_CONN_ESTABLISHED) { |
45 | check |= mem[i]; | 47 | return 1; |
46 | } | 48 | } |
47 | 49 | ||
48 | return check; // We return zero if mem is made out of zeroes. | 50 | return 0; |
49 | } | 51 | } |
50 | 52 | ||
51 | /* Precomputes the shared key from their public_key and our secret_key. | 53 | /* cookie timeout in seconds */ |
52 | * This way we can avoid an expensive elliptic curve scalar multiply for each | 54 | #define COOKIE_TIMEOUT 10 |
53 | * encrypt/decrypt operation. | 55 | #define COOKIE_DATA_LENGTH (crypto_box_PUBLICKEYBYTES * 2) |
54 | * enc_key has to be crypto_box_BEFORENMBYTES bytes long. | 56 | #define COOKIE_CONTENTS_LENGTH (sizeof(uint64_t) + COOKIE_DATA_LENGTH) |
57 | #define COOKIE_LENGTH (crypto_box_NONCEBYTES + COOKIE_CONTENTS_LENGTH + crypto_box_MACBYTES) | ||
58 | |||
59 | #define COOKIE_REQUEST_PLAIN_LENGTH (COOKIE_DATA_LENGTH + sizeof(uint64_t)) | ||
60 | #define COOKIE_REQUEST_LENGTH (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + COOKIE_REQUEST_PLAIN_LENGTH + crypto_box_MACBYTES) | ||
61 | #define COOKIE_RESPONSE_LENGTH (1 + crypto_box_NONCEBYTES + COOKIE_LENGTH + sizeof(uint64_t) + crypto_box_MACBYTES) | ||
62 | |||
63 | /* Create a cookie request packet and put it in packet. | ||
64 | * dht_public_key is the dht public key of the other | ||
65 | * | ||
66 | * packet must be of size COOKIE_REQUEST_LENGTH or bigger. | ||
67 | * | ||
68 | * return -1 on failure. | ||
69 | * return COOKIE_REQUEST_LENGTH on success. | ||
55 | */ | 70 | */ |
56 | void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_key) | 71 | static int create_cookie_request(Net_Crypto *c, uint8_t *packet, uint8_t *dht_public_key, uint64_t number, |
72 | uint8_t *shared_key) | ||
57 | { | 73 | { |
58 | crypto_box_beforenm(enc_key, public_key, secret_key); | 74 | uint8_t plain[COOKIE_REQUEST_PLAIN_LENGTH]; |
75 | uint8_t padding[crypto_box_PUBLICKEYBYTES] = {0}; | ||
76 | |||
77 | memcpy(plain, c->self_public_key, crypto_box_PUBLICKEYBYTES); | ||
78 | memcpy(plain + crypto_box_PUBLICKEYBYTES, padding, crypto_box_PUBLICKEYBYTES); | ||
79 | memcpy(plain + (crypto_box_PUBLICKEYBYTES * 2), &number, sizeof(uint64_t)); | ||
80 | |||
81 | DHT_get_shared_key_sent(c->dht, shared_key, dht_public_key); | ||
82 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
83 | new_nonce(nonce); | ||
84 | packet[0] = NET_PACKET_COOKIE_REQUEST; | ||
85 | memcpy(packet + 1, c->dht->self_public_key, crypto_box_PUBLICKEYBYTES); | ||
86 | memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); | ||
87 | int len = encrypt_data_symmetric(shared_key, nonce, plain, sizeof(plain), | ||
88 | packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); | ||
89 | |||
90 | if (len != COOKIE_REQUEST_PLAIN_LENGTH + crypto_box_MACBYTES) | ||
91 | return -1; | ||
92 | |||
93 | return (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + len); | ||
59 | } | 94 | } |
60 | 95 | ||
61 | /* Fast encrypt. Depends on enc_key from encrypt_precompute. */ | 96 | /* Create cookie of length COOKIE_LENGTH from bytes of length COOKIE_DATA_LENGTH using encryption_key |
62 | int encrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, | 97 | * |
63 | uint8_t *plain, uint32_t length, uint8_t *encrypted) | 98 | * return -1 on failure. |
99 | * return 0 on success. | ||
100 | */ | ||
101 | static int create_cookie(uint8_t *cookie, uint8_t *bytes, uint8_t *encryption_key) | ||
64 | { | 102 | { |
65 | if (length + crypto_box_MACBYTES > MAX_DATA_SIZE || length == 0) | 103 | uint8_t contents[COOKIE_CONTENTS_LENGTH]; |
104 | uint64_t temp_time = unix_time(); | ||
105 | memcpy(contents, &temp_time, sizeof(temp_time)); | ||
106 | memcpy(contents + sizeof(temp_time), bytes, COOKIE_DATA_LENGTH); | ||
107 | new_nonce(cookie); | ||
108 | int len = encrypt_data_symmetric(encryption_key, cookie, contents, sizeof(contents), cookie + crypto_box_NONCEBYTES); | ||
109 | |||
110 | if (len != COOKIE_LENGTH - crypto_box_NONCEBYTES) | ||
66 | return -1; | 111 | return -1; |
67 | 112 | ||
68 | uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES] = {0}; | 113 | return 0; |
69 | uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES]; | 114 | } |
115 | |||
116 | /* Open cookie of length COOKIE_LENGTH to bytes of length COOKIE_DATA_LENGTH using encryption_key | ||
117 | * | ||
118 | * return -1 on failure. | ||
119 | * return 0 on success. | ||
120 | */ | ||
121 | static int open_cookie(uint8_t *bytes, uint8_t *cookie, uint8_t *encryption_key) | ||
122 | { | ||
123 | uint8_t contents[COOKIE_CONTENTS_LENGTH]; | ||
124 | int len = decrypt_data_symmetric(encryption_key, cookie, cookie + crypto_box_NONCEBYTES, | ||
125 | COOKIE_LENGTH - crypto_box_NONCEBYTES, contents); | ||
70 | 126 | ||
71 | memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); // Pad the message with 32 0 bytes. | 127 | if (len != sizeof(contents)) |
128 | return -1; | ||
72 | 129 | ||
73 | crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, enc_key); | 130 | uint64_t cookie_time; |
131 | memcpy(&cookie_time, contents, sizeof(cookie_time)); | ||
132 | uint64_t temp_time = unix_time(); | ||
74 | 133 | ||
75 | if (crypto_iszero(temp_encrypted, crypto_box_BOXZEROBYTES) != 0) | 134 | if (cookie_time + COOKIE_TIMEOUT < temp_time || temp_time < cookie_time) |
76 | return -1; | 135 | return -1; |
77 | 136 | ||
78 | /* Unpad the encrypted message. */ | 137 | memcpy(bytes, contents + sizeof(cookie_time), COOKIE_DATA_LENGTH); |
79 | memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES); | 138 | return 0; |
80 | return length + crypto_box_MACBYTES; | ||
81 | } | 139 | } |
82 | 140 | ||
83 | /* Fast decrypt. Depends on enc_ley from encrypt_precompute. */ | 141 | |
84 | int decrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, | 142 | /* Create a cookie response packet and put it in packet. |
85 | uint8_t *encrypted, uint32_t length, uint8_t *plain) | 143 | * request_plain must be COOKIE_REQUEST_PLAIN_LENGTH bytes. |
144 | * packet must be of size COOKIE_RESPONSE_LENGTH or bigger. | ||
145 | * | ||
146 | * return -1 on failure. | ||
147 | * return COOKIE_RESPONSE_LENGTH on success. | ||
148 | */ | ||
149 | static int create_cookie_response(Net_Crypto *c, uint8_t *packet, uint8_t *request_plain, uint8_t *shared_key, | ||
150 | uint8_t *dht_public_key) | ||
86 | { | 151 | { |
87 | if (length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES) | 152 | uint8_t cookie_plain[COOKIE_DATA_LENGTH]; |
153 | memcpy(cookie_plain, request_plain, crypto_box_PUBLICKEYBYTES); | ||
154 | memcpy(cookie_plain + crypto_box_PUBLICKEYBYTES, dht_public_key, crypto_box_PUBLICKEYBYTES); | ||
155 | uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)]; | ||
156 | |||
157 | if (create_cookie(plain, cookie_plain, c->secret_symmetric_key) != 0) | ||
88 | return -1; | 158 | return -1; |
89 | 159 | ||
90 | uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES]; | 160 | memcpy(plain + COOKIE_LENGTH, request_plain + COOKIE_DATA_LENGTH, sizeof(uint64_t)); |
91 | uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES] = {0}; | 161 | packet[0] = NET_PACKET_COOKIE_RESPONSE; |
162 | new_nonce(packet + 1); | ||
163 | int len = encrypt_data_symmetric(shared_key, packet + 1, plain, sizeof(plain), packet + 1 + crypto_box_NONCEBYTES); | ||
164 | |||
165 | if (len != COOKIE_RESPONSE_LENGTH - (1 + crypto_box_NONCEBYTES)) | ||
166 | return -1; | ||
92 | 167 | ||
93 | memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); // Pad the message with 16 0 bytes. | 168 | return COOKIE_RESPONSE_LENGTH; |
169 | } | ||
94 | 170 | ||
95 | if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, | 171 | /* Handle the cookie request packet of length length. |
96 | nonce, enc_key) == -1) | 172 | * Put what was in the request in request_plain (must be of size COOKIE_REQUEST_PLAIN_LENGTH) |
173 | * Put the key used to decrypt the request into shared_key (of size crypto_box_BEFORENMBYTES) for use in the response. | ||
174 | * | ||
175 | * return -1 on failure. | ||
176 | * return 0 on success. | ||
177 | */ | ||
178 | static int handle_cookie_request(Net_Crypto *c, uint8_t *request_plain, uint8_t *shared_key, uint8_t *dht_public_key, | ||
179 | uint8_t *packet, uint16_t length) | ||
180 | { | ||
181 | if (length != COOKIE_REQUEST_LENGTH) | ||
97 | return -1; | 182 | return -1; |
98 | 183 | ||
99 | /* If decryption is successful the first crypto_box_ZEROBYTES of the message will be zero. | 184 | memcpy(dht_public_key, packet + 1, crypto_box_PUBLICKEYBYTES); |
100 | * Apparently memcmp should not be used so we do this instead: | 185 | DHT_get_shared_key_sent(c->dht, shared_key, dht_public_key); |
101 | */ | 186 | int len = decrypt_data_symmetric(shared_key, packet + 1 + crypto_box_PUBLICKEYBYTES, |
102 | if (crypto_iszero(temp_plain, crypto_box_ZEROBYTES) != 0) | 187 | packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, COOKIE_REQUEST_PLAIN_LENGTH + crypto_box_MACBYTES, |
188 | request_plain); | ||
189 | |||
190 | if (len != COOKIE_REQUEST_PLAIN_LENGTH) | ||
103 | return -1; | 191 | return -1; |
104 | 192 | ||
105 | /* Unpad the plain message. */ | 193 | return 0; |
106 | memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES); | ||
107 | return length - crypto_box_MACBYTES; | ||
108 | } | 194 | } |
109 | 195 | ||
110 | int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | 196 | /* Handle the cookie request packet (for raw UDP) |
111 | uint8_t *plain, uint32_t length, uint8_t *encrypted) | 197 | */ |
198 | static int udp_handle_cookie_request(void *object, IP_Port source, uint8_t *packet, uint32_t length) | ||
112 | { | 199 | { |
113 | uint8_t k[crypto_box_BEFORENMBYTES]; | 200 | Net_Crypto *c = object; |
114 | encrypt_precompute(public_key, secret_key, k); | 201 | uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH]; |
115 | return encrypt_data_fast(k, nonce, plain, length, encrypted); | 202 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; |
203 | uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; | ||
204 | |||
205 | if (handle_cookie_request(c, request_plain, shared_key, dht_public_key, packet, length) != 0) | ||
206 | return 1; | ||
207 | |||
208 | uint8_t data[COOKIE_RESPONSE_LENGTH]; | ||
209 | |||
210 | if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) | ||
211 | return 1; | ||
212 | |||
213 | if ((uint32_t)sendpacket(c->dht->net, source, data, sizeof(data)) != sizeof(data)) | ||
214 | return 1; | ||
215 | |||
216 | return 0; | ||
116 | } | 217 | } |
117 | 218 | ||
118 | int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | 219 | /* Handle the cookie request packet (for TCP) |
119 | uint8_t *encrypted, uint32_t length, uint8_t *plain) | 220 | */ |
221 | static int tcp_handle_cookie_request(Net_Crypto *c, TCP_Client_Connection *TCP_con, uint8_t conn_id, uint8_t *packet, | ||
222 | uint32_t length) | ||
120 | { | 223 | { |
121 | uint8_t k[crypto_box_BEFORENMBYTES]; | 224 | uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH]; |
122 | encrypt_precompute(public_key, secret_key, k); | 225 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; |
123 | return decrypt_data_fast(k, nonce, encrypted, length, plain); | 226 | uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; |
227 | |||
228 | if (handle_cookie_request(c, request_plain, shared_key, dht_public_key, packet, length) != 0) | ||
229 | return -1; | ||
230 | |||
231 | uint8_t data[COOKIE_RESPONSE_LENGTH]; | ||
232 | |||
233 | if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) | ||
234 | return -1; | ||
235 | |||
236 | if (send_data(TCP_con, conn_id, data, sizeof(data)) != 1) | ||
237 | return -1; | ||
238 | |||
239 | return 0; | ||
124 | } | 240 | } |
125 | 241 | ||
126 | int encrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *plain, uint32_t length, uint8_t *encrypted) | 242 | /* Handle the cookie request packet (for TCP oob packets) |
243 | */ | ||
244 | static int tcp_oob_handle_cookie_request(Net_Crypto *c, TCP_Client_Connection *TCP_con, uint8_t *dht_public_key, | ||
245 | uint8_t *packet, uint32_t length) | ||
127 | { | 246 | { |
128 | if (length == 0) | 247 | uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH]; |
248 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; | ||
249 | uint8_t dht_public_key_temp[crypto_box_PUBLICKEYBYTES]; | ||
250 | |||
251 | if (handle_cookie_request(c, request_plain, shared_key, dht_public_key_temp, packet, length) != 0) | ||
252 | return -1; | ||
253 | |||
254 | if (memcmp(dht_public_key, dht_public_key_temp, crypto_box_PUBLICKEYBYTES) != 0) | ||
129 | return -1; | 255 | return -1; |
130 | 256 | ||
131 | uint8_t temp_plain[length + crypto_secretbox_ZEROBYTES]; | 257 | uint8_t data[COOKIE_RESPONSE_LENGTH]; |
132 | uint8_t temp_encrypted[length + crypto_secretbox_MACBYTES + crypto_secretbox_BOXZEROBYTES]; | 258 | |
259 | if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) | ||
260 | return -1; | ||
133 | 261 | ||
134 | memset(temp_plain, 0, crypto_secretbox_ZEROBYTES); | 262 | if (send_oob_packet(TCP_con, dht_public_key, data, sizeof(data)) != 1) |
135 | memcpy(temp_plain + crypto_secretbox_ZEROBYTES, plain, length); // Pad the message with 32 0 bytes. | 263 | return -1; |
136 | 264 | ||
137 | crypto_secretbox(temp_encrypted, temp_plain, length + crypto_secretbox_ZEROBYTES, nonce, secret_key); | 265 | return 0; |
138 | /* Unpad the encrypted message. */ | ||
139 | memcpy(encrypted, temp_encrypted + crypto_secretbox_BOXZEROBYTES, length + crypto_secretbox_MACBYTES); | ||
140 | return length + crypto_secretbox_MACBYTES; | ||
141 | } | 266 | } |
142 | 267 | ||
143 | int decrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *encrypted, uint32_t length, uint8_t *plain) | 268 | /* Handle a cookie response packet of length encrypted with shared_key. |
269 | * put the cookie in the response in cookie | ||
270 | * | ||
271 | * cookie must be of length COOKIE_LENGTH. | ||
272 | * | ||
273 | * return -1 on failure. | ||
274 | * return COOKIE_LENGTH on success. | ||
275 | */ | ||
276 | static int handle_cookie_response(uint8_t *cookie, uint64_t *number, uint8_t *packet, uint32_t length, | ||
277 | uint8_t *shared_key) | ||
278 | { | ||
279 | if (length != COOKIE_RESPONSE_LENGTH) | ||
280 | return -1; | ||
281 | |||
282 | uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)]; | ||
283 | int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES, | ||
284 | length - (1 + crypto_box_NONCEBYTES), plain); | ||
285 | |||
286 | if (len != sizeof(plain)) | ||
287 | return -1; | ||
288 | |||
289 | memcpy(cookie, plain, COOKIE_LENGTH); | ||
290 | memcpy(number, plain + COOKIE_LENGTH, sizeof(uint64_t)); | ||
291 | return COOKIE_LENGTH; | ||
292 | } | ||
293 | |||
294 | #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) | ||
295 | |||
296 | /* Create a handshake packet and put it in packet. | ||
297 | * cookie must be COOKIE_LENGTH bytes. | ||
298 | * packet must be of size HANDSHAKE_PACKET_LENGTH or bigger. | ||
299 | * | ||
300 | * return -1 on failure. | ||
301 | * return HANDSHAKE_PACKET_LENGTH on success. | ||
302 | */ | ||
303 | static int create_crypto_handshake(Net_Crypto *c, uint8_t *packet, uint8_t *cookie, uint8_t *nonce, uint8_t *session_pk, | ||
304 | uint8_t *peer_real_pk, uint8_t *peer_dht_pubkey) | ||
305 | { | ||
306 | uint8_t plain[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_hash_sha512_BYTES + COOKIE_LENGTH]; | ||
307 | memcpy(plain, nonce, crypto_box_NONCEBYTES); | ||
308 | memcpy(plain + crypto_box_NONCEBYTES, session_pk, crypto_box_PUBLICKEYBYTES); | ||
309 | crypto_hash_sha512(plain + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, cookie, COOKIE_LENGTH); | ||
310 | uint8_t cookie_plain[COOKIE_DATA_LENGTH]; | ||
311 | memcpy(cookie_plain, peer_real_pk, crypto_box_PUBLICKEYBYTES); | ||
312 | memcpy(cookie_plain + crypto_box_PUBLICKEYBYTES, peer_dht_pubkey, crypto_box_PUBLICKEYBYTES); | ||
313 | |||
314 | if (create_cookie(plain + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_hash_sha512_BYTES, cookie_plain, | ||
315 | c->secret_symmetric_key) != 0) | ||
316 | return -1; | ||
317 | |||
318 | new_nonce(packet + 1 + COOKIE_LENGTH); | ||
319 | int len = encrypt_data(peer_real_pk, c->self_secret_key, packet + 1 + COOKIE_LENGTH, plain, sizeof(plain), | ||
320 | packet + 1 + COOKIE_LENGTH + crypto_box_NONCEBYTES); | ||
321 | |||
322 | if (len != HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + crypto_box_NONCEBYTES)) | ||
323 | return -1; | ||
324 | |||
325 | packet[0] = NET_PACKET_CRYPTO_HS; | ||
326 | memcpy(packet + 1, cookie, COOKIE_LENGTH); | ||
327 | |||
328 | return HANDSHAKE_PACKET_LENGTH; | ||
329 | } | ||
330 | |||
331 | /* Handle a crypto handshake packet of length. | ||
332 | * put the nonce contained in the packet in nonce, | ||
333 | * the session public key in session_pk | ||
334 | * the real public key of the peer in peer_real_pk | ||
335 | * the dht public key of the peer in dht_public_key and | ||
336 | * the cookie inside the encrypted part of the packet in cookie. | ||
337 | * | ||
338 | * if expected_real_pk isn't NULL it denotes the real public key | ||
339 | * the packet should be from. | ||
340 | * | ||
341 | * nonce must be at least crypto_box_NONCEBYTES | ||
342 | * session_pk must be at least crypto_box_PUBLICKEYBYTES | ||
343 | * peer_real_pk must be at least crypto_box_PUBLICKEYBYTES | ||
344 | * cookie must be at least COOKIE_LENGTH | ||
345 | * | ||
346 | * return -1 on failure. | ||
347 | * return 0 on success. | ||
348 | */ | ||
349 | static int handle_crypto_handshake(Net_Crypto *c, uint8_t *nonce, uint8_t *session_pk, uint8_t *peer_real_pk, | ||
350 | uint8_t *dht_public_key, uint8_t *cookie, uint8_t *packet, uint32_t length, uint8_t *expected_real_pk) | ||
144 | { | 351 | { |
145 | if (length <= crypto_secretbox_BOXZEROBYTES) | 352 | if (length != HANDSHAKE_PACKET_LENGTH) |
353 | return -1; | ||
354 | |||
355 | uint8_t cookie_plain[COOKIE_DATA_LENGTH]; | ||
356 | |||
357 | if (open_cookie(cookie_plain, packet + 1, c->secret_symmetric_key) != 0) | ||
146 | return -1; | 358 | return -1; |
147 | 359 | ||
148 | uint8_t temp_plain[length + crypto_secretbox_ZEROBYTES]; | 360 | if (expected_real_pk) |
149 | uint8_t temp_encrypted[length + crypto_secretbox_BOXZEROBYTES]; | 361 | if (crypto_cmp(cookie_plain, expected_real_pk, crypto_box_PUBLICKEYBYTES) != 0) |
362 | return -1; | ||
363 | |||
364 | uint8_t cookie_hash[crypto_hash_sha512_BYTES]; | ||
365 | crypto_hash_sha512(cookie_hash, packet + 1, COOKIE_LENGTH); | ||
150 | 366 | ||
151 | memset(temp_plain, 0, crypto_secretbox_BOXZEROBYTES); | 367 | uint8_t plain[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_hash_sha512_BYTES + COOKIE_LENGTH]; |
152 | memcpy(temp_encrypted + crypto_secretbox_BOXZEROBYTES, encrypted, length); // Pad the message with 16 0 bytes. | 368 | int len = decrypt_data(cookie_plain, c->self_secret_key, packet + 1 + COOKIE_LENGTH, |
369 | packet + 1 + COOKIE_LENGTH + crypto_box_NONCEBYTES, | ||
370 | HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + crypto_box_NONCEBYTES), plain); | ||
153 | 371 | ||
154 | if (crypto_secretbox_open(temp_plain, temp_encrypted, length + crypto_secretbox_BOXZEROBYTES, nonce, secret_key) == -1) | 372 | if (len != sizeof(plain)) |
155 | return -1; | 373 | return -1; |
156 | 374 | ||
157 | memcpy(plain, temp_plain + crypto_secretbox_ZEROBYTES, length - crypto_secretbox_MACBYTES); | 375 | if (memcmp(cookie_hash, plain + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, crypto_hash_sha512_BYTES) != 0) |
158 | return length - crypto_secretbox_MACBYTES; | 376 | return -1; |
377 | |||
378 | memcpy(nonce, plain, crypto_box_NONCEBYTES); | ||
379 | memcpy(session_pk, plain + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES); | ||
380 | memcpy(cookie, plain + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_hash_sha512_BYTES, COOKIE_LENGTH); | ||
381 | memcpy(peer_real_pk, cookie_plain, crypto_box_PUBLICKEYBYTES); | ||
382 | memcpy(dht_public_key, cookie_plain + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); | ||
383 | return 0; | ||
159 | } | 384 | } |
160 | 385 | ||
161 | /* Increment the given nonce by 1. */ | 386 | |
162 | void increment_nonce(uint8_t *nonce) | 387 | static Crypto_Connection *get_crypto_connection(Net_Crypto *c, int crypt_connection_id) |
163 | { | 388 | { |
389 | if (crypt_connection_id_not_valid(c, crypt_connection_id)) | ||
390 | return 0; | ||
391 | |||
392 | return &c->crypto_connections[crypt_connection_id]; | ||
393 | } | ||
394 | |||
395 | |||
396 | /* Sends a packet to the peer using the fastest route. | ||
397 | * | ||
398 | * return -1 on failure. | ||
399 | * return 0 on success. | ||
400 | */ | ||
401 | static int send_packet_to(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint16_t length) | ||
402 | { | ||
403 | //TODO TCP, etc... | ||
404 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
405 | |||
406 | if (conn == 0) | ||
407 | return -1; | ||
408 | |||
409 | int direct_send_attempt = 0; | ||
410 | |||
411 | //TODO: on bad networks, direct connections might not last indefinitely. | ||
412 | if (conn->ip_port.ip.family != 0) { | ||
413 | uint8_t direct_connected = 0; | ||
414 | crypto_connection_status(c, crypt_connection_id, &direct_connected); | ||
415 | |||
416 | if (direct_connected && (uint32_t)sendpacket(c->dht->net, conn->ip_port, data, length) == length) | ||
417 | return 0; | ||
418 | |||
419 | //TODO: a better way of sending packets directly to confirm the others ip. | ||
420 | if (length < 96 || data[0] == NET_PACKET_COOKIE_REQUEST || data[0] == NET_PACKET_CRYPTO_HS) { | ||
421 | if ((uint32_t)sendpacket(c->dht->net, conn->ip_port, data, length) == length) | ||
422 | direct_send_attempt = 1; | ||
423 | } | ||
424 | |||
425 | } | ||
426 | |||
427 | //TODO: spread packets over many relays, detect and kill bad relays. | ||
164 | uint32_t i; | 428 | uint32_t i; |
165 | 429 | ||
166 | for (i = 0; i < crypto_box_NONCEBYTES; ++i) { | 430 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { |
167 | ++nonce[i]; | 431 | if (conn->status_tcp[i] == STATUS_TCP_ONLINE) {/* friend is connected to this relay. */ |
432 | if (send_data(c->tcp_connections[i], conn->con_number_tcp[i], data, length) == 1) | ||
433 | return 0; | ||
434 | } | ||
435 | } | ||
168 | 436 | ||
169 | if (nonce[i] != 0) | 437 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { |
170 | break; | 438 | if (conn->status_tcp[i] == STATUS_TCP_INVISIBLE) { |
439 | if (send_oob_packet(c->tcp_connections[i], conn->dht_public_key, data, length) == 1) | ||
440 | return 0; | ||
441 | } | ||
442 | } | ||
443 | |||
444 | if (direct_send_attempt) { | ||
445 | return 0; | ||
171 | } | 446 | } |
447 | |||
448 | return -1; | ||
172 | } | 449 | } |
173 | 450 | ||
174 | #if crypto_box_NONCEBYTES != crypto_secretbox_NONCEBYTES | 451 | /** START: Array Related functions **/ |
175 | /*if they no longer equal each other, this function must be split into two.*/ | 452 | |
176 | #error random_nonce(): crypto_box_NONCEBYTES must equal crypto_secretbox_NONCEBYTES. | 453 | |
177 | #endif | 454 | /* Return number of packets in array |
178 | /* Fill the given nonce with random bytes. */ | 455 | * Note that holes are counted too. |
179 | void random_nonce(uint8_t *nonce) | 456 | */ |
457 | static uint32_t num_packets_array(Packets_Array *array) | ||
180 | { | 458 | { |
181 | randombytes(nonce, crypto_box_NONCEBYTES); | 459 | return array->buffer_end - array->buffer_start; |
182 | } | 460 | } |
183 | 461 | ||
184 | /* Fill a key crypto_secretbox_KEYBYTES big with random bytes */ | 462 | /* Add data with packet number to array. |
185 | void new_symmetric_key(uint8_t *key) | 463 | * |
464 | * return -1 on failure. | ||
465 | * return 0 on success. | ||
466 | */ | ||
467 | static int add_data_to_buffer(Packets_Array *array, uint32_t number, Packet_Data *data) | ||
186 | { | 468 | { |
187 | randombytes(key, crypto_secretbox_KEYBYTES); | 469 | if (number - array->buffer_start > CRYPTO_PACKET_BUFFER_SIZE) |
470 | return -1; | ||
471 | |||
472 | uint32_t num = number % CRYPTO_PACKET_BUFFER_SIZE; | ||
473 | |||
474 | if (array->buffer[num]) | ||
475 | return -1; | ||
476 | |||
477 | Packet_Data *new_d = malloc(sizeof(Packet_Data)); | ||
478 | |||
479 | if (new_d == NULL) | ||
480 | return -1; | ||
481 | |||
482 | memcpy(new_d, data, sizeof(Packet_Data)); | ||
483 | array->buffer[num] = new_d; | ||
484 | |||
485 | if ((number - array->buffer_start) >= (array->buffer_end - array->buffer_start)) | ||
486 | array->buffer_end = number + 1; | ||
487 | |||
488 | return 0; | ||
188 | } | 489 | } |
189 | 490 | ||
190 | static uint8_t base_nonce[crypto_box_NONCEBYTES]; | 491 | /* Get pointer of data with packet number. |
191 | static uint8_t nonce_set = 0; | 492 | * |
493 | * return -1 on failure. | ||
494 | * return 0 if data at number is empty. | ||
495 | * return 1 if data pointer was put in data. | ||
496 | */ | ||
497 | static int get_data_pointer(Packets_Array *array, Packet_Data **data, uint32_t number) | ||
498 | { | ||
499 | uint32_t num_spots = array->buffer_end - array->buffer_start; | ||
500 | |||
501 | if (array->buffer_end - number > num_spots || number - array->buffer_start >= num_spots) | ||
502 | return -1; | ||
503 | |||
504 | uint32_t num = number % CRYPTO_PACKET_BUFFER_SIZE; | ||
192 | 505 | ||
193 | #if crypto_box_NONCEBYTES != crypto_secretbox_NONCEBYTES | 506 | if (!array->buffer[num]) |
194 | /*if they no longer equal each other, this function must be split into two.*/ | 507 | return 0; |
195 | #error new_nonce(): crypto_box_NONCEBYTES must equal crypto_secretbox_NONCEBYTES. | 508 | |
196 | #endif | 509 | *data = array->buffer[num]; |
197 | /* Gives a nonce guaranteed to be different from previous ones.*/ | 510 | return 1; |
198 | void new_nonce(uint8_t *nonce) | 511 | } |
512 | |||
513 | /* Add data to end of array. | ||
514 | * | ||
515 | * return -1 on failure. | ||
516 | * return packet number on success. | ||
517 | */ | ||
518 | static int64_t add_data_end_of_buffer(Packets_Array *array, Packet_Data *data) | ||
199 | { | 519 | { |
200 | if (nonce_set == 0) { | 520 | if (num_packets_array(array) >= CRYPTO_PACKET_BUFFER_SIZE) |
201 | random_nonce(base_nonce); | 521 | return -1; |
202 | nonce_set = 1; | 522 | |
203 | } | 523 | Packet_Data *new_d = malloc(sizeof(Packet_Data)); |
524 | |||
525 | if (new_d == NULL) | ||
526 | return -1; | ||
204 | 527 | ||
205 | increment_nonce(base_nonce); | 528 | memcpy(new_d, data, sizeof(Packet_Data)); |
206 | memcpy(nonce, base_nonce, crypto_box_NONCEBYTES); | 529 | uint32_t id = array->buffer_end; |
530 | array->buffer[id % CRYPTO_PACKET_BUFFER_SIZE] = new_d; | ||
531 | ++array->buffer_end; | ||
532 | return id; | ||
207 | } | 533 | } |
208 | 534 | ||
535 | /* Read data from begginning of array. | ||
536 | * | ||
537 | * return -1 on failure. | ||
538 | * return packet number on success. | ||
539 | */ | ||
540 | static int64_t read_data_beg_buffer(Packets_Array *array, Packet_Data *data) | ||
541 | { | ||
542 | if (array->buffer_end == array->buffer_start) | ||
543 | return -1; | ||
209 | 544 | ||
210 | /* return 0 if there is no received data in the buffer. | 545 | uint32_t num = array->buffer_start % CRYPTO_PACKET_BUFFER_SIZE; |
211 | * return -1 if the packet was discarded. | 546 | |
212 | * return length of received data if successful. | 547 | if (!array->buffer[num]) |
548 | return -1; | ||
549 | |||
550 | memcpy(data, array->buffer[num], sizeof(Packet_Data)); | ||
551 | uint32_t id = array->buffer_start; | ||
552 | ++array->buffer_start; | ||
553 | free(array->buffer[num]); | ||
554 | array->buffer[num] = NULL; | ||
555 | return id; | ||
556 | } | ||
557 | |||
558 | /* Delete all packets in array before number (but not number) | ||
559 | * | ||
560 | * return -1 on failure. | ||
561 | * return 0 on success | ||
213 | */ | 562 | */ |
214 | int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data) | 563 | static int clear_buffer_until(Packets_Array *array, uint32_t number) |
215 | { | 564 | { |
216 | if (crypt_connection_id_not_valid(c, crypt_connection_id)) | 565 | uint32_t num_spots = array->buffer_end - array->buffer_start; |
217 | return 0; | ||
218 | 566 | ||
219 | if (c->crypto_connections[crypt_connection_id].status != CRYPTO_CONN_ESTABLISHED) | 567 | if (array->buffer_end - number >= num_spots || number - array->buffer_start > num_spots) |
220 | return 0; | 568 | return -1; |
569 | |||
570 | uint32_t i; | ||
221 | 571 | ||
222 | uint8_t temp_data[MAX_DATA_SIZE]; | 572 | for (i = array->buffer_start; i != number; ++i) { |
223 | int length = read_packet(c->lossless_udp, c->crypto_connections[crypt_connection_id].number, temp_data); | 573 | uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE; |
224 | 574 | ||
225 | if (length == 0) | 575 | if (array->buffer[num]) { |
226 | return 0; | 576 | free(array->buffer[num]); |
577 | array->buffer[num] = NULL; | ||
578 | } | ||
579 | } | ||
580 | |||
581 | array->buffer_start = i; | ||
582 | return 0; | ||
583 | } | ||
227 | 584 | ||
228 | if (temp_data[0] != 3) | 585 | /* Set array buffer end to number. |
586 | * | ||
587 | * return -1 on failure. | ||
588 | * return 0 on success. | ||
589 | */ | ||
590 | static int set_buffer_end(Packets_Array *array, uint32_t number) | ||
591 | { | ||
592 | if ((number - array->buffer_start) > CRYPTO_PACKET_BUFFER_SIZE) | ||
593 | return -1; | ||
594 | |||
595 | if ((number - array->buffer_end) > CRYPTO_PACKET_BUFFER_SIZE) | ||
229 | return -1; | 596 | return -1; |
230 | 597 | ||
231 | int len = decrypt_data_fast(c->crypto_connections[crypt_connection_id].shared_key, | 598 | array->buffer_end = number; |
232 | c->crypto_connections[crypt_connection_id].recv_nonce, | 599 | return 0; |
233 | temp_data + 1, length - 1, data); | 600 | } |
601 | |||
602 | /* Create a packet request packet from recv_array and send_buffer_end into | ||
603 | * data of length. | ||
604 | * | ||
605 | * return -1 on failure. | ||
606 | * return length of packet on success. | ||
607 | */ | ||
608 | static int generate_request_packet(uint8_t *data, uint16_t length, Packets_Array *recv_array, uint32_t send_buffer_end) | ||
609 | { | ||
610 | if (length <= (sizeof(uint32_t) * 2)) | ||
611 | return -1; | ||
612 | |||
613 | uint32_t recv_buffer_start = htonl(recv_array->buffer_start); | ||
614 | send_buffer_end = htonl(send_buffer_end); | ||
615 | memcpy(data, &recv_buffer_start, sizeof(uint32_t)); | ||
616 | memcpy(data + sizeof(uint32_t), &send_buffer_end, sizeof(uint32_t)); | ||
617 | data[sizeof(uint32_t) * 2] = PACKET_ID_REQUEST; | ||
618 | |||
619 | uint16_t cur_len = sizeof(uint32_t) * 2 + 1; | ||
620 | |||
621 | if (recv_array->buffer_start == recv_array->buffer_end) | ||
622 | return cur_len; | ||
623 | |||
624 | if (length <= cur_len) | ||
625 | return cur_len; | ||
626 | |||
627 | uint32_t i, n = 1; | ||
628 | |||
629 | for (i = recv_array->buffer_start; i != recv_array->buffer_end; ++i) { | ||
630 | uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE; | ||
631 | |||
632 | if (!recv_array->buffer[num]) { | ||
633 | data[cur_len] = n; | ||
634 | n = 0; | ||
635 | ++cur_len; | ||
636 | |||
637 | if (length <= cur_len) | ||
638 | return cur_len; | ||
639 | |||
640 | } else if (n == 255) { | ||
641 | data[cur_len] = 0; | ||
642 | n = 0; | ||
643 | ++cur_len; | ||
644 | |||
645 | if (length <= cur_len) | ||
646 | return cur_len; | ||
647 | } | ||
234 | 648 | ||
235 | if (len != -1) { | 649 | ++n; |
236 | increment_nonce(c->crypto_connections[crypt_connection_id].recv_nonce); | ||
237 | return len; | ||
238 | } | 650 | } |
239 | 651 | ||
240 | return -1; | 652 | return cur_len; |
241 | } | 653 | } |
242 | 654 | ||
243 | /* returns the number of packet slots left in the sendbuffer. | 655 | /* Handle a request data packet. |
244 | * return 0 if failure. | 656 | * Remove all the packets the other recieved from the array. |
657 | * | ||
658 | * return -1 on failure. | ||
659 | * return number of requested packets on success. | ||
245 | */ | 660 | */ |
246 | uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) | 661 | static int handle_request_packet(Packets_Array *send_array, uint8_t *data, uint16_t length) |
247 | { | 662 | { |
248 | if (crypt_connection_id_not_valid(c, crypt_connection_id)) | 663 | if (length < 1) |
664 | return -1; | ||
665 | |||
666 | if (data[0] != PACKET_ID_REQUEST) | ||
667 | return -1; | ||
668 | |||
669 | if (length == 1) | ||
249 | return 0; | 670 | return 0; |
250 | 671 | ||
251 | return num_free_sendqueue_slots(c->lossless_udp, c->crypto_connections[crypt_connection_id].number); | 672 | ++data; |
673 | --length; | ||
674 | |||
675 | uint32_t i, n = 1; | ||
676 | uint32_t requested = 0; | ||
677 | |||
678 | for (i = send_array->buffer_start; i != send_array->buffer_end; ++i) { | ||
679 | if (length == 0) | ||
680 | break; | ||
681 | |||
682 | uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE; | ||
683 | |||
684 | if (n == data[0]) { | ||
685 | if (send_array->buffer[num]) { | ||
686 | send_array->buffer[num]->time = 0; | ||
687 | } | ||
688 | |||
689 | ++data; | ||
690 | --length; | ||
691 | n = 0; | ||
692 | ++requested; | ||
693 | } else { | ||
694 | free(send_array->buffer[num]); | ||
695 | send_array->buffer[num] = NULL; | ||
696 | } | ||
697 | |||
698 | if (n == 255) { | ||
699 | n = 1; | ||
700 | |||
701 | if (data[0] != 0) | ||
702 | return -1; | ||
703 | |||
704 | ++data; | ||
705 | --length; | ||
706 | } else { | ||
707 | ++n; | ||
708 | } | ||
709 | } | ||
710 | |||
711 | return requested; | ||
252 | } | 712 | } |
253 | 713 | ||
254 | /* return 0 if data could not be put in packet queue. | 714 | /** END: Array Related functions **/ |
255 | * return 1 if data was put into the queue. | 715 | |
716 | #define MAX_DATA_DATA_PACKET_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) | ||
717 | |||
718 | /* Creates and sends a data packet to the peer using the fastest route. | ||
719 | * | ||
720 | * return -1 on failure. | ||
721 | * return 0 on success. | ||
256 | */ | 722 | */ |
257 | int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length) | 723 | static int send_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint16_t length) |
258 | { | 724 | { |
259 | if (crypt_connection_id_not_valid(c, crypt_connection_id)) | 725 | if (length == 0 || length + (1 + sizeof(uint16_t) + crypto_box_MACBYTES) > MAX_CRYPTO_PACKET_SIZE) |
260 | return 0; | 726 | return -1; |
261 | 727 | ||
262 | if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1) | 728 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); |
263 | return 0; | ||
264 | 729 | ||
265 | if (c->crypto_connections[crypt_connection_id].status != CRYPTO_CONN_ESTABLISHED) | 730 | if (conn == 0) |
266 | return 0; | 731 | return -1; |
267 | 732 | ||
268 | uint8_t temp_data[MAX_DATA_SIZE]; | 733 | uint8_t packet[1 + sizeof(uint16_t) + length + crypto_box_MACBYTES]; |
269 | int len = encrypt_data_fast(c->crypto_connections[crypt_connection_id].shared_key, | 734 | packet[0] = NET_PACKET_CRYPTO_DATA; |
270 | c->crypto_connections[crypt_connection_id].sent_nonce, | 735 | memcpy(packet + 1, conn->sent_nonce + (crypto_box_NONCEBYTES - sizeof(uint16_t)), sizeof(uint16_t)); |
271 | data, length, temp_data + 1); | 736 | int len = encrypt_data_symmetric(conn->shared_key, conn->sent_nonce, data, length, packet + 1 + sizeof(uint16_t)); |
272 | 737 | ||
273 | if (len == -1) | 738 | if (len + 1 + sizeof(uint16_t) != sizeof(packet)) |
274 | return 0; | 739 | return -1; |
275 | 740 | ||
276 | temp_data[0] = 3; | 741 | increment_nonce(conn->sent_nonce); |
742 | return send_packet_to(c, crypt_connection_id, packet, sizeof(packet)); | ||
743 | } | ||
277 | 744 | ||
278 | if (write_packet(c->lossless_udp, c->crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0) | 745 | /* Creates and sends a data packet with buffer_start and num to the peer using the fastest route. |
279 | return 0; | 746 | * |
747 | * return -1 on failure. | ||
748 | * return 0 on success. | ||
749 | */ | ||
750 | static int send_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint32_t buffer_start, uint32_t num, | ||
751 | uint8_t *data, uint32_t length) | ||
752 | { | ||
753 | num = htonl(num); | ||
754 | buffer_start = htonl(buffer_start); | ||
755 | uint8_t packet[sizeof(uint32_t) + sizeof(uint32_t) + length]; | ||
756 | memcpy(packet, &buffer_start, sizeof(uint32_t)); | ||
757 | memcpy(packet + sizeof(uint32_t), &num, sizeof(uint32_t)); | ||
758 | memcpy(packet + (sizeof(uint32_t) * 2), data, length); | ||
759 | |||
760 | return send_data_packet(c, crypt_connection_id, packet, sizeof(packet)); | ||
761 | } | ||
280 | 762 | ||
281 | increment_nonce(c->crypto_connections[crypt_connection_id].sent_nonce); | 763 | /* return -1 if data could not be put in packet queue. |
282 | return 1; | 764 | * return positive packet number if data was put into the queue. |
765 | */ | ||
766 | static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length) | ||
767 | { | ||
768 | if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) | ||
769 | return -1; | ||
770 | |||
771 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
772 | |||
773 | if (conn == 0) | ||
774 | return -1; | ||
775 | |||
776 | Packet_Data dt; | ||
777 | dt.time = current_time_monotonic(); | ||
778 | dt.length = length; | ||
779 | memcpy(dt.data, data, length); | ||
780 | int64_t packet_num = add_data_end_of_buffer(&conn->send_array, &dt); | ||
781 | |||
782 | if (packet_num == -1) | ||
783 | return -1; | ||
784 | |||
785 | if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, data, length) != 0) | ||
786 | fprintf(stderr, "send_data_packet failed\n"); | ||
787 | |||
788 | return packet_num; | ||
789 | } | ||
790 | |||
791 | /* Get the lowest 2 bytes from the nonce and convert | ||
792 | * them to host byte format before returning them. | ||
793 | */ | ||
794 | static uint16_t get_nonce_uint16(uint8_t *nonce) | ||
795 | { | ||
796 | uint16_t num; | ||
797 | memcpy(&num, nonce + (crypto_box_NONCEBYTES - sizeof(uint16_t)), sizeof(uint16_t)); | ||
798 | return ntohs(num); | ||
283 | } | 799 | } |
284 | 800 | ||
285 | /* Create a request to peer. | 801 | #define DATA_NUM_THRESHOLD 21845 |
286 | * send_public_key and send_secret_key are the pub/secret keys of the sender. | 802 | |
287 | * recv_public_key is public key of reciever. | 803 | /* Handle a data packet. |
288 | * packet must be an array of MAX_DATA_SIZE big. | 804 | * Decrypt packet of length and put it into data. |
289 | * Data represents the data we send with the request with length being the length of the data. | 805 | * data must be at least MAX_DATA_DATA_PACKET_SIZE big. |
290 | * request_id is the id of the request (32 = friend request, 254 = ping request). | ||
291 | * | 806 | * |
292 | * return -1 on failure. | 807 | * return -1 on failure. |
293 | * return the length of the created packet on success. | 808 | * return length of data on success. |
294 | */ | 809 | */ |
295 | int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t *packet, uint8_t *recv_public_key, | 810 | static int handle_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint8_t *packet, uint16_t length) |
296 | uint8_t *data, uint32_t length, uint8_t request_id) | ||
297 | { | 811 | { |
298 | if (MAX_DATA_SIZE < length + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + crypto_box_MACBYTES) | 812 | if (length <= (1 + sizeof(uint16_t) + crypto_box_MACBYTES) || length > MAX_CRYPTO_PACKET_SIZE) |
813 | return -1; | ||
814 | |||
815 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
816 | |||
817 | if (conn == 0) | ||
299 | return -1; | 818 | return -1; |
300 | 819 | ||
301 | uint8_t nonce[crypto_box_NONCEBYTES]; | 820 | uint8_t nonce[crypto_box_NONCEBYTES]; |
302 | uint8_t temp[MAX_DATA_SIZE]; | 821 | memcpy(nonce, conn->recv_nonce, crypto_box_NONCEBYTES); |
303 | memcpy(temp + 1, data, length); | 822 | uint16_t num_cur_nonce = get_nonce_uint16(nonce); |
304 | temp[0] = request_id; | 823 | uint16_t num; |
305 | new_nonce(nonce); | 824 | memcpy(&num, packet + 1, sizeof(uint16_t)); |
306 | int len = encrypt_data(recv_public_key, send_secret_key, nonce, temp, length + 1, | 825 | num = ntohs(num); |
307 | 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + packet); | 826 | uint16_t diff = num - num_cur_nonce; |
827 | increment_nonce_number(nonce, diff); | ||
828 | int len = decrypt_data_symmetric(conn->shared_key, nonce, packet + 1 + sizeof(uint16_t), | ||
829 | length - (1 + sizeof(uint16_t)), data); | ||
830 | |||
831 | if ((unsigned int)len != length - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) | ||
832 | return -1; | ||
308 | 833 | ||
309 | if (len == -1) | 834 | if (diff > DATA_NUM_THRESHOLD * 2) { |
835 | increment_nonce_number(conn->recv_nonce, DATA_NUM_THRESHOLD); | ||
836 | } | ||
837 | |||
838 | return len; | ||
839 | } | ||
840 | |||
841 | /* Send a request packet. | ||
842 | * | ||
843 | * return -1 on failure. | ||
844 | * return 0 on success. | ||
845 | */ | ||
846 | static int send_request_packet(Net_Crypto *c, int crypt_connection_id) | ||
847 | { | ||
848 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
849 | |||
850 | if (conn == 0) | ||
310 | return -1; | 851 | return -1; |
311 | 852 | ||
312 | packet[0] = NET_PACKET_CRYPTO; | 853 | uint8_t packet[MAX_DATA_DATA_PACKET_SIZE]; |
313 | memcpy(packet + 1, recv_public_key, crypto_box_PUBLICKEYBYTES); | 854 | int len = generate_request_packet(packet, sizeof(packet), &conn->recv_array, conn->send_array.buffer_end); |
314 | memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, send_public_key, crypto_box_PUBLICKEYBYTES); | ||
315 | memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES * 2, nonce, crypto_box_NONCEBYTES); | ||
316 | 855 | ||
317 | return len + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES; | 856 | if (len == -1) |
857 | return -1; | ||
858 | |||
859 | return send_data_packet(c, crypt_connection_id, packet, len); | ||
318 | } | 860 | } |
319 | 861 | ||
320 | /* Puts the senders public key in the request in public_key, the data from the request | 862 | /* Send up to max num previously requested data packets. |
321 | * in data if a friend or ping request was sent to us and returns the length of the data. | ||
322 | * packet is the request packet and length is its length. | ||
323 | * | 863 | * |
324 | * return -1 if not valid request. | 864 | * return -1 on failure. |
865 | * return number of packets sent on success. | ||
325 | */ | 866 | */ |
326 | int handle_request(uint8_t *self_public_key, uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data, | 867 | static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint16_t max_num) |
327 | uint8_t *request_id, uint8_t *packet, uint16_t length) | ||
328 | { | 868 | { |
329 | if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + crypto_box_MACBYTES && | 869 | if (max_num == 0) |
330 | length <= MAX_DATA_SIZE) { | 870 | return -1; |
331 | if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { | ||
332 | memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); | ||
333 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
334 | uint8_t temp[MAX_DATA_SIZE]; | ||
335 | memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES); | ||
336 | int len1 = decrypt_data(public_key, self_secret_key, nonce, | ||
337 | packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES, | ||
338 | length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), temp); | ||
339 | 871 | ||
340 | if (len1 == -1 || len1 == 0) | 872 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); |
341 | return -1; | 873 | |
874 | if (conn == 0) | ||
875 | return -1; | ||
876 | |||
877 | uint32_t i, num_sent = 0, array_size = num_packets_array(&conn->send_array); | ||
342 | 878 | ||
343 | request_id[0] = temp[0]; | 879 | for (i = 0; i < array_size; ++i) { |
344 | --len1; | 880 | Packet_Data *dt; |
345 | memcpy(data, temp + 1, len1); | 881 | uint32_t packet_num = (i + conn->send_array.buffer_start); |
346 | return len1; | 882 | int ret = get_data_pointer(&conn->send_array, &dt, packet_num); |
883 | |||
884 | if (ret == -1) { | ||
885 | return -1; | ||
886 | } else if (ret == 0) { | ||
887 | continue; | ||
888 | } | ||
889 | |||
890 | if (dt->time != 0) { | ||
891 | continue; | ||
347 | } | 892 | } |
893 | |||
894 | dt->time = current_time_monotonic(); | ||
895 | |||
896 | if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, dt->data, | ||
897 | dt->length) == 0) | ||
898 | ++num_sent; | ||
899 | |||
900 | if (num_sent >= max_num) | ||
901 | break; | ||
348 | } | 902 | } |
349 | 903 | ||
350 | return -1; | 904 | return num_sent; |
351 | } | 905 | } |
352 | 906 | ||
353 | void cryptopacket_registerhandler(Net_Crypto *c, uint8_t byte, cryptopacket_handler_callback cb, void *object) | 907 | |
908 | /* Add a new temp packet to send repeatedly. | ||
909 | * | ||
910 | * return -1 on failure. | ||
911 | * return 0 on success. | ||
912 | */ | ||
913 | static int new_temp_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *packet, uint16_t length) | ||
354 | { | 914 | { |
355 | c->cryptopackethandlers[byte].function = cb; | 915 | if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) |
356 | c->cryptopackethandlers[byte].object = object; | 916 | return -1; |
917 | |||
918 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
919 | |||
920 | if (conn == 0) | ||
921 | return -1; | ||
922 | |||
923 | uint8_t *temp_packet = malloc(length); | ||
924 | |||
925 | if (temp_packet == 0) | ||
926 | return -1; | ||
927 | |||
928 | if (conn->temp_packet) | ||
929 | free(conn->temp_packet); | ||
930 | |||
931 | memcpy(temp_packet, packet, length); | ||
932 | conn->temp_packet = temp_packet; | ||
933 | conn->temp_packet_length = length; | ||
934 | conn->temp_packet_sent_time = 0; | ||
935 | conn->temp_packet_num_sent = 0; | ||
936 | return 0; | ||
357 | } | 937 | } |
358 | 938 | ||
359 | static int cryptopacket_handle(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 939 | /* Clear the temp packet. |
940 | * | ||
941 | * return -1 on failure. | ||
942 | * return 0 on success. | ||
943 | */ | ||
944 | static int clear_temp_packet(Net_Crypto *c, int crypt_connection_id) | ||
360 | { | 945 | { |
361 | DHT *dht = object; | 946 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); |
362 | 947 | ||
363 | if (packet[0] == NET_PACKET_CRYPTO) { | 948 | if (conn == 0) |
364 | if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + crypto_box_MACBYTES || | 949 | return -1; |
365 | length > MAX_DATA_SIZE + crypto_box_MACBYTES) | ||
366 | return 1; | ||
367 | 950 | ||
368 | if (memcmp(packet + 1, dht->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { // Check if request is for us. | 951 | if (conn->temp_packet) |
369 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; | 952 | free(conn->temp_packet); |
370 | uint8_t data[MAX_DATA_SIZE]; | ||
371 | uint8_t number; | ||
372 | int len = handle_request(dht->self_public_key, dht->self_secret_key, public_key, data, &number, packet, length); | ||
373 | 953 | ||
374 | if (len == -1 || len == 0) | 954 | conn->temp_packet = 0; |
375 | return 1; | 955 | conn->temp_packet_length = 0; |
956 | conn->temp_packet_sent_time = 0; | ||
957 | conn->temp_packet_num_sent = 0; | ||
958 | return 0; | ||
959 | } | ||
376 | 960 | ||
377 | if (!dht->c->cryptopackethandlers[number].function) return 1; | ||
378 | 961 | ||
379 | return dht->c->cryptopackethandlers[number].function(dht->c->cryptopackethandlers[number].object, source, public_key, | 962 | /* Send the temp packet. |
380 | data, len); | 963 | * |
964 | * return -1 on failure. | ||
965 | * return 0 on success. | ||
966 | */ | ||
967 | static int send_temp_packet(Net_Crypto *c, int crypt_connection_id) | ||
968 | { | ||
969 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
381 | 970 | ||
382 | } else { /* If request is not for us, try routing it. */ | 971 | if (conn == 0) |
383 | int retval = route_packet(dht, packet + 1, packet, length); | 972 | return -1; |
384 | 973 | ||
385 | if ((unsigned int)retval == length) | 974 | if (!conn->temp_packet) |
386 | return 0; | 975 | return -1; |
387 | } | ||
388 | } | ||
389 | 976 | ||
390 | return 1; | 977 | if (send_packet_to(c, crypt_connection_id, conn->temp_packet, conn->temp_packet_length) != 0) |
978 | return -1; | ||
979 | |||
980 | conn->temp_packet_sent_time = current_time_monotonic(); | ||
981 | ++conn->temp_packet_num_sent; | ||
982 | return 0; | ||
391 | } | 983 | } |
392 | 984 | ||
393 | /* Send a crypto handshake packet containing an encrypted secret nonce and session public key | 985 | /* Create a handshake packet and set it as a temp packet. |
394 | * to peer with connection_id and public_key. | 986 | * cookie must be COOKIE_LENGTH. |
395 | * The packet is encrypted with a random nonce which is sent in plain text with the packet. | 987 | * |
988 | * return -1 on failure. | ||
989 | * return 0 on success. | ||
396 | */ | 990 | */ |
397 | static int send_cryptohandshake(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce, | 991 | static int create_send_handshake(Net_Crypto *c, int crypt_connection_id, uint8_t *cookie, uint8_t *dht_public_key) |
398 | uint8_t *session_key) | ||
399 | { | 992 | { |
400 | uint8_t temp_data[MAX_DATA_SIZE]; | 993 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); |
401 | uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; | ||
402 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
403 | 994 | ||
404 | new_nonce(nonce); | 995 | if (conn == 0) |
405 | memcpy(temp, secret_nonce, crypto_box_NONCEBYTES); | 996 | return -1; |
406 | memcpy(temp + crypto_box_NONCEBYTES, session_key, crypto_box_PUBLICKEYBYTES); | ||
407 | 997 | ||
408 | int len = encrypt_data(public_key, c->self_secret_key, nonce, temp, crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, | 998 | uint8_t handshake_packet[HANDSHAKE_PACKET_LENGTH]; |
409 | 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data); | ||
410 | 999 | ||
411 | if (len == -1) | 1000 | if (create_crypto_handshake(c, handshake_packet, cookie, conn->sent_nonce, conn->sessionpublic_key, |
412 | return 0; | 1001 | conn->public_key, dht_public_key) != sizeof(handshake_packet)) |
1002 | return -1; | ||
1003 | |||
1004 | if (new_temp_packet(c, crypt_connection_id, handshake_packet, sizeof(handshake_packet)) != 0) | ||
1005 | return -1; | ||
413 | 1006 | ||
414 | temp_data[0] = 2; | 1007 | send_temp_packet(c, crypt_connection_id); |
415 | memcpy(temp_data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES); | 1008 | return 0; |
416 | memcpy(temp_data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); | ||
417 | return write_packet(c->lossless_udp, connection_id, temp_data, | ||
418 | len + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); | ||
419 | } | 1009 | } |
420 | 1010 | ||
421 | /* Extract secret nonce, session public key and public_key from a packet(data) with length length. | 1011 | /* Send a kill packet. |
422 | * | 1012 | * |
423 | * return 1 if successful. | 1013 | * return -1 on failure. |
424 | * return 0 if failure. | 1014 | * return 0 on success. |
425 | */ | 1015 | */ |
426 | static int handle_cryptohandshake(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, | 1016 | static int send_kill_packet(Net_Crypto *c, int crypt_connection_id) |
427 | uint8_t *session_key, uint8_t *data, uint16_t length) | ||
428 | { | 1017 | { |
429 | int pad = (- crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES); | 1018 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); |
430 | 1019 | ||
431 | if (length != 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES | 1020 | if (conn == 0) |
432 | + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad) { | 1021 | return -1; |
433 | return 0; | 1022 | |
1023 | uint8_t kill_packet = PACKET_ID_KILL; | ||
1024 | return send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, conn->send_array.buffer_end, | ||
1025 | &kill_packet, sizeof(kill_packet)); | ||
1026 | } | ||
1027 | |||
1028 | /* Handle a recieved data packet. | ||
1029 | * | ||
1030 | * return -1 on failure. | ||
1031 | * return 0 on success. | ||
1032 | */ | ||
1033 | static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint8_t *packet, uint16_t length) | ||
1034 | { | ||
1035 | if (length > MAX_CRYPTO_PACKET_SIZE || length <= CRYPTO_DATA_PACKET_MIN_SIZE) | ||
1036 | return -1; | ||
1037 | |||
1038 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
1039 | |||
1040 | if (conn == 0) | ||
1041 | return -1; | ||
1042 | |||
1043 | uint8_t data[MAX_DATA_DATA_PACKET_SIZE]; | ||
1044 | int len = handle_data_packet(c, crypt_connection_id, data, packet, length); | ||
1045 | |||
1046 | if (len <= (int)(sizeof(uint32_t) * 2)) | ||
1047 | return -1; | ||
1048 | |||
1049 | uint32_t buffer_start, num; | ||
1050 | memcpy(&buffer_start, data, sizeof(uint32_t)); | ||
1051 | memcpy(&num, data + sizeof(uint32_t), sizeof(uint32_t)); | ||
1052 | buffer_start = ntohl(buffer_start); | ||
1053 | num = ntohl(num); | ||
1054 | |||
1055 | if (buffer_start != conn->send_array.buffer_start && clear_buffer_until(&conn->send_array, buffer_start) != 0) | ||
1056 | return -1; | ||
1057 | |||
1058 | uint8_t *real_data = data + (sizeof(uint32_t) * 2); | ||
1059 | uint16_t real_length = len - (sizeof(uint32_t) * 2); | ||
1060 | |||
1061 | while (real_data[0] == 0) { /* Remove Padding */ | ||
1062 | ++real_data; | ||
1063 | --real_length; | ||
1064 | |||
1065 | if (real_length == 0) | ||
1066 | return -1; | ||
434 | } | 1067 | } |
435 | 1068 | ||
436 | if (data[0] != 2) | 1069 | if (real_data[0] == PACKET_ID_REQUEST) { |
1070 | int requested = handle_request_packet(&conn->send_array, real_data, real_length); | ||
1071 | |||
1072 | if (requested == -1) { | ||
1073 | return -1; | ||
1074 | } else { | ||
1075 | //TODO? | ||
1076 | } | ||
1077 | |||
1078 | set_buffer_end(&conn->recv_array, num); | ||
1079 | } else if (real_data[0] == PACKET_ID_KILL) { | ||
1080 | conn->killed = 1; | ||
437 | return 0; | 1081 | return 0; |
1082 | } else { | ||
1083 | Packet_Data dt; | ||
1084 | dt.time = current_time_monotonic(); | ||
1085 | dt.length = real_length; | ||
1086 | memcpy(dt.data, real_data, real_length); | ||
438 | 1087 | ||
439 | uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; | 1088 | if (add_data_to_buffer(&conn->recv_array, num, &dt) != 0) |
1089 | return -1; | ||
440 | 1090 | ||
441 | memcpy(public_key, data + 1, crypto_box_PUBLICKEYBYTES); | 1091 | while (read_data_beg_buffer(&conn->recv_array, &dt) != -1) { |
1092 | if (conn->connection_data_callback) | ||
1093 | conn->connection_data_callback(conn->connection_data_callback_object, conn->connection_data_callback_id, dt.data, | ||
1094 | dt.length); | ||
1095 | } | ||
442 | 1096 | ||
443 | int len = decrypt_data(public_key, c->self_secret_key, data + 1 + crypto_box_PUBLICKEYBYTES, | 1097 | /* Packet counter. */ |
444 | data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, | 1098 | ++conn->packet_counter; |
445 | crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad, temp); | 1099 | } |
446 | 1100 | ||
447 | if (len != crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES) | 1101 | if (conn->status == CRYPTO_CONN_NOT_CONFIRMED) { |
448 | return 0; | 1102 | if (conn->connection_status_callback) |
1103 | conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 1); | ||
449 | 1104 | ||
450 | memcpy(secret_nonce, temp, crypto_box_NONCEBYTES); | 1105 | clear_temp_packet(c, crypt_connection_id); |
451 | memcpy(session_key, temp + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES); | 1106 | conn->status = CRYPTO_CONN_ESTABLISHED; |
452 | return 1; | 1107 | } |
1108 | |||
1109 | return 0; | ||
453 | } | 1110 | } |
454 | 1111 | ||
455 | /* Get crypto connection id from public key of peer. | 1112 | /* Handle a packet that was recieved for the connection. |
456 | * | 1113 | * |
457 | * return -1 if there are no connections like we are looking for. | 1114 | * return -1 on failure. |
458 | * return id if it found it. | 1115 | * return 0 on success. |
459 | */ | 1116 | */ |
460 | static int getcryptconnection_id(Net_Crypto *c, uint8_t *public_key) | 1117 | static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint8_t *packet, uint16_t length) |
461 | { | 1118 | { |
462 | uint32_t i; | 1119 | if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) |
1120 | return -1; | ||
463 | 1121 | ||
464 | for (i = 0; i < c->crypto_connections_length; ++i) { | 1122 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); |
465 | if (c->crypto_connections[i].status != CRYPTO_CONN_NO_CONNECTION) | 1123 | |
466 | if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) | 1124 | if (conn == 0) |
467 | return i; | 1125 | return -1; |
1126 | |||
1127 | switch (packet[0]) { | ||
1128 | case NET_PACKET_COOKIE_RESPONSE: { | ||
1129 | if (conn->status != CRYPTO_CONN_COOKIE_REQUESTING) | ||
1130 | return -1; | ||
1131 | |||
1132 | uint8_t cookie[COOKIE_LENGTH]; | ||
1133 | uint64_t number; | ||
1134 | |||
1135 | if (handle_cookie_response(cookie, &number, packet, length, conn->shared_key) != sizeof(cookie)) | ||
1136 | return -1; | ||
1137 | |||
1138 | if (number != conn->cookie_request_number) | ||
1139 | return -1; | ||
1140 | |||
1141 | if (create_send_handshake(c, crypt_connection_id, cookie, conn->dht_public_key) != 0) | ||
1142 | return -1; | ||
1143 | |||
1144 | conn->status = CRYPTO_CONN_HANDSHAKE_SENT; | ||
1145 | return 0; | ||
1146 | } | ||
1147 | |||
1148 | case NET_PACKET_CRYPTO_HS: { | ||
1149 | if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT) { | ||
1150 | uint8_t peer_real_pk[crypto_box_PUBLICKEYBYTES]; | ||
1151 | uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; | ||
1152 | uint8_t cookie[COOKIE_LENGTH]; | ||
1153 | |||
1154 | if (handle_crypto_handshake(c, conn->recv_nonce, conn->peersessionpublic_key, peer_real_pk, dht_public_key, cookie, | ||
1155 | packet, length, conn->public_key) != 0) | ||
1156 | return -1; | ||
1157 | |||
1158 | encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key); | ||
1159 | |||
1160 | if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING) { | ||
1161 | if (create_send_handshake(c, crypt_connection_id, cookie, dht_public_key) != 0) | ||
1162 | return -1; | ||
1163 | } | ||
1164 | |||
1165 | conn->status = CRYPTO_CONN_NOT_CONFIRMED; | ||
1166 | /* Status needs to be CRYPTO_CONN_NOT_CONFIRMED for this to work. */ | ||
1167 | set_connection_dht_public_key(c, crypt_connection_id, dht_public_key, current_time_monotonic()); | ||
1168 | } else { | ||
1169 | return -1; | ||
1170 | } | ||
1171 | |||
1172 | return 0; | ||
1173 | } | ||
1174 | |||
1175 | case NET_PACKET_CRYPTO_DATA: { | ||
1176 | if (conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED) { | ||
1177 | return handle_data_packet_helper(c, crypt_connection_id, packet, length); | ||
1178 | } else { | ||
1179 | return -1; | ||
1180 | } | ||
1181 | |||
1182 | return 0; | ||
1183 | } | ||
1184 | |||
1185 | default: { | ||
1186 | return -1; | ||
1187 | } | ||
468 | } | 1188 | } |
469 | 1189 | ||
470 | return -1; | 1190 | return 0; |
471 | } | 1191 | } |
472 | 1192 | ||
473 | /* Set the size of the friend list to numfriends. | 1193 | /* Set the size of the friend list to numfriends. |
@@ -492,326 +1212,1100 @@ static int realloc_cryptoconnection(Net_Crypto *c, uint32_t num) | |||
492 | return 0; | 1212 | return 0; |
493 | } | 1213 | } |
494 | 1214 | ||
495 | /* Start a secure connection with other peer who has public_key and ip_port. | 1215 | |
1216 | /* Create a new empty crypto connection. | ||
496 | * | 1217 | * |
497 | * return -1 if failure. | 1218 | * return -1 on failure. |
498 | * return crypt_connection_id of the initialized connection if everything went well. | 1219 | * return connection id on success. |
499 | */ | 1220 | */ |
500 | int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port) | 1221 | static int create_crypto_connection(Net_Crypto *c) |
501 | { | 1222 | { |
502 | uint32_t i; | 1223 | uint32_t i; |
503 | int id_existing = getcryptconnection_id(c, public_key); | ||
504 | 1224 | ||
505 | if (id_existing != -1) { | 1225 | for (i = 0; i < c->crypto_connections_length; ++i) { |
506 | IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id_existing].number); | 1226 | if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) |
507 | 1227 | return i; | |
508 | if (ipport_equal(&c_ip, &ip_port)) | ||
509 | return -1; | ||
510 | } | 1228 | } |
511 | 1229 | ||
512 | if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1 | 1230 | if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1) |
513 | || c->crypto_connections == NULL) | ||
514 | return -1; | 1231 | return -1; |
515 | 1232 | ||
516 | memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection)); | 1233 | memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection)); |
517 | c->crypto_connections[c->crypto_connections_length].number = ~0; | 1234 | int id = c->crypto_connections_length; |
1235 | ++c->crypto_connections_length; | ||
1236 | return id; | ||
1237 | } | ||
518 | 1238 | ||
519 | for (i = 0; i <= c->crypto_connections_length; ++i) { | 1239 | /* Wipe a crypto connection. |
520 | if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) { | 1240 | * |
521 | int id_new = new_connection(c->lossless_udp, ip_port); | 1241 | * return -1 on failure. |
1242 | * return 0 on success. | ||
1243 | */ | ||
1244 | static int wipe_crypto_connection(Net_Crypto *c, int crypt_connection_id) | ||
1245 | { | ||
1246 | if (crypt_connection_id_not_valid(c, crypt_connection_id)) | ||
1247 | return -1; | ||
522 | 1248 | ||
523 | if (id_new == -1) | 1249 | uint32_t i; |
524 | return -1; | 1250 | memset(&(c->crypto_connections[crypt_connection_id]), 0 , sizeof(Crypto_Connection)); |
525 | 1251 | ||
526 | c->crypto_connections[i].number = id_new; | 1252 | for (i = c->crypto_connections_length; i != 0; --i) { |
527 | c->crypto_connections[i].status = CRYPTO_CONN_HANDSHAKE_SENT; | 1253 | if (c->crypto_connections[i - 1].status != CRYPTO_CONN_NO_CONNECTION) |
528 | random_nonce(c->crypto_connections[i].recv_nonce); | 1254 | break; |
529 | memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); | 1255 | } |
530 | crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key); | ||
531 | c->crypto_connections[i].timeout = unix_time() + CRYPTO_HANDSHAKE_TIMEOUT; | ||
532 | 1256 | ||
533 | if (c->crypto_connections_length == i) | 1257 | if (c->crypto_connections_length != i) { |
534 | ++c->crypto_connections_length; | 1258 | c->crypto_connections_length = i; |
1259 | realloc_cryptoconnection(c, c->crypto_connections_length); | ||
1260 | } | ||
535 | 1261 | ||
536 | if (send_cryptohandshake(c, id_new, public_key, c->crypto_connections[i].recv_nonce, | 1262 | return 0; |
537 | c->crypto_connections[i].sessionpublic_key) == 1) { | 1263 | } |
538 | increment_nonce(c->crypto_connections[i].recv_nonce); | 1264 | |
1265 | /* Get crypto connection id from public key of peer. | ||
1266 | * | ||
1267 | * return -1 if there are no connections like we are looking for. | ||
1268 | * return id if it found it. | ||
1269 | */ | ||
1270 | static int getcryptconnection_id(Net_Crypto *c, uint8_t *public_key) | ||
1271 | { | ||
1272 | uint32_t i; | ||
1273 | |||
1274 | for (i = 0; i < c->crypto_connections_length; ++i) { | ||
1275 | if (c->crypto_connections[i].status != CRYPTO_CONN_NO_CONNECTION) | ||
1276 | if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) | ||
539 | return i; | 1277 | return i; |
540 | } | 1278 | } |
541 | 1279 | ||
542 | return -1; /* This should never happen. */ | 1280 | return -1; |
543 | } | 1281 | } |
1282 | |||
1283 | /* Get crypto connection id from public key of peer. | ||
1284 | * | ||
1285 | * return -1 if there are no connections like we are looking for. | ||
1286 | * return id if it found it. | ||
1287 | */ | ||
1288 | static int getcryptconnection_id_dht_pubkey(Net_Crypto *c, uint8_t *dht_public_key) | ||
1289 | { | ||
1290 | uint32_t i; | ||
1291 | |||
1292 | for (i = 0; i < c->crypto_connections_length; ++i) { | ||
1293 | if (c->crypto_connections[i].status != CRYPTO_CONN_NO_CONNECTION && c->crypto_connections[i].dht_public_key_set) | ||
1294 | if (memcmp(dht_public_key, c->crypto_connections[i].dht_public_key, crypto_box_PUBLICKEYBYTES) == 0) | ||
1295 | return i; | ||
544 | } | 1296 | } |
545 | 1297 | ||
546 | return -1; | 1298 | return -1; |
547 | } | 1299 | } |
548 | 1300 | ||
549 | /* Handle an incoming connection. | 1301 | /* Add a source to the crypto connection. |
1302 | * This is to be used only when we have recieved a packet from that source. | ||
550 | * | 1303 | * |
551 | * return -1 if no crypto inbound connection. | 1304 | * return -1 on failure. |
552 | * return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection. | 1305 | * return positive number on success. |
1306 | * 0 if source was a direct UDP connection. | ||
1307 | * TODO | ||
1308 | */ | ||
1309 | static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id, IP_Port source) | ||
1310 | { | ||
1311 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
1312 | |||
1313 | if (conn == 0) | ||
1314 | return -1; | ||
1315 | |||
1316 | if (source.ip.family == AF_INET || source.ip.family == AF_INET6) { | ||
1317 | conn->ip_port = source; | ||
1318 | conn->direct_lastrecv_time = current_time_monotonic(); | ||
1319 | return 0; | ||
1320 | } | ||
1321 | |||
1322 | return -1; | ||
1323 | } | ||
1324 | |||
1325 | |||
1326 | /* Set function to be called when someone requests a new connection to us. | ||
553 | * | 1327 | * |
554 | * Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce | 1328 | * The set function should return -1 on failure and 0 on success. |
555 | * and the session public key for the connection in session_key. | 1329 | * |
556 | * to accept it see: accept_crypto_inbound(...). | 1330 | * n_c is only valid for the duration of the function call. |
557 | * to refuse it just call kill_connection(...) on the connection id. | ||
558 | */ | 1331 | */ |
559 | int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key) | 1332 | void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c), |
1333 | void *object) | ||
560 | { | 1334 | { |
561 | while (1) { | 1335 | c->new_connection_callback = new_connection_callback; |
562 | int incoming_con = incoming_connection(c->lossless_udp, 1); | 1336 | c->new_connection_callback_object = object; |
1337 | } | ||
563 | 1338 | ||
564 | if (incoming_con != -1) { | 1339 | /* Handle a handshake packet by someone who wants to initiate a new connection with us. |
565 | if (is_connected(c->lossless_udp, incoming_con) == LUDP_TIMED_OUT) { | 1340 | * This calls the callback set by new_connection_handler() if the handshake is ok. |
566 | kill_connection(c->lossless_udp, incoming_con); | 1341 | * |
567 | continue; | 1342 | * return -1 on failure. |
568 | } | 1343 | * return 0 on success. |
1344 | */ | ||
1345 | static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, uint8_t *data, uint16_t length) | ||
1346 | { | ||
1347 | New_Connection n_c; | ||
1348 | n_c.cookie = malloc(COOKIE_LENGTH); | ||
569 | 1349 | ||
570 | if (id_packet(c->lossless_udp, incoming_con) == 2) { | 1350 | if (n_c.cookie == NULL) |
571 | uint8_t temp_data[MAX_DATA_SIZE]; | 1351 | return -1; |
572 | uint16_t len = read_packet_silent(c->lossless_udp, incoming_con, temp_data); | ||
573 | 1352 | ||
574 | if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) { | 1353 | n_c.source = source; |
575 | return incoming_con; | 1354 | n_c.cookie_length = COOKIE_LENGTH; |
576 | } else { | 1355 | |
577 | kill_connection(c->lossless_udp, incoming_con); | 1356 | if (handle_crypto_handshake(c, n_c.recv_nonce, n_c.peersessionpublic_key, n_c.public_key, n_c.dht_public_key, |
578 | } | 1357 | n_c.cookie, data, length, 0) != 0) { |
579 | } else { | 1358 | free(n_c.cookie); |
580 | kill_connection(c->lossless_udp, incoming_con); | 1359 | return -1; |
1360 | } | ||
1361 | |||
1362 | int crypt_connection_id = getcryptconnection_id(c, n_c.public_key); | ||
1363 | |||
1364 | if (crypt_connection_id != -1) { | ||
1365 | int ret = -1; | ||
1366 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
1367 | |||
1368 | if (conn != 0 && (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT)) { | ||
1369 | memcpy(conn->recv_nonce, n_c.recv_nonce, crypto_box_NONCEBYTES); | ||
1370 | memcpy(conn->peersessionpublic_key, n_c.peersessionpublic_key, crypto_box_PUBLICKEYBYTES); | ||
1371 | encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key); | ||
1372 | |||
1373 | crypto_connection_add_source(c, crypt_connection_id, source); | ||
1374 | |||
1375 | if (create_send_handshake(c, crypt_connection_id, n_c.cookie, n_c.dht_public_key) == 0) { | ||
1376 | conn->status = CRYPTO_CONN_NOT_CONFIRMED; | ||
1377 | /* Status needs to be CRYPTO_CONN_NOT_CONFIRMED for this to work. */ | ||
1378 | set_connection_dht_public_key(c, crypt_connection_id, n_c.dht_public_key, current_time_monotonic()); | ||
1379 | ret = 0; | ||
581 | } | 1380 | } |
582 | } else { | ||
583 | break; | ||
584 | } | 1381 | } |
1382 | |||
1383 | free(n_c.cookie); | ||
1384 | return ret; | ||
585 | } | 1385 | } |
586 | 1386 | ||
587 | return -1; | 1387 | int ret = c->new_connection_callback(c->new_connection_callback_object, &n_c); |
1388 | free(n_c.cookie); | ||
1389 | return ret; | ||
588 | } | 1390 | } |
589 | 1391 | ||
590 | /* Kill a crypto connection. | 1392 | /* Accept a crypto connection. |
591 | * | 1393 | * |
592 | * return 0 if killed successfully. | 1394 | * return -1 on failure. |
593 | * return 1 if there was a problem. | 1395 | * return connection id on success. |
594 | */ | 1396 | */ |
595 | int crypto_kill(Net_Crypto *c, int crypt_connection_id) | 1397 | int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) |
596 | { | 1398 | { |
597 | if (crypt_connection_id_not_valid(c, crypt_connection_id)) | 1399 | if (getcryptconnection_id(c, n_c->public_key) != -1) |
598 | return 1; | 1400 | return -1; |
1401 | |||
1402 | int crypt_connection_id = create_crypto_connection(c); | ||
1403 | |||
1404 | if (crypt_connection_id == -1) | ||
1405 | return -1; | ||
599 | 1406 | ||
600 | if (c->crypto_connections[crypt_connection_id].status != CRYPTO_CONN_NO_CONNECTION) { | 1407 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); |
601 | c->crypto_connections[crypt_connection_id].status = CRYPTO_CONN_NO_CONNECTION; | ||
602 | kill_connection(c->lossless_udp, c->crypto_connections[crypt_connection_id].number); | ||
603 | memset(&(c->crypto_connections[crypt_connection_id]), 0 , sizeof(Crypto_Connection)); | ||
604 | c->crypto_connections[crypt_connection_id].number = ~0; | ||
605 | uint32_t i; | ||
606 | 1408 | ||
607 | for (i = c->crypto_connections_length; i != 0; --i) { | 1409 | if (conn == 0) |
608 | if (c->crypto_connections[i - 1].status != CRYPTO_CONN_NO_CONNECTION) | 1410 | return -1; |
609 | break; | 1411 | |
1412 | memcpy(conn->public_key, n_c->public_key, crypto_box_PUBLICKEYBYTES); | ||
1413 | memcpy(conn->recv_nonce, n_c->recv_nonce, crypto_box_NONCEBYTES); | ||
1414 | memcpy(conn->peersessionpublic_key, n_c->peersessionpublic_key, crypto_box_PUBLICKEYBYTES); | ||
1415 | random_nonce(conn->sent_nonce); | ||
1416 | crypto_box_keypair(conn->sessionpublic_key, conn->sessionsecret_key); | ||
1417 | encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key); | ||
1418 | |||
1419 | if (n_c->cookie_length != COOKIE_LENGTH) | ||
1420 | return -1; | ||
1421 | |||
1422 | if (create_send_handshake(c, crypt_connection_id, n_c->cookie, n_c->dht_public_key) != 0) | ||
1423 | return -1; | ||
1424 | |||
1425 | conn->status = CRYPTO_CONN_NOT_CONFIRMED; | ||
1426 | /* Status needs to be CRYPTO_CONN_NOT_CONFIRMED for this to work. */ | ||
1427 | set_connection_dht_public_key(c, crypt_connection_id, n_c->dht_public_key, current_time_monotonic()); | ||
1428 | conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; | ||
1429 | crypto_connection_add_source(c, crypt_connection_id, n_c->source); | ||
1430 | return crypt_connection_id; | ||
1431 | } | ||
1432 | |||
1433 | /* Create a crypto connection. | ||
1434 | * If one to that real public key already exists, return it. | ||
1435 | * | ||
1436 | * return -1 on failure. | ||
1437 | * return connection id on success. | ||
1438 | */ | ||
1439 | int new_crypto_connection(Net_Crypto *c, uint8_t *real_public_key) | ||
1440 | { | ||
1441 | int crypt_connection_id = getcryptconnection_id(c, real_public_key); | ||
1442 | |||
1443 | if (crypt_connection_id != -1) | ||
1444 | return crypt_connection_id; | ||
1445 | |||
1446 | crypt_connection_id = create_crypto_connection(c); | ||
1447 | |||
1448 | if (crypt_connection_id == -1) | ||
1449 | return -1; | ||
1450 | |||
1451 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
1452 | |||
1453 | if (conn == 0) | ||
1454 | return -1; | ||
1455 | |||
1456 | memcpy(conn->public_key, real_public_key, crypto_box_PUBLICKEYBYTES); | ||
1457 | random_nonce(conn->sent_nonce); | ||
1458 | crypto_box_keypair(conn->sessionpublic_key, conn->sessionsecret_key); | ||
1459 | conn->status = CRYPTO_CONN_COOKIE_REQUESTING; | ||
1460 | conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; | ||
1461 | return crypt_connection_id; | ||
1462 | } | ||
1463 | |||
1464 | /* Disconnect peer from all associated TCP connections. | ||
1465 | * | ||
1466 | * return -1 on failure. | ||
1467 | * return 0 on success. | ||
1468 | */ | ||
1469 | static int disconnect_peer_tcp(Net_Crypto *c, int crypt_connection_id) | ||
1470 | { | ||
1471 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
1472 | |||
1473 | if (conn == 0) | ||
1474 | return -1; | ||
1475 | |||
1476 | uint32_t i; | ||
1477 | |||
1478 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1479 | if (conn->status_tcp[i] != STATUS_TCP_NULL) { | ||
1480 | send_disconnect_request(c->tcp_connections[i], conn->con_number_tcp[i]); | ||
1481 | conn->status_tcp[i] = STATUS_TCP_NULL; | ||
1482 | conn->con_number_tcp[i] = 0; | ||
610 | } | 1483 | } |
1484 | } | ||
611 | 1485 | ||
612 | if (c->crypto_connections_length != i) { | 1486 | return 0; |
613 | c->crypto_connections_length = i; | 1487 | } |
614 | realloc_cryptoconnection(c, c->crypto_connections_length); | 1488 | |
1489 | /* Connect peer to all associated TCP connections. | ||
1490 | * | ||
1491 | * return -1 on failure. | ||
1492 | * return 0 on success. | ||
1493 | */ | ||
1494 | static int connect_peer_tcp(Net_Crypto *c, int crypt_connection_id) | ||
1495 | { | ||
1496 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
1497 | |||
1498 | if (conn == 0) | ||
1499 | return -1; | ||
1500 | |||
1501 | uint32_t i; | ||
1502 | |||
1503 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1504 | if (c->tcp_connections[i] == NULL) | ||
1505 | continue; | ||
1506 | |||
1507 | //TODO check function return? | ||
1508 | send_routing_request(c->tcp_connections[i], conn->dht_public_key); | ||
1509 | } | ||
1510 | |||
1511 | return 0; | ||
1512 | } | ||
1513 | |||
1514 | /* Copy friends DHT public key into dht_key. | ||
1515 | * | ||
1516 | * return 0 on failure (no key copied). | ||
1517 | * return timestamp on success (key copied). | ||
1518 | */ | ||
1519 | uint64_t get_connection_dht_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key) | ||
1520 | { | ||
1521 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
1522 | |||
1523 | if (conn == 0) | ||
1524 | return 0; | ||
1525 | |||
1526 | if (conn->dht_public_key_set == 0) | ||
1527 | return 0; | ||
1528 | |||
1529 | memcpy(dht_public_key, conn->dht_public_key, crypto_box_PUBLICKEYBYTES); | ||
1530 | return conn->dht_public_key_timestamp; | ||
1531 | } | ||
1532 | |||
1533 | |||
1534 | /* Set the DHT public key of the crypto connection. | ||
1535 | * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to | ||
1536 | * the other peer. | ||
1537 | * | ||
1538 | * return -1 on failure. | ||
1539 | * return 0 on success. | ||
1540 | */ | ||
1541 | int set_connection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key, uint64_t timestamp) | ||
1542 | { | ||
1543 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
1544 | |||
1545 | if (conn == 0) | ||
1546 | return -1; | ||
1547 | |||
1548 | if (timestamp <= conn->dht_public_key_timestamp) | ||
1549 | return -1; | ||
1550 | |||
1551 | if (conn->dht_public_key_set == 1 && memcmp(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0) | ||
1552 | return -1; | ||
1553 | |||
1554 | if (conn->dht_public_key_set == 1) { | ||
1555 | disconnect_peer_tcp(c, crypt_connection_id); | ||
1556 | } | ||
1557 | |||
1558 | memcpy(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES); | ||
1559 | conn->dht_public_key_set = 1; | ||
1560 | conn->dht_public_key_timestamp = timestamp; | ||
1561 | |||
1562 | if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING) { | ||
1563 | conn->cookie_request_number = random_64b(); | ||
1564 | uint8_t cookie_request[COOKIE_REQUEST_LENGTH]; | ||
1565 | |||
1566 | if (create_cookie_request(c, cookie_request, conn->dht_public_key, conn->cookie_request_number, | ||
1567 | conn->shared_key) != sizeof(cookie_request)) | ||
1568 | return -1; | ||
1569 | |||
1570 | if (new_temp_packet(c, crypt_connection_id, cookie_request, sizeof(cookie_request)) != 0) | ||
1571 | return -1; | ||
1572 | }//TODO | ||
1573 | |||
1574 | connect_peer_tcp(c, crypt_connection_id); | ||
1575 | return 0; | ||
1576 | } | ||
1577 | |||
1578 | /* Set the direct ip of the crypto connection. | ||
1579 | * | ||
1580 | * return -1 on failure. | ||
1581 | * return 0 on success. | ||
1582 | */ | ||
1583 | int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port) | ||
1584 | { | ||
1585 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
1586 | |||
1587 | if (conn == 0) | ||
1588 | return -1; | ||
1589 | |||
1590 | if (!ipport_equal(&ip_port, &conn->ip_port)) { | ||
1591 | conn->ip_port = ip_port; | ||
1592 | conn->direct_lastrecv_time = 0; | ||
1593 | return 0; | ||
1594 | } | ||
1595 | |||
1596 | return -1; | ||
1597 | } | ||
1598 | |||
1599 | static int tcp_response_callback(void *object, uint8_t connection_id, uint8_t *public_key) | ||
1600 | { | ||
1601 | TCP_Client_Connection *TCP_con = object; | ||
1602 | Net_Crypto *c = TCP_con->net_crypto_pointer; | ||
1603 | |||
1604 | int crypt_connection_id = getcryptconnection_id_dht_pubkey(c, public_key); | ||
1605 | |||
1606 | if (crypt_connection_id == -1) | ||
1607 | return -1; | ||
1608 | |||
1609 | set_tcp_connection_number(TCP_con, connection_id, crypt_connection_id); | ||
1610 | |||
1611 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
1612 | |||
1613 | if (conn == 0) | ||
1614 | return -1; | ||
1615 | |||
1616 | uint32_t location = TCP_con->net_crypto_location; | ||
1617 | |||
1618 | if (location >= MAX_TCP_CONNECTIONS) | ||
1619 | return -1; | ||
1620 | |||
1621 | if (c->tcp_connections[location] != TCP_con) | ||
1622 | return -1; | ||
1623 | |||
1624 | conn->con_number_tcp[location] = connection_id; | ||
1625 | uint32_t i; | ||
1626 | |||
1627 | for (i = 0; i < conn->num_tcp_relays; ++i) { | ||
1628 | if (memcmp(TCP_con->public_key, conn->tcp_relays[i].client_id, crypto_box_PUBLICKEYBYTES) == 0) { | ||
1629 | conn->status_tcp[location] = STATUS_TCP_INVISIBLE; | ||
1630 | return 0; | ||
1631 | } | ||
1632 | } | ||
1633 | |||
1634 | conn->status_tcp[location] = STATUS_TCP_OFFLINE; | ||
1635 | return 0; | ||
1636 | } | ||
1637 | |||
1638 | static int tcp_status_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t status) | ||
1639 | { | ||
1640 | TCP_Client_Connection *TCP_con = object; | ||
1641 | Net_Crypto *c = TCP_con->net_crypto_pointer; | ||
1642 | |||
1643 | Crypto_Connection *conn = get_crypto_connection(c, number); | ||
1644 | |||
1645 | if (conn == 0) | ||
1646 | return -1; | ||
1647 | |||
1648 | uint32_t location = TCP_con->net_crypto_location; | ||
1649 | |||
1650 | if (location >= MAX_TCP_CONNECTIONS) | ||
1651 | return -1; | ||
1652 | |||
1653 | if (c->tcp_connections[location] != TCP_con) | ||
1654 | return -1; | ||
1655 | |||
1656 | if (status == 1) { | ||
1657 | conn->status_tcp[location] = STATUS_TCP_OFFLINE; | ||
1658 | } else if (status == 2) { | ||
1659 | conn->status_tcp[location] = STATUS_TCP_ONLINE; | ||
1660 | } | ||
1661 | |||
1662 | conn->con_number_tcp[location] = connection_id; | ||
1663 | return 0; | ||
1664 | } | ||
1665 | |||
1666 | static int tcp_data_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t *data, uint16_t length) | ||
1667 | { | ||
1668 | |||
1669 | if (length == 0) | ||
1670 | return -1; | ||
1671 | |||
1672 | TCP_Client_Connection *TCP_con = object; | ||
1673 | Net_Crypto *c = TCP_con->net_crypto_pointer; | ||
1674 | |||
1675 | if (data[0] == NET_PACKET_COOKIE_REQUEST) { | ||
1676 | return tcp_handle_cookie_request(c, TCP_con, connection_id, data, length); | ||
1677 | } | ||
1678 | |||
1679 | Crypto_Connection *conn = get_crypto_connection(c, number); | ||
1680 | |||
1681 | if (conn == 0) | ||
1682 | return -1; | ||
1683 | |||
1684 | if (handle_packet_connection(c, number, data, length) != 0) | ||
1685 | return -1; | ||
1686 | |||
1687 | //TODO detect and kill bad TCP connections. | ||
1688 | return 0; | ||
1689 | } | ||
1690 | |||
1691 | static int tcp_oob_callback(void *object, uint8_t *public_key, uint8_t *data, uint16_t length) | ||
1692 | { | ||
1693 | if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) | ||
1694 | return -1; | ||
1695 | |||
1696 | TCP_Client_Connection *TCP_con = object; | ||
1697 | Net_Crypto *c = TCP_con->net_crypto_pointer; | ||
1698 | uint32_t location = TCP_con->net_crypto_location; | ||
1699 | |||
1700 | if (data[0] == NET_PACKET_COOKIE_REQUEST) { | ||
1701 | return tcp_oob_handle_cookie_request(c, TCP_con, public_key, data, length); | ||
1702 | } | ||
1703 | |||
1704 | int crypt_connection_id = getcryptconnection_id_dht_pubkey(c, public_key); | ||
1705 | |||
1706 | if (crypt_connection_id == -1) { | ||
1707 | IP_Port source; | ||
1708 | source.ip.family = TCP_FAMILY; | ||
1709 | source.ip.ip6.uint32[0] = location; | ||
1710 | |||
1711 | if (data[0] != NET_PACKET_CRYPTO_HS) { | ||
1712 | fprintf(stderr, "tcp snhappen %u\n", data[0]); | ||
1713 | return -1; | ||
615 | } | 1714 | } |
616 | 1715 | ||
1716 | if (handle_new_connection_handshake(c, source, data, length) != 0) | ||
1717 | return -1; | ||
1718 | |||
617 | return 0; | 1719 | return 0; |
618 | } | 1720 | } |
619 | 1721 | ||
620 | return 1; | 1722 | if (handle_packet_connection(c, crypt_connection_id, data, length) != 0) |
1723 | return -1; | ||
1724 | |||
1725 | return 0; | ||
621 | } | 1726 | } |
622 | 1727 | ||
623 | /* Accept an incoming connection using the parameters provided by crypto_inbound. | 1728 | /* Check if tcp connection to public key can be created. |
624 | * | 1729 | * |
625 | * return -1 if not successful. | 1730 | * return -1 if it can't. |
626 | * return the crypt_connection_id if successful. | 1731 | * return 0 if it can. |
627 | */ | 1732 | */ |
628 | int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce, | 1733 | static int tcp_connection_check(Net_Crypto *c, uint8_t *public_key) |
629 | uint8_t *session_key) | ||
630 | { | 1734 | { |
631 | uint32_t i; | 1735 | uint32_t i; |
632 | 1736 | ||
633 | if (discard_packet(c->lossless_udp, connection_id) == -1) | 1737 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { |
1738 | if (c->tcp_connections_new[i] == NULL) | ||
1739 | continue; | ||
1740 | |||
1741 | if (memcmp(c->tcp_connections_new[i]->public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) | ||
1742 | return -1; | ||
1743 | } | ||
1744 | |||
1745 | uint32_t num = 0; | ||
1746 | |||
1747 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1748 | if (c->tcp_connections[i] == NULL) | ||
1749 | continue; | ||
1750 | |||
1751 | if (memcmp(c->tcp_connections[i]->public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) | ||
1752 | return -1; | ||
1753 | |||
1754 | ++num; | ||
1755 | } | ||
1756 | |||
1757 | if (num == MAX_TCP_CONNECTIONS) | ||
634 | return -1; | 1758 | return -1; |
635 | 1759 | ||
636 | /* | 1760 | return 0; |
637 | * if(getcryptconnection_id(public_key) != -1) | 1761 | } |
638 | * { | ||
639 | * return -1; | ||
640 | * } | ||
641 | */ | ||
642 | 1762 | ||
643 | if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1 | 1763 | /* Add a tcp relay, associating it to a crypt_connection_id. |
644 | || c->crypto_connections == NULL) | 1764 | * |
1765 | * return 0 if it was added. | ||
1766 | * return -1 if it wasn't. | ||
1767 | */ | ||
1768 | int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, uint8_t *public_key) | ||
1769 | { | ||
1770 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
1771 | |||
1772 | if (conn == 0) | ||
645 | return -1; | 1773 | return -1; |
646 | 1774 | ||
647 | memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection)); | 1775 | if (ip_port.ip.family == TCP_INET) { |
648 | c->crypto_connections[c->crypto_connections_length].number = ~0; | 1776 | ip_port.ip.family = AF_INET; |
649 | 1777 | } else if (ip_port.ip.family == TCP_INET6) { | |
650 | for (i = 0; i <= c->crypto_connections_length; ++i) { | 1778 | ip_port.ip.family = AF_INET6; |
651 | if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) { | 1779 | } |
652 | c->crypto_connections[i].number = connection_id; | 1780 | |
653 | c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED; | 1781 | if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6) |
654 | c->crypto_connections[i].timeout = unix_time() + CRYPTO_HANDSHAKE_TIMEOUT; | 1782 | return -1; |
655 | random_nonce(c->crypto_connections[i].recv_nonce); | 1783 | |
656 | memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); | 1784 | uint32_t i; |
657 | memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); | 1785 | |
658 | increment_nonce(c->crypto_connections[i].sent_nonce); | 1786 | for (i = 0; i < conn->num_tcp_relays; ++i) { |
659 | memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); | 1787 | if (memcmp(conn->tcp_relays[i].client_id, public_key, crypto_box_PUBLICKEYBYTES) == 0) { |
660 | 1788 | conn->tcp_relays[i].ip_port = ip_port; | |
661 | crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key); | 1789 | return 0; |
662 | 1790 | } | |
663 | if (c->crypto_connections_length == i) | 1791 | } |
664 | ++c->crypto_connections_length; | ||
665 | |||
666 | if (send_cryptohandshake(c, connection_id, public_key, c->crypto_connections[i].recv_nonce, | ||
667 | c->crypto_connections[i].sessionpublic_key) == 1) { | ||
668 | increment_nonce(c->crypto_connections[i].recv_nonce); | ||
669 | uint32_t zero = 0; | ||
670 | encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, | ||
671 | c->crypto_connections[i].sessionsecret_key, | ||
672 | c->crypto_connections[i].shared_key); | ||
673 | c->crypto_connections[i].status = | ||
674 | CRYPTO_CONN_ESTABLISHED; /* Connection status needs to be 3 for write_cryptpacket() to work. */ | ||
675 | write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero)); | ||
676 | c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED; /* Set it to its proper value right after. */ | ||
677 | return i; | ||
678 | } | ||
679 | 1792 | ||
680 | return -1; /* This should never happen. */ | 1793 | if (conn->num_tcp_relays == MAX_TCP_RELAYS_PEER) { |
1794 | uint16_t index = rand() % MAX_TCP_RELAYS_PEER; | ||
1795 | conn->tcp_relays[index].ip_port = ip_port; | ||
1796 | memcpy(conn->tcp_relays[index].client_id, public_key, crypto_box_PUBLICKEYBYTES); | ||
1797 | } else { | ||
1798 | conn->tcp_relays[conn->num_tcp_relays].ip_port = ip_port; | ||
1799 | memcpy(conn->tcp_relays[conn->num_tcp_relays].client_id, public_key, crypto_box_PUBLICKEYBYTES); | ||
1800 | ++conn->num_tcp_relays; | ||
1801 | } | ||
1802 | |||
1803 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1804 | if (c->tcp_connections[i] == NULL) | ||
1805 | continue; | ||
1806 | |||
1807 | if (memcmp(c->tcp_connections[i]->public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) { | ||
1808 | if (conn->status_tcp[i] == STATUS_TCP_OFFLINE) | ||
1809 | conn->status_tcp[i] = STATUS_TCP_INVISIBLE; | ||
1810 | } | ||
1811 | } | ||
1812 | |||
1813 | return add_tcp_relay(c, ip_port, public_key); | ||
1814 | } | ||
1815 | |||
1816 | /* Add a tcp relay to the array. | ||
1817 | * | ||
1818 | * return 0 if it was added. | ||
1819 | * return -1 if it wasn't. | ||
1820 | */ | ||
1821 | int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, uint8_t *public_key) | ||
1822 | { | ||
1823 | if (ip_port.ip.family == TCP_INET) { | ||
1824 | ip_port.ip.family = AF_INET; | ||
1825 | } else if (ip_port.ip.family == TCP_INET6) { | ||
1826 | ip_port.ip.family = AF_INET6; | ||
1827 | } | ||
1828 | |||
1829 | if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6) | ||
1830 | return -1; | ||
1831 | |||
1832 | if (tcp_connection_check(c, public_key) != 0) | ||
1833 | return -1; | ||
1834 | |||
1835 | uint32_t i; | ||
1836 | |||
1837 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1838 | if (c->tcp_connections_new[i] == NULL) { | ||
1839 | c->tcp_connections_new[i] = new_TCP_connection(ip_port, public_key, c->dht->self_public_key, c->dht->self_secret_key); | ||
1840 | return 0; | ||
681 | } | 1841 | } |
682 | } | 1842 | } |
683 | 1843 | ||
684 | return -1; | 1844 | return -1; |
685 | } | 1845 | } |
686 | 1846 | ||
687 | /* return 0 if no connection. | 1847 | /* Copy a maximum of num TCP relays we are connected to to tcp_relays. |
688 | * return 1 we have sent a handshake. | 1848 | * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6. |
689 | * return 2 if connection is not confirmed yet (we have received a handshake but no empty data packet). | 1849 | * |
690 | * return 3 if the connection is established. | 1850 | * return number of relays copied to tcp_relays on success. |
691 | * return 4 if the connection is timed out and waiting to be killed. | 1851 | * return 0 on failure. |
692 | */ | 1852 | */ |
693 | int is_cryptoconnected(Net_Crypto *c, int crypt_connection_id) | 1853 | unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, uint16_t num) |
694 | { | 1854 | { |
695 | if ((unsigned int)crypt_connection_id < c->crypto_connections_length) | 1855 | if (num == 0) |
696 | return c->crypto_connections[crypt_connection_id].status; | 1856 | return 0; |
1857 | |||
1858 | uint32_t i; | ||
1859 | uint16_t copied = 0; | ||
1860 | |||
1861 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1862 | if (c->tcp_connections[i] != NULL) { | ||
1863 | memcpy(tcp_relays[copied].client_id, c->tcp_connections[i]->public_key, crypto_box_PUBLICKEYBYTES); | ||
1864 | tcp_relays[copied].ip_port = c->tcp_connections[i]->ip_port; | ||
1865 | |||
1866 | if (tcp_relays[copied].ip_port.ip.family == AF_INET) { | ||
1867 | tcp_relays[copied].ip_port.ip.family = TCP_INET; | ||
1868 | } else if (tcp_relays[copied].ip_port.ip.family == AF_INET6) { | ||
1869 | tcp_relays[copied].ip_port.ip.family = TCP_INET6; | ||
1870 | } | ||
1871 | |||
1872 | ++copied; | ||
1873 | |||
1874 | if (copied == num) | ||
1875 | return copied; | ||
1876 | } | ||
1877 | } | ||
697 | 1878 | ||
698 | return CRYPTO_CONN_NO_CONNECTION; | 1879 | return copied; |
699 | } | 1880 | } |
700 | 1881 | ||
701 | void new_keys(Net_Crypto *c) | 1882 | /* Add a connected tcp connection to the tcp_connections array. |
1883 | * | ||
1884 | * return 0 if it was added. | ||
1885 | * return -1 if it wasn't. | ||
1886 | */ | ||
1887 | static int add_tcp_connected(Net_Crypto *c, TCP_Client_Connection *tcp_con) | ||
702 | { | 1888 | { |
703 | crypto_box_keypair(c->self_public_key, c->self_secret_key); | 1889 | uint32_t i; |
1890 | |||
1891 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1892 | if (c->tcp_connections[i] == NULL) | ||
1893 | break; | ||
1894 | } | ||
1895 | |||
1896 | if (i == MAX_TCP_CONNECTIONS) | ||
1897 | return -1; | ||
1898 | |||
1899 | uint32_t tcp_num = i; | ||
1900 | |||
1901 | for (i = 0; i < c->crypto_connections_length; ++i) { | ||
1902 | Crypto_Connection *conn = get_crypto_connection(c, i); | ||
1903 | |||
1904 | if (conn == 0) | ||
1905 | return -1; | ||
1906 | |||
1907 | if (conn->status == CRYPTO_CONN_NO_CONNECTION) | ||
1908 | continue; | ||
1909 | |||
1910 | if (conn->status == CRYPTO_CONN_TIMED_OUT) | ||
1911 | continue; | ||
1912 | |||
1913 | if (conn->dht_public_key_set) | ||
1914 | if (send_routing_request(tcp_con, conn->dht_public_key) != 1) | ||
1915 | return -1; | ||
1916 | |||
1917 | } | ||
1918 | |||
1919 | tcp_con->net_crypto_pointer = c; | ||
1920 | tcp_con->net_crypto_location = tcp_num; | ||
1921 | routing_response_handler(tcp_con, tcp_response_callback, tcp_con); | ||
1922 | routing_status_handler(tcp_con, tcp_status_callback, tcp_con); | ||
1923 | routing_data_handler(tcp_con, tcp_data_callback, tcp_con); | ||
1924 | oob_data_handler(tcp_con, tcp_oob_callback, tcp_con); | ||
1925 | c->tcp_connections[tcp_num] = tcp_con; | ||
1926 | return 0; | ||
704 | } | 1927 | } |
705 | 1928 | ||
706 | /* Save the public and private keys to the keys array. | 1929 | static void do_tcp(Net_Crypto *c) |
707 | * Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES. | 1930 | { |
1931 | uint32_t i; | ||
1932 | |||
1933 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1934 | if (c->tcp_connections_new[i] == NULL) | ||
1935 | continue; | ||
1936 | |||
1937 | do_TCP_connection(c->tcp_connections_new[i]); | ||
1938 | |||
1939 | if (c->tcp_connections_new[i]->status == TCP_CLIENT_CONFIRMED) { | ||
1940 | if (add_tcp_connected(c, c->tcp_connections_new[i]) == 0) { | ||
1941 | c->tcp_connections_new[i] = NULL; | ||
1942 | } else { | ||
1943 | kill_TCP_connection(c->tcp_connections_new[i]); | ||
1944 | c->tcp_connections_new[i] = NULL; | ||
1945 | } | ||
1946 | } | ||
1947 | } | ||
1948 | |||
1949 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1950 | if (c->tcp_connections[i] == NULL) | ||
1951 | continue; | ||
1952 | |||
1953 | do_TCP_connection(c->tcp_connections[i]); | ||
1954 | } | ||
1955 | } | ||
1956 | |||
1957 | static void clear_disconnected_tcp_peer(Crypto_Connection *conn, uint32_t number) | ||
1958 | { | ||
1959 | if (conn->status == CRYPTO_CONN_NO_CONNECTION) | ||
1960 | return; | ||
1961 | |||
1962 | if (number >= MAX_TCP_CONNECTIONS) | ||
1963 | return; | ||
1964 | |||
1965 | conn->status_tcp[number] = STATUS_TCP_NULL; | ||
1966 | conn->con_number_tcp[number] = 0; | ||
1967 | } | ||
1968 | |||
1969 | static void clear_disconnected_tcp(Net_Crypto *c) | ||
1970 | { | ||
1971 | uint32_t i, j; | ||
1972 | |||
1973 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1974 | if (c->tcp_connections_new[i] == NULL) | ||
1975 | continue; | ||
1976 | |||
1977 | if (c->tcp_connections_new[i]->status != TCP_CLIENT_DISCONNECTED) | ||
1978 | continue; | ||
1979 | |||
1980 | kill_TCP_connection(c->tcp_connections_new[i]); | ||
1981 | c->tcp_connections_new[i] = NULL; | ||
1982 | } | ||
1983 | |||
1984 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { | ||
1985 | if (c->tcp_connections[i] == NULL) | ||
1986 | continue; | ||
1987 | |||
1988 | TCP_Client_Connection *tcp_con = c->tcp_connections[i]; | ||
1989 | |||
1990 | if (tcp_con->status != TCP_CLIENT_DISCONNECTED) | ||
1991 | continue; | ||
1992 | |||
1993 | c->tcp_connections[i] = NULL; | ||
1994 | kill_TCP_connection(tcp_con); | ||
1995 | |||
1996 | for (j = 0; j < c->crypto_connections_length; ++j) { | ||
1997 | Crypto_Connection *conn = get_crypto_connection(c, j); | ||
1998 | |||
1999 | if (conn == 0) | ||
2000 | return; | ||
2001 | |||
2002 | clear_disconnected_tcp_peer(conn, i); | ||
2003 | } | ||
2004 | } | ||
2005 | } | ||
2006 | |||
2007 | /* Set function to be called when connection with crypt_connection_id goes connects/disconnects. | ||
2008 | * | ||
2009 | * The set function should return -1 on failure and 0 on success. | ||
2010 | * Note that if this function is set, the connection will clear itself on disconnect. | ||
2011 | * Object and id will be passed to this function untouched. | ||
2012 | * status is 1 if the connection is going online, 0 if it is going offline. | ||
2013 | * | ||
2014 | * return -1 on failure. | ||
2015 | * return 0 on success. | ||
708 | */ | 2016 | */ |
709 | void save_keys(Net_Crypto *c, uint8_t *keys) | 2017 | int connection_status_handler(Net_Crypto *c, int crypt_connection_id, int (*connection_status_callback)(void *object, |
2018 | int id, uint8_t status), void *object, int id) | ||
710 | { | 2019 | { |
711 | memcpy(keys, c->self_public_key, crypto_box_PUBLICKEYBYTES); | 2020 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); |
712 | memcpy(keys + crypto_box_PUBLICKEYBYTES, c->self_secret_key, crypto_box_SECRETKEYBYTES); | 2021 | |
2022 | if (conn == 0) | ||
2023 | return -1; | ||
2024 | |||
2025 | conn->connection_status_callback = connection_status_callback; | ||
2026 | conn->connection_status_callback_object = object; | ||
2027 | conn->connection_status_callback_id = id; | ||
2028 | return 0; | ||
713 | } | 2029 | } |
714 | 2030 | ||
715 | /* Load the public and private keys from the keys array. | 2031 | /* Set function to be called when connection with crypt_connection_id receives a data packet of length. |
716 | * Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES. | 2032 | * |
2033 | * The set function should return -1 on failure and 0 on success. | ||
2034 | * Object and id will be passed to this function untouched. | ||
2035 | * | ||
2036 | * return -1 on failure. | ||
2037 | * return 0 on success. | ||
717 | */ | 2038 | */ |
718 | void load_keys(Net_Crypto *c, uint8_t *keys) | 2039 | int connection_data_handler(Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object, |
2040 | int id, uint8_t *data, uint16_t length), void *object, int id) | ||
719 | { | 2041 | { |
720 | memcpy(c->self_public_key, keys, crypto_box_PUBLICKEYBYTES); | 2042 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); |
721 | memcpy(c->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES); | 2043 | |
2044 | if (conn == 0) | ||
2045 | return -1; | ||
2046 | |||
2047 | conn->connection_data_callback = connection_data_callback; | ||
2048 | conn->connection_data_callback_object = object; | ||
2049 | conn->connection_data_callback_id = id; | ||
2050 | return 0; | ||
722 | } | 2051 | } |
723 | 2052 | ||
724 | /* Handle received packets for not yet established crypto connections. */ | 2053 | /* Get the crypto connection id from the ip_port. |
725 | static void receive_crypto(Net_Crypto *c) | 2054 | * |
2055 | * return -1 on failure. | ||
2056 | * return connection id on success. | ||
2057 | */ | ||
2058 | static int crypto_id_ip_port(Net_Crypto *c, IP_Port ip_port) | ||
726 | { | 2059 | { |
727 | uint32_t i; | 2060 | uint32_t i; |
728 | uint64_t temp_time = unix_time(); | ||
729 | 2061 | ||
730 | for (i = 0; i < c->crypto_connections_length; ++i) { | 2062 | for (i = 0; i < c->crypto_connections_length; ++i) { |
731 | if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) | 2063 | if (is_alive(c->crypto_connections[i].status)) |
732 | continue; | 2064 | if (ipport_equal(&ip_port, &c->crypto_connections[i].ip_port)) |
2065 | return i; | ||
2066 | } | ||
733 | 2067 | ||
734 | if (c->crypto_connections[i].status == CRYPTO_CONN_HANDSHAKE_SENT) { | 2068 | return -1; |
735 | uint8_t temp_data[MAX_DATA_SIZE]; | 2069 | } |
736 | uint8_t secret_nonce[crypto_box_NONCEBYTES]; | 2070 | |
737 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; | 2071 | #define CRYPTO_MIN_PACKET_SIZE (1 + sizeof(uint16_t) + crypto_box_MACBYTES) |
738 | uint8_t session_key[crypto_box_PUBLICKEYBYTES]; | 2072 | |
739 | uint16_t len; | 2073 | /* Handle raw UDP packets coming directly from the socket. |
740 | 2074 | * | |
741 | if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 2) { /* Handle handshake packet. */ | 2075 | * Handles: |
742 | len = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data); | 2076 | * Cookie response packets. |
743 | 2077 | * Crypto handshake packets. | |
744 | if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) { | 2078 | * Crypto data packets. |
745 | if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) { | 2079 | * |
746 | memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); | 2080 | */ |
747 | memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); | 2081 | static int udp_handle_packet(void *object, IP_Port source, uint8_t *packet, uint32_t length) |
748 | increment_nonce(c->crypto_connections[i].sent_nonce); | 2082 | { |
749 | uint32_t zero = 0; | 2083 | if (length <= CRYPTO_MIN_PACKET_SIZE || length > MAX_CRYPTO_PACKET_SIZE) |
750 | encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, | 2084 | return 1; |
751 | c->crypto_connections[i].sessionsecret_key, | 2085 | |
752 | c->crypto_connections[i].shared_key); | 2086 | Net_Crypto *c = object; |
753 | c->crypto_connections[i].status = | 2087 | int crypt_connection_id = crypto_id_ip_port(c, source); |
754 | CRYPTO_CONN_ESTABLISHED; /* Connection status needs to be 3 for write_cryptpacket() to work. */ | 2088 | |
755 | write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero)); | 2089 | if (crypt_connection_id == -1) { |
756 | c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED; /* Set it to its proper value right after. */ | 2090 | if (packet[0] != NET_PACKET_CRYPTO_HS) |
757 | } else { | 2091 | return 1; |
758 | /* This should not happen, timeout the connection if it does. */ | 2092 | |
759 | c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; | 2093 | if (handle_new_connection_handshake(c, source, packet, length) != 0) |
760 | } | 2094 | return 1; |
761 | } else { | 2095 | |
762 | /* This should not happen, timeout the connection if it does. */ | 2096 | return 0; |
763 | c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; | 2097 | } |
764 | } | 2098 | |
765 | } else if (id_packet(c->lossless_udp, | 2099 | if (handle_packet_connection(c, crypt_connection_id, packet, length) != 0) |
766 | c->crypto_connections[i].number) != (uint8_t)~0) { | 2100 | return 1; |
767 | /* This should not happen, timeout the connection if it does. */ | 2101 | |
768 | c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; | 2102 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); |
2103 | |||
2104 | if (conn == 0) | ||
2105 | return -1; | ||
2106 | |||
2107 | conn->direct_lastrecv_time = current_time_monotonic(); | ||
2108 | return 0; | ||
2109 | } | ||
2110 | |||
2111 | /* The dT for the average packet recieving rate calculations. | ||
2112 | Also used as the */ | ||
2113 | #define PACKET_COUNTER_AVERAGE_INTERVAL 200 | ||
2114 | |||
2115 | /* Ratio of recv queue size / recv packet rate (in seconds) times | ||
2116 | * the number of ms between request packets to send at that ratio | ||
2117 | */ | ||
2118 | #define REQUEST_PACKETS_COMPARE_CONSTANT (0.5 * 100.0) | ||
2119 | static void send_crypto_packets(Net_Crypto *c) | ||
2120 | { | ||
2121 | uint32_t i; | ||
2122 | uint64_t temp_time = current_time_monotonic(); | ||
2123 | |||
2124 | for (i = 0; i < c->crypto_connections_length; ++i) { | ||
2125 | Crypto_Connection *conn = get_crypto_connection(c, i); | ||
2126 | |||
2127 | if (conn == 0) | ||
2128 | return; | ||
2129 | |||
2130 | if (CRYPTO_SEND_PACKET_INTERVAL + conn->temp_packet_sent_time < temp_time) { | ||
2131 | send_temp_packet(c, i); | ||
2132 | } | ||
2133 | |||
2134 | if ((conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED) | ||
2135 | && (CRYPTO_SEND_PACKET_INTERVAL + conn->last_request_packet_sent) < temp_time) { | ||
2136 | if (send_request_packet(c, i) == 0) { | ||
2137 | conn->last_request_packet_sent = temp_time; | ||
769 | } | 2138 | } |
2139 | |||
770 | } | 2140 | } |
771 | 2141 | ||
772 | if (c->crypto_connections[i].status == CRYPTO_CONN_NOT_CONFIRMED) { | 2142 | if (conn->status == CRYPTO_CONN_ESTABLISHED) { |
773 | if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 3) { | 2143 | if (((double)num_packets_array(&conn->recv_array) / (conn->packet_recv_rate + 1.0)) * (double)( |
774 | uint8_t temp_data[MAX_DATA_SIZE]; | 2144 | temp_time - conn->last_request_packet_sent) > REQUEST_PACKETS_COMPARE_CONSTANT) { |
775 | uint8_t data[MAX_DATA_SIZE]; | 2145 | if (send_request_packet(c, i) == 0) { |
776 | int length = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data); | 2146 | conn->last_request_packet_sent = temp_time; |
777 | int len = decrypt_data(c->crypto_connections[i].peersessionpublic_key, | 2147 | } |
778 | c->crypto_connections[i].sessionsecret_key, | 2148 | } |
779 | c->crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data); | 2149 | |
780 | uint32_t zero = 0; | 2150 | if ((PACKET_COUNTER_AVERAGE_INTERVAL + conn->packet_counter_set) < temp_time) { |
781 | 2151 | conn->packet_recv_rate = (double)conn->packet_counter / ((double)(temp_time - conn->packet_counter_set) / 1000.0); | |
782 | if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) { | 2152 | conn->packet_counter = 0; |
783 | increment_nonce(c->crypto_connections[i].recv_nonce); | 2153 | conn->packet_counter_set = temp_time; |
784 | encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, | 2154 | |
785 | c->crypto_connections[i].sessionsecret_key, | 2155 | if ((double)num_packets_array(&conn->send_array) < 0.3 * (conn->packet_send_rate)) { |
786 | c->crypto_connections[i].shared_key); | 2156 | conn->packet_send_rate *= 1.2; |
787 | c->crypto_connections[i].status = CRYPTO_CONN_ESTABLISHED; | 2157 | } else if ((double)num_packets_array(&conn->send_array) > 0.4 * (conn->packet_send_rate)) { |
788 | c->crypto_connections[i].timeout = ~0; | 2158 | conn->packet_send_rate *= 0.8; |
789 | /* Connection is accepted. */ | 2159 | } |
790 | confirm_connection(c->lossless_udp, c->crypto_connections[i].number); | 2160 | |
2161 | if (conn->packet_send_rate < CRYPTO_PACKET_MIN_RATE || !conn->sending) | ||
2162 | conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; | ||
2163 | |||
2164 | if (conn->packet_send_rate > CRYPTO_PACKET_BUFFER_SIZE * 2) | ||
2165 | conn->packet_send_rate = CRYPTO_PACKET_BUFFER_SIZE * 2; | ||
2166 | |||
2167 | } | ||
2168 | |||
2169 | if (conn->last_packets_left_set == 0) { | ||
2170 | conn->last_packets_left_set = temp_time; | ||
2171 | conn->packets_left = conn->packet_send_rate; | ||
2172 | } else if (((1000.0 / conn->packet_send_rate) + conn->last_packets_left_set) < temp_time) { | ||
2173 | uint32_t num_packets = conn->packet_send_rate * ((double)(temp_time - conn->last_packets_left_set) / 1000.0); | ||
2174 | |||
2175 | if (conn->packets_left > num_packets * 2 + CRYPTO_MIN_QUEUE_LENGTH) { | ||
2176 | conn->packets_left = num_packets * 2 + CRYPTO_MIN_QUEUE_LENGTH; | ||
791 | } else { | 2177 | } else { |
792 | /* This should not happen, timeout the connection if it does. */ | 2178 | conn->packets_left += num_packets; |
793 | c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; | ||
794 | } | 2179 | } |
795 | } else if (id_packet(c->lossless_udp, c->crypto_connections[i].number) != (uint8_t)~0) { | 2180 | |
796 | /* This should not happen, timeout the connection if it does. */ | 2181 | conn->last_packets_left_set = temp_time; |
797 | c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; | ||
798 | } | 2182 | } |
799 | } | ||
800 | 2183 | ||
801 | if (temp_time > c->crypto_connections[i].timeout) { | 2184 | int ret = send_requested_packets(c, i, conn->packets_left); |
802 | c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; | 2185 | |
2186 | if (ret != -1) { | ||
2187 | conn->packets_left -= ret; | ||
2188 | } | ||
2189 | |||
2190 | if (conn->sending != 0 && num_packets_array(&conn->send_array) < CRYPTO_MIN_QUEUE_LENGTH) { | ||
2191 | --conn->sending; | ||
2192 | } | ||
803 | } | 2193 | } |
804 | } | 2194 | } |
805 | } | 2195 | } |
806 | 2196 | ||
2197 | |||
2198 | /* returns the number of packet slots left in the sendbuffer. | ||
2199 | * return 0 if failure. | ||
2200 | */ | ||
2201 | uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) | ||
2202 | { | ||
2203 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
2204 | |||
2205 | if (conn == 0) | ||
2206 | return 0; | ||
2207 | |||
2208 | return conn->packets_left; | ||
2209 | } | ||
2210 | |||
2211 | |||
2212 | |||
2213 | |||
2214 | /* return -1 if data could not be put in packet queue. | ||
2215 | * return positive packet number if data was put into the queue. | ||
2216 | */ | ||
2217 | int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length) | ||
2218 | { | ||
2219 | if (length == 0) | ||
2220 | return -1; | ||
2221 | |||
2222 | if (data[0] < CRYPTO_RESERVED_PACKETS) | ||
2223 | return -1; | ||
2224 | |||
2225 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
2226 | |||
2227 | if (conn == 0) | ||
2228 | return -1; | ||
2229 | |||
2230 | if (conn->status != CRYPTO_CONN_ESTABLISHED) | ||
2231 | return -1; | ||
2232 | |||
2233 | if (conn->packets_left == 0) | ||
2234 | return -1; | ||
2235 | |||
2236 | int64_t ret = send_lossless_packet(c, crypt_connection_id, data, length); | ||
2237 | |||
2238 | if (ret == -1) | ||
2239 | return -1; | ||
2240 | |||
2241 | --conn->packets_left; | ||
2242 | conn->sending = CRYPTO_MIN_QUEUE_LENGTH; | ||
2243 | return ret; | ||
2244 | } | ||
2245 | |||
2246 | /* Kill a crypto connection. | ||
2247 | * | ||
2248 | * return -1 on failure. | ||
2249 | * return 0 on success. | ||
2250 | */ | ||
2251 | int crypto_kill(Net_Crypto *c, int crypt_connection_id) | ||
2252 | { | ||
2253 | //TODO | ||
2254 | send_kill_packet(c, crypt_connection_id); | ||
2255 | disconnect_peer_tcp(c, crypt_connection_id); | ||
2256 | return wipe_crypto_connection(c, crypt_connection_id); | ||
2257 | } | ||
2258 | |||
2259 | /* return one of CRYPTO_CONN_* values indicating the state of the connection. | ||
2260 | * | ||
2261 | * sets direct_connected to 1 if connection connects directly to other, 0 if it isn't. | ||
2262 | */ | ||
2263 | unsigned int crypto_connection_status(Net_Crypto *c, int crypt_connection_id, uint8_t *direct_connected) | ||
2264 | { | ||
2265 | Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); | ||
2266 | |||
2267 | if (conn == 0) | ||
2268 | return CRYPTO_CONN_NO_CONNECTION; | ||
2269 | |||
2270 | *direct_connected = 0; | ||
2271 | |||
2272 | if ((CRYPTO_SEND_PACKET_INTERVAL * MAX_NUM_SENDPACKET_TRIES + conn->direct_lastrecv_time) > current_time_monotonic()) | ||
2273 | *direct_connected = 1; | ||
2274 | |||
2275 | return conn->status; | ||
2276 | } | ||
2277 | |||
2278 | void new_keys(Net_Crypto *c) | ||
2279 | { | ||
2280 | crypto_box_keypair(c->self_public_key, c->self_secret_key); | ||
2281 | } | ||
2282 | |||
2283 | /* Save the public and private keys to the keys array. | ||
2284 | * Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES. | ||
2285 | */ | ||
2286 | void save_keys(Net_Crypto *c, uint8_t *keys) | ||
2287 | { | ||
2288 | memcpy(keys, c->self_public_key, crypto_box_PUBLICKEYBYTES); | ||
2289 | memcpy(keys + crypto_box_PUBLICKEYBYTES, c->self_secret_key, crypto_box_SECRETKEYBYTES); | ||
2290 | } | ||
2291 | |||
2292 | /* Load the public and private keys from the keys array. | ||
2293 | * Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES. | ||
2294 | */ | ||
2295 | void load_keys(Net_Crypto *c, uint8_t *keys) | ||
2296 | { | ||
2297 | memcpy(c->self_public_key, keys, crypto_box_PUBLICKEYBYTES); | ||
2298 | memcpy(c->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES); | ||
2299 | } | ||
2300 | |||
807 | /* Run this to (re)initialize net_crypto. | 2301 | /* Run this to (re)initialize net_crypto. |
808 | * Sets all the global connection variables to their default values. | 2302 | * Sets all the global connection variables to their default values. |
809 | */ | 2303 | */ |
810 | Net_Crypto *new_net_crypto(Networking_Core *net) | 2304 | Net_Crypto *new_net_crypto(DHT *dht) |
811 | { | 2305 | { |
812 | unix_time_update(); | 2306 | unix_time_update(); |
813 | 2307 | ||
814 | if (net == NULL) | 2308 | if (dht == NULL) |
815 | return NULL; | 2309 | return NULL; |
816 | 2310 | ||
817 | Net_Crypto *temp = calloc(1, sizeof(Net_Crypto)); | 2311 | Net_Crypto *temp = calloc(1, sizeof(Net_Crypto)); |
@@ -819,31 +2313,55 @@ Net_Crypto *new_net_crypto(Networking_Core *net) | |||
819 | if (temp == NULL) | 2313 | if (temp == NULL) |
820 | return NULL; | 2314 | return NULL; |
821 | 2315 | ||
822 | temp->lossless_udp = new_lossless_udp(net); | 2316 | temp->dht = dht; |
823 | |||
824 | if (temp->lossless_udp == NULL) { | ||
825 | free(temp); | ||
826 | return NULL; | ||
827 | } | ||
828 | 2317 | ||
829 | new_keys(temp); | 2318 | new_keys(temp); |
830 | return temp; | 2319 | new_symmetric_key(temp->secret_symmetric_key); |
831 | } | ||
832 | 2320 | ||
833 | void init_cryptopackets(void *dht) | 2321 | networking_registerhandler(dht->net, NET_PACKET_COOKIE_REQUEST, &udp_handle_cookie_request, temp); |
834 | { | 2322 | networking_registerhandler(dht->net, NET_PACKET_COOKIE_RESPONSE, &udp_handle_packet, temp); |
835 | DHT *s_dht = dht; | 2323 | networking_registerhandler(dht->net, NET_PACKET_CRYPTO_HS, &udp_handle_packet, temp); |
836 | networking_registerhandler(s_dht->c->lossless_udp->net, NET_PACKET_CRYPTO, &cryptopacket_handle, s_dht); | 2324 | networking_registerhandler(dht->net, NET_PACKET_CRYPTO_DATA, &udp_handle_packet, temp); |
2325 | return temp; | ||
837 | } | 2326 | } |
838 | 2327 | ||
839 | static void kill_timedout(Net_Crypto *c) | 2328 | static void kill_timedout(Net_Crypto *c) |
840 | { | 2329 | { |
841 | uint32_t i; | 2330 | uint32_t i; |
2331 | //uint64_t temp_time = current_time_monotonic(); | ||
842 | 2332 | ||
843 | for (i = 0; i < c->crypto_connections_length; ++i) { | 2333 | for (i = 0; i < c->crypto_connections_length; ++i) { |
844 | if (c->crypto_connections[i].status != CRYPTO_CONN_NO_CONNECTION | 2334 | Crypto_Connection *conn = get_crypto_connection(c, i); |
845 | && is_connected(c->lossless_udp, c->crypto_connections[i].number) == LUDP_TIMED_OUT) | 2335 | |
846 | c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; | 2336 | if (conn == 0) |
2337 | return; | ||
2338 | |||
2339 | if (conn->status == CRYPTO_CONN_NO_CONNECTION || conn->status == CRYPTO_CONN_TIMED_OUT) | ||
2340 | continue; | ||
2341 | |||
2342 | if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT | ||
2343 | || conn->status == CRYPTO_CONN_NOT_CONFIRMED) { | ||
2344 | if (conn->temp_packet_num_sent < MAX_NUM_SENDPACKET_TRIES) | ||
2345 | continue; | ||
2346 | |||
2347 | conn->killed = 1; | ||
2348 | |||
2349 | } | ||
2350 | |||
2351 | if (conn->killed) { | ||
2352 | if (conn->connection_status_callback) { | ||
2353 | conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 0); | ||
2354 | crypto_kill(c, i); | ||
2355 | continue; | ||
2356 | } | ||
2357 | |||
2358 | conn->status = CRYPTO_CONN_TIMED_OUT; | ||
2359 | continue; | ||
2360 | } | ||
2361 | |||
2362 | if (conn->status == CRYPTO_CONN_ESTABLISHED) { | ||
2363 | //TODO: add a timeout here? | ||
2364 | } | ||
847 | } | 2365 | } |
848 | } | 2366 | } |
849 | 2367 | ||
@@ -851,9 +2369,10 @@ static void kill_timedout(Net_Crypto *c) | |||
851 | void do_net_crypto(Net_Crypto *c) | 2369 | void do_net_crypto(Net_Crypto *c) |
852 | { | 2370 | { |
853 | unix_time_update(); | 2371 | unix_time_update(); |
854 | do_lossless_udp(c->lossless_udp); | ||
855 | kill_timedout(c); | 2372 | kill_timedout(c); |
856 | receive_crypto(c); | 2373 | do_tcp(c); |
2374 | clear_disconnected_tcp(c); | ||
2375 | send_crypto_packets(c); | ||
857 | } | 2376 | } |
858 | 2377 | ||
859 | void kill_net_crypto(Net_Crypto *c) | 2378 | void kill_net_crypto(Net_Crypto *c) |
@@ -864,7 +2383,15 @@ void kill_net_crypto(Net_Crypto *c) | |||
864 | crypto_kill(c, i); | 2383 | crypto_kill(c, i); |
865 | } | 2384 | } |
866 | 2385 | ||
867 | kill_lossless_udp(c->lossless_udp); | 2386 | for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { |
2387 | kill_TCP_connection(c->tcp_connections_new[i]); | ||
2388 | kill_TCP_connection(c->tcp_connections[i]); | ||
2389 | } | ||
2390 | |||
2391 | networking_registerhandler(c->dht->net, NET_PACKET_COOKIE_REQUEST, NULL, NULL); | ||
2392 | networking_registerhandler(c->dht->net, NET_PACKET_COOKIE_RESPONSE, NULL, NULL); | ||
2393 | networking_registerhandler(c->dht->net, NET_PACKET_CRYPTO_HS, NULL, NULL); | ||
2394 | networking_registerhandler(c->dht->net, NET_PACKET_CRYPTO_DATA, NULL, NULL); | ||
868 | memset(c, 0, sizeof(Net_Crypto)); | 2395 | memset(c, 0, sizeof(Net_Crypto)); |
869 | free(c); | 2396 | free(c); |
870 | } | 2397 | } |
diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index da776527..25f8c2f7 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h | |||
@@ -24,21 +24,62 @@ | |||
24 | #ifndef NET_CRYPTO_H | 24 | #ifndef NET_CRYPTO_H |
25 | #define NET_CRYPTO_H | 25 | #define NET_CRYPTO_H |
26 | 26 | ||
27 | #include "Lossless_UDP.h" | 27 | #include "DHT.h" |
28 | 28 | #include "TCP_client.h" | |
29 | #define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */ | ||
30 | #define CRYPTO_PACKET_HARDENING 48 /* Hardening crypto packet ID. */ | ||
31 | #define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID. */ | ||
32 | #define CRYPTO_PACKET_GROUP_CHAT_GET_NODES 48 /* Group chat get Nodes packet */ | ||
33 | #define CRYPTO_PACKET_GROUP_CHAT_SEND_NODES 49 /* Group chat send Nodes packet */ | ||
34 | #define CRYPTO_PACKET_GROUP_CHAT_BROADCAST 50 /* Group chat broadcast packet */ | ||
35 | #define CRYPTO_HANDSHAKE_TIMEOUT (CONNECTION_TIMEOUT * 2) | ||
36 | 29 | ||
37 | #define CRYPTO_CONN_NO_CONNECTION 0 | 30 | #define CRYPTO_CONN_NO_CONNECTION 0 |
38 | #define CRYPTO_CONN_HANDSHAKE_SENT 1 | 31 | #define CRYPTO_CONN_COOKIE_REQUESTING 1 //send cookie request packets |
39 | #define CRYPTO_CONN_NOT_CONFIRMED 2 | 32 | #define CRYPTO_CONN_HANDSHAKE_SENT 2 //send handshake packets |
40 | #define CRYPTO_CONN_ESTABLISHED 3 | 33 | #define CRYPTO_CONN_NOT_CONFIRMED 3 //send handshake packets |
41 | #define CRYPTO_CONN_TIMED_OUT 4 | 34 | #define CRYPTO_CONN_ESTABLISHED 4 |
35 | #define CRYPTO_CONN_TIMED_OUT 5 | ||
36 | |||
37 | #define CRYPTO_PACKET_BUFFER_SIZE 16384 /* Must be a power of 2 */ | ||
38 | |||
39 | /* Minimum packet rate per second. */ | ||
40 | #define CRYPTO_PACKET_MIN_RATE 40.0 | ||
41 | |||
42 | /* Minimum packet queue max length. */ | ||
43 | #define CRYPTO_MIN_QUEUE_LENGTH 8 | ||
44 | |||
45 | #define MAX_CRYPTO_PACKET_SIZE 1400 | ||
46 | |||
47 | #define CRYPTO_DATA_PACKET_MIN_SIZE (1 + sizeof(uint16_t) + (sizeof(uint32_t) + sizeof(uint32_t)) + crypto_box_MACBYTES) | ||
48 | |||
49 | /* Max size of data in packets TODO*/ | ||
50 | #define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - CRYPTO_DATA_PACKET_MIN_SIZE) | ||
51 | |||
52 | /* Interval in ms between sending cookie request/handshake packets. */ | ||
53 | #define CRYPTO_SEND_PACKET_INTERVAL 500 | ||
54 | /* The maximum number of times we try to send the cookie request and handshake | ||
55 | before giving up. */ | ||
56 | #define MAX_NUM_SENDPACKET_TRIES 8 | ||
57 | |||
58 | #define PACKET_ID_PADDING 0 | ||
59 | #define PACKET_ID_REQUEST 1 | ||
60 | #define PACKET_ID_KILL 2 | ||
61 | |||
62 | #define CRYPTO_RESERVED_PACKETS 16 | ||
63 | |||
64 | #define MAX_TCP_CONNECTIONS 32 | ||
65 | #define MAX_TCP_RELAYS_PEER 4 | ||
66 | |||
67 | #define STATUS_TCP_NULL 0 | ||
68 | #define STATUS_TCP_OFFLINE 1 | ||
69 | #define STATUS_TCP_INVISIBLE 2 /* we know the other peer is connected to this relay but he isn't appearing online */ | ||
70 | #define STATUS_TCP_ONLINE 3 | ||
71 | |||
72 | typedef struct { | ||
73 | uint64_t time; | ||
74 | uint16_t length; | ||
75 | uint8_t data[MAX_CRYPTO_DATA_SIZE]; | ||
76 | } Packet_Data; | ||
77 | |||
78 | typedef struct { | ||
79 | Packet_Data *buffer[CRYPTO_PACKET_BUFFER_SIZE]; | ||
80 | uint32_t buffer_start; | ||
81 | uint32_t buffer_end; /* packet numbers in array: {buffer_start, buffer_end) */ | ||
82 | } Packets_Array; | ||
42 | 83 | ||
43 | typedef struct { | 84 | typedef struct { |
44 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */ | 85 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */ |
@@ -48,27 +89,73 @@ typedef struct { | |||
48 | uint8_t sessionsecret_key[crypto_box_SECRETKEYBYTES]; /* Our private key for this session. */ | 89 | uint8_t sessionsecret_key[crypto_box_SECRETKEYBYTES]; /* Our private key for this session. */ |
49 | uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */ | 90 | uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */ |
50 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; /* The precomputed shared key from encrypt_precompute. */ | 91 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; /* The precomputed shared key from encrypt_precompute. */ |
51 | uint8_t status; /* 0 if no connection, 1 we have sent a handshake, 2 if connection is not confirmed yet | 92 | uint8_t status; /* 0 if no connection, 1 we are sending cookie request packets, |
52 | * (we have received a handshake but no empty data packet), 3 if the connection is established. | 93 | * 2 if we are sending handshake packets |
53 | * 4 if the connection is timed out. | 94 | * 3 if connection is not confirmed yet (we have received a handshake but no data packets yet), |
95 | * 4 if the connection is established. | ||
96 | * 5 if the connection is timed out. | ||
54 | */ | 97 | */ |
55 | uint16_t number; /* Lossless_UDP connection number corresponding to this connection. */ | 98 | uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */ |
56 | uint64_t timeout; | 99 | uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; /* The dht public key of the peer */ |
100 | uint8_t dht_public_key_set; /* True if the dht public key is set, false if it isn't. */ | ||
101 | uint64_t dht_public_key_timestamp; /* Timestamp of the last time we confirmed the key was correct. */ | ||
57 | 102 | ||
58 | } Crypto_Connection; | 103 | uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */ |
104 | uint16_t temp_packet_length; | ||
105 | uint64_t temp_packet_sent_time; /* The time at which the last temp_packet was sent in ms. */ | ||
106 | uint32_t temp_packet_num_sent; | ||
107 | |||
108 | IP_Port ip_port; /* The ip and port to contact this guy directly.*/ | ||
109 | uint64_t direct_lastrecv_time; /* The Time at which we last received a direct packet in ms. */ | ||
110 | |||
111 | Packets_Array send_array; | ||
112 | Packets_Array recv_array; | ||
113 | |||
114 | int (*connection_status_callback)(void *object, int id, uint8_t status); | ||
115 | void *connection_status_callback_object; | ||
116 | int connection_status_callback_id; | ||
117 | |||
118 | int (*connection_data_callback)(void *object, int id, uint8_t *data, uint16_t length); | ||
119 | void *connection_data_callback_object; | ||
120 | int connection_data_callback_id; | ||
121 | |||
122 | uint64_t last_request_packet_sent; | ||
123 | |||
124 | uint32_t packet_counter; | ||
125 | double packet_recv_rate; | ||
126 | uint64_t packet_counter_set; | ||
127 | |||
128 | double packet_send_rate; | ||
129 | uint32_t packets_left; | ||
130 | uint64_t last_packets_left_set; | ||
131 | |||
132 | uint8_t sending; /* indicates if data is being sent or not. */ | ||
59 | 133 | ||
60 | typedef int (*cryptopacket_handler_callback)(void *object, IP_Port ip_port, uint8_t *source_pubkey, uint8_t *data, | 134 | uint8_t killed; /* set to 1 to kill the connection. */ |
61 | uint32_t len); | 135 | |
136 | uint8_t status_tcp[MAX_TCP_CONNECTIONS]; /* set to one of STATUS_TCP_* */ | ||
137 | uint8_t con_number_tcp[MAX_TCP_CONNECTIONS]; | ||
138 | |||
139 | Node_format tcp_relays[MAX_TCP_RELAYS_PEER]; | ||
140 | uint16_t num_tcp_relays; | ||
141 | } Crypto_Connection; | ||
62 | 142 | ||
63 | typedef struct { | 143 | typedef struct { |
64 | cryptopacket_handler_callback function; | 144 | IP_Port source; |
65 | void *object; | 145 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */ |
66 | } Cryptopacket_Handles; | 146 | uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; /* The dht public key of the peer. */ |
147 | uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */ | ||
148 | uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */ | ||
149 | uint8_t *cookie; | ||
150 | uint8_t cookie_length; | ||
151 | } New_Connection; | ||
67 | 152 | ||
68 | typedef struct { | 153 | typedef struct { |
69 | Lossless_UDP *lossless_udp; | 154 | DHT *dht; |
70 | 155 | ||
71 | Crypto_Connection *crypto_connections; | 156 | Crypto_Connection *crypto_connections; |
157 | TCP_Client_Connection *tcp_connections_new[MAX_TCP_CONNECTIONS]; | ||
158 | TCP_Client_Connection *tcp_connections[MAX_TCP_CONNECTIONS]; | ||
72 | 159 | ||
73 | uint32_t crypto_connections_length; /* Length of connections array. */ | 160 | uint32_t crypto_connections_length; /* Length of connections array. */ |
74 | 161 | ||
@@ -76,154 +163,131 @@ typedef struct { | |||
76 | uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; | 163 | uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; |
77 | uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; | 164 | uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; |
78 | 165 | ||
79 | Cryptopacket_Handles cryptopackethandlers[256]; | 166 | /* The secret key used for cookies */ |
80 | } Net_Crypto; | 167 | uint8_t secret_symmetric_key[crypto_box_KEYBYTES]; |
81 | 168 | ||
82 | #include "DHT.h" | 169 | int (*new_connection_callback)(void *object, New_Connection *n_c); |
170 | void *new_connection_callback_object; | ||
171 | } Net_Crypto; | ||
83 | 172 | ||
84 | /* return zero if the buffer contains only zeros. */ | ||
85 | uint8_t crypto_iszero(uint8_t *buffer, uint32_t blen); | ||
86 | 173 | ||
87 | /* Encrypts plain of length length to encrypted of length + 16 using the | 174 | /* Set function to be called when someone requests a new connection to us. |
88 | * public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce. | 175 | * |
176 | * The set function should return -1 on failure and 0 on success. | ||
89 | * | 177 | * |
90 | * return -1 if there was a problem. | 178 | * n_c is only valid for the duration of the function call. |
91 | * return length of encrypted data if everything was fine. | ||
92 | */ | 179 | */ |
93 | int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | 180 | void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c), |
94 | uint8_t *plain, uint32_t length, uint8_t *encrypted); | 181 | void *object); |
95 | |||
96 | 182 | ||
97 | /* Decrypts encrypted of length length to plain of length length - 16 using the | 183 | /* Accept a crypto connection. |
98 | * public key(32 bytes) of the sender, the secret key of the receiver and a 24 byte nonce. | ||
99 | * | 184 | * |
100 | * return -1 if there was a problem (decryption failed). | 185 | * return -1 on failure. |
101 | * return length of plain data if everything was fine. | 186 | * return connection id on success. |
102 | */ | 187 | */ |
103 | int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | 188 | int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c); |
104 | uint8_t *encrypted, uint32_t length, uint8_t *plain); | ||
105 | |||
106 | /* Fast encrypt/decrypt operations. Use if this is not a one-time communication. | ||
107 | encrypt_precompute does the shared-key generation once so it does not have | ||
108 | to be preformed on every encrypt/decrypt. */ | ||
109 | void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_key); | ||
110 | 189 | ||
111 | /* Fast encrypt. Depends on enc_key from encrypt_precompute. */ | 190 | /* Create a crypto connection. |
112 | int encrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, | 191 | * If one to that real public key already exists, return it. |
113 | uint8_t *plain, uint32_t length, uint8_t *encrypted); | ||
114 | |||
115 | /* Fast decrypt. Depends on enc_ley from encrypt_precompute. */ | ||
116 | int decrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, | ||
117 | uint8_t *encrypted, uint32_t length, uint8_t *plain); | ||
118 | |||
119 | /* Encrypts plain of length length to encrypted of length + 16 using a | ||
120 | * secret key crypto_secretbox_KEYBYTES big and a 24 byte nonce. | ||
121 | * | 192 | * |
122 | * return -1 if there was a problem. | 193 | * return -1 on failure. |
123 | * return length of encrypted data if everything was fine. | 194 | * return connection id on success. |
124 | */ | 195 | */ |
125 | int encrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *plain, uint32_t length, uint8_t *encrypted); | 196 | int new_crypto_connection(Net_Crypto *c, uint8_t *real_public_key); |
126 | 197 | ||
127 | /* Decrypts encrypted of length length to plain of length length - 16 using a | 198 | /* Copy friends DHT public key into dht_key. |
128 | * secret key crypto_secretbox_KEYBYTES big and a 24 byte nonce. | ||
129 | * | 199 | * |
130 | * return -1 if there was a problem (decryption failed). | 200 | * return 0 on failure (no key copied). |
131 | * return length of plain data if everything was fine. | 201 | * return timestamp on success (key copied). |
132 | */ | 202 | */ |
133 | int decrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *encrypted, uint32_t length, uint8_t *plain); | 203 | uint64_t get_connection_dht_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key); |
134 | |||
135 | /* Increment the given nonce by 1. */ | ||
136 | void increment_nonce(uint8_t *nonce); | ||
137 | 204 | ||
138 | /* Fill the given nonce with random bytes. */ | 205 | /* Set the DHT public key of the crypto connection. |
139 | void random_nonce(uint8_t *nonce); | 206 | * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to |
207 | * the other peer. | ||
208 | * | ||
209 | * return -1 on failure. | ||
210 | * return 0 on success. | ||
211 | */ | ||
212 | int set_connection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key, uint64_t timestamp); | ||
140 | 213 | ||
141 | /* Fill a key crypto_secretbox_KEYBYTES big with random bytes */ | 214 | /* Set the direct ip of the crypto connection. |
142 | void new_symmetric_key(uint8_t *key); | 215 | * |
216 | * return -1 on failure. | ||
217 | * return 0 on success. | ||
218 | */ | ||
219 | int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port); | ||
143 | 220 | ||
144 | /*Gives a nonce guaranteed to be different from previous ones.*/ | 221 | /* Set function to be called when connection with crypt_connection_id goes connects/disconnects. |
145 | void new_nonce(uint8_t *nonce); | 222 | * |
223 | * The set function should return -1 on failure and 0 on success. | ||
224 | * Note that if this function is set, the connection will clear itself on disconnect. | ||
225 | * Object and id will be passed to this function untouched. | ||
226 | * status is 1 if the connection is going online, 0 if it is going offline. | ||
227 | * | ||
228 | * return -1 on failure. | ||
229 | * return 0 on success. | ||
230 | */ | ||
231 | int connection_status_handler(Net_Crypto *c, int crypt_connection_id, int (*connection_status_callback)(void *object, | ||
232 | int id, uint8_t status), void *object, int id); | ||
146 | 233 | ||
147 | /* return 0 if there is no received data in the buffer. | 234 | /* Set function to be called when connection with crypt_connection_id receives a data packet of length. |
148 | * return -1 if the packet was discarded. | 235 | * |
149 | * return length of received data if successful. | 236 | * The set function should return -1 on failure and 0 on success. |
237 | * Object and id will be passed to this function untouched. | ||
238 | * | ||
239 | * return -1 on failure. | ||
240 | * return 0 on success. | ||
150 | */ | 241 | */ |
151 | int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data); | 242 | int connection_data_handler(Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object, |
243 | int id, uint8_t *data, uint16_t length), void *object, int id); | ||
244 | |||
152 | 245 | ||
153 | /* returns the number of packet slots left in the sendbuffer. | 246 | /* returns the number of packet slots left in the sendbuffer. |
154 | * return 0 if failure. | 247 | * return 0 if failure. |
155 | */ | 248 | */ |
156 | uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id); | 249 | uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id); |
157 | 250 | ||
158 | /* return 0 if data could not be put in packet queue. | 251 | /* return -1 if data could not be put in packet queue. |
159 | * return 1 if data was put into the queue. | 252 | * return positive packet number if data was put into the queue. |
160 | */ | 253 | */ |
161 | int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length); | 254 | int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length); |
162 | 255 | ||
163 | /* Create a request to peer. | 256 | /* Add a tcp relay, associating it to a crypt_connection_id. |
164 | * send_public_key and send_secret_key are the pub/secret keys of the sender. | ||
165 | * recv_public_key is public key of reciever. | ||
166 | * packet must be an array of MAX_DATA_SIZE big. | ||
167 | * Data represents the data we send with the request with length being the length of the data. | ||
168 | * request_id is the id of the request (32 = friend request, 254 = ping request). | ||
169 | * | 257 | * |
170 | * return -1 on failure. | 258 | * return 0 if it was added. |
171 | * return the length of the created packet on success. | 259 | * return -1 if it wasn't. |
172 | */ | 260 | */ |
173 | int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t *packet, uint8_t *recv_public_key, | 261 | int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, uint8_t *public_key); |
174 | uint8_t *data, uint32_t length, uint8_t request_id); | ||
175 | 262 | ||
176 | /* puts the senders public key in the request in public_key, the data from the request | 263 | /* Add a tcp relay to the array. |
177 | in data if a friend or ping request was sent to us and returns the length of the data. | 264 | * |
178 | packet is the request packet and length is its length | 265 | * return 0 if it was added. |
179 | return -1 if not valid request. */ | 266 | * return -1 if it wasn't. |
180 | int handle_request(uint8_t *self_public_key, uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data, | 267 | */ |
181 | uint8_t *request_id, uint8_t *packet, uint16_t length); | 268 | int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, uint8_t *public_key); |
182 | |||
183 | /* Function to call when request beginning with byte is received. */ | ||
184 | void cryptopacket_registerhandler(Net_Crypto *c, uint8_t byte, cryptopacket_handler_callback cb, void *object); | ||
185 | 269 | ||
186 | /* Start a secure connection with other peer who has public_key and ip_port. | 270 | /* Copy a maximum of num TCP relays we are connected to to tcp_relays. |
271 | * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6. | ||
187 | * | 272 | * |
188 | * return -1 if failure. | 273 | * return number of relays copied to tcp_relays on success. |
189 | * return crypt_connection_id of the initialized connection if everything went well. | 274 | * return 0 on failure. |
190 | */ | 275 | */ |
191 | int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port); | 276 | unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, uint16_t num); |
192 | 277 | ||
193 | /* Kill a crypto connection. | 278 | /* Kill a crypto connection. |
194 | * | 279 | * |
195 | * return 0 if killed successfully. | 280 | * return -1 on failure. |
196 | * return 1 if there was a problem. | 281 | * return 0 on success. |
197 | */ | 282 | */ |
198 | int crypto_kill(Net_Crypto *c, int crypt_connection_id); | 283 | int crypto_kill(Net_Crypto *c, int crypt_connection_id); |
199 | 284 | ||
200 | /* Handle an incoming connection. | ||
201 | * | ||
202 | * return -1 if no crypto inbound connection. | ||
203 | * return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection. | ||
204 | * | ||
205 | * Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce | ||
206 | * and the session public key for the connection in session_key. | ||
207 | * to accept it see: accept_crypto_inbound(...). | ||
208 | * to refuse it just call kill_connection(...) on the connection id. | ||
209 | */ | ||
210 | int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key); | ||
211 | 285 | ||
212 | /* Accept an incoming connection using the parameters provided by crypto_inbound. | 286 | /* return one of CRYPTO_CONN_* values indicating the state of the connection. |
213 | * | 287 | * |
214 | * return -1 if not successful. | 288 | * sets direct_connected to 1 if connection connects directly to other, 0 if it isn't. |
215 | * return crypt_connection_id if successful. | ||
216 | */ | ||
217 | int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce, | ||
218 | uint8_t *session_key); | ||
219 | |||
220 | /* return 0 if no connection. | ||
221 | * return 1 we have sent a handshake | ||
222 | * return 2 if connexion is not confirmed yet (we have received a handshake but no empty data packet). | ||
223 | * return 3 if the connection is established. | ||
224 | * return 4 if the connection is timed out and waiting to be killed. | ||
225 | */ | 289 | */ |
226 | int is_cryptoconnected(Net_Crypto *c, int crypt_connection_id); | 290 | unsigned int crypto_connection_status(Net_Crypto *c, int crypt_connection_id, uint8_t *direct_connected); |
227 | 291 | ||
228 | 292 | ||
229 | /* Generate our public and private keys. | 293 | /* Generate our public and private keys. |
@@ -244,15 +308,13 @@ void load_keys(Net_Crypto *c, uint8_t *keys); | |||
244 | /* Create new instance of Net_Crypto. | 308 | /* Create new instance of Net_Crypto. |
245 | * Sets all the global connection variables to their default values. | 309 | * Sets all the global connection variables to their default values. |
246 | */ | 310 | */ |
247 | Net_Crypto *new_net_crypto(Networking_Core *net); | 311 | Net_Crypto *new_net_crypto(DHT *dht); |
248 | 312 | ||
249 | /* Main loop. */ | 313 | /* Main loop. */ |
250 | void do_net_crypto(Net_Crypto *c); | 314 | void do_net_crypto(Net_Crypto *c); |
251 | 315 | ||
252 | void kill_net_crypto(Net_Crypto *c); | 316 | void kill_net_crypto(Net_Crypto *c); |
253 | 317 | ||
254 | /* Initialize the cryptopacket handling. */ | ||
255 | void init_cryptopackets(void *dht); | ||
256 | 318 | ||
257 | 319 | ||
258 | #endif | 320 | #endif |
diff --git a/toxcore/network.c b/toxcore/network.c index 5980abe3..a8ed4294 100644 --- a/toxcore/network.c +++ b/toxcore/network.c | |||
@@ -29,13 +29,17 @@ | |||
29 | #include "config.h" | 29 | #include "config.h" |
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | #define LOGGING | ||
33 | #include "logger.h" | 32 | #include "logger.h" |
34 | 33 | ||
35 | #if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32) | 34 | #if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32) |
36 | #include <errno.h> | 35 | #include <errno.h> |
37 | #endif | 36 | #endif |
38 | 37 | ||
38 | #ifdef __APPLE__ | ||
39 | #include <mach/clock.h> | ||
40 | #include <mach/mach.h> | ||
41 | #endif | ||
42 | |||
39 | #include "network.h" | 43 | #include "network.h" |
40 | #include "util.h" | 44 | #include "util.h" |
41 | 45 | ||
@@ -153,6 +157,21 @@ int set_socket_nonblock(sock_t sock) | |||
153 | #endif | 157 | #endif |
154 | } | 158 | } |
155 | 159 | ||
160 | /* Set socket to not emit SIGPIPE | ||
161 | * | ||
162 | * return 1 on success | ||
163 | * return 0 on failure | ||
164 | */ | ||
165 | int set_socket_nosigpipe(sock_t sock) | ||
166 | { | ||
167 | #if defined(__MACH__) | ||
168 | int set = 1; | ||
169 | return (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)) == 0); | ||
170 | #else | ||
171 | return 1; | ||
172 | #endif | ||
173 | } | ||
174 | |||
156 | /* Set socket to dual (IPv4 + IPv6 socket) | 175 | /* Set socket to dual (IPv4 + IPv6 socket) |
157 | * | 176 | * |
158 | * return 1 on success | 177 | * return 1 on success |
@@ -160,7 +179,7 @@ int set_socket_nonblock(sock_t sock) | |||
160 | */ | 179 | */ |
161 | int set_socket_dualstack(sock_t sock) | 180 | int set_socket_dualstack(sock_t sock) |
162 | { | 181 | { |
163 | char ipv6only = 0; | 182 | int ipv6only = 0; |
164 | socklen_t optsize = sizeof(ipv6only); | 183 | socklen_t optsize = sizeof(ipv6only); |
165 | int res = getsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, &optsize); | 184 | int res = getsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, &optsize); |
166 | 185 | ||
@@ -171,8 +190,9 @@ int set_socket_dualstack(sock_t sock) | |||
171 | return (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only)) == 0); | 190 | return (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only)) == 0); |
172 | } | 191 | } |
173 | 192 | ||
193 | |||
174 | /* return current UNIX time in microseconds (us). */ | 194 | /* return current UNIX time in microseconds (us). */ |
175 | uint64_t current_time(void) | 195 | static uint64_t current_time_actual(void) |
176 | { | 196 | { |
177 | uint64_t time; | 197 | uint64_t time; |
178 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) | 198 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) |
@@ -192,29 +212,52 @@ uint64_t current_time(void) | |||
192 | #endif | 212 | #endif |
193 | } | 213 | } |
194 | 214 | ||
195 | /* return a random number. | ||
196 | */ | ||
197 | uint32_t random_int(void) | ||
198 | { | ||
199 | uint32_t randnum; | ||
200 | randombytes((uint8_t *)&randnum , sizeof(randnum)); | ||
201 | return randnum; | ||
202 | } | ||
203 | 215 | ||
204 | uint64_t random_64b(void) | 216 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) |
217 | static uint64_t last_monotime; | ||
218 | static uint64_t add_monotime; | ||
219 | #endif | ||
220 | |||
221 | /* return current monotonic time in milliseconds (ms). */ | ||
222 | uint64_t current_time_monotonic(void) | ||
205 | { | 223 | { |
206 | uint64_t randnum; | 224 | uint64_t time; |
207 | randombytes((uint8_t *)&randnum, sizeof(randnum)); | 225 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) |
208 | return randnum; | 226 | time = (uint64_t)GetTickCount() + add_monotime; |
227 | |||
228 | if (time < last_monotime) { /* Prevent time from ever decreasing because of 32 bit wrap. */ | ||
229 | uint32_t add = ~0; | ||
230 | add_monotime += add; | ||
231 | time += add; | ||
232 | } | ||
233 | |||
234 | last_monotime = time; | ||
235 | #else | ||
236 | struct timespec monotime; | ||
237 | #if defined(__linux__) | ||
238 | clock_gettime(CLOCK_MONOTONIC_RAW, &monotime); | ||
239 | #elif defined(__APPLE__) | ||
240 | clock_serv_t muhclock; | ||
241 | mach_timespec_t machtime; | ||
242 | |||
243 | host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &muhclock); | ||
244 | clock_get_time(muhclock, &machtime); | ||
245 | mach_port_deallocate(mach_task_self(), muhclock); | ||
246 | |||
247 | monotime.tv_sec = machtime.tv_sec; | ||
248 | monotime.tv_nsec = machtime.tv_nsec; | ||
249 | #else | ||
250 | clock_gettime(CLOCK_MONOTONIC, &monotime); | ||
251 | #endif | ||
252 | time = 1000ULL * monotime.tv_sec + (monotime.tv_nsec / 1000000ULL); | ||
253 | #endif | ||
254 | return time; | ||
209 | } | 255 | } |
210 | 256 | ||
211 | /* In case no logging */ | 257 | /* In case no logging */ |
212 | #ifndef LOGGING | 258 | #ifndef LOGGING |
213 | |||
214 | #define loglogdata(__message__, __buffer__, __buflen__, __ip_port__, __res__) | 259 | #define loglogdata(__message__, __buffer__, __buflen__, __ip_port__, __res__) |
215 | 260 | #else | |
216 | #else | ||
217 | |||
218 | #define data_0(__buflen__, __buffer__) __buflen__ > 4 ? ntohl(*(uint32_t *)&__buffer__[1]) : 0 | 261 | #define data_0(__buflen__, __buffer__) __buflen__ > 4 ? ntohl(*(uint32_t *)&__buffer__[1]) : 0 |
219 | #define data_1(__buflen__, __buffer__) __buflen__ > 7 ? ntohl(*(uint32_t *)&__buffer__[5]) : 0 | 262 | #define data_1(__buflen__, __buffer__) __buflen__ > 7 ? ntohl(*(uint32_t *)&__buffer__[5]) : 0 |
220 | 263 | ||
@@ -299,7 +342,7 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t le | |||
299 | if ((res >= 0) && ((uint32_t)res == length)) | 342 | if ((res >= 0) && ((uint32_t)res == length)) |
300 | net->send_fail_eagain = 0; | 343 | net->send_fail_eagain = 0; |
301 | else if ((res < 0) && (errno == EWOULDBLOCK)) | 344 | else if ((res < 0) && (errno == EWOULDBLOCK)) |
302 | net->send_fail_eagain = current_time(); | 345 | net->send_fail_eagain = current_time_monotonic(); |
303 | 346 | ||
304 | return res; | 347 | return res; |
305 | } | 348 | } |
@@ -308,7 +351,6 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t le | |||
308 | * ip and port of sender is put into ip_port. | 351 | * ip and port of sender is put into ip_port. |
309 | * Packet data is put into data. | 352 | * Packet data is put into data. |
310 | * Packet length is put into length. | 353 | * Packet length is put into length. |
311 | * Dump all empty packets. | ||
312 | */ | 354 | */ |
313 | static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t *length) | 355 | static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t *length) |
314 | { | 356 | { |
@@ -322,7 +364,7 @@ static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t | |||
322 | *length = 0; | 364 | *length = 0; |
323 | int fail_or_len = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen); | 365 | int fail_or_len = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen); |
324 | 366 | ||
325 | if (fail_or_len <= 0) { | 367 | if (fail_or_len < 0) { |
326 | 368 | ||
327 | LOGGER_SCOPE( if ((fail_or_len < 0) && (errno != EWOULDBLOCK)) | 369 | LOGGER_SCOPE( if ((fail_or_len < 0) && (errno != EWOULDBLOCK)) |
328 | LOGGER_ERROR("Unexpected error reading from socket: %u, %s\n", errno, strerror(errno)); ); | 370 | LOGGER_ERROR("Unexpected error reading from socket: %u, %s\n", errno, strerror(errno)); ); |
@@ -438,13 +480,13 @@ int networking_wait_execute(uint8_t *data, long seconds, long microseconds) | |||
438 | * that code) | 480 | * that code) |
439 | */ | 481 | */ |
440 | if (s->send_fail_eagain != 0) { | 482 | if (s->send_fail_eagain != 0) { |
441 | // current_time(): microseconds | 483 | // current_time(): milliseconds |
442 | uint64_t now = current_time(); | 484 | uint64_t now = current_time_monotonic(); |
443 | 485 | ||
444 | /* s->sendqueue_length: might be used to guess how long we keep checking */ | 486 | /* s->sendqueue_length: might be used to guess how long we keep checking */ |
445 | /* for now, threshold is hardcoded to 250ms, too long for a really really | 487 | /* for now, threshold is hardcoded to 250ms, too long for a really really |
446 | * fast link, but too short for a sloooooow link... */ | 488 | * fast link, but too short for a sloooooow link... */ |
447 | if (now - s->send_fail_eagain < 250000) { | 489 | if (now - s->send_fail_eagain < 250) { |
448 | writefds_add = 1; | 490 | writefds_add = 1; |
449 | } | 491 | } |
450 | } | 492 | } |
@@ -508,6 +550,11 @@ int networking_wait_cleanup(Networking_Core *net, uint8_t *data) | |||
508 | return 1; | 550 | return 1; |
509 | } | 551 | } |
510 | 552 | ||
553 | #ifndef VANILLA_NACL | ||
554 | /* Used for sodium_init() */ | ||
555 | #include <sodium.h> | ||
556 | #endif | ||
557 | |||
511 | uint8_t at_startup_ran = 0; | 558 | uint8_t at_startup_ran = 0; |
512 | int networking_at_startup(void) | 559 | int networking_at_startup(void) |
513 | { | 560 | { |
@@ -531,9 +578,9 @@ int networking_at_startup(void) | |||
531 | return -1; | 578 | return -1; |
532 | 579 | ||
533 | #else | 580 | #else |
534 | srandom((uint32_t)current_time()); | 581 | srandom((uint32_t)current_time_actual()); |
535 | #endif | 582 | #endif |
536 | srand((uint32_t)current_time()); | 583 | srand((uint32_t)current_time_actual()); |
537 | at_startup_ran = 1; | 584 | at_startup_ran = 1; |
538 | return 0; | 585 | return 0; |
539 | } | 586 | } |
@@ -637,7 +684,6 @@ Networking_Core *new_networking(IP ip, uint16_t port) | |||
637 | } | 684 | } |
638 | 685 | ||
639 | if (ip.family == AF_INET6) { | 686 | if (ip.family == AF_INET6) { |
640 | |||
641 | #ifdef LOGGING | 687 | #ifdef LOGGING |
642 | int is_dualstack = | 688 | int is_dualstack = |
643 | #endif /* LOGGING */ | 689 | #endif /* LOGGING */ |
@@ -650,7 +696,6 @@ Networking_Core *new_networking(IP ip, uint16_t port) | |||
650 | mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02; | 696 | mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02; |
651 | mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01; | 697 | mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01; |
652 | mreq.ipv6mr_interface = 0; | 698 | mreq.ipv6mr_interface = 0; |
653 | |||
654 | #ifdef LOGGING | 699 | #ifdef LOGGING |
655 | int res = | 700 | int res = |
656 | #endif /* LOGGING */ | 701 | #endif /* LOGGING */ |
@@ -829,6 +874,31 @@ void ipport_copy(IP_Port *target, IP_Port *source) | |||
829 | memcpy(target, source, sizeof(IP_Port)); | 874 | memcpy(target, source, sizeof(IP_Port)); |
830 | }; | 875 | }; |
831 | 876 | ||
877 | /* packing and unpacking functions */ | ||
878 | void ip_pack(uint8_t *data, IP *source) | ||
879 | { | ||
880 | data[0] = source->family; | ||
881 | memcpy(data + 1, &source->ip6, SIZE_IP6); | ||
882 | } | ||
883 | |||
884 | void ip_unpack(IP *target, uint8_t *data) | ||
885 | { | ||
886 | target->family = data[0]; | ||
887 | memcpy(&target->ip6, data + 1, SIZE_IP6); | ||
888 | } | ||
889 | |||
890 | void ipport_pack(uint8_t *data, IP_Port *source) | ||
891 | { | ||
892 | ip_pack(data, &source->ip); | ||
893 | memcpy(data + SIZE_IP, &source->port, SIZE_PORT); | ||
894 | } | ||
895 | |||
896 | void ipport_unpack(IP_Port *target, uint8_t *data) | ||
897 | { | ||
898 | ip_unpack(&target->ip, data); | ||
899 | memcpy(&target->port, data + SIZE_IP, SIZE_PORT); | ||
900 | } | ||
901 | |||
832 | /* ip_ntoa | 902 | /* ip_ntoa |
833 | * converts ip into a string | 903 | * converts ip into a string |
834 | * uses a static buffer, so mustn't used multiple times in the same output | 904 | * uses a static buffer, so mustn't used multiple times in the same output |
diff --git a/toxcore/network.h b/toxcore/network.h index 42ade800..0eb7bbd0 100644 --- a/toxcore/network.h +++ b/toxcore/network.h | |||
@@ -89,7 +89,7 @@ typedef int sock_t; | |||
89 | #endif | 89 | #endif |
90 | 90 | ||
91 | #if defined(__sun__) | 91 | #if defined(__sun__) |
92 | #define __EXTENSIONS__ 1 // SunOS! | 92 | #define __EXTENSIONS__ 1 // SunOS! |
93 | #if defined(__SunOS5_6__) || defined(__SunOS5_7__) || defined(__SunOS5_8__) || defined(__SunOS5_9__) || defined(__SunOS5_10__) | 93 | #if defined(__SunOS5_6__) || defined(__SunOS5_7__) || defined(__SunOS5_8__) || defined(__SunOS5_9__) || defined(__SunOS5_10__) |
94 | //Nothing needed | 94 | //Nothing needed |
95 | #else | 95 | #else |
@@ -97,21 +97,6 @@ typedef int sock_t; | |||
97 | #endif | 97 | #endif |
98 | #endif | 98 | #endif |
99 | 99 | ||
100 | #ifndef VANILLA_NACL | ||
101 | /* We use libsodium by default. */ | ||
102 | #include <sodium.h> | ||
103 | #else | ||
104 | #include <crypto_box.h> | ||
105 | #include <crypto_secretbox.h> | ||
106 | #include <randombytes.h> | ||
107 | #include <crypto_hash_sha256.h> | ||
108 | #define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) | ||
109 | #endif | ||
110 | |||
111 | #ifndef crypto_secretbox_MACBYTES | ||
112 | #define crypto_secretbox_MACBYTES (crypto_secretbox_ZEROBYTES - crypto_secretbox_BOXZEROBYTES) | ||
113 | #endif | ||
114 | |||
115 | #ifndef IPV6_ADD_MEMBERSHIP | 100 | #ifndef IPV6_ADD_MEMBERSHIP |
116 | #ifdef IPV6_JOIN_GROUP | 101 | #ifdef IPV6_JOIN_GROUP |
117 | #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP | 102 | #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP |
@@ -129,6 +114,10 @@ typedef int sock_t; | |||
129 | #define NET_PACKET_HANDSHAKE 16 /* Handshake packet ID. */ | 114 | #define NET_PACKET_HANDSHAKE 16 /* Handshake packet ID. */ |
130 | #define NET_PACKET_SYNC 17 /* SYNC packet ID. */ | 115 | #define NET_PACKET_SYNC 17 /* SYNC packet ID. */ |
131 | #define NET_PACKET_DATA 18 /* Data packet ID. */ | 116 | #define NET_PACKET_DATA 18 /* Data packet ID. */ |
117 | #define NET_PACKET_COOKIE_REQUEST 24 /* Cookie request packet */ | ||
118 | #define NET_PACKET_COOKIE_RESPONSE 25 /* Cookie response packet */ | ||
119 | #define NET_PACKET_CRYPTO_HS 26 /* Crypto handshake packet */ | ||
120 | #define NET_PACKET_CRYPTO_DATA 27 /* Crypto data packet */ | ||
132 | #define NET_PACKET_CRYPTO 32 /* Encrypted data packet ID. */ | 121 | #define NET_PACKET_CRYPTO 32 /* Encrypted data packet ID. */ |
133 | #define NET_PACKET_LAN_DISCOVERY 33 /* LAN discovery packet ID. */ | 122 | #define NET_PACKET_LAN_DISCOVERY 33 /* LAN discovery packet ID. */ |
134 | #define NET_PACKET_GROUP_CHATS 48 /* Group chats packet ID. */ | 123 | #define NET_PACKET_GROUP_CHATS 48 /* Group chats packet ID. */ |
@@ -161,8 +150,11 @@ typedef int sock_t; | |||
161 | #define TOX_PORTRANGE_TO 33545 | 150 | #define TOX_PORTRANGE_TO 33545 |
162 | #define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM | 151 | #define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM |
163 | 152 | ||
164 | 153 | /* TCP related */ | |
165 | /* TODO: remove padding bytes next time we need to break compatibility with old versions of core. */ | 154 | #define TCP_ONION_FAMILY (AF_INET6 + 1) |
155 | #define TCP_INET (AF_INET6 + 2) | ||
156 | #define TCP_INET6 (AF_INET6 + 3) | ||
157 | #define TCP_FAMILY (AF_INET6 + 4) | ||
166 | 158 | ||
167 | typedef union __attribute__ ((__packed__)) | 159 | typedef union __attribute__ ((__packed__)) |
168 | { | 160 | { |
@@ -186,8 +178,6 @@ IP6; | |||
186 | typedef struct __attribute__ ((__packed__)) | 178 | typedef struct __attribute__ ((__packed__)) |
187 | { | 179 | { |
188 | uint8_t family; | 180 | uint8_t family; |
189 | /* Not used for anything right now. */ | ||
190 | uint8_t padding[3]; | ||
191 | union { | 181 | union { |
192 | IP4 ip4; | 182 | IP4 ip4; |
193 | IP6 ip6; | 183 | IP6 ip6; |
@@ -195,23 +185,19 @@ typedef struct __attribute__ ((__packed__)) | |||
195 | } | 185 | } |
196 | IP; | 186 | IP; |
197 | 187 | ||
198 | typedef union __attribute__ ((__packed__)) | 188 | typedef struct __attribute__ ((__packed__)) __attribute__((gcc_struct)) |
199 | { | 189 | { |
200 | struct { | ||
201 | IP4 ip; | ||
202 | uint16_t port; | ||
203 | /* Not used for anything right now. */ | ||
204 | uint16_t padding; | ||
205 | }; | ||
206 | uint8_t uint8[8]; | ||
207 | } | ||
208 | IP4_Port; | ||
209 | |||
210 | typedef struct __attribute__ ((__packed__)) IP_Port { | ||
211 | IP ip; | 190 | IP ip; |
212 | uint16_t port; | 191 | uint16_t port; |
213 | uint16_t padding; | 192 | } |
214 | } IP_Port; | 193 | IP_Port; |
194 | |||
195 | |||
196 | #define SIZE_IP4 4 | ||
197 | #define SIZE_IP6 16 | ||
198 | #define SIZE_IP (1 + SIZE_IP6) | ||
199 | #define SIZE_PORT 2 | ||
200 | #define SIZE_IPPORT (SIZE_IP + SIZE_PORT) | ||
215 | 201 | ||
216 | #define TOX_ENABLE_IPV6_DEFAULT 1 | 202 | #define TOX_ENABLE_IPV6_DEFAULT 1 |
217 | 203 | ||
@@ -250,6 +236,16 @@ void ip_copy(IP *target, IP *source); | |||
250 | /* copies an ip_port structure */ | 236 | /* copies an ip_port structure */ |
251 | void ipport_copy(IP_Port *target, IP_Port *source); | 237 | void ipport_copy(IP_Port *target, IP_Port *source); |
252 | 238 | ||
239 | |||
240 | /* packs IP into data, writes SIZE_IP bytes to data */ | ||
241 | void ip_pack(uint8_t *data, IP *source); | ||
242 | /* unpacks IP from data, reads SIZE_IP bytes from data */ | ||
243 | void ip_unpack(IP *target, uint8_t *data); | ||
244 | /* packs IP_Port into data, writes SIZE_IPPORT bytes to data */ | ||
245 | void ipport_pack(uint8_t *data, IP_Port *source); | ||
246 | /* unpacks IP_Port from data, reads SIZE_IPPORT bytes to data */ | ||
247 | void ipport_unpack(IP_Port *target, uint8_t *data); | ||
248 | |||
253 | /* | 249 | /* |
254 | * addr_resolve(): | 250 | * addr_resolve(): |
255 | * uses getaddrinfo to resolve an address into an IP address | 251 | * uses getaddrinfo to resolve an address into an IP address |
@@ -332,6 +328,13 @@ void kill_sock(sock_t sock); | |||
332 | */ | 328 | */ |
333 | int set_socket_nonblock(sock_t sock); | 329 | int set_socket_nonblock(sock_t sock); |
334 | 330 | ||
331 | /* Set socket to not emit SIGPIPE | ||
332 | * | ||
333 | * return 1 on success | ||
334 | * return 0 on failure | ||
335 | */ | ||
336 | int set_socket_nosigpipe(sock_t sock); | ||
337 | |||
335 | /* Set socket to dual (IPv4 + IPv6 socket) | 338 | /* Set socket to dual (IPv4 + IPv6 socket) |
336 | * | 339 | * |
337 | * return 1 on success | 340 | * return 1 on success |
@@ -339,13 +342,8 @@ int set_socket_nonblock(sock_t sock); | |||
339 | */ | 342 | */ |
340 | int set_socket_dualstack(sock_t sock); | 343 | int set_socket_dualstack(sock_t sock); |
341 | 344 | ||
342 | /* return current time in milleseconds since the epoch. */ | 345 | /* return current monotonic time in milliseconds (ms). */ |
343 | uint64_t current_time(void); | 346 | uint64_t current_time_monotonic(void); |
344 | |||
345 | /* return a random number. | ||
346 | */ | ||
347 | uint32_t random_int(void); | ||
348 | uint64_t random_64b(void); | ||
349 | 347 | ||
350 | /* Basic network functions: */ | 348 | /* Basic network functions: */ |
351 | 349 | ||
diff --git a/toxcore/onion.c b/toxcore/onion.c index ccb729f3..479c6209 100644 --- a/toxcore/onion.c +++ b/toxcore/onion.c | |||
@@ -26,8 +26,6 @@ | |||
26 | #include "onion.h" | 26 | #include "onion.h" |
27 | #include "util.h" | 27 | #include "util.h" |
28 | 28 | ||
29 | #define MAX_ONION_SIZE MAX_DATA_SIZE | ||
30 | |||
31 | #define RETURN_1 ONION_RETURN_1 | 29 | #define RETURN_1 ONION_RETURN_1 |
32 | #define RETURN_2 ONION_RETURN_2 | 30 | #define RETURN_2 ONION_RETURN_2 |
33 | #define RETURN_3 ONION_RETURN_3 | 31 | #define RETURN_3 ONION_RETURN_3 |
@@ -89,41 +87,43 @@ int create_onion_path(DHT *dht, Onion_Path *new_path, Node_format *nodes) | |||
89 | /* Create and send a onion packet. | 87 | /* Create and send a onion packet. |
90 | * | 88 | * |
91 | * Use Onion_Path path to send data of length to dest. | 89 | * Use Onion_Path path to send data of length to dest. |
90 | * Maximum length of data is ONION_MAX_DATA_SIZE. | ||
92 | * | 91 | * |
93 | * return -1 on failure. | 92 | * return -1 on failure. |
94 | * return 0 on success. | 93 | * return 0 on success. |
95 | */ | 94 | */ |
96 | int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *data, uint32_t length) | 95 | int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *data, uint32_t length) |
97 | { | 96 | { |
98 | if (1 + length + SEND_1 > MAX_ONION_SIZE || length == 0) | 97 | if (1 + length + SEND_1 > ONION_MAX_PACKET_SIZE || length == 0) |
99 | return -1; | 98 | return -1; |
100 | 99 | ||
101 | to_net_family(&dest.ip); | 100 | to_net_family(&dest.ip); |
102 | uint8_t step1[sizeof(IP_Port) + length]; | 101 | uint8_t step1[SIZE_IPPORT + length]; |
102 | |||
103 | 103 | ||
104 | memcpy(step1, &dest, sizeof(IP_Port)); | 104 | ipport_pack(step1, &dest); |
105 | memcpy(step1 + sizeof(IP_Port), data, length); | 105 | memcpy(step1 + SIZE_IPPORT, data, length); |
106 | 106 | ||
107 | uint8_t nonce[crypto_box_NONCEBYTES]; | 107 | uint8_t nonce[crypto_box_NONCEBYTES]; |
108 | random_nonce(nonce); | 108 | random_nonce(nonce); |
109 | 109 | ||
110 | uint8_t step2[sizeof(IP_Port) + SEND_BASE + length]; | 110 | uint8_t step2[SIZE_IPPORT + SEND_BASE + length]; |
111 | memcpy(step2, &path->ip_port3, sizeof(IP_Port)); | 111 | ipport_pack(step2, &path->ip_port3); |
112 | memcpy(step2 + sizeof(IP_Port), path->public_key3, crypto_box_PUBLICKEYBYTES); | 112 | memcpy(step2 + SIZE_IPPORT, path->public_key3, crypto_box_PUBLICKEYBYTES); |
113 | 113 | ||
114 | int len = encrypt_data_fast(path->shared_key3, nonce, step1, sizeof(step1), | 114 | int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, sizeof(step1), |
115 | step2 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES); | 115 | step2 + SIZE_IPPORT + crypto_box_PUBLICKEYBYTES); |
116 | 116 | ||
117 | if ((uint32_t)len != sizeof(IP_Port) + length + crypto_box_MACBYTES) | 117 | if ((uint32_t)len != SIZE_IPPORT + length + crypto_box_MACBYTES) |
118 | return -1; | 118 | return -1; |
119 | 119 | ||
120 | uint8_t step3[sizeof(IP_Port) + SEND_BASE * 2 + length]; | 120 | uint8_t step3[SIZE_IPPORT + SEND_BASE * 2 + length]; |
121 | memcpy(step3, &path->ip_port2, sizeof(IP_Port)); | 121 | ipport_pack(step3, &path->ip_port2); |
122 | memcpy(step3 + sizeof(IP_Port), path->public_key2, crypto_box_PUBLICKEYBYTES); | 122 | memcpy(step3 + SIZE_IPPORT, path->public_key2, crypto_box_PUBLICKEYBYTES); |
123 | len = encrypt_data_fast(path->shared_key2, nonce, step2, sizeof(step2), | 123 | len = encrypt_data_symmetric(path->shared_key2, nonce, step2, sizeof(step2), |
124 | step3 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES); | 124 | step3 + SIZE_IPPORT + crypto_box_PUBLICKEYBYTES); |
125 | 125 | ||
126 | if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE + length + crypto_box_MACBYTES) | 126 | if ((uint32_t)len != SIZE_IPPORT + SEND_BASE + length + crypto_box_MACBYTES) |
127 | return -1; | 127 | return -1; |
128 | 128 | ||
129 | uint8_t packet[1 + length + SEND_1]; | 129 | uint8_t packet[1 + length + SEND_1]; |
@@ -131,10 +131,10 @@ int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint | |||
131 | memcpy(packet + 1, nonce, crypto_box_NONCEBYTES); | 131 | memcpy(packet + 1, nonce, crypto_box_NONCEBYTES); |
132 | memcpy(packet + 1 + crypto_box_NONCEBYTES, path->public_key1, crypto_box_PUBLICKEYBYTES); | 132 | memcpy(packet + 1 + crypto_box_NONCEBYTES, path->public_key1, crypto_box_PUBLICKEYBYTES); |
133 | 133 | ||
134 | len = encrypt_data_fast(path->shared_key1, nonce, step3, sizeof(step3), | 134 | len = encrypt_data_symmetric(path->shared_key1, nonce, step3, sizeof(step3), |
135 | packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); | 135 | packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); |
136 | 136 | ||
137 | if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE * 2 + length + crypto_box_MACBYTES) | 137 | if ((uint32_t)len != SIZE_IPPORT + SEND_BASE * 2 + length + crypto_box_MACBYTES) |
138 | return -1; | 138 | return -1; |
139 | 139 | ||
140 | if ((uint32_t)sendpacket(net, path->ip_port1, packet, sizeof(packet)) != sizeof(packet)) | 140 | if ((uint32_t)sendpacket(net, path->ip_port1, packet, sizeof(packet)) != sizeof(packet)) |
@@ -142,13 +142,18 @@ int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint | |||
142 | 142 | ||
143 | return 0; | 143 | return 0; |
144 | } | 144 | } |
145 | |||
145 | /* Create and send a onion response sent initially to dest with. | 146 | /* Create and send a onion response sent initially to dest with. |
147 | * Maximum length of data is ONION_RESPONSE_MAX_DATA_SIZE. | ||
146 | * | 148 | * |
147 | * return -1 on failure. | 149 | * return -1 on failure. |
148 | * return 0 on success. | 150 | * return 0 on success. |
149 | */ | 151 | */ |
150 | int send_onion_response(Networking_Core *net, IP_Port dest, uint8_t *data, uint32_t length, uint8_t *ret) | 152 | int send_onion_response(Networking_Core *net, IP_Port dest, uint8_t *data, uint32_t length, uint8_t *ret) |
151 | { | 153 | { |
154 | if (length > ONION_RESPONSE_MAX_DATA_SIZE || length == 0) | ||
155 | return -1; | ||
156 | |||
152 | uint8_t packet[1 + RETURN_3 + length]; | 157 | uint8_t packet[1 + RETURN_3 + length]; |
153 | packet[0] = NET_PACKET_ONION_RECV_3; | 158 | packet[0] = NET_PACKET_ONION_RECV_3; |
154 | memcpy(packet + 1, ret, RETURN_3); | 159 | memcpy(packet + 1, ret, RETURN_3); |
@@ -164,7 +169,7 @@ static int handle_send_initial(void *object, IP_Port source, uint8_t *packet, ui | |||
164 | { | 169 | { |
165 | Onion *onion = object; | 170 | Onion *onion = object; |
166 | 171 | ||
167 | if (length > MAX_ONION_SIZE) | 172 | if (length > ONION_MAX_PACKET_SIZE) |
168 | return 1; | 173 | return 1; |
169 | 174 | ||
170 | if (length <= 1 + SEND_1) | 175 | if (length <= 1 + SEND_1) |
@@ -172,11 +177,11 @@ static int handle_send_initial(void *object, IP_Port source, uint8_t *packet, ui | |||
172 | 177 | ||
173 | change_symmetric_key(onion); | 178 | change_symmetric_key(onion); |
174 | 179 | ||
175 | uint8_t plain[MAX_ONION_SIZE]; | 180 | uint8_t plain[ONION_MAX_PACKET_SIZE]; |
176 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; | 181 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; |
177 | get_shared_key(&onion->shared_keys_1, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); | 182 | get_shared_key(&onion->shared_keys_1, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); |
178 | int len = decrypt_data_fast(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, | 183 | int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, |
179 | length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), plain); | 184 | length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), plain); |
180 | 185 | ||
181 | if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)) | 186 | if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)) |
182 | return 1; | 187 | return 1; |
@@ -187,23 +192,26 @@ static int handle_send_initial(void *object, IP_Port source, uint8_t *packet, ui | |||
187 | int onion_send_1(Onion *onion, uint8_t *plain, uint32_t len, IP_Port source, uint8_t *nonce) | 192 | int onion_send_1(Onion *onion, uint8_t *plain, uint32_t len, IP_Port source, uint8_t *nonce) |
188 | { | 193 | { |
189 | IP_Port send_to; | 194 | IP_Port send_to; |
190 | memcpy(&send_to, plain, sizeof(IP_Port)); | 195 | ipport_unpack(&send_to, plain); |
191 | to_host_family(&send_to.ip); | 196 | to_host_family(&send_to.ip); |
192 | 197 | ||
193 | uint8_t data[MAX_ONION_SIZE]; | 198 | uint8_t ip_port[SIZE_IPPORT]; |
199 | ipport_pack(ip_port, &source); | ||
200 | |||
201 | uint8_t data[ONION_MAX_PACKET_SIZE]; | ||
194 | data[0] = NET_PACKET_ONION_SEND_1; | 202 | data[0] = NET_PACKET_ONION_SEND_1; |
195 | memcpy(data + 1, nonce, crypto_box_NONCEBYTES); | 203 | memcpy(data + 1, nonce, crypto_box_NONCEBYTES); |
196 | memcpy(data + 1 + crypto_box_NONCEBYTES, plain + sizeof(IP_Port), len - sizeof(IP_Port)); | 204 | memcpy(data + 1 + crypto_box_NONCEBYTES, plain + SIZE_IPPORT, len - SIZE_IPPORT); |
197 | uint32_t data_len = 1 + crypto_box_NONCEBYTES + (len - sizeof(IP_Port)); | 205 | uint32_t data_len = 1 + crypto_box_NONCEBYTES + (len - SIZE_IPPORT); |
198 | uint8_t *ret_part = data + data_len; | 206 | uint8_t *ret_part = data + data_len; |
199 | new_nonce(ret_part); | 207 | new_nonce(ret_part); |
200 | len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, (uint8_t *)&source, sizeof(IP_Port), | 208 | len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ip_port, SIZE_IPPORT, |
201 | ret_part + crypto_secretbox_NONCEBYTES); | 209 | ret_part + crypto_box_NONCEBYTES); |
202 | 210 | ||
203 | if (len != sizeof(IP_Port) + crypto_secretbox_MACBYTES) | 211 | if (len != SIZE_IPPORT + crypto_box_MACBYTES) |
204 | return 1; | 212 | return 1; |
205 | 213 | ||
206 | data_len += crypto_secretbox_NONCEBYTES + len; | 214 | data_len += crypto_box_NONCEBYTES + len; |
207 | 215 | ||
208 | if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) | 216 | if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) |
209 | return 1; | 217 | return 1; |
@@ -215,7 +223,7 @@ static int handle_send_1(void *object, IP_Port source, uint8_t *packet, uint32_t | |||
215 | { | 223 | { |
216 | Onion *onion = object; | 224 | Onion *onion = object; |
217 | 225 | ||
218 | if (length > MAX_ONION_SIZE) | 226 | if (length > ONION_MAX_PACKET_SIZE) |
219 | return 1; | 227 | return 1; |
220 | 228 | ||
221 | if (length <= 1 + SEND_2) | 229 | if (length <= 1 + SEND_2) |
@@ -223,36 +231,36 @@ static int handle_send_1(void *object, IP_Port source, uint8_t *packet, uint32_t | |||
223 | 231 | ||
224 | change_symmetric_key(onion); | 232 | change_symmetric_key(onion); |
225 | 233 | ||
226 | uint8_t plain[MAX_ONION_SIZE]; | 234 | uint8_t plain[ONION_MAX_PACKET_SIZE]; |
227 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; | 235 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; |
228 | get_shared_key(&onion->shared_keys_2, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); | 236 | get_shared_key(&onion->shared_keys_2, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); |
229 | int len = decrypt_data_fast(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, | 237 | int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, |
230 | length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1), plain); | 238 | length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1), plain); |
231 | 239 | ||
232 | if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1 + crypto_box_MACBYTES)) | 240 | if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1 + crypto_box_MACBYTES)) |
233 | return 1; | 241 | return 1; |
234 | 242 | ||
235 | IP_Port send_to; | 243 | IP_Port send_to; |
236 | memcpy(&send_to, plain, sizeof(IP_Port)); | 244 | ipport_unpack(&send_to, plain); |
237 | to_host_family(&send_to.ip); | 245 | to_host_family(&send_to.ip); |
238 | 246 | ||
239 | uint8_t data[MAX_ONION_SIZE]; | 247 | uint8_t data[ONION_MAX_PACKET_SIZE]; |
240 | data[0] = NET_PACKET_ONION_SEND_2; | 248 | data[0] = NET_PACKET_ONION_SEND_2; |
241 | memcpy(data + 1, packet + 1, crypto_box_NONCEBYTES); | 249 | memcpy(data + 1, packet + 1, crypto_box_NONCEBYTES); |
242 | memcpy(data + 1 + crypto_box_NONCEBYTES, plain + sizeof(IP_Port), len - sizeof(IP_Port)); | 250 | memcpy(data + 1 + crypto_box_NONCEBYTES, plain + SIZE_IPPORT, len - SIZE_IPPORT); |
243 | uint32_t data_len = 1 + crypto_box_NONCEBYTES + (len - sizeof(IP_Port)); | 251 | uint32_t data_len = 1 + crypto_box_NONCEBYTES + (len - SIZE_IPPORT); |
244 | uint8_t *ret_part = data + data_len; | 252 | uint8_t *ret_part = data + data_len; |
245 | new_nonce(ret_part); | 253 | new_nonce(ret_part); |
246 | uint8_t ret_data[RETURN_1 + sizeof(IP_Port)]; | 254 | uint8_t ret_data[RETURN_1 + SIZE_IPPORT]; |
247 | memcpy(ret_data, &source, sizeof(IP_Port)); | 255 | ipport_pack(ret_data, &source); |
248 | memcpy(ret_data + sizeof(IP_Port), packet + (length - RETURN_1), RETURN_1); | 256 | memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_1), RETURN_1); |
249 | len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data), | 257 | len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data), |
250 | ret_part + crypto_secretbox_NONCEBYTES); | 258 | ret_part + crypto_box_NONCEBYTES); |
251 | 259 | ||
252 | if (len != RETURN_2 - crypto_secretbox_NONCEBYTES) | 260 | if (len != RETURN_2 - crypto_box_NONCEBYTES) |
253 | return 1; | 261 | return 1; |
254 | 262 | ||
255 | data_len += crypto_secretbox_NONCEBYTES + len; | 263 | data_len += crypto_box_NONCEBYTES + len; |
256 | 264 | ||
257 | if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) | 265 | if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) |
258 | return 1; | 266 | return 1; |
@@ -264,7 +272,7 @@ static int handle_send_2(void *object, IP_Port source, uint8_t *packet, uint32_t | |||
264 | { | 272 | { |
265 | Onion *onion = object; | 273 | Onion *onion = object; |
266 | 274 | ||
267 | if (length > MAX_ONION_SIZE) | 275 | if (length > ONION_MAX_PACKET_SIZE) |
268 | return 1; | 276 | return 1; |
269 | 277 | ||
270 | if (length <= 1 + SEND_3) | 278 | if (length <= 1 + SEND_3) |
@@ -272,31 +280,31 @@ static int handle_send_2(void *object, IP_Port source, uint8_t *packet, uint32_t | |||
272 | 280 | ||
273 | change_symmetric_key(onion); | 281 | change_symmetric_key(onion); |
274 | 282 | ||
275 | uint8_t plain[MAX_ONION_SIZE]; | 283 | uint8_t plain[ONION_MAX_PACKET_SIZE]; |
276 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; | 284 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; |
277 | get_shared_key(&onion->shared_keys_3, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); | 285 | get_shared_key(&onion->shared_keys_3, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); |
278 | int len = decrypt_data_fast(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, | 286 | int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, |
279 | length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2), plain); | 287 | length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2), plain); |
280 | 288 | ||
281 | if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2 + crypto_box_MACBYTES)) | 289 | if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2 + crypto_box_MACBYTES)) |
282 | return 1; | 290 | return 1; |
283 | 291 | ||
284 | IP_Port send_to; | 292 | IP_Port send_to; |
285 | memcpy(&send_to, plain, sizeof(IP_Port)); | 293 | ipport_unpack(&send_to, plain); |
286 | to_host_family(&send_to.ip); | 294 | to_host_family(&send_to.ip); |
287 | 295 | ||
288 | uint8_t data[MAX_ONION_SIZE]; | 296 | uint8_t data[ONION_MAX_PACKET_SIZE]; |
289 | memcpy(data, plain + sizeof(IP_Port), len - sizeof(IP_Port)); | 297 | memcpy(data, plain + SIZE_IPPORT, len - SIZE_IPPORT); |
290 | uint32_t data_len = (len - sizeof(IP_Port)); | 298 | uint32_t data_len = (len - SIZE_IPPORT); |
291 | uint8_t *ret_part = data + (len - sizeof(IP_Port)); | 299 | uint8_t *ret_part = data + (len - SIZE_IPPORT); |
292 | new_nonce(ret_part); | 300 | new_nonce(ret_part); |
293 | uint8_t ret_data[RETURN_2 + sizeof(IP_Port)]; | 301 | uint8_t ret_data[RETURN_2 + SIZE_IPPORT]; |
294 | memcpy(ret_data, &source, sizeof(IP_Port)); | 302 | ipport_pack(ret_data, &source); |
295 | memcpy(ret_data + sizeof(IP_Port), packet + (length - RETURN_2), RETURN_2); | 303 | memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_2), RETURN_2); |
296 | len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data), | 304 | len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data), |
297 | ret_part + crypto_secretbox_NONCEBYTES); | 305 | ret_part + crypto_box_NONCEBYTES); |
298 | 306 | ||
299 | if (len != RETURN_3 - crypto_secretbox_NONCEBYTES) | 307 | if (len != RETURN_3 - crypto_box_NONCEBYTES) |
300 | return 1; | 308 | return 1; |
301 | 309 | ||
302 | data_len += RETURN_3; | 310 | data_len += RETURN_3; |
@@ -312,7 +320,7 @@ static int handle_recv_3(void *object, IP_Port source, uint8_t *packet, uint32_t | |||
312 | { | 320 | { |
313 | Onion *onion = object; | 321 | Onion *onion = object; |
314 | 322 | ||
315 | if (length > MAX_ONION_SIZE) | 323 | if (length > ONION_MAX_PACKET_SIZE) |
316 | return 1; | 324 | return 1; |
317 | 325 | ||
318 | if (length <= 1 + RETURN_3) | 326 | if (length <= 1 + RETURN_3) |
@@ -320,19 +328,19 @@ static int handle_recv_3(void *object, IP_Port source, uint8_t *packet, uint32_t | |||
320 | 328 | ||
321 | change_symmetric_key(onion); | 329 | change_symmetric_key(onion); |
322 | 330 | ||
323 | uint8_t plain[sizeof(IP_Port) + RETURN_2]; | 331 | uint8_t plain[SIZE_IPPORT + RETURN_2]; |
324 | int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_secretbox_NONCEBYTES, | 332 | int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES, |
325 | sizeof(IP_Port) + RETURN_2 + crypto_secretbox_MACBYTES, plain); | 333 | SIZE_IPPORT + RETURN_2 + crypto_box_MACBYTES, plain); |
326 | 334 | ||
327 | if ((uint32_t)len != sizeof(plain)) | 335 | if ((uint32_t)len != sizeof(plain)) |
328 | return 1; | 336 | return 1; |
329 | 337 | ||
330 | IP_Port send_to; | 338 | IP_Port send_to; |
331 | memcpy(&send_to, plain, sizeof(IP_Port)); | 339 | ipport_unpack(&send_to, plain); |
332 | 340 | ||
333 | uint8_t data[MAX_ONION_SIZE]; | 341 | uint8_t data[ONION_MAX_PACKET_SIZE]; |
334 | data[0] = NET_PACKET_ONION_RECV_2; | 342 | data[0] = NET_PACKET_ONION_RECV_2; |
335 | memcpy(data + 1, plain + sizeof(IP_Port), RETURN_2); | 343 | memcpy(data + 1, plain + SIZE_IPPORT, RETURN_2); |
336 | memcpy(data + 1 + RETURN_2, packet + 1 + RETURN_3, length - (1 + RETURN_3)); | 344 | memcpy(data + 1 + RETURN_2, packet + 1 + RETURN_3, length - (1 + RETURN_3)); |
337 | uint32_t data_len = 1 + RETURN_2 + (length - (1 + RETURN_3)); | 345 | uint32_t data_len = 1 + RETURN_2 + (length - (1 + RETURN_3)); |
338 | 346 | ||
@@ -346,7 +354,7 @@ static int handle_recv_2(void *object, IP_Port source, uint8_t *packet, uint32_t | |||
346 | { | 354 | { |
347 | Onion *onion = object; | 355 | Onion *onion = object; |
348 | 356 | ||
349 | if (length > MAX_ONION_SIZE) | 357 | if (length > ONION_MAX_PACKET_SIZE) |
350 | return 1; | 358 | return 1; |
351 | 359 | ||
352 | if (length <= 1 + RETURN_2) | 360 | if (length <= 1 + RETURN_2) |
@@ -354,19 +362,19 @@ static int handle_recv_2(void *object, IP_Port source, uint8_t *packet, uint32_t | |||
354 | 362 | ||
355 | change_symmetric_key(onion); | 363 | change_symmetric_key(onion); |
356 | 364 | ||
357 | uint8_t plain[sizeof(IP_Port) + RETURN_1]; | 365 | uint8_t plain[SIZE_IPPORT + RETURN_1]; |
358 | int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_secretbox_NONCEBYTES, | 366 | int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES, |
359 | sizeof(IP_Port) + RETURN_1 + crypto_secretbox_MACBYTES, plain); | 367 | SIZE_IPPORT + RETURN_1 + crypto_box_MACBYTES, plain); |
360 | 368 | ||
361 | if ((uint32_t)len != sizeof(plain)) | 369 | if ((uint32_t)len != sizeof(plain)) |
362 | return 1; | 370 | return 1; |
363 | 371 | ||
364 | IP_Port send_to; | 372 | IP_Port send_to; |
365 | memcpy(&send_to, plain, sizeof(IP_Port)); | 373 | ipport_unpack(&send_to, plain); |
366 | 374 | ||
367 | uint8_t data[MAX_ONION_SIZE]; | 375 | uint8_t data[ONION_MAX_PACKET_SIZE]; |
368 | data[0] = NET_PACKET_ONION_RECV_1; | 376 | data[0] = NET_PACKET_ONION_RECV_1; |
369 | memcpy(data + 1, plain + sizeof(IP_Port), RETURN_1); | 377 | memcpy(data + 1, plain + SIZE_IPPORT, RETURN_1); |
370 | memcpy(data + 1 + RETURN_1, packet + 1 + RETURN_2, length - (1 + RETURN_2)); | 378 | memcpy(data + 1 + RETURN_1, packet + 1 + RETURN_2, length - (1 + RETURN_2)); |
371 | uint32_t data_len = 1 + RETURN_1 + (length - (1 + RETURN_2)); | 379 | uint32_t data_len = 1 + RETURN_1 + (length - (1 + RETURN_2)); |
372 | 380 | ||
@@ -380,7 +388,7 @@ static int handle_recv_1(void *object, IP_Port source, uint8_t *packet, uint32_t | |||
380 | { | 388 | { |
381 | Onion *onion = object; | 389 | Onion *onion = object; |
382 | 390 | ||
383 | if (length > MAX_ONION_SIZE) | 391 | if (length > ONION_MAX_PACKET_SIZE) |
384 | return 1; | 392 | return 1; |
385 | 393 | ||
386 | if (length <= 1 + RETURN_1) | 394 | if (length <= 1 + RETURN_1) |
@@ -388,14 +396,16 @@ static int handle_recv_1(void *object, IP_Port source, uint8_t *packet, uint32_t | |||
388 | 396 | ||
389 | change_symmetric_key(onion); | 397 | change_symmetric_key(onion); |
390 | 398 | ||
391 | IP_Port send_to; | 399 | uint8_t plain[SIZE_IPPORT]; |
392 | 400 | int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES, | |
393 | int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_secretbox_NONCEBYTES, | 401 | SIZE_IPPORT + crypto_box_MACBYTES, plain); |
394 | sizeof(IP_Port) + crypto_secretbox_MACBYTES, (uint8_t *) &send_to); | ||
395 | 402 | ||
396 | if ((uint32_t)len != sizeof(IP_Port)) | 403 | if ((uint32_t)len != SIZE_IPPORT) |
397 | return 1; | 404 | return 1; |
398 | 405 | ||
406 | IP_Port send_to; | ||
407 | ipport_unpack(&send_to, plain); | ||
408 | |||
399 | uint32_t data_len = length - (1 + RETURN_1); | 409 | uint32_t data_len = length - (1 + RETURN_1); |
400 | 410 | ||
401 | if (onion->recv_1_function && send_to.ip.family != AF_INET && send_to.ip.family != AF_INET6) | 411 | if (onion->recv_1_function && send_to.ip.family != AF_INET && send_to.ip.family != AF_INET6) |
@@ -424,7 +434,7 @@ Onion *new_onion(DHT *dht) | |||
424 | return NULL; | 434 | return NULL; |
425 | 435 | ||
426 | onion->dht = dht; | 436 | onion->dht = dht; |
427 | onion->net = dht->c->lossless_udp->net; | 437 | onion->net = dht->net; |
428 | new_symmetric_key(onion->secret_symmetric_key); | 438 | new_symmetric_key(onion->secret_symmetric_key); |
429 | onion->timestamp = unix_time(); | 439 | onion->timestamp = unix_time(); |
430 | 440 | ||
diff --git a/toxcore/onion.h b/toxcore/onion.h index 4e363724..13dc8f52 100644 --- a/toxcore/onion.h +++ b/toxcore/onion.h | |||
@@ -28,7 +28,7 @@ | |||
28 | typedef struct { | 28 | typedef struct { |
29 | DHT *dht; | 29 | DHT *dht; |
30 | Networking_Core *net; | 30 | Networking_Core *net; |
31 | uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES]; | 31 | uint8_t secret_symmetric_key[crypto_box_KEYBYTES]; |
32 | uint64_t timestamp; | 32 | uint64_t timestamp; |
33 | 33 | ||
34 | Shared_Keys shared_keys_1; | 34 | Shared_Keys shared_keys_1; |
@@ -39,15 +39,20 @@ typedef struct { | |||
39 | void *callback_object; | 39 | void *callback_object; |
40 | } Onion; | 40 | } Onion; |
41 | 41 | ||
42 | #define ONION_RETURN_1 (crypto_secretbox_NONCEBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES) | 42 | #define ONION_MAX_PACKET_SIZE 1400 |
43 | #define ONION_RETURN_2 (crypto_secretbox_NONCEBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES + ONION_RETURN_1) | ||
44 | #define ONION_RETURN_3 (crypto_secretbox_NONCEBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES + ONION_RETURN_2) | ||
45 | 43 | ||
46 | #define ONION_SEND_BASE (crypto_box_PUBLICKEYBYTES + sizeof(IP_Port) + crypto_box_MACBYTES) | 44 | #define ONION_RETURN_1 (crypto_box_NONCEBYTES + SIZE_IPPORT + crypto_box_MACBYTES) |
45 | #define ONION_RETURN_2 (crypto_box_NONCEBYTES + SIZE_IPPORT + crypto_box_MACBYTES + ONION_RETURN_1) | ||
46 | #define ONION_RETURN_3 (crypto_box_NONCEBYTES + SIZE_IPPORT + crypto_box_MACBYTES + ONION_RETURN_2) | ||
47 | |||
48 | #define ONION_SEND_BASE (crypto_box_PUBLICKEYBYTES + SIZE_IPPORT + crypto_box_MACBYTES) | ||
47 | #define ONION_SEND_3 (crypto_box_NONCEBYTES + ONION_SEND_BASE + ONION_RETURN_2) | 49 | #define ONION_SEND_3 (crypto_box_NONCEBYTES + ONION_SEND_BASE + ONION_RETURN_2) |
48 | #define ONION_SEND_2 (crypto_box_NONCEBYTES + ONION_SEND_BASE*2 + ONION_RETURN_1) | 50 | #define ONION_SEND_2 (crypto_box_NONCEBYTES + ONION_SEND_BASE*2 + ONION_RETURN_1) |
49 | #define ONION_SEND_1 (crypto_box_NONCEBYTES + ONION_SEND_BASE*3) | 51 | #define ONION_SEND_1 (crypto_box_NONCEBYTES + ONION_SEND_BASE*3) |
50 | 52 | ||
53 | #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 | |||
51 | typedef struct { | 56 | typedef struct { |
52 | uint8_t shared_key1[crypto_box_BEFORENMBYTES]; | 57 | uint8_t shared_key1[crypto_box_BEFORENMBYTES]; |
53 | uint8_t shared_key2[crypto_box_BEFORENMBYTES]; | 58 | uint8_t shared_key2[crypto_box_BEFORENMBYTES]; |
@@ -76,6 +81,7 @@ int create_onion_path(DHT *dht, Onion_Path *new_path, Node_format *nodes); | |||
76 | /* Create and send a onion packet. | 81 | /* Create and send a onion packet. |
77 | * | 82 | * |
78 | * Use Onion_Path path to send data of length to dest. | 83 | * Use Onion_Path path to send data of length to dest. |
84 | * Maximum length of data is ONION_MAX_DATA_SIZE. | ||
79 | * | 85 | * |
80 | * return -1 on failure. | 86 | * return -1 on failure. |
81 | * return 0 on success. | 87 | * return 0 on success. |
@@ -83,6 +89,7 @@ int create_onion_path(DHT *dht, Onion_Path *new_path, Node_format *nodes); | |||
83 | int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *data, uint32_t length); | 89 | int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *data, uint32_t length); |
84 | 90 | ||
85 | /* Create and send a onion response sent initially to dest with. | 91 | /* Create and send a onion response sent initially to dest with. |
92 | * Maximum length of data is ONION_RESPONSE_MAX_DATA_SIZE. | ||
86 | * | 93 | * |
87 | * return -1 on failure. | 94 | * return -1 on failure. |
88 | * return 0 on success. | 95 | * return 0 on success. |
diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c index 331e54d8..e6489a67 100644 --- a/toxcore/onion_announce.c +++ b/toxcore/onion_announce.c | |||
@@ -32,7 +32,7 @@ | |||
32 | #define 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) | 32 | #define 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) |
33 | #define ANNOUNCE_REQUEST_SIZE_RECV (ANNOUNCE_REQUEST_SIZE + ONION_RETURN_3) | 33 | #define ANNOUNCE_REQUEST_SIZE_RECV (ANNOUNCE_REQUEST_SIZE + ONION_RETURN_3) |
34 | 34 | ||
35 | #define DATA_REQUEST_MIN_SIZE (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) | 35 | #define DATA_REQUEST_MIN_SIZE ONION_DATA_REQUEST_MIN_SIZE |
36 | #define DATA_REQUEST_MIN_SIZE_RECV (DATA_REQUEST_MIN_SIZE + ONION_RETURN_3) | 36 | #define DATA_REQUEST_MIN_SIZE_RECV (DATA_REQUEST_MIN_SIZE + ONION_RETURN_3) |
37 | 37 | ||
38 | /* Create and send an onion announce request packet. | 38 | /* Create and send an onion announce request packet. |
@@ -50,14 +50,14 @@ | |||
50 | * return 0 on success. | 50 | * return 0 on success. |
51 | */ | 51 | */ |
52 | int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format dest, uint8_t *public_key, | 52 | int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format dest, uint8_t *public_key, |
53 | uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data) | 53 | uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint64_t sendback_data) |
54 | { | 54 | { |
55 | uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; | 55 | uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; |
56 | memcpy(plain, ping_id, ONION_PING_ID_SIZE); | 56 | memcpy(plain, ping_id, ONION_PING_ID_SIZE); |
57 | memcpy(plain + ONION_PING_ID_SIZE, client_id, crypto_box_PUBLICKEYBYTES); | 57 | memcpy(plain + ONION_PING_ID_SIZE, client_id, crypto_box_PUBLICKEYBYTES); |
58 | memcpy(plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES, data_public_key, crypto_box_PUBLICKEYBYTES); | 58 | memcpy(plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES, data_public_key, crypto_box_PUBLICKEYBYTES); |
59 | memcpy(plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES, sendback_data, | 59 | memcpy(plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES, &sendback_data, |
60 | ONION_ANNOUNCE_SENDBACK_DATA_LENGTH); | 60 | sizeof(sendback_data)); |
61 | uint8_t packet[ANNOUNCE_REQUEST_SIZE]; | 61 | uint8_t packet[ANNOUNCE_REQUEST_SIZE]; |
62 | packet[0] = NET_PACKET_ANNOUNCE_REQUEST; | 62 | packet[0] = NET_PACKET_ANNOUNCE_REQUEST; |
63 | random_nonce(packet + 1); | 63 | random_nonce(packet + 1); |
@@ -90,6 +90,9 @@ int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format de | |||
90 | int send_data_request(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *public_key, | 90 | int send_data_request(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *public_key, |
91 | uint8_t *encrypt_public_key, uint8_t *nonce, uint8_t *data, uint16_t length) | 91 | uint8_t *encrypt_public_key, uint8_t *nonce, uint8_t *data, uint16_t length) |
92 | { | 92 | { |
93 | if ((unsigned int)DATA_REQUEST_MIN_SIZE + length > ONION_MAX_DATA_SIZE) | ||
94 | return -1; | ||
95 | |||
93 | uint8_t packet[DATA_REQUEST_MIN_SIZE + length]; | 96 | uint8_t packet[DATA_REQUEST_MIN_SIZE + length]; |
94 | packet[0] = NET_PACKET_ONION_DATA_REQUEST; | 97 | packet[0] = NET_PACKET_ONION_DATA_REQUEST; |
95 | memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); | 98 | memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); |
@@ -115,11 +118,11 @@ static void generate_ping_id(Onion_Announce *onion_a, uint64_t time, uint8_t *pu | |||
115 | uint8_t *ping_id) | 118 | uint8_t *ping_id) |
116 | { | 119 | { |
117 | time /= PING_ID_TIMEOUT; | 120 | time /= PING_ID_TIMEOUT; |
118 | uint8_t data[crypto_secretbox_KEYBYTES + sizeof(time) + crypto_box_PUBLICKEYBYTES + sizeof(ret_ip_port)]; | 121 | uint8_t data[crypto_box_KEYBYTES + sizeof(time) + crypto_box_PUBLICKEYBYTES + sizeof(ret_ip_port)]; |
119 | memcpy(data, onion_a->secret_bytes, crypto_secretbox_KEYBYTES); | 122 | memcpy(data, onion_a->secret_bytes, crypto_box_KEYBYTES); |
120 | memcpy(data + crypto_secretbox_KEYBYTES, &time, sizeof(time)); | 123 | memcpy(data + crypto_box_KEYBYTES, &time, sizeof(time)); |
121 | memcpy(data + crypto_secretbox_KEYBYTES + sizeof(time), public_key, crypto_box_PUBLICKEYBYTES); | 124 | memcpy(data + crypto_box_KEYBYTES + sizeof(time), public_key, crypto_box_PUBLICKEYBYTES); |
122 | memcpy(data + crypto_secretbox_KEYBYTES + sizeof(time) + crypto_box_PUBLICKEYBYTES, &ret_ip_port, sizeof(ret_ip_port)); | 125 | memcpy(data + crypto_box_KEYBYTES + sizeof(time) + crypto_box_PUBLICKEYBYTES, &ret_ip_port, sizeof(ret_ip_port)); |
123 | crypto_hash_sha256(ping_id, data, sizeof(data)); | 126 | crypto_hash_sha256(ping_id, data, sizeof(data)); |
124 | } | 127 | } |
125 | 128 | ||
@@ -221,9 +224,9 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet | |||
221 | get_shared_key(&onion_a->shared_keys_recv, shared_key, onion_a->dht->self_secret_key, packet_public_key); | 224 | get_shared_key(&onion_a->shared_keys_recv, shared_key, onion_a->dht->self_secret_key, packet_public_key); |
222 | 225 | ||
223 | uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; | 226 | uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; |
224 | int len = decrypt_data_fast(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, | 227 | int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, |
225 | ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + | 228 | ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + |
226 | crypto_box_MACBYTES, plain); | 229 | crypto_box_MACBYTES, plain); |
227 | 230 | ||
228 | if ((uint32_t)len != sizeof(plain)) | 231 | if ((uint32_t)len != sizeof(plain)) |
229 | return 1; | 232 | return 1; |
@@ -247,14 +250,8 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet | |||
247 | 250 | ||
248 | /*Respond with a announce response packet*/ | 251 | /*Respond with a announce response packet*/ |
249 | Node_format nodes_list[MAX_SENT_NODES]; | 252 | Node_format nodes_list[MAX_SENT_NODES]; |
250 | uint32_t num_nodes = get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, source.ip.family, | 253 | uint32_t num_nodes = get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, 0, LAN_ip(source.ip) == 0, |
251 | LAN_ip(source.ip) == 0, 1); | 254 | 1); |
252 | |||
253 | uint32_t i; | ||
254 | |||
255 | for (i = 0; i < num_nodes; ++i) | ||
256 | to_net_family(&nodes_list[i].ip_port.ip); | ||
257 | |||
258 | uint8_t nonce[crypto_box_NONCEBYTES]; | 255 | uint8_t nonce[crypto_box_NONCEBYTES]; |
259 | random_nonce(nonce); | 256 | random_nonce(nonce); |
260 | 257 | ||
@@ -274,13 +271,20 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet | |||
274 | } | 271 | } |
275 | } | 272 | } |
276 | 273 | ||
277 | memcpy(pl + 1 + ONION_PING_ID_SIZE, nodes_list, num_nodes * sizeof(Node_format)); | 274 | int nodes_length = 0; |
275 | |||
276 | if (num_nodes != 0) { | ||
277 | nodes_length = pack_nodes(pl + 1 + ONION_PING_ID_SIZE, sizeof(nodes_list), nodes_list, num_nodes); | ||
278 | |||
279 | if (nodes_length <= 0) | ||
280 | return 1; | ||
281 | } | ||
278 | 282 | ||
279 | uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE]; | 283 | uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE]; |
280 | len = encrypt_data_fast(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format), | 284 | len = encrypt_data_symmetric(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + nodes_length, |
281 | data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES); | 285 | data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES); |
282 | 286 | ||
283 | if ((uint32_t)len != 1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format) + crypto_box_MACBYTES) | 287 | if (len != 1 + ONION_PING_ID_SIZE + nodes_length + crypto_box_MACBYTES) |
284 | return 1; | 288 | return 1; |
285 | 289 | ||
286 | data[0] = NET_PACKET_ANNOUNCE_RESPONSE; | 290 | data[0] = NET_PACKET_ANNOUNCE_RESPONSE; |
@@ -303,7 +307,7 @@ static int handle_data_request(void *object, IP_Port source, uint8_t *packet, ui | |||
303 | if (length <= DATA_REQUEST_MIN_SIZE_RECV) | 307 | if (length <= DATA_REQUEST_MIN_SIZE_RECV) |
304 | return 1; | 308 | return 1; |
305 | 309 | ||
306 | if (length >= MAX_DATA_SIZE) | 310 | if (length > ONION_MAX_PACKET_SIZE) |
307 | return 1; | 311 | return 1; |
308 | 312 | ||
309 | int index = in_entries(onion_a, packet + 1); | 313 | int index = in_entries(onion_a, packet + 1); |
diff --git a/toxcore/onion_announce.h b/toxcore/onion_announce.h index b7e08363..ea320998 100644 --- a/toxcore/onion_announce.h +++ b/toxcore/onion_announce.h | |||
@@ -29,7 +29,7 @@ | |||
29 | #define ONION_ANNOUNCE_TIMEOUT 300 | 29 | #define ONION_ANNOUNCE_TIMEOUT 300 |
30 | #define ONION_PING_ID_SIZE crypto_hash_sha256_BYTES | 30 | #define ONION_PING_ID_SIZE crypto_hash_sha256_BYTES |
31 | 31 | ||
32 | #define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (crypto_secretbox_NONCEBYTES + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES) | 32 | #define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (sizeof(uint64_t)) |
33 | 33 | ||
34 | #define ONION_ANNOUNCE_RESPONSE_MIN_SIZE (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES + 1 + ONION_PING_ID_SIZE + crypto_box_MACBYTES) | 34 | #define ONION_ANNOUNCE_RESPONSE_MIN_SIZE (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES + 1 + ONION_PING_ID_SIZE + crypto_box_MACBYTES) |
35 | #define ONION_ANNOUNCE_RESPONSE_MAX_SIZE (ONION_ANNOUNCE_RESPONSE_MIN_SIZE + sizeof(Node_format)*MAX_SENT_NODES) | 35 | #define ONION_ANNOUNCE_RESPONSE_MAX_SIZE (ONION_ANNOUNCE_RESPONSE_MIN_SIZE + sizeof(Node_format)*MAX_SENT_NODES) |
@@ -40,6 +40,9 @@ | |||
40 | #error announce response packets assume that ONION_PING_ID_SIZE is equal to crypto_box_PUBLICKEYBYTES | 40 | #error announce response packets assume that ONION_PING_ID_SIZE is equal to crypto_box_PUBLICKEYBYTES |
41 | #endif | 41 | #endif |
42 | 42 | ||
43 | #define ONION_DATA_REQUEST_MIN_SIZE (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) | ||
44 | #define MAX_DATA_REQUEST_SIZE (ONION_MAX_DATA_SIZE - ONION_DATA_REQUEST_MIN_SIZE) | ||
45 | |||
43 | typedef struct { | 46 | typedef struct { |
44 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; | 47 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; |
45 | IP_Port ret_ip_port; | 48 | IP_Port ret_ip_port; |
@@ -52,8 +55,8 @@ typedef struct { | |||
52 | DHT *dht; | 55 | DHT *dht; |
53 | Networking_Core *net; | 56 | Networking_Core *net; |
54 | Onion_Announce_Entry entries[ONION_ANNOUNCE_MAX_ENTRIES]; | 57 | Onion_Announce_Entry entries[ONION_ANNOUNCE_MAX_ENTRIES]; |
55 | /* This is crypto_secretbox_KEYBYTES long just so we can use new_symmetric_key() to fill it */ | 58 | /* This is crypto_box_KEYBYTES long just so we can use new_symmetric_key() to fill it */ |
56 | uint8_t secret_bytes[crypto_secretbox_KEYBYTES]; | 59 | uint8_t secret_bytes[crypto_box_KEYBYTES]; |
57 | 60 | ||
58 | Shared_Keys shared_keys_recv; | 61 | Shared_Keys shared_keys_recv; |
59 | } Onion_Announce; | 62 | } Onion_Announce; |
@@ -73,7 +76,7 @@ typedef struct { | |||
73 | * return 0 on success. | 76 | * return 0 on success. |
74 | */ | 77 | */ |
75 | int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format dest, uint8_t *public_key, | 78 | int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format dest, uint8_t *public_key, |
76 | uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data); | 79 | uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint64_t sendback_data); |
77 | 80 | ||
78 | /* Create and send an onion data request packet. | 81 | /* Create and send an onion data request packet. |
79 | * | 82 | * |
@@ -86,6 +89,8 @@ int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format de | |||
86 | * | 89 | * |
87 | * nonce is the nonce to encrypt this packet with | 90 | * nonce is the nonce to encrypt this packet with |
88 | * | 91 | * |
92 | * The maximum length of data is MAX_DATA_REQUEST_SIZE. | ||
93 | * | ||
89 | * return -1 on failure. | 94 | * return -1 on failure. |
90 | * return 0 on success. | 95 | * return 0 on success. |
91 | */ | 96 | */ |
diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 329b1d13..dfdb1638 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c | |||
@@ -28,8 +28,37 @@ | |||
28 | #include "util.h" | 28 | #include "util.h" |
29 | #include "LAN_discovery.h" | 29 | #include "LAN_discovery.h" |
30 | 30 | ||
31 | /* defines for the array size and | ||
32 | timeout for onion announce packets. */ | ||
33 | #define ANNOUNCE_ARRAY_SIZE 256 | ||
31 | #define ANNOUNCE_TIMEOUT 10 | 34 | #define ANNOUNCE_TIMEOUT 10 |
32 | 35 | ||
36 | |||
37 | /* | ||
38 | * return -1 if nodes are suitable for creating a new path. | ||
39 | * return path number of already existing similar path if one already exists. | ||
40 | */ | ||
41 | static int is_path_used(Onion_Client_Paths *onion_paths, Node_format *nodes) | ||
42 | { | ||
43 | uint32_t i; | ||
44 | |||
45 | for (i = 0; i < NUMBER_ONION_PATHS; ++i) { | ||
46 | if (is_timeout(onion_paths->last_path_success[i], ONION_PATH_TIMEOUT)) { | ||
47 | continue; | ||
48 | } | ||
49 | |||
50 | if (is_timeout(onion_paths->path_creation_time[i], ONION_PATH_MAX_LIFETIME)) { | ||
51 | continue; | ||
52 | } | ||
53 | |||
54 | if (ipport_equal(&onion_paths->paths[i].ip_port1, &nodes[0].ip_port)) { | ||
55 | return i; | ||
56 | } | ||
57 | } | ||
58 | |||
59 | return -1; | ||
60 | } | ||
61 | |||
33 | /* Create a new path or use an old suitable one (if pathnum is valid) | 62 | /* Create a new path or use an old suitable one (if pathnum is valid) |
34 | * or a rondom one from onion_paths. | 63 | * or a rondom one from onion_paths. |
35 | * | 64 | * |
@@ -51,11 +80,17 @@ static int random_path(DHT *dht, Onion_Client_Paths *onion_paths, uint32_t pathn | |||
51 | if (random_nodes_path(dht, nodes, 3) != 3) | 80 | if (random_nodes_path(dht, nodes, 3) != 3) |
52 | return -1; | 81 | return -1; |
53 | 82 | ||
54 | if (create_onion_path(dht, &onion_paths->paths[pathnum], nodes) == -1) | 83 | int n = is_path_used(onion_paths, nodes); |
55 | return -1; | ||
56 | 84 | ||
57 | onion_paths->last_path_success[pathnum] = unix_time() + ONION_PATH_FIRST_TIMEOUT - ONION_PATH_TIMEOUT; | 85 | if (n == -1) { |
58 | onion_paths->path_creation_time[pathnum] = unix_time(); | 86 | if (create_onion_path(dht, &onion_paths->paths[pathnum], nodes) == -1) |
87 | return -1; | ||
88 | |||
89 | onion_paths->last_path_success[pathnum] = unix_time() + ONION_PATH_FIRST_TIMEOUT - ONION_PATH_TIMEOUT; | ||
90 | onion_paths->path_creation_time[pathnum] = unix_time(); | ||
91 | } else { | ||
92 | pathnum = n; | ||
93 | } | ||
59 | } | 94 | } |
60 | 95 | ||
61 | memcpy(path, &onion_paths->paths[pathnum], sizeof(Onion_Path)); | 96 | memcpy(path, &onion_paths->paths[pathnum], sizeof(Onion_Path)); |
@@ -105,20 +140,15 @@ static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, IP_Port s | |||
105 | * return 0 on success | 140 | * return 0 on success |
106 | * | 141 | * |
107 | */ | 142 | */ |
108 | static int new_sendback(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port, uint8_t *sendback) | 143 | static int new_sendback(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port, uint64_t *sendback) |
109 | { | 144 | { |
110 | uint8_t plain[sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port)]; | 145 | uint8_t data[sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port)]; |
111 | uint64_t time = unix_time(); | 146 | memcpy(data, &num, sizeof(uint32_t)); |
112 | random_nonce(sendback); | 147 | memcpy(data + sizeof(uint32_t), public_key, crypto_box_PUBLICKEYBYTES); |
113 | memcpy(plain, &num, sizeof(uint32_t)); | 148 | memcpy(data + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES, &ip_port, sizeof(IP_Port)); |
114 | memcpy(plain + sizeof(uint32_t), &time, sizeof(uint64_t)); | 149 | *sendback = ping_array_add(&onion_c->announce_ping_array, data, sizeof(data)); |
115 | memcpy(plain + sizeof(uint32_t) + sizeof(uint64_t), public_key, crypto_box_PUBLICKEYBYTES); | ||
116 | memcpy(plain + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, &ip_port, sizeof(IP_Port)); | ||
117 | |||
118 | int len = encrypt_data_symmetric(onion_c->secret_symmetric_key, sendback, plain, sizeof(plain), | ||
119 | sendback + crypto_secretbox_NONCEBYTES); | ||
120 | 150 | ||
121 | if ((uint32_t)len + crypto_secretbox_NONCEBYTES != ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) | 151 | if (*sendback == 0) |
122 | return -1; | 152 | return -1; |
123 | 153 | ||
124 | return 0; | 154 | return 0; |
@@ -136,24 +166,17 @@ static int new_sendback(Onion_Client *onion_c, uint32_t num, uint8_t *public_key | |||
136 | */ | 166 | */ |
137 | static uint32_t check_sendback(Onion_Client *onion_c, uint8_t *sendback, uint8_t *ret_pubkey, IP_Port *ret_ip_port) | 167 | static uint32_t check_sendback(Onion_Client *onion_c, uint8_t *sendback, uint8_t *ret_pubkey, IP_Port *ret_ip_port) |
138 | { | 168 | { |
139 | uint8_t plain[sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port)]; | 169 | uint64_t sback; |
140 | int len = decrypt_data_symmetric(onion_c->secret_symmetric_key, sendback, sendback + crypto_secretbox_NONCEBYTES, | 170 | memcpy(&sback, sendback, sizeof(uint64_t)); |
141 | ONION_ANNOUNCE_SENDBACK_DATA_LENGTH - crypto_secretbox_NONCEBYTES, plain); | 171 | uint8_t data[sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port)]; |
142 | 172 | ||
143 | if ((uint32_t)len != sizeof(plain)) | 173 | if (ping_array_check(data, sizeof(data), &onion_c->announce_ping_array, sback) != sizeof(data)) |
144 | return ~0; | ||
145 | |||
146 | uint64_t timestamp; | ||
147 | memcpy(×tamp, plain + sizeof(uint32_t), sizeof(uint64_t)); | ||
148 | uint64_t temp_time = unix_time(); | ||
149 | |||
150 | if (timestamp + ANNOUNCE_TIMEOUT < temp_time || temp_time < timestamp) | ||
151 | return ~0; | 174 | return ~0; |
152 | 175 | ||
153 | memcpy(ret_pubkey, plain + sizeof(uint32_t) + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES); | 176 | memcpy(ret_pubkey, data + sizeof(uint32_t), crypto_box_PUBLICKEYBYTES); |
154 | memcpy(ret_ip_port, plain + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, sizeof(IP_Port)); | 177 | memcpy(ret_ip_port, data + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES, sizeof(IP_Port)); |
155 | uint32_t num; | 178 | uint32_t num; |
156 | memcpy(&num, plain, sizeof(uint32_t)); | 179 | memcpy(&num, data, sizeof(uint32_t)); |
157 | return num; | 180 | return num; |
158 | } | 181 | } |
159 | 182 | ||
@@ -163,9 +186,9 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_ | |||
163 | if (num > onion_c->num_friends) | 186 | if (num > onion_c->num_friends) |
164 | return -1; | 187 | return -1; |
165 | 188 | ||
166 | uint8_t sendback[ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; | 189 | uint64_t sendback; |
167 | 190 | ||
168 | if (new_sendback(onion_c, num, dest_pubkey, dest, sendback) == -1) | 191 | if (new_sendback(onion_c, num, dest_pubkey, dest, &sendback) == -1) |
169 | return -1; | 192 | return -1; |
170 | 193 | ||
171 | uint8_t zero_ping_id[ONION_PING_ID_SIZE] = {0}; | 194 | uint8_t zero_ping_id[ONION_PING_ID_SIZE] = {0}; |
@@ -183,9 +206,9 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_ | |||
183 | if (random_path(onion_c->dht, &onion_c->onion_paths, pathnum, &path) == -1) | 206 | if (random_path(onion_c->dht, &onion_c->onion_paths, pathnum, &path) == -1) |
184 | return -1; | 207 | return -1; |
185 | 208 | ||
186 | return send_announce_request(onion_c->net, &path, dest_node, onion_c->dht->c->self_public_key, | 209 | return send_announce_request(onion_c->net, &path, dest_node, onion_c->c->self_public_key, |
187 | onion_c->dht->c->self_secret_key, ping_id, | 210 | onion_c->c->self_secret_key, ping_id, |
188 | onion_c->dht->c->self_public_key, onion_c->temp_public_key, sendback); | 211 | onion_c->c->self_public_key, onion_c->temp_public_key, sendback); |
189 | } else { | 212 | } else { |
190 | if (random_path(onion_c->dht, &onion_c->friends_list[num - 1].onion_paths, pathnum, &path) == -1) | 213 | if (random_path(onion_c->dht, &onion_c->friends_list[num - 1].onion_paths, pathnum, &path) == -1) |
191 | return -1; | 214 | return -1; |
@@ -236,7 +259,7 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *publ | |||
236 | 259 | ||
237 | if (num == 0) { | 260 | if (num == 0) { |
238 | list_nodes = onion_c->clients_announce_list; | 261 | list_nodes = onion_c->clients_announce_list; |
239 | reference_id = onion_c->dht->c->self_public_key; | 262 | reference_id = onion_c->c->self_public_key; |
240 | 263 | ||
241 | if (is_stored && memcmp(pingid_or_key, onion_c->temp_public_key, crypto_box_PUBLICKEYBYTES) != 0) { | 264 | if (is_stored && memcmp(pingid_or_key, onion_c->temp_public_key, crypto_box_PUBLICKEYBYTES) != 0) { |
242 | is_stored = 0; | 265 | is_stored = 0; |
@@ -253,16 +276,9 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *publ | |||
253 | int index = -1; | 276 | int index = -1; |
254 | uint32_t i; | 277 | uint32_t i; |
255 | 278 | ||
256 | for (i = 0; i < MAX_ONION_CLIENTS; ++i) { | 279 | if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT) |
257 | if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT) | 280 | || id_closest(reference_id, list_nodes[0].client_id, public_key) == 2) { |
258 | || id_closest(reference_id, list_nodes[i].client_id, public_key) == 2) { | 281 | index = 0; |
259 | index = i; | ||
260 | |||
261 | if (i != 0) | ||
262 | break; | ||
263 | } else { | ||
264 | break; | ||
265 | } | ||
266 | } | 282 | } |
267 | 283 | ||
268 | for (i = 0; i < MAX_ONION_CLIENTS; ++i) { | 284 | for (i = 0; i < MAX_ONION_CLIENTS; ++i) { |
@@ -286,7 +302,7 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *publ | |||
286 | 302 | ||
287 | list_nodes[index].is_stored = is_stored; | 303 | list_nodes[index].is_stored = is_stored; |
288 | list_nodes[index].timestamp = unix_time(); | 304 | list_nodes[index].timestamp = unix_time(); |
289 | list_nodes[index].last_pinged = unix_time(); | 305 | list_nodes[index].last_pinged = 0; |
290 | list_nodes[index].path_used = set_path_timeouts(onion_c, num, source); | 306 | list_nodes[index].path_used = set_path_timeouts(onion_c, num, source); |
291 | return 0; | 307 | return 0; |
292 | } | 308 | } |
@@ -318,21 +334,18 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n | |||
318 | 334 | ||
319 | Onion_Node *list_nodes = NULL; | 335 | Onion_Node *list_nodes = NULL; |
320 | uint8_t *reference_id = NULL; | 336 | uint8_t *reference_id = NULL; |
321 | uint32_t *ping_nodes_sent_second = NULL; | ||
322 | 337 | ||
323 | Last_Pinged *last_pinged = NULL; | 338 | Last_Pinged *last_pinged = NULL; |
324 | uint8_t *last_pinged_index = NULL; | 339 | uint8_t *last_pinged_index = NULL; |
325 | 340 | ||
326 | if (num == 0) { | 341 | if (num == 0) { |
327 | list_nodes = onion_c->clients_announce_list; | 342 | list_nodes = onion_c->clients_announce_list; |
328 | reference_id = onion_c->dht->c->self_public_key; | 343 | reference_id = onion_c->c->self_public_key; |
329 | ping_nodes_sent_second = &onion_c->ping_nodes_sent_second; | ||
330 | last_pinged = onion_c->last_pinged; | 344 | last_pinged = onion_c->last_pinged; |
331 | last_pinged_index = &onion_c->last_pinged_index; | 345 | last_pinged_index = &onion_c->last_pinged_index; |
332 | } else { | 346 | } else { |
333 | list_nodes = onion_c->friends_list[num - 1].clients_list; | 347 | list_nodes = onion_c->friends_list[num - 1].clients_list; |
334 | reference_id = onion_c->friends_list[num - 1].real_client_id; | 348 | reference_id = onion_c->friends_list[num - 1].real_client_id; |
335 | ping_nodes_sent_second = &onion_c->friends_list[num - 1].ping_nodes_sent_second; | ||
336 | last_pinged = onion_c->friends_list[num - 1].last_pinged; | 349 | last_pinged = onion_c->friends_list[num - 1].last_pinged; |
337 | last_pinged_index = &onion_c->friends_list[num - 1].last_pinged_index; | 350 | last_pinged_index = &onion_c->friends_list[num - 1].last_pinged_index; |
338 | } | 351 | } |
@@ -342,11 +355,6 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n | |||
342 | 355 | ||
343 | for (i = 0; i < num_nodes; ++i) { | 356 | for (i = 0; i < num_nodes; ++i) { |
344 | 357 | ||
345 | if (*ping_nodes_sent_second > MAX_PING_NODES_SECOND_PEER) | ||
346 | return 0; | ||
347 | |||
348 | to_host_family(&nodes[i].ip_port.ip); | ||
349 | |||
350 | if (!lan_ips_accepted) | 358 | if (!lan_ips_accepted) |
351 | if (LAN_ip(nodes[i].ip_port.ip) == 0) | 359 | if (LAN_ip(nodes[i].ip_port.ip) == 0) |
352 | continue; | 360 | continue; |
@@ -361,8 +369,7 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n | |||
361 | } | 369 | } |
362 | 370 | ||
363 | if (j == MAX_ONION_CLIENTS && good_to_ping(last_pinged, last_pinged_index, nodes[i].client_id)) { | 371 | if (j == MAX_ONION_CLIENTS && good_to_ping(last_pinged, last_pinged_index, nodes[i].client_id)) { |
364 | if (client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL, ~0) == 0) | 372 | client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL, ~0); |
365 | ++*ping_nodes_sent_second; | ||
366 | } | 373 | } |
367 | } | 374 | } |
368 | } | 375 | } |
@@ -377,10 +384,7 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe | |||
377 | if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) | 384 | if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) |
378 | return 1; | 385 | return 1; |
379 | 386 | ||
380 | if ((length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE) % sizeof(Node_format) != 0) | 387 | uint16_t len_nodes = length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE; |
381 | return 1; | ||
382 | |||
383 | uint16_t num_nodes = (length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE) / sizeof(Node_format); | ||
384 | 388 | ||
385 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; | 389 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; |
386 | IP_Port ip_port; | 390 | IP_Port ip_port; |
@@ -389,11 +393,11 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe | |||
389 | if (num > onion_c->num_friends) | 393 | if (num > onion_c->num_friends) |
390 | return 1; | 394 | return 1; |
391 | 395 | ||
392 | uint8_t plain[1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format)]; | 396 | uint8_t plain[1 + ONION_PING_ID_SIZE + len_nodes]; |
393 | int len = -1; | 397 | int len = -1; |
394 | 398 | ||
395 | if (num == 0) { | 399 | if (num == 0) { |
396 | len = decrypt_data(public_key, onion_c->dht->c->self_secret_key, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, | 400 | len = decrypt_data(public_key, onion_c->c->self_secret_key, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, |
397 | packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES, | 401 | packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES, |
398 | length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES), plain); | 402 | length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES), plain); |
399 | } else { | 403 | } else { |
@@ -409,20 +413,24 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe | |||
409 | if ((uint32_t)len != sizeof(plain)) | 413 | if ((uint32_t)len != sizeof(plain)) |
410 | return 1; | 414 | return 1; |
411 | 415 | ||
412 | |||
413 | if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, source) == -1) | 416 | if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, source) == -1) |
414 | return 1; | 417 | return 1; |
415 | 418 | ||
416 | Node_format nodes[MAX_SENT_NODES]; | 419 | if (len_nodes != 0) { |
417 | memcpy(nodes, plain + 1 + ONION_PING_ID_SIZE, num_nodes * sizeof(Node_format)); | 420 | Node_format nodes[MAX_SENT_NODES]; |
421 | int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, plain + 1 + ONION_PING_ID_SIZE, len_nodes, 0); | ||
418 | 422 | ||
419 | if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1) | 423 | if (num_nodes <= 0) |
420 | return 1; | 424 | return 1; |
425 | |||
426 | if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1) | ||
427 | return 1; | ||
428 | } | ||
421 | 429 | ||
422 | return 0; | 430 | return 0; |
423 | } | 431 | } |
424 | 432 | ||
425 | #define DATA_IN_RESPONSE_MIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) | 433 | #define DATA_IN_RESPONSE_MIN_SIZE ONION_DATA_IN_RESPONSE_MIN_SIZE |
426 | 434 | ||
427 | static int handle_data_response(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 435 | static int handle_data_response(void *object, IP_Port source, uint8_t *packet, uint32_t length) |
428 | { | 436 | { |
@@ -431,7 +439,7 @@ static int handle_data_response(void *object, IP_Port source, uint8_t *packet, u | |||
431 | if (length <= (ONION_DATA_RESPONSE_MIN_SIZE + DATA_IN_RESPONSE_MIN_SIZE)) | 439 | if (length <= (ONION_DATA_RESPONSE_MIN_SIZE + DATA_IN_RESPONSE_MIN_SIZE)) |
432 | return 1; | 440 | return 1; |
433 | 441 | ||
434 | if (length > MAX_DATA_SIZE) | 442 | if (length > MAX_DATA_REQUEST_SIZE) |
435 | return 1; | 443 | return 1; |
436 | 444 | ||
437 | uint8_t temp_plain[length - ONION_DATA_RESPONSE_MIN_SIZE]; | 445 | uint8_t temp_plain[length - ONION_DATA_RESPONSE_MIN_SIZE]; |
@@ -443,7 +451,7 @@ static int handle_data_response(void *object, IP_Port source, uint8_t *packet, u | |||
443 | return 1; | 451 | return 1; |
444 | 452 | ||
445 | uint8_t plain[sizeof(temp_plain) - DATA_IN_RESPONSE_MIN_SIZE]; | 453 | uint8_t plain[sizeof(temp_plain) - DATA_IN_RESPONSE_MIN_SIZE]; |
446 | len = decrypt_data(temp_plain, onion_c->dht->c->self_secret_key, packet + 1, temp_plain + crypto_box_PUBLICKEYBYTES, | 454 | len = decrypt_data(temp_plain, onion_c->c->self_secret_key, packet + 1, temp_plain + crypto_box_PUBLICKEYBYTES, |
447 | sizeof(temp_plain) - crypto_box_PUBLICKEYBYTES, plain); | 455 | sizeof(temp_plain) - crypto_box_PUBLICKEYBYTES, plain); |
448 | 456 | ||
449 | if ((uint32_t)len != sizeof(plain)) | 457 | if ((uint32_t)len != sizeof(plain)) |
@@ -469,9 +477,6 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t | |||
469 | if (length > FAKEID_DATA_MAX_LENGTH) | 477 | if (length > FAKEID_DATA_MAX_LENGTH) |
470 | return 1; | 478 | return 1; |
471 | 479 | ||
472 | if ((length - FAKEID_DATA_MIN_LENGTH) % sizeof(Node_format) != 0) | ||
473 | return 1; | ||
474 | |||
475 | int friend_num = onion_friend_num(onion_c, source_pubkey); | 480 | int friend_num = onion_friend_num(onion_c, source_pubkey); |
476 | 481 | ||
477 | if (friend_num == -1) | 482 | if (friend_num == -1) |
@@ -485,37 +490,42 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t | |||
485 | return 1; | 490 | return 1; |
486 | 491 | ||
487 | onion_c->friends_list[friend_num].last_noreplay = no_replay; | 492 | onion_c->friends_list[friend_num].last_noreplay = no_replay; |
493 | onion_set_friend_DHT_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t), current_time_monotonic()); | ||
494 | onion_c->friends_list[friend_num].last_seen = unix_time(); | ||
488 | 495 | ||
489 | if (memcmp(data + 1 + sizeof(uint64_t), onion_c->friends_list[friend_num].fake_client_id, | 496 | uint16_t len_nodes = length - FAKEID_DATA_MIN_LENGTH; |
490 | crypto_box_PUBLICKEYBYTES) != 0) { | ||
491 | DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id); | ||
492 | 497 | ||
493 | onion_c->friends_list[friend_num].last_seen = unix_time(); | 498 | if (len_nodes != 0) { |
499 | Node_format nodes[MAX_SENT_NODES]; | ||
500 | int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, | ||
501 | len_nodes, 1); | ||
494 | 502 | ||
495 | if (DHT_addfriend(onion_c->dht, data + 1 + sizeof(uint64_t)) == 1) { | 503 | if (num_nodes <= 0) |
496 | return 1; | 504 | return 1; |
497 | } | ||
498 | 505 | ||
499 | onion_c->friends_list[friend_num].is_fake_clientid = 1; | 506 | int i; |
500 | memcpy(onion_c->friends_list[friend_num].fake_client_id, data + 1 + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES); | ||
501 | } | ||
502 | 507 | ||
503 | uint16_t num_nodes = (length - FAKEID_DATA_MIN_LENGTH) / sizeof(Node_format); | 508 | for (i = 0; i < num_nodes; ++i) { |
504 | Node_format nodes[num_nodes]; | 509 | uint8_t family = nodes[i].ip_port.ip.family; |
505 | memcpy(nodes, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, sizeof(nodes)); | ||
506 | uint32_t i; | ||
507 | 510 | ||
508 | for (i = 0; i < num_nodes; ++i) { | 511 | if (family == AF_INET || family == AF_INET6) { |
509 | to_host_family(&nodes[i].ip_port.ip); | 512 | DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id); |
510 | DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id); | 513 | } else if (family == TCP_INET || family == TCP_INET6) { |
514 | if (onion_c->friends_list[friend_num].tcp_relay_node_callback) { | ||
515 | void *obj = onion_c->friends_list[friend_num].tcp_relay_node_callback_object; | ||
516 | uint32_t number = onion_c->friends_list[friend_num].tcp_relay_node_callback_number; | ||
517 | onion_c->friends_list[friend_num].tcp_relay_node_callback(obj, number, nodes[i].ip_port, nodes[i].client_id); | ||
518 | } | ||
519 | } | ||
520 | } | ||
511 | } | 521 | } |
512 | 522 | ||
513 | return 0; | 523 | return 0; |
514 | } | 524 | } |
515 | /* Send data of length length to friendnum. | 525 | /* Send data of length length to friendnum. |
516 | * This data will be recieved by the friend using the Onion_Data_Handlers callbacks. | 526 | * This data will be received by the friend using the Onion_Data_Handlers callbacks. |
517 | * | 527 | * |
518 | * Even if this function succeeds, the friend might not recieve any data. | 528 | * Even if this function succeeds, the friend might not receive any data. |
519 | * | 529 | * |
520 | * return the number of packets sent on success | 530 | * return the number of packets sent on success |
521 | * return -1 on failure. | 531 | * return -1 on failure. |
@@ -525,7 +535,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32 | |||
525 | if ((uint32_t)friend_num >= onion_c->num_friends) | 535 | if ((uint32_t)friend_num >= onion_c->num_friends) |
526 | return -1; | 536 | return -1; |
527 | 537 | ||
528 | if (length + DATA_IN_RESPONSE_MIN_SIZE + ONION_DATA_RESPONSE_MIN_SIZE + ONION_SEND_1 > MAX_DATA_SIZE) | 538 | if (length + DATA_IN_RESPONSE_MIN_SIZE > MAX_DATA_REQUEST_SIZE) |
529 | return -1; | 539 | return -1; |
530 | 540 | ||
531 | if (length == 0) | 541 | if (length == 0) |
@@ -535,8 +545,8 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32 | |||
535 | random_nonce(nonce); | 545 | random_nonce(nonce); |
536 | 546 | ||
537 | uint8_t packet[DATA_IN_RESPONSE_MIN_SIZE + length]; | 547 | uint8_t packet[DATA_IN_RESPONSE_MIN_SIZE + length]; |
538 | memcpy(packet, onion_c->dht->c->self_public_key, crypto_box_PUBLICKEYBYTES); | 548 | memcpy(packet, onion_c->c->self_public_key, crypto_box_PUBLICKEYBYTES); |
539 | int len = encrypt_data(onion_c->friends_list[friend_num].real_client_id, onion_c->dht->c->self_secret_key, nonce, data, | 549 | int len = encrypt_data(onion_c->friends_list[friend_num].real_client_id, onion_c->c->self_secret_key, nonce, data, |
540 | length, packet + crypto_box_PUBLICKEYBYTES); | 550 | length, packet + crypto_box_PUBLICKEYBYTES); |
541 | 551 | ||
542 | if ((uint32_t)len + crypto_box_PUBLICKEYBYTES != sizeof(packet)) | 552 | if ((uint32_t)len + crypto_box_PUBLICKEYBYTES != sizeof(packet)) |
@@ -578,7 +588,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32 | |||
578 | 588 | ||
579 | /* Try to send the fakeid via the DHT instead of onion | 589 | /* Try to send the fakeid via the DHT instead of onion |
580 | * | 590 | * |
581 | * Even if this function succeeds, the friend might not recieve any data. | 591 | * Even if this function succeeds, the friend might not receive any data. |
582 | * | 592 | * |
583 | * return the number of packets sent on success | 593 | * return the number of packets sent on success |
584 | * return -1 on failure. | 594 | * return -1 on failure. |
@@ -595,15 +605,15 @@ static int send_dht_fakeid(Onion_Client *onion_c, int friend_num, uint8_t *data, | |||
595 | new_nonce(nonce); | 605 | new_nonce(nonce); |
596 | 606 | ||
597 | uint8_t temp[DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES + length]; | 607 | uint8_t temp[DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES + length]; |
598 | memcpy(temp, onion_c->dht->c->self_public_key, crypto_box_PUBLICKEYBYTES); | 608 | memcpy(temp, onion_c->c->self_public_key, crypto_box_PUBLICKEYBYTES); |
599 | memcpy(temp + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); | 609 | memcpy(temp + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); |
600 | int len = encrypt_data(onion_c->friends_list[friend_num].real_client_id, onion_c->dht->c->self_secret_key, nonce, data, | 610 | int len = encrypt_data(onion_c->friends_list[friend_num].real_client_id, onion_c->c->self_secret_key, nonce, data, |
601 | length, temp + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); | 611 | length, temp + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); |
602 | 612 | ||
603 | if ((uint32_t)len + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES != sizeof(temp)) | 613 | if ((uint32_t)len + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES != sizeof(temp)) |
604 | return -1; | 614 | return -1; |
605 | 615 | ||
606 | uint8_t packet[MAX_DATA_SIZE]; | 616 | uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; |
607 | len = create_request(onion_c->dht->self_public_key, onion_c->dht->self_secret_key, packet, | 617 | len = create_request(onion_c->dht->self_public_key, onion_c->dht->self_secret_key, packet, |
608 | onion_c->friends_list[friend_num].fake_client_id, temp, sizeof(temp), FAKEID_DATA_ID); | 618 | onion_c->friends_list[friend_num].fake_client_id, temp, sizeof(temp), FAKEID_DATA_ID); |
609 | 619 | ||
@@ -624,14 +634,14 @@ static int handle_dht_fakeid(void *object, IP_Port source, uint8_t *source_pubke | |||
624 | return 1; | 634 | return 1; |
625 | 635 | ||
626 | uint8_t plain[FAKEID_DATA_MAX_LENGTH]; | 636 | uint8_t plain[FAKEID_DATA_MAX_LENGTH]; |
627 | int len = decrypt_data(packet, onion_c->dht->c->self_secret_key, packet + crypto_box_PUBLICKEYBYTES, | 637 | int len = decrypt_data(packet, onion_c->c->self_secret_key, packet + crypto_box_PUBLICKEYBYTES, |
628 | packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, | 638 | packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, |
629 | length - (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES), plain); | 639 | length - (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES), plain); |
630 | 640 | ||
631 | if ((uint32_t)len != length - (DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES)) | 641 | if ((uint32_t)len != length - (DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES)) |
632 | return 1; | 642 | return 1; |
633 | 643 | ||
634 | if (memcpy(source_pubkey, packet, crypto_box_PUBLICKEYBYTES) != 0) | 644 | if (memcmp(source_pubkey, plain + 1 + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES) != 0) |
635 | return 1; | 645 | return 1; |
636 | 646 | ||
637 | return handle_fakeid_announce(onion_c, packet, plain, len); | 647 | return handle_fakeid_announce(onion_c, packet, plain, len); |
@@ -657,20 +667,26 @@ static int send_fakeid_announce(Onion_Client *onion_c, uint16_t friend_num, uint | |||
657 | memcpy(data + 1, &no_replay, sizeof(no_replay)); | 667 | memcpy(data + 1, &no_replay, sizeof(no_replay)); |
658 | memcpy(data + 1 + sizeof(uint64_t), onion_c->dht->self_public_key, crypto_box_PUBLICKEYBYTES); | 668 | memcpy(data + 1 + sizeof(uint64_t), onion_c->dht->self_public_key, crypto_box_PUBLICKEYBYTES); |
659 | Node_format nodes[MAX_SENT_NODES]; | 669 | Node_format nodes[MAX_SENT_NODES]; |
660 | uint16_t num_nodes = closelist_nodes(onion_c->dht, nodes, MAX_SENT_NODES); | 670 | uint16_t num_relays = copy_connected_tcp_relays(onion_c->c, nodes, (MAX_SENT_NODES / 2)); |
661 | uint32_t i; | 671 | uint16_t num_nodes = closelist_nodes(onion_c->dht, &nodes[num_relays], MAX_SENT_NODES - num_relays); |
672 | num_nodes += num_relays; | ||
673 | int nodes_len = 0; | ||
674 | |||
675 | if (num_nodes != 0) { | ||
676 | nodes_len = pack_nodes(data + FAKEID_DATA_MIN_LENGTH, FAKEID_DATA_MAX_LENGTH - FAKEID_DATA_MIN_LENGTH, nodes, | ||
677 | num_nodes); | ||
662 | 678 | ||
663 | for (i = 0; i < num_nodes; ++i) | 679 | if (nodes_len <= 0) |
664 | to_net_family(&nodes[i].ip_port.ip); | 680 | return -1; |
681 | } | ||
665 | 682 | ||
666 | memcpy(data + FAKEID_DATA_MIN_LENGTH, nodes, sizeof(Node_format) * num_nodes); | ||
667 | int num1 = -1, num2 = -1; | 683 | int num1 = -1, num2 = -1; |
668 | 684 | ||
669 | if (onion_dht_both != 1) | 685 | if (onion_dht_both != 1) |
670 | num1 = send_onion_data(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + sizeof(Node_format) * num_nodes); | 686 | num1 = send_onion_data(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + nodes_len); |
671 | 687 | ||
672 | if (onion_dht_both != 0) | 688 | if (onion_dht_both != 0) |
673 | num2 = send_dht_fakeid(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + sizeof(Node_format) * num_nodes); | 689 | num2 = send_dht_fakeid(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + nodes_len); |
674 | 690 | ||
675 | if (num1 == -1) | 691 | if (num1 == -1) |
676 | return num2; | 692 | return num2; |
@@ -788,14 +804,34 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num) | |||
788 | return friend_num; | 804 | return friend_num; |
789 | } | 805 | } |
790 | 806 | ||
791 | /* Get the ip of friend friendnum and put it in ip_port | 807 | /* Set the function for this friend that will be callbacked with object and number |
808 | * when that friends gives us one of the TCP relays he is connected to. | ||
792 | * | 809 | * |
793 | * return -1, -- if client_id does NOT refer to a friend | 810 | * object and number will be passed as argument to this function. |
794 | * return 0, -- if client_id refers to a friend and we failed to find the friend (yet) | ||
795 | * return 1, ip if client_id refers to a friend and we found him | ||
796 | * | 811 | * |
812 | * return -1 on failure. | ||
813 | * return 0 on success. | ||
797 | */ | 814 | */ |
798 | int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port) | 815 | int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num, int (*tcp_relay_node_callback)(void *object, |
816 | uint32_t number, IP_Port ip_port, uint8_t *public_key), void *object, uint32_t number) | ||
817 | { | ||
818 | if ((uint32_t)friend_num >= onion_c->num_friends) | ||
819 | return -1; | ||
820 | |||
821 | onion_c->friends_list[friend_num].tcp_relay_node_callback = tcp_relay_node_callback; | ||
822 | onion_c->friends_list[friend_num].tcp_relay_node_callback_object = object; | ||
823 | onion_c->friends_list[friend_num].tcp_relay_node_callback_number = number; | ||
824 | return 0; | ||
825 | } | ||
826 | |||
827 | /* Set a friends DHT public key. | ||
828 | * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to | ||
829 | * the other peer. | ||
830 | * | ||
831 | * return -1 on failure. | ||
832 | * return 0 on success. | ||
833 | */ | ||
834 | int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key, uint64_t timestamp) | ||
799 | { | 835 | { |
800 | if ((uint32_t)friend_num >= onion_c->num_friends) | 836 | if ((uint32_t)friend_num >= onion_c->num_friends) |
801 | return -1; | 837 | return -1; |
@@ -803,12 +839,67 @@ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port) | |||
803 | if (onion_c->friends_list[friend_num].status == 0) | 839 | if (onion_c->friends_list[friend_num].status == 0) |
804 | return -1; | 840 | return -1; |
805 | 841 | ||
842 | if (onion_c->friends_list[friend_num].fake_client_id_timestamp >= timestamp) | ||
843 | return -1; | ||
844 | |||
845 | if (onion_c->friends_list[friend_num].is_fake_clientid) { | ||
846 | if (memcmp(dht_key, onion_c->friends_list[friend_num].fake_client_id, crypto_box_PUBLICKEYBYTES) == 0) { | ||
847 | return -1; | ||
848 | } | ||
849 | |||
850 | DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id); | ||
851 | } | ||
852 | |||
853 | if (DHT_addfriend(onion_c->dht, dht_key) == 1) { | ||
854 | return -1; | ||
855 | } | ||
856 | |||
857 | onion_c->friends_list[friend_num].last_seen = unix_time(); | ||
858 | onion_c->friends_list[friend_num].is_fake_clientid = 1; | ||
859 | onion_c->friends_list[friend_num].fake_client_id_timestamp = timestamp; | ||
860 | memcpy(onion_c->friends_list[friend_num].fake_client_id, dht_key, crypto_box_PUBLICKEYBYTES); | ||
861 | |||
862 | return 0; | ||
863 | } | ||
864 | |||
865 | /* Copy friends DHT public key into dht_key. | ||
866 | * | ||
867 | * return 0 on failure (no key copied). | ||
868 | * return timestamp on success (key copied). | ||
869 | */ | ||
870 | uint64_t onion_getfriend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key) | ||
871 | { | ||
872 | if ((uint32_t)friend_num >= onion_c->num_friends) | ||
873 | return 0; | ||
874 | |||
875 | if (onion_c->friends_list[friend_num].status == 0) | ||
876 | return 0; | ||
877 | |||
806 | if (!onion_c->friends_list[friend_num].is_fake_clientid) | 878 | if (!onion_c->friends_list[friend_num].is_fake_clientid) |
879 | return 0; | ||
880 | |||
881 | memcpy(dht_key, onion_c->friends_list[friend_num].fake_client_id, crypto_box_PUBLICKEYBYTES); | ||
882 | return onion_c->friends_list[friend_num].fake_client_id_timestamp; | ||
883 | } | ||
884 | |||
885 | /* Get the ip of friend friendnum and put it in ip_port | ||
886 | * | ||
887 | * return -1, -- if client_id does NOT refer to a friend | ||
888 | * return 0, -- if client_id refers to a friend and we failed to find the friend (yet) | ||
889 | * return 1, ip if client_id refers to a friend and we found him | ||
890 | * | ||
891 | */ | ||
892 | int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port) | ||
893 | { | ||
894 | uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; | ||
895 | |||
896 | if (onion_getfriend_DHT_pubkey(onion_c, friend_num, dht_public_key) == 0) | ||
807 | return -1; | 897 | return -1; |
808 | 898 | ||
809 | return DHT_getfriendip(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id, ip_port); | 899 | return DHT_getfriendip(onion_c->dht, dht_public_key, ip_port); |
810 | } | 900 | } |
811 | 901 | ||
902 | |||
812 | /* Set if friend is online or not. | 903 | /* Set if friend is online or not. |
813 | * NOTE: This function is there and should be used so that we don't send useless packets to the friend if he is online. | 904 | * NOTE: This function is there and should be used so that we don't send useless packets to the friend if he is online. |
814 | * | 905 | * |
@@ -856,6 +947,11 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum) | |||
856 | 947 | ||
857 | ++count; | 948 | ++count; |
858 | 949 | ||
950 | if (list_nodes[i].last_pinged == 0) { | ||
951 | list_nodes[i].last_pinged = unix_time(); | ||
952 | continue; | ||
953 | } | ||
954 | |||
859 | if (is_timeout(list_nodes[i].last_pinged, ANNOUNCE_FRIEND)) { | 955 | if (is_timeout(list_nodes[i].last_pinged, ANNOUNCE_FRIEND)) { |
860 | if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].client_id, 0, ~0) == 0) { | 956 | if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].client_id, 0, ~0) == 0) { |
861 | list_nodes[i].last_pinged = unix_time(); | 957 | list_nodes[i].last_pinged = unix_time(); |
@@ -924,6 +1020,13 @@ static void do_announce(Onion_Client *onion_c) | |||
924 | continue; | 1020 | continue; |
925 | 1021 | ||
926 | ++count; | 1022 | ++count; |
1023 | |||
1024 | /* Don't announce ourselves the first time this is run to new peers */ | ||
1025 | if (list_nodes[i].last_pinged == 0) { | ||
1026 | list_nodes[i].last_pinged = 1; | ||
1027 | continue; | ||
1028 | } | ||
1029 | |||
927 | uint32_t interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED; | 1030 | uint32_t interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED; |
928 | 1031 | ||
929 | if (list_nodes[i].is_stored) { | 1032 | if (list_nodes[i].is_stored) { |
@@ -941,7 +1044,7 @@ static void do_announce(Onion_Client *onion_c) | |||
941 | if (count != MAX_ONION_CLIENTS) { | 1044 | if (count != MAX_ONION_CLIENTS) { |
942 | if (count < (uint32_t)rand() % MAX_ONION_CLIENTS) { | 1045 | if (count < (uint32_t)rand() % MAX_ONION_CLIENTS) { |
943 | Node_format nodes_list[MAX_SENT_NODES]; | 1046 | Node_format nodes_list[MAX_SENT_NODES]; |
944 | uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->dht->c->self_public_key, nodes_list, | 1047 | uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->c->self_public_key, nodes_list, |
945 | rand() % 2 ? AF_INET : AF_INET6, 1, 0); | 1048 | rand() % 2 ? AF_INET : AF_INET6, 1, 0); |
946 | 1049 | ||
947 | for (i = 0; i < num_nodes; ++i) { | 1050 | for (i = 0; i < num_nodes; ++i) { |
@@ -963,16 +1066,14 @@ void do_onion_client(Onion_Client *onion_c) | |||
963 | for (i = 0; i < onion_c->num_friends; ++i) { | 1066 | for (i = 0; i < onion_c->num_friends; ++i) { |
964 | do_friend(onion_c, i); | 1067 | do_friend(onion_c, i); |
965 | cleanup_friend(onion_c, i); | 1068 | cleanup_friend(onion_c, i); |
966 | onion_c->friends_list[i].ping_nodes_sent_second = 0; | ||
967 | } | 1069 | } |
968 | 1070 | ||
969 | onion_c->ping_nodes_sent_second = 0; | ||
970 | onion_c->last_run = unix_time(); | 1071 | onion_c->last_run = unix_time(); |
971 | } | 1072 | } |
972 | 1073 | ||
973 | Onion_Client *new_onion_client(DHT *dht) | 1074 | Onion_Client *new_onion_client(Net_Crypto *c) |
974 | { | 1075 | { |
975 | if (dht == NULL) | 1076 | if (c == NULL) |
976 | return NULL; | 1077 | return NULL; |
977 | 1078 | ||
978 | Onion_Client *onion_c = calloc(1, sizeof(Onion_Client)); | 1079 | Onion_Client *onion_c = calloc(1, sizeof(Onion_Client)); |
@@ -980,14 +1081,20 @@ Onion_Client *new_onion_client(DHT *dht) | |||
980 | if (onion_c == NULL) | 1081 | if (onion_c == NULL) |
981 | return NULL; | 1082 | return NULL; |
982 | 1083 | ||
983 | onion_c->dht = dht; | 1084 | if (ping_array_init(&onion_c->announce_ping_array, ANNOUNCE_ARRAY_SIZE, ANNOUNCE_TIMEOUT) != 0) { |
984 | onion_c->net = dht->c->lossless_udp->net; | 1085 | free(onion_c); |
1086 | return NULL; | ||
1087 | } | ||
1088 | |||
1089 | onion_c->dht = c->dht; | ||
1090 | onion_c->net = c->dht->net; | ||
1091 | onion_c->c = c; | ||
985 | new_symmetric_key(onion_c->secret_symmetric_key); | 1092 | new_symmetric_key(onion_c->secret_symmetric_key); |
986 | crypto_box_keypair(onion_c->temp_public_key, onion_c->temp_secret_key); | 1093 | crypto_box_keypair(onion_c->temp_public_key, onion_c->temp_secret_key); |
987 | networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_announce_response, onion_c); | 1094 | networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_announce_response, onion_c); |
988 | networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_data_response, onion_c); | 1095 | networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_data_response, onion_c); |
989 | oniondata_registerhandler(onion_c, FAKEID_DATA_ID, &handle_fakeid_announce, onion_c); | 1096 | oniondata_registerhandler(onion_c, FAKEID_DATA_ID, &handle_fakeid_announce, onion_c); |
990 | cryptopacket_registerhandler(onion_c->dht->c, FAKEID_DATA_ID, &handle_dht_fakeid, onion_c); | 1097 | cryptopacket_registerhandler(onion_c->dht, FAKEID_DATA_ID, &handle_dht_fakeid, onion_c); |
991 | 1098 | ||
992 | return onion_c; | 1099 | return onion_c; |
993 | } | 1100 | } |
@@ -997,11 +1104,12 @@ void kill_onion_client(Onion_Client *onion_c) | |||
997 | if (onion_c == NULL) | 1104 | if (onion_c == NULL) |
998 | return; | 1105 | return; |
999 | 1106 | ||
1107 | ping_array_free_all(&onion_c->announce_ping_array); | ||
1000 | realloc_onion_friends(onion_c, 0); | 1108 | realloc_onion_friends(onion_c, 0); |
1001 | networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, NULL, NULL); | 1109 | networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, NULL, NULL); |
1002 | networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, NULL, NULL); | 1110 | networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, NULL, NULL); |
1003 | oniondata_registerhandler(onion_c, FAKEID_DATA_ID, NULL, NULL); | 1111 | oniondata_registerhandler(onion_c, FAKEID_DATA_ID, NULL, NULL); |
1004 | cryptopacket_registerhandler(onion_c->dht->c, FAKEID_DATA_ID, NULL, NULL); | 1112 | cryptopacket_registerhandler(onion_c->dht, FAKEID_DATA_ID, NULL, NULL); |
1005 | memset(onion_c, 0, sizeof(Onion_Client)); | 1113 | memset(onion_c, 0, sizeof(Onion_Client)); |
1006 | free(onion_c); | 1114 | free(onion_c); |
1007 | } | 1115 | } |
diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index 4045cc0e..9cf6cf3e 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h | |||
@@ -25,6 +25,8 @@ | |||
25 | #define ONION_CLIENT_H | 25 | #define ONION_CLIENT_H |
26 | 26 | ||
27 | #include "onion_announce.h" | 27 | #include "onion_announce.h" |
28 | #include "net_crypto.h" | ||
29 | #include "ping_array.h" | ||
28 | 30 | ||
29 | #define MAX_ONION_CLIENTS 8 | 31 | #define MAX_ONION_CLIENTS 8 |
30 | #define ONION_NODE_PING_INTERVAL 30 | 32 | #define ONION_NODE_PING_INTERVAL 30 |
@@ -42,11 +44,6 @@ | |||
42 | #define ONION_PATH_TIMEOUT 30 | 44 | #define ONION_PATH_TIMEOUT 30 |
43 | #define ONION_PATH_MAX_LIFETIME 600 | 45 | #define ONION_PATH_MAX_LIFETIME 600 |
44 | 46 | ||
45 | /* A cheap way of making it take less bandwidth at startup: | ||
46 | by limiting the number of ping packets we can send per | ||
47 | second per peer. */ | ||
48 | #define MAX_PING_NODES_SECOND_PEER 5 | ||
49 | |||
50 | #define MAX_STORED_PINGED_NODES 9 | 47 | #define MAX_STORED_PINGED_NODES 9 |
51 | #define MIN_NODE_PING_TIME 10 | 48 | #define MIN_NODE_PING_TIME 10 |
52 | 49 | ||
@@ -80,6 +77,7 @@ typedef struct { | |||
80 | uint8_t is_online; /* Set by the onion_set_friend_status function. */ | 77 | uint8_t is_online; /* Set by the onion_set_friend_status function. */ |
81 | 78 | ||
82 | uint8_t is_fake_clientid; /* 0 if we don't know the fake client id of the other 1 if we do. */ | 79 | uint8_t is_fake_clientid; /* 0 if we don't know the fake client id of the other 1 if we do. */ |
80 | uint64_t fake_client_id_timestamp; | ||
83 | uint8_t fake_client_id[crypto_box_PUBLICKEYBYTES]; | 81 | uint8_t fake_client_id[crypto_box_PUBLICKEYBYTES]; |
84 | uint8_t real_client_id[crypto_box_PUBLICKEYBYTES]; | 82 | uint8_t real_client_id[crypto_box_PUBLICKEYBYTES]; |
85 | 83 | ||
@@ -95,16 +93,20 @@ typedef struct { | |||
95 | uint64_t last_seen; | 93 | uint64_t last_seen; |
96 | 94 | ||
97 | Onion_Client_Paths onion_paths; | 95 | Onion_Client_Paths onion_paths; |
98 | uint32_t ping_nodes_sent_second; | ||
99 | 96 | ||
100 | Last_Pinged last_pinged[MAX_STORED_PINGED_NODES]; | 97 | Last_Pinged last_pinged[MAX_STORED_PINGED_NODES]; |
101 | uint8_t last_pinged_index; | 98 | uint8_t last_pinged_index; |
99 | |||
100 | int (*tcp_relay_node_callback)(void *object, uint32_t number, IP_Port ip_port, uint8_t *public_key); | ||
101 | void *tcp_relay_node_callback_object; | ||
102 | uint32_t tcp_relay_node_callback_number; | ||
102 | } Onion_Friend; | 103 | } Onion_Friend; |
103 | 104 | ||
104 | typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len); | 105 | typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len); |
105 | 106 | ||
106 | typedef struct { | 107 | typedef struct { |
107 | DHT *dht; | 108 | DHT *dht; |
109 | Net_Crypto *c; | ||
108 | Networking_Core *net; | 110 | Networking_Core *net; |
109 | Onion_Friend *friends_list; | 111 | Onion_Friend *friends_list; |
110 | uint16_t num_friends; | 112 | uint16_t num_friends; |
@@ -113,15 +115,15 @@ typedef struct { | |||
113 | 115 | ||
114 | Onion_Client_Paths onion_paths; | 116 | Onion_Client_Paths onion_paths; |
115 | 117 | ||
116 | uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES]; | 118 | uint8_t secret_symmetric_key[crypto_box_KEYBYTES]; |
117 | uint64_t last_run; | 119 | uint64_t last_run; |
118 | 120 | ||
119 | uint8_t temp_public_key[crypto_box_PUBLICKEYBYTES]; | 121 | uint8_t temp_public_key[crypto_box_PUBLICKEYBYTES]; |
120 | uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES]; | 122 | uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES]; |
121 | 123 | ||
122 | uint32_t ping_nodes_sent_second; | ||
123 | |||
124 | Last_Pinged last_pinged[MAX_STORED_PINGED_NODES]; | 124 | Last_Pinged last_pinged[MAX_STORED_PINGED_NODES]; |
125 | |||
126 | Ping_Array announce_ping_array; | ||
125 | uint8_t last_pinged_index; | 127 | uint8_t last_pinged_index; |
126 | struct { | 128 | struct { |
127 | oniondata_handler_callback function; | 129 | oniondata_handler_callback function; |
@@ -170,11 +172,41 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on | |||
170 | */ | 172 | */ |
171 | int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port); | 173 | int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port); |
172 | 174 | ||
175 | /* Set the function for this friend that will be callbacked with object and number | ||
176 | * when that friends gives us one of the TCP relays he is connected to. | ||
177 | * | ||
178 | * object and number will be passed as argument to this function. | ||
179 | * | ||
180 | * return -1 on failure. | ||
181 | * return 0 on success. | ||
182 | */ | ||
183 | int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num, int (*tcp_relay_node_callback)(void *object, | ||
184 | uint32_t number, IP_Port ip_port, uint8_t *public_key), void *object, uint32_t number); | ||
185 | |||
186 | /* Set a friends DHT public key. | ||
187 | * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to | ||
188 | * the other peer. | ||
189 | * | ||
190 | * return -1 on failure. | ||
191 | * return 0 on success. | ||
192 | */ | ||
193 | int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key, uint64_t timestamp); | ||
194 | |||
195 | /* Copy friends DHT public key into dht_key. | ||
196 | * | ||
197 | * return 0 on failure (no key copied). | ||
198 | * return timestamp on success (key copied). | ||
199 | */ | ||
200 | uint64_t onion_getfriend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key); | ||
201 | |||
202 | #define ONION_DATA_IN_RESPONSE_MIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) | ||
203 | #define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE) | ||
173 | 204 | ||
174 | /* Send data of length length to friendnum. | 205 | /* Send data of length length to friendnum. |
175 | * This data will be recieved by the friend using the Onion_Data_Handlers callbacks. | 206 | * Maximum length of data is ONION_CLIENT_MAX_DATA_SIZE. |
207 | * This data will be received by the friend using the Onion_Data_Handlers callbacks. | ||
176 | * | 208 | * |
177 | * Even if this function succeeds, the friend might not recieve any data. | 209 | * Even if this function succeeds, the friend might not receive any data. |
178 | * | 210 | * |
179 | * return the number of packets sent on success | 211 | * return the number of packets sent on success |
180 | * return -1 on failure. | 212 | * return -1 on failure. |
@@ -186,7 +218,7 @@ void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_ha | |||
186 | 218 | ||
187 | void do_onion_client(Onion_Client *onion_c); | 219 | void do_onion_client(Onion_Client *onion_c); |
188 | 220 | ||
189 | Onion_Client *new_onion_client(DHT *dht); | 221 | Onion_Client *new_onion_client(Net_Crypto *c); |
190 | 222 | ||
191 | void kill_onion_client(Onion_Client *onion_c); | 223 | void kill_onion_client(Onion_Client *onion_c); |
192 | 224 | ||
diff --git a/toxcore/ping.c b/toxcore/ping.c index 649d3fff..c01170ab 100644 --- a/toxcore/ping.c +++ b/toxcore/ping.c | |||
@@ -34,118 +34,29 @@ | |||
34 | 34 | ||
35 | #include "network.h" | 35 | #include "network.h" |
36 | #include "util.h" | 36 | #include "util.h" |
37 | #include "ping_array.h" | ||
37 | 38 | ||
38 | #define PING_NUM_MAX 512 | 39 | #define PING_NUM_MAX 512 |
39 | 40 | ||
40 | /* Maximum newly announced nodes to ping per TIME_TO_PING seconds. */ | 41 | /* Maximum newly announced nodes to ping per TIME_TO_PING seconds. */ |
41 | #define MAX_TO_PING 16 | 42 | #define MAX_TO_PING 8 |
42 | 43 | ||
43 | /* Ping newly announced nodes to ping per TIME_TO_PING seconds*/ | 44 | /* Ping newly announced nodes to ping per TIME_TO_PING seconds*/ |
44 | #define TIME_TO_PING 5 | 45 | #define TIME_TO_PING 8 |
45 | 46 | ||
46 | typedef struct { | ||
47 | IP_Port ip_port; | ||
48 | uint64_t id; | ||
49 | uint64_t timestamp; | ||
50 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; | ||
51 | } pinged_t; | ||
52 | 47 | ||
53 | struct PING { | 48 | struct PING { |
54 | DHT *dht; | 49 | DHT *dht; |
55 | 50 | ||
56 | pinged_t pings[PING_NUM_MAX]; | 51 | Ping_Array ping_array; |
57 | size_t num_pings; | ||
58 | size_t pos_pings; | ||
59 | |||
60 | Node_format to_ping[MAX_TO_PING]; | 52 | Node_format to_ping[MAX_TO_PING]; |
61 | uint64_t last_to_ping; | 53 | uint64_t last_to_ping; |
62 | }; | 54 | }; |
63 | 55 | ||
64 | static int is_ping_timeout(uint64_t time) | ||
65 | { | ||
66 | return is_timeout(time, PING_TIMEOUT); | ||
67 | } | ||
68 | |||
69 | static void remove_timeouts(PING *ping) // O(n) | ||
70 | { | ||
71 | size_t i, id; | ||
72 | size_t new_pos = ping->pos_pings; | ||
73 | size_t new_num = ping->num_pings; | ||
74 | |||
75 | // Loop through buffer, oldest first. | ||
76 | for (i = 0; i < ping->num_pings; i++) { | ||
77 | id = (ping->pos_pings + i) % PING_NUM_MAX; | ||
78 | |||
79 | if (is_ping_timeout(ping->pings[id].timestamp)) { | ||
80 | new_pos++; | ||
81 | new_num--; | ||
82 | } | ||
83 | // Break here because list is sorted. | ||
84 | else { | ||
85 | break; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | ping->num_pings = new_num; | ||
90 | ping->pos_pings = new_pos % PING_NUM_MAX; | ||
91 | } | ||
92 | |||
93 | static uint64_t add_ping(PING *ping, IP_Port ipp, uint8_t *shared_encryption_key) // O(n) | ||
94 | { | ||
95 | size_t p; | ||
96 | |||
97 | remove_timeouts(ping); | ||
98 | |||
99 | /* Remove oldest ping if full buffer. */ | ||
100 | if (ping->num_pings == PING_NUM_MAX) { | ||
101 | ping->num_pings--; | ||
102 | ping->pos_pings = (ping->pos_pings + 1) % PING_NUM_MAX; | ||
103 | } | ||
104 | |||
105 | /* Insert new ping at end of list. */ | ||
106 | p = (ping->pos_pings + ping->num_pings) % PING_NUM_MAX; | ||
107 | |||
108 | ping->pings[p].ip_port = ipp; | ||
109 | ping->pings[p].timestamp = unix_time(); | ||
110 | ping->pings[p].id = random_64b(); | ||
111 | memcpy(ping->pings[p].shared_key, shared_encryption_key, crypto_box_BEFORENMBYTES); | ||
112 | |||
113 | ping->num_pings++; | ||
114 | return ping->pings[p].id; | ||
115 | } | ||
116 | |||
117 | /* checks if ip/port or ping_id are already in the list to ping | ||
118 | * if both are set, both must match, otherwise the set must match | ||
119 | * | ||
120 | * returns 0 if neither is set or no match was found | ||
121 | * returns the (index + 1) of the match if one was found | ||
122 | */ | ||
123 | static int is_pinging(PING *ping, IP_Port ipp, uint64_t ping_id) | ||
124 | { | ||
125 | // O(n) TODO: Replace this with something else. | ||
126 | |||
127 | /* at least one MUST be set */ | ||
128 | uint8_t ip_valid = ip_isset(&ipp.ip); | ||
129 | |||
130 | if (!ip_valid && !ping_id) | ||
131 | return 0; | ||
132 | |||
133 | size_t i; | ||
134 | |||
135 | remove_timeouts(ping); | ||
136 | |||
137 | for (i = 0; i < ping->num_pings; i++) { | ||
138 | size_t id = (ping->pos_pings + i) % PING_NUM_MAX; | ||
139 | 56 | ||
140 | if (!ping_id || (ping->pings[id].id == ping_id)) | 57 | #define PING_PLAIN_SIZE (1 + sizeof(uint64_t)) |
141 | if (!ip_valid || ipport_equal(&ping->pings[id].ip_port, &ipp)) | 58 | #define DHT_PING_SIZE (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + PING_PLAIN_SIZE + crypto_box_MACBYTES) |
142 | return id + 1; | 59 | #define PING_DATA_SIZE (CLIENT_ID_SIZE + sizeof(IP_Port)) |
143 | } | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | #define DHT_PING_SIZE (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(uint64_t) + crypto_box_MACBYTES) | ||
149 | 60 | ||
150 | int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) | 61 | int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) |
151 | { | 62 | { |
@@ -153,7 +64,7 @@ int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) | |||
153 | int rc; | 64 | int rc; |
154 | uint64_t ping_id; | 65 | uint64_t ping_id; |
155 | 66 | ||
156 | if (is_pinging(ping, ipp, 0) || id_equal(client_id, ping->dht->self_public_key)) | 67 | if (id_equal(client_id, ping->dht->self_public_key)) |
157 | return 1; | 68 | return 1; |
158 | 69 | ||
159 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; | 70 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; |
@@ -161,19 +72,29 @@ int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) | |||
161 | // generate key to encrypt ping_id with recipient privkey | 72 | // generate key to encrypt ping_id with recipient privkey |
162 | DHT_get_shared_key_sent(ping->dht, shared_key, client_id); | 73 | DHT_get_shared_key_sent(ping->dht, shared_key, client_id); |
163 | // Generate random ping_id. | 74 | // Generate random ping_id. |
164 | ping_id = add_ping(ping, ipp, shared_key); | 75 | uint8_t data[PING_DATA_SIZE]; |
76 | id_copy(data, client_id); | ||
77 | memcpy(data + CLIENT_ID_SIZE, &ipp, sizeof(IP_Port)); | ||
78 | ping_id = ping_array_add(&ping->ping_array, data, sizeof(data)); | ||
79 | |||
80 | if (ping_id == 0) | ||
81 | return 1; | ||
82 | |||
83 | uint8_t ping_plain[PING_PLAIN_SIZE]; | ||
84 | ping_plain[0] = NET_PACKET_PING_REQUEST; | ||
85 | memcpy(ping_plain + 1, &ping_id, sizeof(ping_id)); | ||
165 | 86 | ||
166 | pk[0] = NET_PACKET_PING_REQUEST; | 87 | pk[0] = NET_PACKET_PING_REQUEST; |
167 | id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey | 88 | id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey |
168 | new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce | 89 | new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce |
169 | 90 | ||
170 | 91 | ||
171 | rc = encrypt_data_fast(shared_key, | 92 | rc = encrypt_data_symmetric(shared_key, |
172 | pk + 1 + CLIENT_ID_SIZE, | 93 | pk + 1 + CLIENT_ID_SIZE, |
173 | (uint8_t *) &ping_id, sizeof(ping_id), | 94 | ping_plain, sizeof(ping_plain), |
174 | pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES); | 95 | pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES); |
175 | 96 | ||
176 | if (rc != sizeof(ping_id) + crypto_box_MACBYTES) | 97 | if (rc != PING_PLAIN_SIZE + crypto_box_MACBYTES) |
177 | return 1; | 98 | return 1; |
178 | 99 | ||
179 | return sendpacket(ping->dht->net, ipp, pk, sizeof(pk)); | 100 | return sendpacket(ping->dht->net, ipp, pk, sizeof(pk)); |
@@ -188,17 +109,21 @@ static int send_ping_response(PING *ping, IP_Port ipp, uint8_t *client_id, uint6 | |||
188 | if (id_equal(client_id, ping->dht->self_public_key)) | 109 | if (id_equal(client_id, ping->dht->self_public_key)) |
189 | return 1; | 110 | return 1; |
190 | 111 | ||
112 | uint8_t ping_plain[PING_PLAIN_SIZE]; | ||
113 | ping_plain[0] = NET_PACKET_PING_RESPONSE; | ||
114 | memcpy(ping_plain + 1, &ping_id, sizeof(ping_id)); | ||
115 | |||
191 | pk[0] = NET_PACKET_PING_RESPONSE; | 116 | pk[0] = NET_PACKET_PING_RESPONSE; |
192 | id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey | 117 | id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey |
193 | new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce | 118 | new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce |
194 | 119 | ||
195 | // Encrypt ping_id using recipient privkey | 120 | // Encrypt ping_id using recipient privkey |
196 | rc = encrypt_data_fast(shared_encryption_key, | 121 | rc = encrypt_data_symmetric(shared_encryption_key, |
197 | pk + 1 + CLIENT_ID_SIZE, | 122 | pk + 1 + CLIENT_ID_SIZE, |
198 | (uint8_t *) &ping_id, sizeof(ping_id), | 123 | ping_plain, sizeof(ping_plain), |
199 | pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES ); | 124 | pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES ); |
200 | 125 | ||
201 | if (rc != sizeof(ping_id) + crypto_box_MACBYTES) | 126 | if (rc != PING_PLAIN_SIZE + crypto_box_MACBYTES) |
202 | return 1; | 127 | return 1; |
203 | 128 | ||
204 | return sendpacket(ping->dht->net, ipp, pk, sizeof(pk)); | 129 | return sendpacket(ping->dht->net, ipp, pk, sizeof(pk)); |
@@ -208,7 +133,6 @@ static int handle_ping_request(void *_dht, IP_Port source, uint8_t *packet, uint | |||
208 | { | 133 | { |
209 | DHT *dht = _dht; | 134 | DHT *dht = _dht; |
210 | int rc; | 135 | int rc; |
211 | uint64_t ping_id; | ||
212 | 136 | ||
213 | if (length != DHT_PING_SIZE) | 137 | if (length != DHT_PING_SIZE) |
214 | return 1; | 138 | return 1; |
@@ -220,17 +144,23 @@ static int handle_ping_request(void *_dht, IP_Port source, uint8_t *packet, uint | |||
220 | 144 | ||
221 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; | 145 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; |
222 | 146 | ||
147 | uint8_t ping_plain[PING_PLAIN_SIZE]; | ||
223 | // Decrypt ping_id | 148 | // Decrypt ping_id |
224 | DHT_get_shared_key_recv(dht, shared_key, packet + 1); | 149 | DHT_get_shared_key_recv(dht, shared_key, packet + 1); |
225 | rc = decrypt_data_fast(shared_key, | 150 | rc = decrypt_data_symmetric(shared_key, |
226 | packet + 1 + CLIENT_ID_SIZE, | 151 | packet + 1 + CLIENT_ID_SIZE, |
227 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, | 152 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, |
228 | sizeof(ping_id) + crypto_box_MACBYTES, | 153 | PING_PLAIN_SIZE + crypto_box_MACBYTES, |
229 | (uint8_t *) &ping_id ); | 154 | ping_plain ); |
155 | |||
156 | if (rc != sizeof(ping_plain)) | ||
157 | return 1; | ||
230 | 158 | ||
231 | if (rc != sizeof(ping_id)) | 159 | if (ping_plain[0] != NET_PACKET_PING_REQUEST) |
232 | return 1; | 160 | return 1; |
233 | 161 | ||
162 | uint64_t ping_id; | ||
163 | memcpy(&ping_id, ping_plain + 1, sizeof(ping_id)); | ||
234 | // Send response | 164 | // Send response |
235 | send_ping_response(ping, source, packet + 1, ping_id, shared_key); | 165 | send_ping_response(ping, source, packet + 1, ping_id, shared_key); |
236 | add_to_ping(ping, packet + 1, source); | 166 | add_to_ping(ping, packet + 1, source); |
@@ -242,7 +172,6 @@ static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uin | |||
242 | { | 172 | { |
243 | DHT *dht = _dht; | 173 | DHT *dht = _dht; |
244 | int rc; | 174 | int rc; |
245 | uint64_t ping_id; | ||
246 | 175 | ||
247 | if (length != DHT_PING_SIZE) | 176 | if (length != DHT_PING_SIZE) |
248 | return 1; | 177 | return 1; |
@@ -252,30 +181,71 @@ static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uin | |||
252 | if (id_equal(packet + 1, ping->dht->self_public_key)) | 181 | if (id_equal(packet + 1, ping->dht->self_public_key)) |
253 | return 1; | 182 | return 1; |
254 | 183 | ||
255 | int ping_index = is_pinging(ping, source, 0); | 184 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; |
256 | 185 | ||
257 | if (!ping_index) | 186 | // generate key to encrypt ping_id with recipient privkey |
258 | return 1; | 187 | DHT_get_shared_key_sent(ping->dht, shared_key, packet + 1); |
259 | 188 | ||
260 | --ping_index; | 189 | uint8_t ping_plain[PING_PLAIN_SIZE]; |
261 | // Decrypt ping_id | 190 | // Decrypt ping_id |
262 | rc = decrypt_data_fast(ping->pings[ping_index].shared_key, | 191 | rc = decrypt_data_symmetric(shared_key, |
263 | packet + 1 + CLIENT_ID_SIZE, | 192 | packet + 1 + CLIENT_ID_SIZE, |
264 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, | 193 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, |
265 | sizeof(ping_id) + crypto_box_MACBYTES, | 194 | PING_PLAIN_SIZE + crypto_box_MACBYTES, |
266 | (uint8_t *) &ping_id); | 195 | ping_plain); |
267 | 196 | ||
268 | if (rc != sizeof(ping_id)) | 197 | if (rc != sizeof(ping_plain)) |
269 | return 1; | 198 | return 1; |
270 | 199 | ||
271 | if (ping->pings[ping_index].id != ping_id) | 200 | if (ping_plain[0] != NET_PACKET_PING_RESPONSE) |
272 | return 1; | 201 | return 1; |
273 | 202 | ||
274 | addto_lists(dht, source, packet + 1); | 203 | uint64_t ping_id; |
204 | memcpy(&ping_id, ping_plain + 1, sizeof(ping_id)); | ||
205 | uint8_t data[PING_DATA_SIZE]; | ||
275 | 206 | ||
207 | if (ping_array_check(data, sizeof(data), &ping->ping_array, ping_id) != sizeof(data)) | ||
208 | return 1; | ||
209 | |||
210 | if (!id_equal(packet + 1, data)) | ||
211 | return 1; | ||
212 | |||
213 | IP_Port ipp; | ||
214 | memcpy(&ipp, data + CLIENT_ID_SIZE, sizeof(IP_Port)); | ||
215 | |||
216 | if (!ipport_equal(&ipp, &source)) | ||
217 | return 1; | ||
218 | |||
219 | addto_lists(dht, source, packet + 1); | ||
276 | return 0; | 220 | return 0; |
277 | } | 221 | } |
278 | 222 | ||
223 | /* Check if client_id with ip_port is in the list. | ||
224 | * | ||
225 | * return 1 if it is. | ||
226 | * return 0 if it isn't. | ||
227 | */ | ||
228 | static int in_list(Client_data *list, uint32_t length, uint8_t *client_id, IP_Port ip_port) | ||
229 | { | ||
230 | uint32_t i; | ||
231 | |||
232 | for (i = 0; i < length; ++i) { | ||
233 | if (id_equal(list[i].client_id, client_id)) { | ||
234 | IPPTsPng *ipptp; | ||
235 | |||
236 | if (ip_port.ip.family == AF_INET) { | ||
237 | ipptp = &list[i].assoc4; | ||
238 | } else { | ||
239 | ipptp = &list[i].assoc6; | ||
240 | } | ||
241 | |||
242 | if (!is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT) && ipport_equal(&ipptp->ip_port, &ip_port)) | ||
243 | return 1; | ||
244 | } | ||
245 | } | ||
246 | |||
247 | return 0; | ||
248 | } | ||
279 | 249 | ||
280 | /* Add nodes to the to_ping list. | 250 | /* Add nodes to the to_ping list. |
281 | * All nodes in this list are pinged every TIME_TO_PING seconds | 251 | * All nodes in this list are pinged every TIME_TO_PING seconds |
@@ -292,6 +262,9 @@ int add_to_ping(PING *ping, uint8_t *client_id, IP_Port ip_port) | |||
292 | if (!ip_isset(&ip_port.ip)) | 262 | if (!ip_isset(&ip_port.ip)) |
293 | return -1; | 263 | return -1; |
294 | 264 | ||
265 | if (in_list(ping->dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) | ||
266 | return -1; | ||
267 | |||
295 | uint32_t i; | 268 | uint32_t i; |
296 | 269 | ||
297 | for (i = 0; i < MAX_TO_PING; ++i) { | 270 | for (i = 0; i < MAX_TO_PING; ++i) { |
@@ -300,12 +273,18 @@ int add_to_ping(PING *ping, uint8_t *client_id, IP_Port ip_port) | |||
300 | ipport_copy(&ping->to_ping[i].ip_port, &ip_port); | 273 | ipport_copy(&ping->to_ping[i].ip_port, &ip_port); |
301 | return 0; | 274 | return 0; |
302 | } | 275 | } |
276 | |||
277 | if (memcmp(ping->to_ping[i].client_id, client_id, CLIENT_ID_SIZE) == 0) { | ||
278 | return -1; | ||
279 | } | ||
303 | } | 280 | } |
304 | 281 | ||
282 | uint32_t r = rand(); | ||
283 | |||
305 | for (i = 0; i < MAX_TO_PING; ++i) { | 284 | for (i = 0; i < MAX_TO_PING; ++i) { |
306 | if (id_closest(ping->dht->self_public_key, ping->to_ping[i].client_id, client_id) == 2) { | 285 | if (id_closest(ping->dht->self_public_key, ping->to_ping[(i + r) % MAX_TO_PING].client_id, client_id) == 2) { |
307 | memcpy(ping->to_ping[i].client_id, client_id, CLIENT_ID_SIZE); | 286 | memcpy(ping->to_ping[(i + r) % MAX_TO_PING].client_id, client_id, CLIENT_ID_SIZE); |
308 | ipport_copy(&ping->to_ping[i].ip_port, &ip_port); | 287 | ipport_copy(&ping->to_ping[(i + r) % MAX_TO_PING].ip_port, &ip_port); |
309 | return 0; | 288 | return 0; |
310 | } | 289 | } |
311 | } | 290 | } |
@@ -342,6 +321,11 @@ PING *new_ping(DHT *dht) | |||
342 | if (ping == NULL) | 321 | if (ping == NULL) |
343 | return NULL; | 322 | return NULL; |
344 | 323 | ||
324 | if (ping_array_init(&ping->ping_array, PING_NUM_MAX, PING_TIMEOUT) != 0) { | ||
325 | free(ping); | ||
326 | return NULL; | ||
327 | } | ||
328 | |||
345 | ping->dht = dht; | 329 | ping->dht = dht; |
346 | networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, &handle_ping_request, dht); | 330 | networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, &handle_ping_request, dht); |
347 | networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, dht); | 331 | networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, dht); |
@@ -353,6 +337,7 @@ void kill_ping(PING *ping) | |||
353 | { | 337 | { |
354 | networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, NULL, NULL); | 338 | networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, NULL, NULL); |
355 | networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, NULL, NULL); | 339 | networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, NULL, NULL); |
340 | ping_array_free_all(&ping->ping_array); | ||
356 | 341 | ||
357 | free(ping); | 342 | free(ping); |
358 | } | 343 | } |
diff --git a/toxcore/ping_array.c b/toxcore/ping_array.c new file mode 100644 index 00000000..e6f684ef --- /dev/null +++ b/toxcore/ping_array.c | |||
@@ -0,0 +1,162 @@ | |||
1 | /* ping_array.c | ||
2 | * | ||
3 | * Implementation of an efficient array to store that we pinged something. | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2014 Tox project All Rights Reserved. | ||
7 | * | ||
8 | * This file is part of Tox. | ||
9 | * | ||
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 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with Tox. If not, see <http://www.gnu.org/licenses/>. | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifdef HAVE_CONFIG_H | ||
26 | #include "config.h" | ||
27 | #endif | ||
28 | |||
29 | #include "ping_array.h" | ||
30 | #include "crypto_core.h" | ||
31 | #include "util.h" | ||
32 | |||
33 | static void clear_entry(Ping_Array *array, uint32_t index) | ||
34 | { | ||
35 | free(array->entries[index].data); | ||
36 | array->entries[index].data = NULL; | ||
37 | array->entries[index].length = | ||
38 | array->entries[index].time = | ||
39 | array->entries[index].ping_id = 0; | ||
40 | } | ||
41 | |||
42 | /* Clear timed out entries. | ||
43 | */ | ||
44 | static void ping_array_clear_timedout(Ping_Array *array) | ||
45 | { | ||
46 | while (array->last_deleted != array->last_added) { | ||
47 | uint32_t index = array->last_deleted % array->total_size; | ||
48 | |||
49 | if (!is_timeout(array->entries[index].time, array->timeout)) | ||
50 | break; | ||
51 | |||
52 | clear_entry(array, index); | ||
53 | ++array->last_deleted; | ||
54 | } | ||
55 | } | ||
56 | |||
57 | /* Add a data with length to the Ping_Array list and return a ping_id. | ||
58 | * | ||
59 | * return ping_id on success. | ||
60 | * return 0 on failure. | ||
61 | */ | ||
62 | uint64_t ping_array_add(Ping_Array *array, uint8_t *data, uint32_t length) | ||
63 | { | ||
64 | ping_array_clear_timedout(array); | ||
65 | uint32_t index = array->last_added % array->total_size; | ||
66 | |||
67 | if (array->entries[index].data != NULL) { | ||
68 | array->last_deleted = array->last_added - array->total_size; | ||
69 | clear_entry(array, index); | ||
70 | } | ||
71 | |||
72 | array->entries[index].data = malloc(length); | ||
73 | |||
74 | if (array->entries[index].data == NULL) | ||
75 | return 0; | ||
76 | |||
77 | memcpy(array->entries[index].data, data, length); | ||
78 | array->entries[index].length = length; | ||
79 | array->entries[index].time = unix_time(); | ||
80 | ++array->last_added; | ||
81 | uint64_t ping_id = random_64b(); | ||
82 | ping_id /= array->total_size; | ||
83 | ping_id *= array->total_size; | ||
84 | ping_id += index; | ||
85 | |||
86 | if (ping_id == 0) | ||
87 | ping_id += array->total_size; | ||
88 | |||
89 | array->entries[index].ping_id = ping_id; | ||
90 | return ping_id; | ||
91 | } | ||
92 | |||
93 | |||
94 | /* Check if ping_id is valid and not timed out. | ||
95 | * | ||
96 | * On success, copies the data into data of length, | ||
97 | * | ||
98 | * return length of data copied on success. | ||
99 | * return -1 on failure. | ||
100 | */ | ||
101 | int ping_array_check(uint8_t *data, uint32_t length, Ping_Array *array, uint64_t ping_id) | ||
102 | { | ||
103 | if (ping_id == 0) | ||
104 | return -1; | ||
105 | |||
106 | uint32_t index = ping_id % array->total_size; | ||
107 | |||
108 | if (array->entries[index].ping_id != ping_id) | ||
109 | return -1; | ||
110 | |||
111 | if (is_timeout(array->entries[index].time, array->timeout)) | ||
112 | return -1; | ||
113 | |||
114 | if (array->entries[index].length > length) | ||
115 | return -1; | ||
116 | |||
117 | if (array->entries[index].data == NULL) | ||
118 | return -1; | ||
119 | |||
120 | memcpy(data, array->entries[index].data, array->entries[index].length); | ||
121 | uint32_t len = array->entries[index].length; | ||
122 | clear_entry(array, index); | ||
123 | return len; | ||
124 | } | ||
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), 1); | ||
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 new file mode 100644 index 00000000..c5811b16 --- /dev/null +++ b/toxcore/ping_array.h | |||
@@ -0,0 +1,75 @@ | |||
1 | /* ping_array.h | ||
2 | * | ||
3 | * Implementation of an efficient array to store that we pinged something. | ||
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 | #ifndef PING_ARRAY_H | ||
24 | #define PING_ARRAY_H | ||
25 | |||
26 | #include "network.h" | ||
27 | |||
28 | typedef struct { | ||
29 | void *data; | ||
30 | uint32_t length; | ||
31 | uint64_t time; | ||
32 | uint64_t ping_id; | ||
33 | } Ping_Array_Entry; | ||
34 | |||
35 | |||
36 | typedef struct { | ||
37 | Ping_Array_Entry *entries; | ||
38 | |||
39 | uint32_t last_deleted; /* number representing the next entry to be deleted. */ | ||
40 | uint32_t last_added; /* number representing the last entry to be added. */ | ||
41 | uint32_t total_size; /* The length of entries */ | ||
42 | uint32_t timeout; /* The timeout after which entries are cleared. */ | ||
43 | } Ping_Array; | ||
44 | |||
45 | |||
46 | /* Add a data with length to the Ping_Array list and return a ping_id. | ||
47 | * | ||
48 | * return ping_id on success. | ||
49 | * return 0 on failure. | ||
50 | */ | ||
51 | uint64_t ping_array_add(Ping_Array *array, uint8_t *data, uint32_t length); | ||
52 | |||
53 | /* Check if ping_id is valid and not timed out. | ||
54 | * | ||
55 | * On success, copies the data into data of length, | ||
56 | * | ||
57 | * return length of data copied on success. | ||
58 | * return -1 on failure. | ||
59 | */ | ||
60 | int ping_array_check(uint8_t *data, uint32_t length, Ping_Array *array, 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 | |||
75 | #endif | ||
diff --git a/toxcore/tox.c b/toxcore/tox.c index 9b99174c..884223ff 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c | |||
@@ -187,7 +187,7 @@ int tox_set_name(Tox *tox, uint8_t *name, uint16_t length) | |||
187 | } | 187 | } |
188 | 188 | ||
189 | /* Get your nickname. | 189 | /* Get your nickname. |
190 | * m - The messanger context to use. | 190 | * m - The messenger context to use. |
191 | * name - Pointer to a string for the name. (must be at least MAX_NAME_LENGTH) | 191 | * name - Pointer to a string for the name. (must be at least MAX_NAME_LENGTH) |
192 | * | 192 | * |
193 | * return length of the name. | 193 | * return length of the name. |
@@ -722,7 +722,7 @@ int tox_file_send_data(Tox *tox, int32_t friendnumber, uint8_t filenumber, uint8 | |||
722 | */ | 722 | */ |
723 | int tox_file_data_size(Tox *tox, int32_t friendnumber) | 723 | int tox_file_data_size(Tox *tox, int32_t friendnumber) |
724 | { | 724 | { |
725 | return MAX_DATA_SIZE - crypto_box_MACBYTES - 3; | 725 | return MAX_CRYPTO_DATA_SIZE - 2; |
726 | } | 726 | } |
727 | 727 | ||
728 | /* Give the number of bytes left to be sent/received. | 728 | /* Give the number of bytes left to be sent/received. |
@@ -740,23 +740,38 @@ uint64_t tox_file_data_remaining(Tox *tox, int32_t friendnumber, uint8_t filenum | |||
740 | 740 | ||
741 | /***************END OF FILE SENDING FUNCTIONS******************/ | 741 | /***************END OF FILE SENDING FUNCTIONS******************/ |
742 | 742 | ||
743 | /* Use these functions to bootstrap the client. | 743 | /* TODO: expose this properly. */ |
744 | * Sends a get nodes request to the given node with ip port and public_key. | 744 | static int tox_add_tcp_relay(Tox *tox, const char *address, uint8_t ipv6enabled, uint16_t port, uint8_t *public_key) |
745 | */ | ||
746 | void tox_bootstrap_from_ip(Tox *tox, tox_IP_Port _ip_port, uint8_t *public_key) | ||
747 | { | 745 | { |
748 | Messenger *m = tox; | 746 | Messenger *m = tox; |
749 | IP_Port ip_port; | 747 | IP_Port ip_port_v64; |
750 | memcpy(&ip_port, &_ip_port, sizeof(IP_Port)); | 748 | IP *ip_extra = NULL; |
751 | DHT_bootstrap(m->dht, ip_port, public_key); | 749 | IP_Port ip_port_v4; |
750 | ip_init(&ip_port_v64.ip, ipv6enabled); | ||
751 | |||
752 | if (ipv6enabled) { | ||
753 | /* setup for getting BOTH: an IPv6 AND an IPv4 address */ | ||
754 | ip_port_v64.ip.family = AF_UNSPEC; | ||
755 | ip_reset(&ip_port_v4.ip); | ||
756 | ip_extra = &ip_port_v4.ip; | ||
757 | } | ||
758 | |||
759 | if (addr_resolve_or_parse_ip(address, &ip_port_v64.ip, ip_extra)) { | ||
760 | ip_port_v64.port = port; | ||
761 | add_tcp_relay(m->net_crypto, ip_port_v64, public_key); | ||
762 | return 1; | ||
763 | } else { | ||
764 | return 0; | ||
765 | } | ||
752 | } | 766 | } |
753 | 767 | ||
754 | int tox_bootstrap_from_address(Tox *tox, const char *address, | 768 | int tox_bootstrap_from_address(Tox *tox, const char *address, |
755 | uint8_t ipv6enabled, uint16_t port, uint8_t *public_key) | 769 | uint8_t ipv6enabled, uint16_t port, uint8_t *public_key) |
756 | { | 770 | { |
757 | Messenger *m = tox; | 771 | Messenger *m = tox; |
772 | tox_add_tcp_relay(tox, address, ipv6enabled, port, public_key); | ||
758 | return DHT_bootstrap_from_address(m->dht, address, ipv6enabled, port, public_key); | 773 | return DHT_bootstrap_from_address(m->dht, address, ipv6enabled, port, public_key); |
759 | }; | 774 | } |
760 | 775 | ||
761 | /* return 0 if we are not connected to the DHT. | 776 | /* return 0 if we are not connected to the DHT. |
762 | * return 1 if we are. | 777 | * return 1 if we are. |
@@ -842,33 +857,3 @@ int tox_load(Tox *tox, uint8_t *data, uint32_t length) | |||
842 | Messenger *m = tox; | 857 | Messenger *m = tox; |
843 | return messenger_load(m, data, length); | 858 | return messenger_load(m, data, length); |
844 | } | 859 | } |
845 | |||
846 | /* return the size of data to pass to messenger_save_encrypted(...) | ||
847 | */ | ||
848 | uint32_t tox_size_encrypted(Tox *tox) | ||
849 | { | ||
850 | Messenger *m = tox; | ||
851 | return messenger_size_encrypted(m); | ||
852 | } | ||
853 | |||
854 | /* Save the messenger, encrypting the data with key of length key_length | ||
855 | * | ||
856 | * return 0 on success. | ||
857 | * return -1 on failure. | ||
858 | */ | ||
859 | int tox_save_encrypted(Tox *tox, uint8_t *data, uint8_t *key, uint16_t key_length) | ||
860 | { | ||
861 | Messenger *m = tox; | ||
862 | return messenger_save_encrypted(m, data, key, key_length); | ||
863 | } | ||
864 | |||
865 | /* Load the messenger from data of size length encrypted with key of key_length. | ||
866 | * | ||
867 | * return 0 on success. | ||
868 | * return -1 on failure. | ||
869 | */ | ||
870 | int tox_load_encrypted(Tox *tox, uint8_t *data, uint32_t length, uint8_t *key, uint16_t key_length) | ||
871 | { | ||
872 | Messenger *m = tox; | ||
873 | return messenger_load_encrypted(m, data, length, key, key_length); | ||
874 | } | ||
diff --git a/toxcore/tox.h b/toxcore/tox.h index d94c0e13..111b2634 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h | |||
@@ -210,7 +210,7 @@ int tox_set_name(Tox *tox, uint8_t *name, uint16_t length); | |||
210 | 210 | ||
211 | /* | 211 | /* |
212 | * Get your nickname. | 212 | * Get your nickname. |
213 | * m - The messanger context to use. | 213 | * m - The messenger context to use. |
214 | * name - needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes. | 214 | * name - needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes. |
215 | * | 215 | * |
216 | * return length of name. | 216 | * return length of name. |
@@ -515,11 +515,11 @@ uint32_t tox_get_chatlist(Tox *tox, int *out_list, uint32_t list_size); | |||
515 | * tox_file_data_remaining(...) can be used to know how many bytes are left to send/receive. | 515 | * tox_file_data_remaining(...) can be used to know how many bytes are left to send/receive. |
516 | * | 516 | * |
517 | * If the connection breaks during file sending (The other person goes offline without pausing the sending and then comes back) | 517 | * If the connection breaks during file sending (The other person goes offline without pausing the sending and then comes back) |
518 | * the reciever must send a control packet with receive_send == 0 message_id = TOX_FILECONTROL_RESUME_BROKEN and the data being | 518 | * the receiver must send a control packet with receive_send == 0 message_id = TOX_FILECONTROL_RESUME_BROKEN and the data being |
519 | * a uint64_t (in host byte order) containing the number of bytes recieved. | 519 | * a uint64_t (in host byte order) containing the number of bytes received. |
520 | * | 520 | * |
521 | * If the sender recieves this packet, he must send a control packet with receive_send == 1 and control_type == TOX_FILECONTROL_ACCEPT | 521 | * If the sender receives this packet, he must send a control packet with receive_send == 1 and control_type == TOX_FILECONTROL_ACCEPT |
522 | * then he must start sending file data from the position (data , uint64_t in host byte order) recieved in the TOX_FILECONTROL_RESUME_BROKEN packet. | 522 | * then he must start sending file data from the position (data , uint64_t in host byte order) received in the TOX_FILECONTROL_RESUME_BROKEN packet. |
523 | * | 523 | * |
524 | * More to come... | 524 | * More to come... |
525 | */ | 525 | */ |
@@ -601,43 +601,6 @@ uint64_t tox_file_data_remaining(Tox *tox, int32_t friendnumber, uint8_t filenum | |||
601 | 601 | ||
602 | /***************END OF FILE SENDING FUNCTIONS******************/ | 602 | /***************END OF FILE SENDING FUNCTIONS******************/ |
603 | 603 | ||
604 | /* WARNING: DEPRECATED, DO NOT USE. */ | ||
605 | typedef union { | ||
606 | uint8_t c[4]; | ||
607 | uint16_t s[2]; | ||
608 | uint32_t i; | ||
609 | } tox_IP4; | ||
610 | |||
611 | typedef union { | ||
612 | uint8_t uint8[16]; | ||
613 | uint16_t uint16[8]; | ||
614 | uint32_t uint32[4]; | ||
615 | struct in6_addr in6_addr; | ||
616 | } tox_IP6; | ||
617 | |||
618 | typedef struct { | ||
619 | uint8_t family; | ||
620 | /* Not used for anything right now. */ | ||
621 | uint8_t padding[3]; | ||
622 | union { | ||
623 | tox_IP4 ip4; | ||
624 | tox_IP6 ip6; | ||
625 | }; | ||
626 | } tox_IP; | ||
627 | |||
628 | /* will replace IP_Port as soon as the complete infrastructure is in place | ||
629 | * removed the unused union and padding also */ | ||
630 | typedef struct { | ||
631 | tox_IP ip; | ||
632 | uint16_t port; | ||
633 | } tox_IP_Port; | ||
634 | /* WARNING: DEPRECATED, DO NOT USE. */ | ||
635 | /* Sends a "get nodes" request to the given node with ip, port and public_key | ||
636 | * to setup connections | ||
637 | */ | ||
638 | void tox_bootstrap_from_ip(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key); | ||
639 | |||
640 | |||
641 | /* | 604 | /* |
642 | * Use this function to bootstrap the client. | 605 | * Use this function to bootstrap the client. |
643 | */ | 606 | */ |
@@ -739,32 +702,6 @@ void tox_save(Tox *tox, uint8_t *data); | |||
739 | */ | 702 | */ |
740 | int tox_load(Tox *tox, uint8_t *data, uint32_t length); | 703 | int tox_load(Tox *tox, uint8_t *data, uint32_t length); |
741 | 704 | ||
742 | /**/ | ||
743 | |||
744 | /* return the size of data to pass to messenger_save_encrypted(...) | ||
745 | */ | ||
746 | uint32_t tox_size_encrypted(Tox *tox); | ||
747 | |||
748 | /* Save the messenger, encrypting the data with key of length key_length | ||
749 | * | ||
750 | * This functions simply calls and then encrypt the output of tox_save(..) | ||
751 | * with crypto_secretbox(...) from NaCl/libsodium with the key | ||
752 | * given to crypto_secretbox(...) being the SHA256 sum of the key | ||
753 | * passed to this function. | ||
754 | * | ||
755 | * return 0 on success. | ||
756 | * return -1 on failure. | ||
757 | */ | ||
758 | int tox_save_encrypted(Tox *tox, uint8_t *data, uint8_t *key, uint16_t key_length); | ||
759 | |||
760 | /* Load the messenger from data of size length encrypted with key of key_length. | ||
761 | * | ||
762 | * return 0 on success. | ||
763 | * return -1 on failure. | ||
764 | */ | ||
765 | int tox_load_encrypted(Tox *tox, uint8_t *data, uint32_t length, uint8_t *key, uint16_t key_length); | ||
766 | |||
767 | |||
768 | #ifdef __cplusplus | 705 | #ifdef __cplusplus |
769 | } | 706 | } |
770 | #endif | 707 | #endif |
diff --git a/toxcore/util.c b/toxcore/util.c index edc611ec..7a2db450 100644 --- a/toxcore/util.c +++ b/toxcore/util.c | |||
@@ -36,10 +36,14 @@ | |||
36 | 36 | ||
37 | /* don't call into system billions of times for no reason */ | 37 | /* don't call into system billions of times for no reason */ |
38 | static uint64_t unix_time_value; | 38 | static uint64_t unix_time_value; |
39 | static uint64_t unix_base_time_value; | ||
39 | 40 | ||
40 | void unix_time_update() | 41 | void unix_time_update() |
41 | { | 42 | { |
42 | unix_time_value = (uint64_t)time(NULL); | 43 | if (unix_base_time_value == 0) |
44 | unix_base_time_value = ((uint64_t)time(NULL) - (current_time_monotonic() / 1000ULL)); | ||
45 | |||
46 | unix_time_value = (current_time_monotonic() / 1000ULL) + unix_base_time_value; | ||
43 | } | 47 | } |
44 | 48 | ||
45 | uint64_t unix_time() | 49 | uint64_t unix_time() |
@@ -49,7 +53,7 @@ uint64_t unix_time() | |||
49 | 53 | ||
50 | int is_timeout(uint64_t timestamp, uint64_t timeout) | 54 | int is_timeout(uint64_t timestamp, uint64_t timeout) |
51 | { | 55 | { |
52 | return timestamp + timeout <= unix_time_value; | 56 | return timestamp + timeout <= unix_time(); |
53 | } | 57 | } |
54 | 58 | ||
55 | 59 | ||
@@ -67,22 +71,17 @@ uint32_t id_copy(uint8_t *dest, uint8_t *src) | |||
67 | 71 | ||
68 | void host_to_net(uint8_t *num, uint16_t numbytes) | 72 | void host_to_net(uint8_t *num, uint16_t numbytes) |
69 | { | 73 | { |
70 | union { | 74 | #ifndef WORDS_BIGENDIAN |
71 | uint32_t i; | 75 | uint32_t i; |
72 | uint8_t c[4]; | 76 | uint8_t buff[numbytes]; |
73 | } a; | ||
74 | a.i = 1; | ||
75 | |||
76 | if (a.c[0] == 1) { | ||
77 | uint32_t i; | ||
78 | uint8_t buff[numbytes]; | ||
79 | |||
80 | for (i = 0; i < numbytes; ++i) { | ||
81 | buff[i] = num[numbytes - i - 1]; | ||
82 | } | ||
83 | 77 | ||
84 | memcpy(num, buff, numbytes); | 78 | for (i = 0; i < numbytes; ++i) { |
79 | buff[i] = num[numbytes - i - 1]; | ||
85 | } | 80 | } |
81 | |||
82 | memcpy(num, buff, numbytes); | ||
83 | #endif | ||
84 | return; | ||
86 | } | 85 | } |
87 | 86 | ||
88 | /* state load/save */ | 87 | /* state load/save */ |
@@ -99,11 +98,11 @@ int load_state(load_state_callback_func load_state_callback, void *outer, | |||
99 | 98 | ||
100 | uint16_t type; | 99 | uint16_t type; |
101 | uint32_t length_sub, cookie_type; | 100 | uint32_t length_sub, cookie_type; |
102 | uint32_t size32 = sizeof(uint32_t), size_head = size32 * 2; | 101 | uint32_t size_head = sizeof(uint32_t) * 2; |
103 | 102 | ||
104 | while (length >= size_head) { | 103 | while (length >= size_head) { |
105 | length_sub = *(uint32_t *)data; | 104 | memcpy(&length_sub, data, sizeof(length_sub)); |
106 | cookie_type = *(uint32_t *)(data + size32); | 105 | memcpy(&cookie_type, data + sizeof(length_sub), sizeof(cookie_type)); |
107 | data += size_head; | 106 | data += size_head; |
108 | length -= size_head; | 107 | length -= size_head; |
109 | 108 | ||