diff options
-rw-r--r-- | testing/Lossless_UDP_testclient.c | 260 | ||||
-rw-r--r-- | testing/Lossless_UDP_testserver.c | 237 | ||||
-rw-r--r-- | testing/Makefile.inc | 36 | ||||
-rw-r--r-- | toxcore/Lossless_UDP.c | 1168 | ||||
-rw-r--r-- | toxcore/Lossless_UDP.h | 262 | ||||
-rw-r--r-- | toxcore/Makefile.inc | 2 | ||||
-rw-r--r-- | toxcore/Messenger.c | 70 | ||||
-rw-r--r-- | toxcore/Messenger.h | 1 | ||||
-rw-r--r-- | toxcore/net_crypto.c | 381 | ||||
-rw-r--r-- | toxcore/net_crypto.h | 41 | ||||
-rw-r--r-- | toxcore/tox.c | 2 |
11 files changed, 60 insertions, 2400 deletions
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/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 587cd9ff..00000000 --- a/toxcore/Lossless_UDP.h +++ /dev/null | |||
@@ -1,262 +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 "crypto_core.h" | ||
29 | #include "misc_tools.h" | ||
30 | |||
31 | |||
32 | /* Maximum length of the data in the data packets. */ | ||
33 | #define MAX_DATA_SIZE 1024 | ||
34 | |||
35 | /* Maximum data packets in sent and receive queues. */ | ||
36 | #define MAX_QUEUE_NUM 1024 | ||
37 | #define DEFAULT_QUEUE_NUM 4 | ||
38 | |||
39 | /* Maximum number of data packets in the buffer. */ | ||
40 | #define MAX_REQUESTED_PACKETS 256 | ||
41 | |||
42 | /* Timeout per connection is randomly set between CONNECTION_TIMEOUT and 2*CONNECTION_TIMEOUT. */ | ||
43 | #define CONNECTION_TIMEOUT 5 | ||
44 | |||
45 | /* Initial amount of sync/handshake packets to send per second. */ | ||
46 | #define SYNC_RATE 2 | ||
47 | |||
48 | /* Initial send rate of data. */ | ||
49 | #define DATA_SYNC_RATE 30 | ||
50 | |||
51 | typedef struct { | ||
52 | uint8_t data[MAX_DATA_SIZE]; | ||
53 | uint16_t size; | ||
54 | } Data; | ||
55 | |||
56 | #define LUDP_NO_CONNECTION 0 | ||
57 | #define LUDP_HANDSHAKE_SENDING 1 | ||
58 | #define LUDP_NOT_CONFIRMED 2 | ||
59 | #define LUDP_ESTABLISHED 3 | ||
60 | #define LUDP_TIMED_OUT 4 | ||
61 | |||
62 | typedef struct { | ||
63 | IP_Port ip_port; | ||
64 | |||
65 | /* | ||
66 | * return LUDP_NO_CONNECTION if connection is dead. | ||
67 | * return LUDP_HANDSHAKE_SENDING if attempting handshake. | ||
68 | * return LUDP_NOT_CONFIRMED if handshake is done (we start sending SYNC packets). | ||
69 | * return LUDP_ESTABLISHED if we are sending SYNC packets and can send data. | ||
70 | * return LUDP_TIMED_OUT if the connection has timed out. | ||
71 | */ | ||
72 | uint8_t status; | ||
73 | |||
74 | /* | ||
75 | * return 0 if connection was not initiated by someone else. | ||
76 | * return 1 if incoming_connection() has returned. | ||
77 | * return 2 if it has not. | ||
78 | */ | ||
79 | uint8_t inbound; | ||
80 | |||
81 | uint16_t SYNC_rate; /* Current SYNC packet send rate packets per second. */ | ||
82 | uint32_t data_rate; /* Current data packet send rate packets per second. */ | ||
83 | |||
84 | uint64_t last_SYNC; /* Time our last SYNC packet was sent. */ | ||
85 | uint64_t last_sent; /* Time our last data or handshake packet was sent. */ | ||
86 | uint64_t last_recvSYNC; /* Time we last received a SYNC packet from the other. */ | ||
87 | uint64_t last_recvdata; /* Time we last received a DATA packet from the other. */ | ||
88 | uint64_t killat; /* Time to kill the connection. */ | ||
89 | |||
90 | Data *sendbuffer; /* packet send buffer. */ | ||
91 | uint32_t sendbuffer_length; | ||
92 | Data *recvbuffer; /* packet receive buffer. */ | ||
93 | uint32_t recvbuffer_length; | ||
94 | uint32_t handshake_id1; | ||
95 | uint32_t handshake_id2; | ||
96 | |||
97 | /* Number of data packets received (also used as handshake_id1). */ | ||
98 | uint32_t recv_packetnum; | ||
99 | |||
100 | /* Number of packets received by the other peer. */ | ||
101 | uint32_t orecv_packetnum; | ||
102 | |||
103 | /* Number of data packets sent. */ | ||
104 | uint32_t sent_packetnum; | ||
105 | |||
106 | /* Number of packets sent by the other peer. */ | ||
107 | uint32_t osent_packetnum; | ||
108 | |||
109 | /* Number of latest packet written onto the sendbuffer. */ | ||
110 | uint32_t sendbuff_packetnum; | ||
111 | |||
112 | /* We know all packets before that number were successfully sent. */ | ||
113 | uint32_t successful_sent; | ||
114 | |||
115 | /* Packet number of last packet read with the read_packet function. */ | ||
116 | uint32_t successful_read; | ||
117 | |||
118 | /* List of currently requested packet numbers(by the other person). */ | ||
119 | uint32_t req_packets[MAX_REQUESTED_PACKETS]; | ||
120 | |||
121 | /* Total number of currently requested packets(by the other person). */ | ||
122 | uint16_t num_req_paquets; | ||
123 | |||
124 | uint8_t recv_counter; | ||
125 | uint8_t send_counter; | ||
126 | uint8_t timeout; /* connection timeout in seconds. */ | ||
127 | |||
128 | /* Is the connection confirmed or not? 1 if yes, 0 if no */ | ||
129 | uint8_t confirmed; | ||
130 | } Connection; | ||
131 | |||
132 | typedef struct { | ||
133 | Networking_Core *net; | ||
134 | |||
135 | tox_array connections; | ||
136 | |||
137 | /* Table of random numbers used in handshake_id. */ | ||
138 | /* IPv6 (16) + port (2)*/ | ||
139 | uint32_t randtable[18][256]; | ||
140 | } Lossless_UDP; | ||
141 | |||
142 | /* | ||
143 | * Initialize a new connection to ip_port. | ||
144 | * | ||
145 | * return an integer corresponding to the connection id. | ||
146 | * return -1 if it could not initialize the connection. | ||
147 | * return number if there already was an existing connection to that ip_port. | ||
148 | */ | ||
149 | int new_connection(Lossless_UDP *ludp, IP_Port ip_port); | ||
150 | |||
151 | /* | ||
152 | * Get connection id from IP_Port. | ||
153 | * | ||
154 | * return -1 if there are no connections like we are looking for. | ||
155 | * return id if it found it . | ||
156 | */ | ||
157 | int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port); | ||
158 | |||
159 | /* | ||
160 | * return an integer corresponding to the next connection in our incoming connection list with at least numpackets in the recieve queue. | ||
161 | * return -1 if there are no new incoming connections in the list. | ||
162 | */ | ||
163 | int incoming_connection(Lossless_UDP *ludp, uint32_t numpackets); | ||
164 | |||
165 | /* return -1 if it could not kill the connection. | ||
166 | * return 0 if killed successfully. | ||
167 | */ | ||
168 | int kill_connection(Lossless_UDP *ludp, int connection_id); | ||
169 | |||
170 | /* | ||
171 | * timeout connection in seconds seconds. | ||
172 | * | ||
173 | * return -1 if it can not kill the connection. | ||
174 | * return 0 if it will kill it. | ||
175 | */ | ||
176 | int timeout_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds); | ||
177 | |||
178 | |||
179 | /* Check if connection is confirmed. | ||
180 | * | ||
181 | * returns 1 if yes. | ||
182 | * returns 0 if no. | ||
183 | */ | ||
184 | int connection_confirmed(Lossless_UDP *ludp, int connection_id); | ||
185 | |||
186 | /* Confirm an incoming connection. | ||
187 | * Also disables the auto kill timeout on incomming connections. | ||
188 | * | ||
189 | * return 0 on success | ||
190 | * return -1 on failure. | ||
191 | */ | ||
192 | int confirm_connection(Lossless_UDP *ludp, int connection_id); | ||
193 | |||
194 | /* returns the ip_port of the corresponding connection. | ||
195 | * return 0 if there is no such connection. | ||
196 | */ | ||
197 | IP_Port connection_ip(Lossless_UDP *ludp, int connection_id); | ||
198 | |||
199 | /* returns the id of the next packet in the queue. | ||
200 | * return -1 if no packet in queue. | ||
201 | */ | ||
202 | uint8_t id_packet(Lossless_UDP *ludp, int connection_id); | ||
203 | |||
204 | /* return 0 if there is no received data in the buffer. | ||
205 | * return length of received packet if successful. | ||
206 | */ | ||
207 | int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data); | ||
208 | |||
209 | /* Like read_packet() but does leaves the queue as is. | ||
210 | * return 0 if there is no received data in the buffer. | ||
211 | * return length of received packet if successful. | ||
212 | */ | ||
213 | int read_packet_silent(Lossless_UDP *ludp, int connection_id, uint8_t *data); | ||
214 | |||
215 | /* Discard the next packet to be read from the queue | ||
216 | * return 0 if success. | ||
217 | * return -1 if failure. | ||
218 | */ | ||
219 | int discard_packet(Lossless_UDP *ludp, int connection_id); | ||
220 | |||
221 | /* returns the number of packet slots left in the sendbuffer. | ||
222 | * return 0 if failure. | ||
223 | */ | ||
224 | uint32_t num_free_sendqueue_slots(Lossless_UDP *ludp, int connection_id); | ||
225 | |||
226 | /* return 0 if data could not be put in packet queue. | ||
227 | * return 1 if data was put into the queue. | ||
228 | */ | ||
229 | int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t length); | ||
230 | |||
231 | /* return number of packets in the queue waiting to be successfully sent. */ | ||
232 | uint32_t sendqueue(Lossless_UDP *ludp, int connection_id); | ||
233 | |||
234 | /* return number of packets in all queues waiting to be successfully sent. */ | ||
235 | uint32_t sendqueue_total(Lossless_UDP *ludp); | ||
236 | |||
237 | /* | ||
238 | * return number of packets in the queue waiting to be successfully | ||
239 | * read with read_packet(...). | ||
240 | */ | ||
241 | uint32_t recvqueue(Lossless_UDP *ludp, int connection_id); | ||
242 | |||
243 | /* Check if connection is connected: | ||
244 | * | ||
245 | * return LUDP_NO_CONNECTION if not. | ||
246 | * return LUDP_HANDSHAKE_SENDING if attempting handshake. | ||
247 | * return LUDP_NOT_CONFIRMED if handshake is done. | ||
248 | * return LUDP_ESTABLISHED if fully connected. | ||
249 | * return LUDP_TIMED_OUT if timed out and wating to be killed. | ||
250 | */ | ||
251 | int is_connected(Lossless_UDP *ludp, int connection_id); | ||
252 | |||
253 | /* Call this function a couple times per second. It is the main loop. */ | ||
254 | void do_lossless_udp(Lossless_UDP *ludp); | ||
255 | |||
256 | /* This function sets up LosslessUDP packet handling. */ | ||
257 | Lossless_UDP *new_lossless_udp(Networking_Core *net); | ||
258 | |||
259 | void kill_lossless_udp(Lossless_UDP *ludp); | ||
260 | |||
261 | |||
262 | #endif | ||
diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc index 7723aeaf..926b4e3f 100644 --- a/toxcore/Makefile.inc +++ b/toxcore/Makefile.inc | |||
@@ -11,8 +11,6 @@ libtoxcore_la_SOURCES = ../toxcore/DHT.h \ | |||
11 | ../toxcore/network.c \ | 11 | ../toxcore/network.c \ |
12 | ../toxcore/crypto_core.h \ | 12 | ../toxcore/crypto_core.h \ |
13 | ../toxcore/crypto_core.c \ | 13 | ../toxcore/crypto_core.c \ |
14 | ../toxcore/Lossless_UDP.h \ | ||
15 | ../toxcore/Lossless_UDP.c \ | ||
16 | ../toxcore/net_crypto.h \ | 14 | ../toxcore/net_crypto.h \ |
17 | ../toxcore/net_crypto.c \ | 15 | ../toxcore/net_crypto.c \ |
18 | ../toxcore/friend_requests.h \ | 16 | ../toxcore/friend_requests.h \ |
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 308cf14e..1a5c93aa 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c | |||
@@ -406,10 +406,10 @@ uint32_t m_sendmessage(Messenger *m, int32_t friendnumber, uint8_t *message, uin | |||
406 | 406 | ||
407 | uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid, uint8_t *message, uint32_t length) | 407 | uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid, uint8_t *message, uint32_t length) |
408 | { | 408 | { |
409 | if (length >= (MAX_DATA_SIZE - sizeof(theid))) | 409 | if (length >= (MAX_CRYPTO_DATA_SIZE - sizeof(theid))) |
410 | return 0; | 410 | return 0; |
411 | 411 | ||
412 | uint8_t temp[MAX_DATA_SIZE]; | 412 | uint8_t temp[MAX_CRYPTO_DATA_SIZE]; |
413 | theid = htonl(theid); | 413 | theid = htonl(theid); |
414 | memcpy(temp, &theid, sizeof(theid)); | 414 | memcpy(temp, &theid, sizeof(theid)); |
415 | memcpy(temp + sizeof(theid), message, length); | 415 | memcpy(temp + sizeof(theid), message, length); |
@@ -440,10 +440,10 @@ uint32_t m_sendaction(Messenger *m, int32_t friendnumber, uint8_t *action, uint3 | |||
440 | 440 | ||
441 | uint32_t m_sendaction_withid(Messenger *m, int32_t friendnumber, uint32_t theid, uint8_t *action, uint32_t length) | 441 | uint32_t m_sendaction_withid(Messenger *m, int32_t friendnumber, uint32_t theid, uint8_t *action, uint32_t length) |
442 | { | 442 | { |
443 | if (length >= (MAX_DATA_SIZE - sizeof(theid))) | 443 | if (length >= (MAX_CRYPTO_DATA_SIZE - sizeof(theid))) |
444 | return 0; | 444 | return 0; |
445 | 445 | ||
446 | uint8_t temp[MAX_DATA_SIZE]; | 446 | uint8_t temp[MAX_CRYPTO_DATA_SIZE]; |
447 | theid = htonl(theid); | 447 | theid = htonl(theid); |
448 | memcpy(temp, &theid, sizeof(theid)); | 448 | memcpy(temp, &theid, sizeof(theid)); |
449 | memcpy(temp + sizeof(theid), action, length); | 449 | memcpy(temp + sizeof(theid), action, length); |
@@ -840,7 +840,7 @@ int write_cryptpacket_id(Messenger *m, int32_t friendnumber, uint8_t packet_id, | |||
840 | if (friend_not_valid(m, friendnumber)) | 840 | if (friend_not_valid(m, friendnumber)) |
841 | return 0; | 841 | return 0; |
842 | 842 | ||
843 | if (length >= MAX_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE) | 843 | if (length >= MAX_CRYPTO_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE) |
844 | return 0; | 844 | return 0; |
845 | 845 | ||
846 | uint8_t packet[length + 1]; | 846 | uint8_t packet[length + 1]; |
@@ -888,7 +888,7 @@ static IP_Port get_friend_ipport(Messenger *m, int32_t friendnumber) | |||
888 | if (is_cryptoconnected(m->net_crypto, crypt_id) != CRYPTO_CONN_ESTABLISHED) | 888 | if (is_cryptoconnected(m->net_crypto, crypt_id) != CRYPTO_CONN_ESTABLISHED) |
889 | return zero; | 889 | return zero; |
890 | 890 | ||
891 | return connection_ip(m->net_crypto->lossless_udp, m->net_crypto->crypto_connections[crypt_id].number); | 891 | return m->net_crypto->crypto_connections[crypt_id].ip_port; |
892 | } | 892 | } |
893 | 893 | ||
894 | /* returns the group number of the chat with public key group_public_key. | 894 | /* returns the group number of the chat with public key group_public_key. |
@@ -1395,7 +1395,7 @@ int new_filesender(Messenger *m, int32_t friendnumber, uint64_t filesize, uint8_ | |||
1395 | int file_control(Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id, | 1395 | int file_control(Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id, |
1396 | uint8_t *data, uint16_t length) | 1396 | uint8_t *data, uint16_t length) |
1397 | { | 1397 | { |
1398 | if (length > MAX_DATA_SIZE - 3) | 1398 | if (length > MAX_CRYPTO_DATA_SIZE - 3) |
1399 | return -1; | 1399 | return -1; |
1400 | 1400 | ||
1401 | if (friend_not_valid(m, friendnumber)) | 1401 | if (friend_not_valid(m, friendnumber)) |
@@ -1412,7 +1412,7 @@ int file_control(Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8 | |||
1412 | if (send_receive > 1) | 1412 | if (send_receive > 1) |
1413 | return -1; | 1413 | return -1; |
1414 | 1414 | ||
1415 | uint8_t packet[MAX_DATA_SIZE]; | 1415 | uint8_t packet[MAX_CRYPTO_DATA_SIZE]; |
1416 | packet[0] = send_receive; | 1416 | packet[0] = send_receive; |
1417 | packet[1] = filenumber; | 1417 | packet[1] = filenumber; |
1418 | packet[2] = message_id; | 1418 | packet[2] = message_id; |
@@ -1482,7 +1482,7 @@ int file_control(Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8 | |||
1482 | */ | 1482 | */ |
1483 | int file_data(Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length) | 1483 | int file_data(Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length) |
1484 | { | 1484 | { |
1485 | if (length > MAX_DATA_SIZE - 1) | 1485 | if (length > MAX_CRYPTO_DATA_SIZE - 1) |
1486 | return -1; | 1486 | return -1; |
1487 | 1487 | ||
1488 | if (friend_not_valid(m, friendnumber)) | 1488 | if (friend_not_valid(m, friendnumber)) |
@@ -1495,7 +1495,7 @@ int file_data(Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t *d | |||
1495 | if (crypto_num_free_sendqueue_slots(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id) < MIN_SLOTS_FREE) | 1495 | if (crypto_num_free_sendqueue_slots(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id) < MIN_SLOTS_FREE) |
1496 | return -1; | 1496 | return -1; |
1497 | 1497 | ||
1498 | uint8_t packet[MAX_DATA_SIZE]; | 1498 | uint8_t packet[MAX_CRYPTO_DATA_SIZE]; |
1499 | packet[0] = filenumber; | 1499 | packet[0] = filenumber; |
1500 | memcpy(packet + 1, data, length); | 1500 | memcpy(packet + 1, data, length); |
1501 | 1501 | ||
@@ -1738,6 +1738,23 @@ static void LANdiscovery(Messenger *m) | |||
1738 | } | 1738 | } |
1739 | } | 1739 | } |
1740 | 1740 | ||
1741 | int handle_new_connections(void *object, New_Connection *n_c) | ||
1742 | { | ||
1743 | Messenger *m = object; | ||
1744 | int friend_id = getfriend_id(m, n_c->public_key); | ||
1745 | |||
1746 | if (friend_id != -1) { | ||
1747 | if (m->friendlist[friend_id].crypt_connection_id != -1) | ||
1748 | return -1; | ||
1749 | |||
1750 | m->friendlist[friend_id].crypt_connection_id = accept_crypto_connection(m->net_crypto, n_c); | ||
1751 | set_friend_status(m, friend_id, FRIEND_CONFIRMED); | ||
1752 | } | ||
1753 | |||
1754 | return -1; | ||
1755 | } | ||
1756 | |||
1757 | |||
1741 | /* Run this at startup. */ | 1758 | /* Run this at startup. */ |
1742 | Messenger *new_messenger(uint8_t ipv6enabled) | 1759 | Messenger *new_messenger(uint8_t ipv6enabled) |
1743 | { | 1760 | { |
@@ -1772,6 +1789,8 @@ Messenger *new_messenger(uint8_t ipv6enabled) | |||
1772 | return NULL; | 1789 | return NULL; |
1773 | } | 1790 | } |
1774 | 1791 | ||
1792 | new_connection_handler(m->net_crypto, &handle_new_connections, m); | ||
1793 | |||
1775 | m->onion = new_onion(m->dht); | 1794 | m->onion = new_onion(m->dht); |
1776 | m->onion_a = new_onion_announce(m->dht); | 1795 | m->onion_a = new_onion_announce(m->dht); |
1777 | m->onion_c = new_onion_client(m->net_crypto); | 1796 | m->onion_c = new_onion_client(m->net_crypto); |
@@ -1843,7 +1862,7 @@ void do_friends(Messenger *m) | |||
1843 | { | 1862 | { |
1844 | uint32_t i; | 1863 | uint32_t i; |
1845 | int len; | 1864 | int len; |
1846 | uint8_t temp[MAX_DATA_SIZE]; | 1865 | uint8_t temp[MAX_CRYPTO_DATA_SIZE]; |
1847 | uint64_t temp_time = unix_time(); | 1866 | uint64_t temp_time = unix_time(); |
1848 | 1867 | ||
1849 | for (i = 0; i < m->numfriends; ++i) { | 1868 | for (i = 0; i < m->numfriends; ++i) { |
@@ -2184,32 +2203,8 @@ void do_friends(Messenger *m) | |||
2184 | } | 2203 | } |
2185 | } | 2204 | } |
2186 | 2205 | ||
2187 | void do_inbound(Messenger *m) | ||
2188 | { | ||
2189 | uint8_t secret_nonce[crypto_box_NONCEBYTES]; | ||
2190 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; | ||
2191 | uint8_t session_key[crypto_box_PUBLICKEYBYTES]; | ||
2192 | int inconnection = crypto_inbound(m->net_crypto, public_key, secret_nonce, session_key); | ||
2193 | |||
2194 | if (inconnection != -1) { | ||
2195 | int friend_id = getfriend_id(m, public_key); | ||
2196 | |||
2197 | if (friend_id != -1) { | ||
2198 | if (m_get_friend_connectionstatus(m, friend_id) == 1) { | ||
2199 | kill_connection(m->net_crypto->lossless_udp, inconnection); | ||
2200 | return; | ||
2201 | } | ||
2202 | 2206 | ||
2203 | crypto_kill(m->net_crypto, m->friendlist[friend_id].crypt_connection_id); | ||
2204 | m->friendlist[friend_id].crypt_connection_id = | ||
2205 | accept_crypto_inbound(m->net_crypto, inconnection, public_key, secret_nonce, session_key); | ||
2206 | 2207 | ||
2207 | set_friend_status(m, friend_id, FRIEND_CONFIRMED); | ||
2208 | } else { | ||
2209 | kill_connection(m->net_crypto->lossless_udp, inconnection); | ||
2210 | } | ||
2211 | } | ||
2212 | } | ||
2213 | 2208 | ||
2214 | #ifdef LOGGING | 2209 | #ifdef LOGGING |
2215 | #define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60UL | 2210 | #define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60UL |
@@ -2238,7 +2233,6 @@ void do_messenger(Messenger *m) | |||
2238 | do_net_crypto(m->net_crypto); | 2233 | do_net_crypto(m->net_crypto); |
2239 | do_onion_client(m->onion_c); | 2234 | do_onion_client(m->onion_c); |
2240 | do_friends(m); | 2235 | do_friends(m); |
2241 | do_inbound(m); | ||
2242 | do_allgroupchats(m); | 2236 | do_allgroupchats(m); |
2243 | LANdiscovery(m); | 2237 | LANdiscovery(m); |
2244 | 2238 | ||
@@ -2381,7 +2375,9 @@ size_t wait_data_size() | |||
2381 | 2375 | ||
2382 | int wait_prepare_messenger(Messenger *m, uint8_t *data) | 2376 | int wait_prepare_messenger(Messenger *m, uint8_t *data) |
2383 | { | 2377 | { |
2384 | return networking_wait_prepare(m->net, sendqueue_total(m->net_crypto->lossless_udp), data); | 2378 | //TODO |
2379 | //return networking_wait_prepare(m->net, sendqueue_total(m->net_crypto->lossless_udp), data); | ||
2380 | return networking_wait_prepare(m->net, 1024, data); | ||
2385 | } | 2381 | } |
2386 | 2382 | ||
2387 | int wait_execute_messenger(uint8_t *data, long seconds, long microseconds) | 2383 | int wait_execute_messenger(uint8_t *data, long seconds, long microseconds) |
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 3d42e911..66ef39e5 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h | |||
@@ -34,6 +34,7 @@ | |||
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)) |
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index ad41ce78..6dbb6258 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c | |||
@@ -705,7 +705,7 @@ static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id, | |||
705 | * | 705 | * |
706 | * The set function should return -1 on failure and 0 on success. | 706 | * The set function should return -1 on failure and 0 on success. |
707 | * | 707 | * |
708 | * n_c is only valid for the duration of this function. | 708 | * n_c is only valid for the duration of the function call. |
709 | */ | 709 | */ |
710 | void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c), | 710 | void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c), |
711 | void *object) | 711 | void *object) |
@@ -968,31 +968,7 @@ static void send_crypto_packets(Net_Crypto *c) | |||
968 | */ | 968 | */ |
969 | int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data) | 969 | int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data) |
970 | { | 970 | { |
971 | if (crypt_connection_id_not_valid(c, crypt_connection_id)) | ||
972 | return 0; | ||
973 | |||
974 | if (c->crypto_connections[crypt_connection_id].status != CRYPTO_CONN_ESTABLISHED) | ||
975 | return 0; | ||
976 | |||
977 | uint8_t temp_data[MAX_DATA_SIZE]; | ||
978 | int length = read_packet(c->lossless_udp, c->crypto_connections[crypt_connection_id].number, temp_data); | ||
979 | |||
980 | if (length == 0) | ||
981 | return 0; | ||
982 | |||
983 | if (temp_data[0] != 3) | ||
984 | return -1; | ||
985 | 971 | ||
986 | int len = decrypt_data_symmetric(c->crypto_connections[crypt_connection_id].shared_key, | ||
987 | c->crypto_connections[crypt_connection_id].recv_nonce, | ||
988 | temp_data + 1, length - 1, data); | ||
989 | |||
990 | if (len != -1) { | ||
991 | increment_nonce(c->crypto_connections[crypt_connection_id].recv_nonce); | ||
992 | return len; | ||
993 | } | ||
994 | |||
995 | return -1; | ||
996 | } | 972 | } |
997 | 973 | ||
998 | /* returns the number of packet slots left in the sendbuffer. | 974 | /* returns the number of packet slots left in the sendbuffer. |
@@ -1000,10 +976,7 @@ int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data) | |||
1000 | */ | 976 | */ |
1001 | uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) | 977 | uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) |
1002 | { | 978 | { |
1003 | if (crypt_connection_id_not_valid(c, crypt_connection_id)) | ||
1004 | return 0; | ||
1005 | 979 | ||
1006 | return num_free_sendqueue_slots(c->lossless_udp, c->crypto_connections[crypt_connection_id].number); | ||
1007 | } | 980 | } |
1008 | 981 | ||
1009 | /* return 0 if data could not be put in packet queue. | 982 | /* return 0 if data could not be put in packet queue. |
@@ -1011,93 +984,7 @@ uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) | |||
1011 | */ | 984 | */ |
1012 | int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length) | 985 | int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length) |
1013 | { | 986 | { |
1014 | if (crypt_connection_id_not_valid(c, crypt_connection_id)) | ||
1015 | return 0; | ||
1016 | |||
1017 | if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1) | ||
1018 | return 0; | ||
1019 | |||
1020 | if (c->crypto_connections[crypt_connection_id].status != CRYPTO_CONN_ESTABLISHED) | ||
1021 | return 0; | ||
1022 | |||
1023 | uint8_t temp_data[MAX_DATA_SIZE]; | ||
1024 | int len = encrypt_data_symmetric(c->crypto_connections[crypt_connection_id].shared_key, | ||
1025 | c->crypto_connections[crypt_connection_id].sent_nonce, | ||
1026 | data, length, temp_data + 1); | ||
1027 | |||
1028 | if (len == -1) | ||
1029 | return 0; | ||
1030 | |||
1031 | temp_data[0] = 3; | ||
1032 | |||
1033 | if (write_packet(c->lossless_udp, c->crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0) | ||
1034 | return 0; | ||
1035 | 987 | ||
1036 | increment_nonce(c->crypto_connections[crypt_connection_id].sent_nonce); | ||
1037 | return 1; | ||
1038 | } | ||
1039 | |||
1040 | |||
1041 | /* Send a crypto handshake packet containing an encrypted secret nonce and session public key | ||
1042 | * to peer with connection_id and public_key. | ||
1043 | * The packet is encrypted with a random nonce which is sent in plain text with the packet. | ||
1044 | */ | ||
1045 | static int send_cryptohandshake(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce, | ||
1046 | uint8_t *session_key) | ||
1047 | { | ||
1048 | uint8_t temp_data[MAX_DATA_SIZE]; | ||
1049 | uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; | ||
1050 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
1051 | |||
1052 | new_nonce(nonce); | ||
1053 | memcpy(temp, secret_nonce, crypto_box_NONCEBYTES); | ||
1054 | memcpy(temp + crypto_box_NONCEBYTES, session_key, crypto_box_PUBLICKEYBYTES); | ||
1055 | |||
1056 | int len = encrypt_data(public_key, c->self_secret_key, nonce, temp, crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, | ||
1057 | 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data); | ||
1058 | |||
1059 | if (len == -1) | ||
1060 | return 0; | ||
1061 | |||
1062 | temp_data[0] = 2; | ||
1063 | memcpy(temp_data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES); | ||
1064 | memcpy(temp_data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); | ||
1065 | return write_packet(c->lossless_udp, connection_id, temp_data, | ||
1066 | len + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); | ||
1067 | } | ||
1068 | |||
1069 | /* Extract secret nonce, session public key and public_key from a packet(data) with length length. | ||
1070 | * | ||
1071 | * return 1 if successful. | ||
1072 | * return 0 if failure. | ||
1073 | */ | ||
1074 | static int handle_cryptohandshake(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, | ||
1075 | uint8_t *session_key, uint8_t *data, uint16_t length) | ||
1076 | { | ||
1077 | int pad = (- crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES); | ||
1078 | |||
1079 | if (length != 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES | ||
1080 | + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad) { | ||
1081 | return 0; | ||
1082 | } | ||
1083 | |||
1084 | if (data[0] != 2) | ||
1085 | return 0; | ||
1086 | |||
1087 | uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; | ||
1088 | |||
1089 | memcpy(public_key, data + 1, crypto_box_PUBLICKEYBYTES); | ||
1090 | |||
1091 | int len = decrypt_data(public_key, c->self_secret_key, data + 1 + crypto_box_PUBLICKEYBYTES, | ||
1092 | data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, | ||
1093 | crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad, temp); | ||
1094 | |||
1095 | if (len != crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES) | ||
1096 | return 0; | ||
1097 | |||
1098 | memcpy(secret_nonce, temp, crypto_box_NONCEBYTES); | ||
1099 | memcpy(session_key, temp + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES); | ||
1100 | return 1; | ||
1101 | } | 988 | } |
1102 | 989 | ||
1103 | 990 | ||
@@ -1108,92 +995,7 @@ static int handle_cryptohandshake(Net_Crypto *c, uint8_t *public_key, uint8_t *s | |||
1108 | */ | 995 | */ |
1109 | int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port) | 996 | int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port) |
1110 | { | 997 | { |
1111 | uint32_t i; | ||
1112 | int id_existing = getcryptconnection_id(c, public_key); | ||
1113 | |||
1114 | if (id_existing != -1) { | ||
1115 | IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id_existing].number); | ||
1116 | 998 | ||
1117 | if (ipport_equal(&c_ip, &ip_port)) | ||
1118 | return -1; | ||
1119 | } | ||
1120 | |||
1121 | if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1 | ||
1122 | || c->crypto_connections == NULL) | ||
1123 | return -1; | ||
1124 | |||
1125 | memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection)); | ||
1126 | c->crypto_connections[c->crypto_connections_length].number = ~0; | ||
1127 | |||
1128 | for (i = 0; i <= c->crypto_connections_length; ++i) { | ||
1129 | if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) { | ||
1130 | int id_new = new_connection(c->lossless_udp, ip_port); | ||
1131 | |||
1132 | if (id_new == -1) | ||
1133 | return -1; | ||
1134 | |||
1135 | c->crypto_connections[i].number = id_new; | ||
1136 | c->crypto_connections[i].status = CRYPTO_CONN_HANDSHAKE_SENT; | ||
1137 | random_nonce(c->crypto_connections[i].recv_nonce); | ||
1138 | memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); | ||
1139 | crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key); | ||
1140 | c->crypto_connections[i].timeout = unix_time() + CRYPTO_HANDSHAKE_TIMEOUT; | ||
1141 | |||
1142 | if (c->crypto_connections_length == i) | ||
1143 | ++c->crypto_connections_length; | ||
1144 | |||
1145 | if (send_cryptohandshake(c, id_new, public_key, c->crypto_connections[i].recv_nonce, | ||
1146 | c->crypto_connections[i].sessionpublic_key) == 1) { | ||
1147 | increment_nonce(c->crypto_connections[i].recv_nonce); | ||
1148 | return i; | ||
1149 | } | ||
1150 | |||
1151 | return -1; /* This should never happen. */ | ||
1152 | } | ||
1153 | } | ||
1154 | |||
1155 | return -1; | ||
1156 | } | ||
1157 | |||
1158 | /* Handle an incoming connection. | ||
1159 | * | ||
1160 | * return -1 if no crypto inbound connection. | ||
1161 | * return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection. | ||
1162 | * | ||
1163 | * Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce | ||
1164 | * and the session public key for the connection in session_key. | ||
1165 | * to accept it see: accept_crypto_inbound(...). | ||
1166 | * to refuse it just call kill_connection(...) on the connection id. | ||
1167 | */ | ||
1168 | int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key) | ||
1169 | { | ||
1170 | while (1) { | ||
1171 | int incoming_con = incoming_connection(c->lossless_udp, 1); | ||
1172 | |||
1173 | if (incoming_con != -1) { | ||
1174 | if (is_connected(c->lossless_udp, incoming_con) == LUDP_TIMED_OUT) { | ||
1175 | kill_connection(c->lossless_udp, incoming_con); | ||
1176 | continue; | ||
1177 | } | ||
1178 | |||
1179 | if (id_packet(c->lossless_udp, incoming_con) == 2) { | ||
1180 | uint8_t temp_data[MAX_DATA_SIZE]; | ||
1181 | uint16_t len = read_packet_silent(c->lossless_udp, incoming_con, temp_data); | ||
1182 | |||
1183 | if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) { | ||
1184 | return incoming_con; | ||
1185 | } else { | ||
1186 | kill_connection(c->lossless_udp, incoming_con); | ||
1187 | } | ||
1188 | } else { | ||
1189 | kill_connection(c->lossless_udp, incoming_con); | ||
1190 | } | ||
1191 | } else { | ||
1192 | break; | ||
1193 | } | ||
1194 | } | ||
1195 | |||
1196 | return -1; | ||
1197 | } | 999 | } |
1198 | 1000 | ||
1199 | /* Kill a crypto connection. | 1001 | /* Kill a crypto connection. |
@@ -1203,94 +1005,7 @@ int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, ui | |||
1203 | */ | 1005 | */ |
1204 | int crypto_kill(Net_Crypto *c, int crypt_connection_id) | 1006 | int crypto_kill(Net_Crypto *c, int crypt_connection_id) |
1205 | { | 1007 | { |
1206 | if (crypt_connection_id_not_valid(c, crypt_connection_id)) | ||
1207 | return 1; | ||
1208 | |||
1209 | if (c->crypto_connections[crypt_connection_id].status != CRYPTO_CONN_NO_CONNECTION) { | ||
1210 | c->crypto_connections[crypt_connection_id].status = CRYPTO_CONN_NO_CONNECTION; | ||
1211 | kill_connection(c->lossless_udp, c->crypto_connections[crypt_connection_id].number); | ||
1212 | memset(&(c->crypto_connections[crypt_connection_id]), 0 , sizeof(Crypto_Connection)); | ||
1213 | c->crypto_connections[crypt_connection_id].number = ~0; | ||
1214 | uint32_t i; | ||
1215 | |||
1216 | for (i = c->crypto_connections_length; i != 0; --i) { | ||
1217 | if (c->crypto_connections[i - 1].status != CRYPTO_CONN_NO_CONNECTION) | ||
1218 | break; | ||
1219 | } | ||
1220 | |||
1221 | if (c->crypto_connections_length != i) { | ||
1222 | c->crypto_connections_length = i; | ||
1223 | realloc_cryptoconnection(c, c->crypto_connections_length); | ||
1224 | } | ||
1225 | |||
1226 | return 0; | ||
1227 | } | ||
1228 | |||
1229 | return 1; | ||
1230 | } | ||
1231 | |||
1232 | /* Accept an incoming connection using the parameters provided by crypto_inbound. | ||
1233 | * | ||
1234 | * return -1 if not successful. | ||
1235 | * return the crypt_connection_id if successful. | ||
1236 | */ | ||
1237 | int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce, | ||
1238 | uint8_t *session_key) | ||
1239 | { | ||
1240 | uint32_t i; | ||
1241 | |||
1242 | if (discard_packet(c->lossless_udp, connection_id) == -1) | ||
1243 | return -1; | ||
1244 | |||
1245 | /* | ||
1246 | * if(getcryptconnection_id(public_key) != -1) | ||
1247 | * { | ||
1248 | * return -1; | ||
1249 | * } | ||
1250 | */ | ||
1251 | |||
1252 | if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1 | ||
1253 | || c->crypto_connections == NULL) | ||
1254 | return -1; | ||
1255 | |||
1256 | memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection)); | ||
1257 | c->crypto_connections[c->crypto_connections_length].number = ~0; | ||
1258 | 1008 | ||
1259 | for (i = 0; i <= c->crypto_connections_length; ++i) { | ||
1260 | if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) { | ||
1261 | c->crypto_connections[i].number = connection_id; | ||
1262 | c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED; | ||
1263 | c->crypto_connections[i].timeout = unix_time() + CRYPTO_HANDSHAKE_TIMEOUT; | ||
1264 | random_nonce(c->crypto_connections[i].recv_nonce); | ||
1265 | memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); | ||
1266 | memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); | ||
1267 | increment_nonce(c->crypto_connections[i].sent_nonce); | ||
1268 | memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); | ||
1269 | |||
1270 | crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key); | ||
1271 | |||
1272 | if (c->crypto_connections_length == i) | ||
1273 | ++c->crypto_connections_length; | ||
1274 | |||
1275 | if (send_cryptohandshake(c, connection_id, public_key, c->crypto_connections[i].recv_nonce, | ||
1276 | c->crypto_connections[i].sessionpublic_key) == 1) { | ||
1277 | increment_nonce(c->crypto_connections[i].recv_nonce); | ||
1278 | uint32_t zero = 0; | ||
1279 | encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, | ||
1280 | c->crypto_connections[i].sessionsecret_key, | ||
1281 | c->crypto_connections[i].shared_key); | ||
1282 | c->crypto_connections[i].status = | ||
1283 | CRYPTO_CONN_ESTABLISHED; /* Connection status needs to be 3 for write_cryptpacket() to work. */ | ||
1284 | write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero)); | ||
1285 | c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED; /* Set it to its proper value right after. */ | ||
1286 | return i; | ||
1287 | } | ||
1288 | |||
1289 | return -1; /* This should never happen. */ | ||
1290 | } | ||
1291 | } | ||
1292 | |||
1293 | return -1; | ||
1294 | } | 1009 | } |
1295 | 1010 | ||
1296 | /* return 0 if no connection. | 1011 | /* return 0 if no connection. |
@@ -1333,84 +1048,7 @@ void load_keys(Net_Crypto *c, uint8_t *keys) | |||
1333 | /* Handle received packets for not yet established crypto connections. */ | 1048 | /* Handle received packets for not yet established crypto connections. */ |
1334 | static void receive_crypto(Net_Crypto *c) | 1049 | static void receive_crypto(Net_Crypto *c) |
1335 | { | 1050 | { |
1336 | uint32_t i; | ||
1337 | uint64_t temp_time = unix_time(); | ||
1338 | |||
1339 | for (i = 0; i < c->crypto_connections_length; ++i) { | ||
1340 | if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) | ||
1341 | continue; | ||
1342 | |||
1343 | if (c->crypto_connections[i].status == CRYPTO_CONN_HANDSHAKE_SENT) { | ||
1344 | uint8_t temp_data[MAX_DATA_SIZE]; | ||
1345 | uint8_t secret_nonce[crypto_box_NONCEBYTES]; | ||
1346 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; | ||
1347 | uint8_t session_key[crypto_box_PUBLICKEYBYTES]; | ||
1348 | uint16_t len; | ||
1349 | |||
1350 | if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 2) { /* Handle handshake packet. */ | ||
1351 | len = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data); | ||
1352 | |||
1353 | if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) { | ||
1354 | if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) { | ||
1355 | memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); | ||
1356 | memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); | ||
1357 | increment_nonce(c->crypto_connections[i].sent_nonce); | ||
1358 | uint32_t zero = 0; | ||
1359 | encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, | ||
1360 | c->crypto_connections[i].sessionsecret_key, | ||
1361 | c->crypto_connections[i].shared_key); | ||
1362 | c->crypto_connections[i].status = | ||
1363 | CRYPTO_CONN_ESTABLISHED; /* Connection status needs to be 3 for write_cryptpacket() to work. */ | ||
1364 | write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero)); | ||
1365 | c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED; /* Set it to its proper value right after. */ | ||
1366 | } else { | ||
1367 | /* This should not happen, timeout the connection if it does. */ | ||
1368 | c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; | ||
1369 | } | ||
1370 | } else { | ||
1371 | /* This should not happen, timeout the connection if it does. */ | ||
1372 | c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; | ||
1373 | } | ||
1374 | } else if (id_packet(c->lossless_udp, | ||
1375 | c->crypto_connections[i].number) != (uint8_t)~0) { | ||
1376 | /* This should not happen, timeout the connection if it does. */ | ||
1377 | c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; | ||
1378 | } | ||
1379 | } | ||
1380 | 1051 | ||
1381 | if (c->crypto_connections[i].status == CRYPTO_CONN_NOT_CONFIRMED) { | ||
1382 | if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 3) { | ||
1383 | uint8_t temp_data[MAX_DATA_SIZE]; | ||
1384 | uint8_t data[MAX_DATA_SIZE]; | ||
1385 | int length = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data); | ||
1386 | int len = decrypt_data(c->crypto_connections[i].peersessionpublic_key, | ||
1387 | c->crypto_connections[i].sessionsecret_key, | ||
1388 | c->crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data); | ||
1389 | uint32_t zero = 0; | ||
1390 | |||
1391 | if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) { | ||
1392 | increment_nonce(c->crypto_connections[i].recv_nonce); | ||
1393 | encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, | ||
1394 | c->crypto_connections[i].sessionsecret_key, | ||
1395 | c->crypto_connections[i].shared_key); | ||
1396 | c->crypto_connections[i].status = CRYPTO_CONN_ESTABLISHED; | ||
1397 | c->crypto_connections[i].timeout = ~0; | ||
1398 | /* Connection is accepted. */ | ||
1399 | confirm_connection(c->lossless_udp, c->crypto_connections[i].number); | ||
1400 | } else { | ||
1401 | /* This should not happen, timeout the connection if it does. */ | ||
1402 | c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; | ||
1403 | } | ||
1404 | } else if (id_packet(c->lossless_udp, c->crypto_connections[i].number) != (uint8_t)~0) { | ||
1405 | /* This should not happen, timeout the connection if it does. */ | ||
1406 | c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; | ||
1407 | } | ||
1408 | } | ||
1409 | |||
1410 | if (temp_time > c->crypto_connections[i].timeout) { | ||
1411 | c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; | ||
1412 | } | ||
1413 | } | ||
1414 | } | 1052 | } |
1415 | 1053 | ||
1416 | /* Run this to (re)initialize net_crypto. | 1054 | /* Run this to (re)initialize net_crypto. |
@@ -1429,12 +1067,6 @@ Net_Crypto *new_net_crypto(DHT *dht) | |||
1429 | return NULL; | 1067 | return NULL; |
1430 | 1068 | ||
1431 | temp->dht = dht; | 1069 | temp->dht = dht; |
1432 | temp->lossless_udp = new_lossless_udp(dht->net); | ||
1433 | |||
1434 | if (temp->lossless_udp == NULL) { | ||
1435 | free(temp); | ||
1436 | return NULL; | ||
1437 | } | ||
1438 | 1070 | ||
1439 | new_keys(temp); | 1071 | new_keys(temp); |
1440 | new_symmetric_key(temp->secret_symmetric_key); | 1072 | new_symmetric_key(temp->secret_symmetric_key); |
@@ -1451,9 +1083,7 @@ static void kill_timedout(Net_Crypto *c) | |||
1451 | uint32_t i; | 1083 | uint32_t i; |
1452 | 1084 | ||
1453 | for (i = 0; i < c->crypto_connections_length; ++i) { | 1085 | for (i = 0; i < c->crypto_connections_length; ++i) { |
1454 | if (c->crypto_connections[i].status != CRYPTO_CONN_NO_CONNECTION | 1086 | //TODO |
1455 | && is_connected(c->lossless_udp, c->crypto_connections[i].number) == LUDP_TIMED_OUT) | ||
1456 | c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; | ||
1457 | } | 1087 | } |
1458 | } | 1088 | } |
1459 | 1089 | ||
@@ -1461,9 +1091,9 @@ static void kill_timedout(Net_Crypto *c) | |||
1461 | void do_net_crypto(Net_Crypto *c) | 1091 | void do_net_crypto(Net_Crypto *c) |
1462 | { | 1092 | { |
1463 | unix_time_update(); | 1093 | unix_time_update(); |
1464 | do_lossless_udp(c->lossless_udp); | ||
1465 | kill_timedout(c); | 1094 | kill_timedout(c); |
1466 | receive_crypto(c); | 1095 | receive_crypto(c); |
1096 | send_crypto_packets(c); | ||
1467 | } | 1097 | } |
1468 | 1098 | ||
1469 | void kill_net_crypto(Net_Crypto *c) | 1099 | void kill_net_crypto(Net_Crypto *c) |
@@ -1474,7 +1104,10 @@ void kill_net_crypto(Net_Crypto *c) | |||
1474 | crypto_kill(c, i); | 1104 | crypto_kill(c, i); |
1475 | } | 1105 | } |
1476 | 1106 | ||
1477 | kill_lossless_udp(c->lossless_udp); | 1107 | networking_registerhandler(c->dht->net, NET_PACKET_COOKIE_REQUEST, NULL, NULL); |
1108 | networking_registerhandler(c->dht->net, NET_PACKET_COOKIE_RESPONSE, NULL, NULL); | ||
1109 | networking_registerhandler(c->dht->net, NET_PACKET_CRYPTO_HS, NULL, NULL); | ||
1110 | networking_registerhandler(c->dht->net, NET_PACKET_CRYPTO_DATA, NULL, NULL); | ||
1478 | memset(c, 0, sizeof(Net_Crypto)); | 1111 | memset(c, 0, sizeof(Net_Crypto)); |
1479 | free(c); | 1112 | free(c); |
1480 | } | 1113 | } |
diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 736d3070..3d58e5c1 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h | |||
@@ -24,7 +24,6 @@ | |||
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" | ||
28 | #include "DHT.h" | 27 | #include "DHT.h" |
29 | 28 | ||
30 | #define CRYPTO_HANDSHAKE_TIMEOUT (CONNECTION_TIMEOUT * 2) | 29 | #define CRYPTO_HANDSHAKE_TIMEOUT (CONNECTION_TIMEOUT * 2) |
@@ -39,6 +38,8 @@ | |||
39 | #define CRYPTO_PACKET_BUFFER_SIZE 64 | 38 | #define CRYPTO_PACKET_BUFFER_SIZE 64 |
40 | 39 | ||
41 | #define MAX_CRYPTO_PACKET_SIZE 1400 | 40 | #define MAX_CRYPTO_PACKET_SIZE 1400 |
41 | |||
42 | /* Max size of data in packets TODO*/ | ||
42 | #define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) | 43 | #define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) |
43 | 44 | ||
44 | /* Interval in ms between sending cookie request/handshake packets. */ | 45 | /* Interval in ms between sending cookie request/handshake packets. */ |
@@ -58,7 +59,6 @@ typedef struct { | |||
58 | * 4 if the connection is established. | 59 | * 4 if the connection is established. |
59 | * 5 if the connection is timed out. | 60 | * 5 if the connection is timed out. |
60 | */ | 61 | */ |
61 | uint16_t number; /* Lossless_UDP connection number corresponding to this connection. */ | ||
62 | uint64_t timeout; | 62 | uint64_t timeout; |
63 | 63 | ||
64 | uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */ | 64 | uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */ |
@@ -71,7 +71,6 @@ typedef struct { | |||
71 | 71 | ||
72 | IP_Port ip_port; /* The ip and port to contact this guy directly.*/ | 72 | IP_Port ip_port; /* The ip and port to contact this guy directly.*/ |
73 | uint64_t direct_lastrecv_time; /* The Time at which we last receive a direct packet. */ | 73 | uint64_t direct_lastrecv_time; /* The Time at which we last receive a direct packet. */ |
74 | |||
75 | } Crypto_Connection; | 74 | } Crypto_Connection; |
76 | 75 | ||
77 | typedef struct { | 76 | typedef struct { |
@@ -84,7 +83,6 @@ typedef struct { | |||
84 | } New_Connection; | 83 | } New_Connection; |
85 | 84 | ||
86 | typedef struct { | 85 | typedef struct { |
87 | Lossless_UDP *lossless_udp; | ||
88 | DHT *dht; | 86 | DHT *dht; |
89 | 87 | ||
90 | Crypto_Connection *crypto_connections; | 88 | Crypto_Connection *crypto_connections; |
@@ -103,6 +101,22 @@ typedef struct { | |||
103 | } Net_Crypto; | 101 | } Net_Crypto; |
104 | 102 | ||
105 | 103 | ||
104 | /* Set function to be called when someone requests a new connection to us. | ||
105 | * | ||
106 | * The set function should return -1 on failure and 0 on success. | ||
107 | * | ||
108 | * n_c is only valid for the duration of the function call. | ||
109 | */ | ||
110 | void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c), | ||
111 | void *object); | ||
112 | |||
113 | /* Accept a crypto connection. | ||
114 | * | ||
115 | * return -1 on failure. | ||
116 | * return connection id on success. | ||
117 | */ | ||
118 | int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c); | ||
119 | |||
106 | 120 | ||
107 | /* return 0 if there is no received data in the buffer. | 121 | /* return 0 if there is no received data in the buffer. |
108 | * return -1 if the packet was discarded. | 122 | * return -1 if the packet was discarded. |
@@ -134,25 +148,6 @@ int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port); | |||
134 | */ | 148 | */ |
135 | int crypto_kill(Net_Crypto *c, int crypt_connection_id); | 149 | int crypto_kill(Net_Crypto *c, int crypt_connection_id); |
136 | 150 | ||
137 | /* Handle an incoming connection. | ||
138 | * | ||
139 | * return -1 if no crypto inbound connection. | ||
140 | * return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection. | ||
141 | * | ||
142 | * Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce | ||
143 | * and the session public key for the connection in session_key. | ||
144 | * to accept it see: accept_crypto_inbound(...). | ||
145 | * to refuse it just call kill_connection(...) on the connection id. | ||
146 | */ | ||
147 | int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key); | ||
148 | |||
149 | /* Accept an incoming connection using the parameters provided by crypto_inbound. | ||
150 | * | ||
151 | * return -1 if not successful. | ||
152 | * return crypt_connection_id if successful. | ||
153 | */ | ||
154 | int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce, | ||
155 | uint8_t *session_key); | ||
156 | 151 | ||
157 | /* return 0 if no connection. | 152 | /* return 0 if no connection. |
158 | * return 1 we have sent a handshake | 153 | * return 1 we have sent a handshake |
diff --git a/toxcore/tox.c b/toxcore/tox.c index 6bd24e92..037cb7f5 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c | |||
@@ -721,7 +721,7 @@ int tox_file_send_data(Tox *tox, int32_t friendnumber, uint8_t filenumber, uint8 | |||
721 | */ | 721 | */ |
722 | int tox_file_data_size(Tox *tox, int32_t friendnumber) | 722 | int tox_file_data_size(Tox *tox, int32_t friendnumber) |
723 | { | 723 | { |
724 | return MAX_DATA_SIZE - crypto_box_MACBYTES - 3; | 724 | return MAX_CRYPTO_DATA_SIZE - 3; |
725 | } | 725 | } |
726 | 726 | ||
727 | /* Give the number of bytes left to be sent/received. | 727 | /* Give the number of bytes left to be sent/received. |