diff options
-rw-r--r-- | auto_tests/messenger_test.c | 3 | ||||
-rw-r--r-- | other/DHT_bootstrap.c | 39 | ||||
-rw-r--r-- | other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c | 7 | ||||
-rw-r--r-- | testing/DHT_test.c | 53 | ||||
-rw-r--r-- | testing/Lossless_UDP_testclient.c | 33 | ||||
-rw-r--r-- | testing/Lossless_UDP_testserver.c | 20 | ||||
-rw-r--r-- | testing/Messenger_test.c | 34 | ||||
-rw-r--r-- | testing/misc_tools.c | 33 | ||||
-rw-r--r-- | testing/nTox.c | 56 | ||||
-rw-r--r-- | toxcore/DHT.c | 334 | ||||
-rw-r--r-- | toxcore/DHT.h | 54 | ||||
-rw-r--r-- | toxcore/LAN_discovery.c | 124 | ||||
-rw-r--r-- | toxcore/LAN_discovery.h | 2 | ||||
-rw-r--r-- | toxcore/Lossless_UDP.c | 58 | ||||
-rw-r--r-- | toxcore/Lossless_UDP.h | 6 | ||||
-rw-r--r-- | toxcore/Messenger.c | 80 | ||||
-rw-r--r-- | toxcore/Messenger.h | 2 | ||||
-rw-r--r-- | toxcore/friend_requests.c | 12 | ||||
-rw-r--r-- | toxcore/group_chats.c | 4 | ||||
-rw-r--r-- | toxcore/net_crypto.c | 2 | ||||
-rw-r--r-- | toxcore/network.c | 667 | ||||
-rw-r--r-- | toxcore/network.h | 139 | ||||
-rw-r--r-- | toxcore/ping.c | 10 | ||||
-rw-r--r-- | toxcore/tox.c | 14 | ||||
-rw-r--r-- | toxcore/tox.h | 101 | ||||
-rw-r--r-- | toxcore/util.c | 37 | ||||
-rw-r--r-- | toxcore/util.h | 18 |
27 files changed, 1627 insertions, 315 deletions
diff --git a/auto_tests/messenger_test.c b/auto_tests/messenger_test.c index 604e282c..1b72a92f 100644 --- a/auto_tests/messenger_test.c +++ b/auto_tests/messenger_test.c | |||
@@ -278,7 +278,8 @@ int main(int argc, char *argv[]) | |||
278 | good_id_b = hex_string_to_bin(good_id_b_str); | 278 | good_id_b = hex_string_to_bin(good_id_b_str); |
279 | bad_id = hex_string_to_bin(bad_id_str); | 279 | bad_id = hex_string_to_bin(bad_id_str); |
280 | 280 | ||
281 | m = initMessenger(); | 281 | /* IPv6 status from global define */ |
282 | m = initMessenger(TOX_ENABLE_IPV6_DEFAULT); | ||
282 | 283 | ||
283 | /* setup a default friend and friendnum */ | 284 | /* setup a default friend and friendnum */ |
284 | if (m_addfriend_norequest(m, (uint8_t *)friend_id) < 0) | 285 | if (m_addfriend_norequest(m, (uint8_t *)friend_id) < 0) |
diff --git a/other/DHT_bootstrap.c b/other/DHT_bootstrap.c index 654b759f..e6e8d59f 100644 --- a/other/DHT_bootstrap.c +++ b/other/DHT_bootstrap.c | |||
@@ -84,11 +84,26 @@ void manage_keys(DHT *dht) | |||
84 | 84 | ||
85 | int main(int argc, char *argv[]) | 85 | int main(int argc, char *argv[]) |
86 | { | 86 | { |
87 | if (argc == 2 && !strncasecmp(argv[1], "-h", 3)) { | ||
88 | printf("Usage (connected) : %s [--ipv4|--ipv6] IP PORT KEY\n", argv[0]); | ||
89 | printf("Usage (unconnected): %s [--ipv4|--ipv6]\n", argv[0]); | ||
90 | exit(0); | ||
91 | } | ||
92 | |||
93 | /* let user override default by cmdline */ | ||
94 | uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */ | ||
95 | int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled); | ||
96 | if (argvoffset < 0) | ||
97 | exit(1); | ||
98 | |||
87 | /* Initialize networking - | 99 | /* Initialize networking - |
88 | Bind to ip 0.0.0.0:PORT */ | 100 | Bind to ip 0.0.0.0 / [::] : PORT */ |
89 | IP ip; | 101 | IP ip; |
90 | ip.uint32 = 0; | 102 | ip_init(&ip, ipv6enabled); |
103 | |||
91 | DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT))); | 104 | DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT))); |
105 | perror("Initialization"); | ||
106 | |||
92 | manage_keys(dht); | 107 | manage_keys(dht); |
93 | printf("Public key: "); | 108 | printf("Public key: "); |
94 | uint32_t i; | 109 | uint32_t i; |
@@ -107,18 +122,20 @@ int main(int argc, char *argv[]) | |||
107 | fclose(file); | 122 | fclose(file); |
108 | 123 | ||
109 | printf("\n"); | 124 | printf("\n"); |
110 | printf("Port: %u\n", PORT); | 125 | printf("Port: %u\n", ntohs(dht->c->lossless_udp->net->port)); |
111 | 126 | ||
112 | perror("Initialization."); | 127 | if (argc > argvoffset + 3) { |
113 | |||
114 | if (argc > 3) { | ||
115 | printf("Trying to bootstrap into the network...\n"); | 128 | printf("Trying to bootstrap into the network...\n"); |
116 | IP_Port bootstrap_info; | 129 | uint16_t port = htons(atoi(argv[argvoffset + 2])); |
117 | bootstrap_info.ip.uint32 = inet_addr(argv[1]); | 130 | uint8_t *bootstrap_key = hex_string_to_bin(argv[argvoffset + 3]); |
118 | bootstrap_info.port = htons(atoi(argv[2])); | 131 | int res = DHT_bootstrap_from_address(dht, argv[argvoffset + 1], |
119 | uint8_t *bootstrap_key = hex_string_to_bin(argv[3]); | 132 | ipv6enabled, port, bootstrap_key); |
120 | DHT_bootstrap(dht, bootstrap_info, bootstrap_key); | ||
121 | free(bootstrap_key); | 133 | free(bootstrap_key); |
134 | |||
135 | if (!res) { | ||
136 | printf("Failed to convert \"%s\" into an IP address. Exiting...\n", argv[argvoffset + 1]); | ||
137 | exit(1); | ||
138 | } | ||
122 | } | 139 | } |
123 | 140 | ||
124 | int is_waiting_for_dht_connection = 1; | 141 | int is_waiting_for_dht_connection = 1; |
diff --git a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c index 0ef1f314..890085cc 100644 --- a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c +++ b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c | |||
@@ -305,7 +305,12 @@ struct server_conf_s configure_server(char *cfg_file) | |||
305 | printf("bootstrap_server %d: Invalid port.\n", i); | 305 | printf("bootstrap_server %d: Invalid port.\n", i); |
306 | } | 306 | } |
307 | 307 | ||
308 | #ifdef TOX_ENABLE_IPV6 | ||
309 | server_conf.info[i].conn.ip.family = AF_INET; | ||
310 | server_conf.info[i].conn.ip.ip4.uint32 = resolve_addr(strcpy(tmp_ip, bs_ip)); | ||
311 | #else | ||
308 | server_conf.info[i].conn.ip.uint32 = resolve_addr(strcpy(tmp_ip, bs_ip)); | 312 | server_conf.info[i].conn.ip.uint32 = resolve_addr(strcpy(tmp_ip, bs_ip)); |
313 | #endif | ||
309 | server_conf.info[i].conn.port = htons(bs_port); | 314 | server_conf.info[i].conn.port = htons(bs_port); |
310 | b16_to_key(strcpy(tmp_pk, bs_pk), bs_pk_p); | 315 | b16_to_key(strcpy(tmp_pk, bs_pk), bs_pk_p); |
311 | } | 316 | } |
@@ -344,7 +349,7 @@ int main(int argc, char *argv[]) | |||
344 | /* Initialize networking | 349 | /* Initialize networking |
345 | bind to ip 0.0.0.0:PORT */ | 350 | bind to ip 0.0.0.0:PORT */ |
346 | IP ip; | 351 | IP ip; |
347 | ip.uint32 = 0; | 352 | ip_init(&ip, 0); |
348 | DHT *dht = new_DHT(new_net_crypto(new_networking(ip, server_conf.port))); | 353 | DHT *dht = new_DHT(new_net_crypto(new_networking(ip, server_conf.port))); |
349 | /* Read the config file */ | 354 | /* Read the config file */ |
350 | printf("PID file: %s\n", server_conf.pid_file); | 355 | printf("PID file: %s\n", server_conf.pid_file); |
diff --git a/testing/DHT_test.c b/testing/DHT_test.c index fce9c257..9eab60de 100644 --- a/testing/DHT_test.c +++ b/testing/DHT_test.c | |||
@@ -66,13 +66,11 @@ void print_clientlist(DHT *dht) | |||
66 | } | 66 | } |
67 | 67 | ||
68 | p_ip = dht->close_clientlist[i].ip_port; | 68 | p_ip = dht->close_clientlist[i].ip_port; |
69 | printf("\nIP: %u.%u.%u.%u Port: %u", p_ip.ip.uint8[0], p_ip.ip.uint8[1], p_ip.ip.uint8[2], p_ip.ip.uint8[3], | 69 | printf("\nIP: %s Port: %u", ip_ntoa(&p_ip.ip), ntohs(p_ip.port)); |
70 | ntohs(p_ip.port)); | ||
71 | printf("\nTimestamp: %llu", (long long unsigned int) dht->close_clientlist[i].timestamp); | 70 | printf("\nTimestamp: %llu", (long long unsigned int) dht->close_clientlist[i].timestamp); |
72 | printf("\nLast pinged: %llu\n", (long long unsigned int) dht->close_clientlist[i].last_pinged); | 71 | printf("\nLast pinged: %llu\n", (long long unsigned int) dht->close_clientlist[i].last_pinged); |
73 | p_ip = dht->close_clientlist[i].ret_ip_port; | 72 | p_ip = dht->close_clientlist[i].ret_ip_port; |
74 | printf("OUR IP: %u.%u.%u.%u Port: %u\n", p_ip.ip.uint8[0], p_ip.ip.uint8[1], p_ip.ip.uint8[2], p_ip.ip.uint8[3], | 73 | printf("OUR IP: %s Port: %u\n", ip_ntoa(&p_ip.ip), ntohs(p_ip.port)); |
75 | ntohs(p_ip.port)); | ||
76 | printf("Timestamp: %llu\n", (long long unsigned int) dht->close_clientlist[i].ret_timestamp); | 74 | printf("Timestamp: %llu\n", (long long unsigned int) dht->close_clientlist[i].ret_timestamp); |
77 | } | 75 | } |
78 | } | 76 | } |
@@ -91,9 +89,8 @@ void print_friendlist(DHT *dht) | |||
91 | printf("%c", dht->friends_list[k].client_id[j]); | 89 | printf("%c", dht->friends_list[k].client_id[j]); |
92 | } | 90 | } |
93 | 91 | ||
94 | p_ip = DHT_getfriendip(dht, dht->friends_list[k].client_id); | 92 | int friendok = DHT_getfriendip(dht, dht->friends_list[k].client_id, &p_ip); |
95 | printf("\nIP: %u.%u.%u.%u:%u", p_ip.ip.uint8[0], p_ip.ip.uint8[1], p_ip.ip.uint8[2], p_ip.ip.uint8[3], | 93 | printf("\nIP: %s:%u", ip_ntoa(&p_ip.ip), ntohs(p_ip.port)); |
96 | ntohs(p_ip.port)); | ||
97 | 94 | ||
98 | printf("\nCLIENTS IN LIST:\n\n"); | 95 | printf("\nCLIENTS IN LIST:\n\n"); |
99 | 96 | ||
@@ -108,13 +105,11 @@ void print_friendlist(DHT *dht) | |||
108 | } | 105 | } |
109 | 106 | ||
110 | p_ip = dht->friends_list[k].client_list[i].ip_port; | 107 | p_ip = dht->friends_list[k].client_list[i].ip_port; |
111 | printf("\nIP: %u.%u.%u.%u:%u", p_ip.ip.uint8[0], p_ip.ip.uint8[1], p_ip.ip.uint8[2], p_ip.ip.uint8[3], | 108 | printf("\nIP: %s:%u", ip_ntoa(&p_ip.ip), ntohs(p_ip.port)); |
112 | ntohs(p_ip.port)); | ||
113 | printf("\nTimestamp: %llu", (long long unsigned int) dht->friends_list[k].client_list[i].timestamp); | 109 | printf("\nTimestamp: %llu", (long long unsigned int) dht->friends_list[k].client_list[i].timestamp); |
114 | printf("\nLast pinged: %llu\n", (long long unsigned int) dht->friends_list[k].client_list[i].last_pinged); | 110 | printf("\nLast pinged: %llu\n", (long long unsigned int) dht->friends_list[k].client_list[i].last_pinged); |
115 | p_ip = dht->friends_list[k].client_list[i].ret_ip_port; | 111 | p_ip = dht->friends_list[k].client_list[i].ret_ip_port; |
116 | printf("ret IP: %u.%u.%u.%u:%u\n", p_ip.ip.uint8[0], p_ip.ip.uint8[1], p_ip.ip.uint8[2], p_ip.ip.uint8[3], | 112 | printf("ret IP: %s:%u\n", ip_ntoa(&p_ip.ip), ntohs(p_ip.port)); |
117 | ntohs(p_ip.port)); | ||
118 | printf("Timestamp: %llu\n", (long long unsigned int)dht->friends_list[k].client_list[i].ret_timestamp); | 113 | printf("Timestamp: %llu\n", (long long unsigned int)dht->friends_list[k].client_list[i].ret_timestamp); |
119 | } | 114 | } |
120 | } | 115 | } |
@@ -138,19 +133,25 @@ void printpacket(uint8_t *data, uint32_t length, IP_Port ip_port) | |||
138 | 133 | ||
139 | int main(int argc, char *argv[]) | 134 | int main(int argc, char *argv[]) |
140 | { | 135 | { |
136 | if (argc < 4) { | ||
137 | printf("Usage: %s [--ipv4|--ipv6] ip port public_key\n", argv[0]); | ||
138 | exit(0); | ||
139 | } | ||
140 | |||
141 | /* let user override default by cmdline */ | ||
142 | uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */ | ||
143 | int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled); | ||
144 | if (argvoffset < 0) | ||
145 | exit(1); | ||
146 | |||
141 | //memcpy(self_client_id, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 32); | 147 | //memcpy(self_client_id, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 32); |
142 | /* initialize networking */ | 148 | /* initialize networking */ |
143 | /* bind to ip 0.0.0.0:PORT */ | 149 | /* bind to ip 0.0.0.0:PORT */ |
144 | IP ip; | 150 | IP ip; |
145 | ip.uint32 = 0; | 151 | ip_init(&ip, ipv6enabled); |
146 | 152 | ||
147 | DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT))); | 153 | DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT))); |
148 | 154 | ||
149 | if (argc < 4) { | ||
150 | printf("usage %s ip port public_key\n", argv[0]); | ||
151 | exit(0); | ||
152 | } | ||
153 | |||
154 | new_keys(dht->c); | 155 | new_keys(dht->c); |
155 | printf("OUR ID: "); | 156 | printf("OUR ID: "); |
156 | uint32_t i; | 157 | uint32_t i; |
@@ -170,16 +171,16 @@ int main(int argc, char *argv[]) | |||
170 | 171 | ||
171 | DHT_addfriend(dht, hex_string_to_bin(temp_id)); | 172 | DHT_addfriend(dht, hex_string_to_bin(temp_id)); |
172 | 173 | ||
173 | |||
174 | perror("Initialization"); | 174 | perror("Initialization"); |
175 | IP_Port bootstrap_ip_port; | 175 | |
176 | bootstrap_ip_port.port = htons(atoi(argv[2])); | 176 | uint16_t port = htons(atoi(argv[argvoffset + 2])); |
177 | /* bootstrap_ip_port.ip.c[0] = 127; | 177 | unsigned char *binary_string = hex_string_to_bin(argv[argvoffset + 3]); |
178 | * bootstrap_ip_port.ip.c[1] = 0; | 178 | int res = DHT_bootstrap_from_address(dht, argv[argvoffset + 1], ipv6enabled, port, binary_string); |
179 | * bootstrap_ip_port.ip.c[2] = 0; | 179 | free(binary_string); |
180 | * bootstrap_ip_port.ip.c[3] = 1; */ | 180 | if (!res) { |
181 | bootstrap_ip_port.ip.uint32 = inet_addr(argv[1]); | 181 | printf("Failed to convert \"%s\" into an IP address. Exiting...\n", argv[argvoffset + 1]); |
182 | DHT_bootstrap(dht, bootstrap_ip_port, hex_string_to_bin(argv[3])); | 182 | return 1; |
183 | } | ||
183 | 184 | ||
184 | /* | 185 | /* |
185 | IP_Port ip_port; | 186 | IP_Port ip_port; |
diff --git a/testing/Lossless_UDP_testclient.c b/testing/Lossless_UDP_testclient.c index d5fb1544..155a412a 100644 --- a/testing/Lossless_UDP_testclient.c +++ b/testing/Lossless_UDP_testclient.c | |||
@@ -34,6 +34,7 @@ | |||
34 | 34 | ||
35 | #include "../toxcore/network.h" | 35 | #include "../toxcore/network.h" |
36 | #include "../toxcore/Lossless_UDP.h" | 36 | #include "../toxcore/Lossless_UDP.h" |
37 | #include "misc_tools.c" | ||
37 | 38 | ||
38 | #ifdef WIN32 | 39 | #ifdef WIN32 |
39 | 40 | ||
@@ -66,8 +67,7 @@ void printpacket(uint8_t *data, uint32_t length, IP_Port ip_port) | |||
66 | 67 | ||
67 | void printip(IP_Port ip_port) | 68 | void printip(IP_Port ip_port) |
68 | { | 69 | { |
69 | printf("\nIP: %u.%u.%u.%u Port: %u", ip_port.ip.uint8[0], ip_port.ip.uint8[1], ip_port.ip.uint8[2], ip_port.ip.uint8[3], | 70 | printf("\nIP: %s Port: %u", ip_ntoa(&ip_port.ip), ntohs(ip_port.port)); |
70 | ntohs(ip_port.port)); | ||
71 | } | 71 | } |
72 | /* | 72 | /* |
73 | void printpackets(Data test) | 73 | void printpackets(Data test) |
@@ -152,30 +152,45 @@ void printconnection(int connection_id) | |||
152 | 152 | ||
153 | int main(int argc, char *argv[]) | 153 | int main(int argc, char *argv[]) |
154 | { | 154 | { |
155 | if (argc < 4) { | 155 | /* let user override default by cmdline */ |
156 | printf("usage: %s ip port filename\n", argv[0]); | 156 | uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */ |
157 | int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled); | ||
158 | if (argvoffset < 0) | ||
159 | exit(1); | ||
160 | |||
161 | if (argc < argvoffset + 4) { | ||
162 | printf("Usage: %s [--ipv4|--ipv6] ip port filename\n", argv[0]); | ||
157 | exit(0); | 163 | exit(0); |
158 | } | 164 | } |
159 | 165 | ||
160 | uint8_t buffer[512]; | 166 | uint8_t buffer[512]; |
161 | int read; | 167 | int read; |
162 | 168 | ||
163 | FILE *file = fopen(argv[3], "rb"); | 169 | FILE *file = fopen(argv[argvoffset + 3], "rb"); |
164 | 170 | ||
165 | if (file == NULL) | 171 | if (file == NULL) { |
172 | printf("Failed to open file \"%s\".\n", argv[argvoffset + 3]); | ||
166 | return 1; | 173 | return 1; |
174 | } | ||
167 | 175 | ||
168 | 176 | ||
169 | /* initialize networking */ | 177 | /* initialize networking */ |
170 | /* bind to ip 0.0.0.0:PORT */ | 178 | /* bind to ip 0.0.0.0:PORT */ |
171 | IP ip; | 179 | IP ip; |
172 | ip.uint32 = 0; | 180 | ip_init(&ip, ipv6enabled); |
181 | |||
173 | Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT)); | 182 | Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT)); |
174 | perror("Initialization"); | 183 | perror("Initialization"); |
184 | |||
175 | IP_Port serverip; | 185 | IP_Port serverip; |
176 | serverip.ip.uint32 = inet_addr(argv[1]); | 186 | ip_init(&serverip.ip, ipv6enabled); |
177 | serverip.port = htons(atoi(argv[2])); | 187 | if (!addr_resolve(argv[argvoffset + 1], &serverip.ip, NULL)) { |
188 | printf("Failed to convert \"%s\" into an IP address.\n", argv[argvoffset + 1]); | ||
189 | return 1; | ||
190 | } | ||
191 | serverip.port = htons(atoi(argv[argvoffset + 2])); | ||
178 | printip(serverip); | 192 | printip(serverip); |
193 | |||
179 | int connection = new_connection(ludp, serverip); | 194 | int connection = new_connection(ludp, serverip); |
180 | uint64_t timer = current_time(); | 195 | uint64_t timer = current_time(); |
181 | 196 | ||
diff --git a/testing/Lossless_UDP_testserver.c b/testing/Lossless_UDP_testserver.c index eb506b3d..0fd4edd9 100644 --- a/testing/Lossless_UDP_testserver.c +++ b/testing/Lossless_UDP_testserver.c | |||
@@ -34,6 +34,7 @@ | |||
34 | 34 | ||
35 | #include "../toxcore/network.h" | 35 | #include "../toxcore/network.h" |
36 | #include "../toxcore/Lossless_UDP.h" | 36 | #include "../toxcore/Lossless_UDP.h" |
37 | #include "misc_tools.c" | ||
37 | 38 | ||
38 | //Sleep function (x = milliseconds) | 39 | //Sleep function (x = milliseconds) |
39 | #ifdef WIN32 | 40 | #ifdef WIN32 |
@@ -147,24 +148,33 @@ void printconnection(int connection_id) | |||
147 | 148 | ||
148 | int main(int argc, char *argv[]) | 149 | int main(int argc, char *argv[]) |
149 | { | 150 | { |
150 | if (argc < 2) { | 151 | /* let user override default by cmdline */ |
151 | printf("usage: %s filename\n", argv[0]); | 152 | uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */ |
153 | int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled); | ||
154 | if (argvoffset < 0) | ||
155 | exit(1); | ||
156 | |||
157 | if (argc < argvoffset + 2) { | ||
158 | printf("Usage: %s [--ipv4|--ipv6] filename\n", argv[0]); | ||
152 | exit(0); | 159 | exit(0); |
153 | } | 160 | } |
154 | 161 | ||
155 | uint8_t buffer[512]; | 162 | uint8_t buffer[512]; |
156 | int read; | 163 | int read; |
157 | 164 | ||
158 | FILE *file = fopen(argv[1], "wb"); | 165 | FILE *file = fopen(argv[argvoffset + 1], "wb"); |
159 | 166 | ||
160 | if (file == NULL) | 167 | if (file == NULL) { |
168 | printf("Failed to open file \"%s\".\n", argv[argvoffset + 1]); | ||
161 | return 1; | 169 | return 1; |
170 | } | ||
162 | 171 | ||
163 | 172 | ||
164 | //initialize networking | 173 | //initialize networking |
165 | //bind to ip 0.0.0.0:PORT | 174 | //bind to ip 0.0.0.0:PORT |
166 | IP ip; | 175 | IP ip; |
167 | ip.uint32 = 0; | 176 | ip_init(&ip, ipv6enabled); |
177 | |||
168 | Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT)); | 178 | Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT)); |
169 | perror("Initialization"); | 179 | perror("Initialization"); |
170 | 180 | ||
diff --git a/testing/Messenger_test.c b/testing/Messenger_test.c index e85a85a2..06f8bdbf 100644 --- a/testing/Messenger_test.c +++ b/testing/Messenger_test.c | |||
@@ -95,27 +95,41 @@ void print_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t len | |||
95 | 95 | ||
96 | int main(int argc, char *argv[]) | 96 | int main(int argc, char *argv[]) |
97 | { | 97 | { |
98 | if (argc < 4 && argc != 2) { | 98 | /* let user override default by cmdline */ |
99 | printf("usage %s ip port public_key (of the DHT bootstrap node)\n or\n %s Save.bak\n", argv[0], argv[0]); | 99 | uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */ |
100 | int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled); | ||
101 | if (argvoffset < 0) | ||
102 | exit(1); | ||
103 | |||
104 | /* with optional --ipvx, now it can be 1-4 arguments... */ | ||
105 | if ((argc != argvoffset + 2) && (argc != argvoffset + 4)) { | ||
106 | printf("Usage: %s [--ipv4|--ipv6] ip port public_key (of the DHT bootstrap node)\n", argv[0]); | ||
107 | printf("or\n"); | ||
108 | printf(" %s [--ipv4|--ipv6] Save.bak (to read Save.bak as state file)\n", argv[0]); | ||
100 | exit(0); | 109 | exit(0); |
101 | } | 110 | } |
102 | 111 | ||
103 | m = initMessenger(); | 112 | m = initMessenger(ipv6enabled); |
104 | 113 | ||
105 | if ( !m ) { | 114 | if ( !m ) { |
106 | fputs("Failed to allocate messenger datastructure\n", stderr); | 115 | fputs("Failed to allocate messenger datastructure\n", stderr); |
107 | exit(0); | 116 | exit(0); |
108 | } | 117 | } |
109 | 118 | ||
110 | if (argc > 3) { | 119 | if (argc == argvoffset + 4) { |
111 | IP_Port bootstrap_ip_port; | 120 | uint16_t port = htons(atoi(argv[argvoffset + 2])); |
112 | bootstrap_ip_port.port = htons(atoi(argv[2])); | 121 | uint8_t *bootstrap_key = hex_string_to_bin(argv[argvoffset + 3]); |
113 | bootstrap_ip_port.ip.uint32 = inet_addr(argv[1]); | 122 | int res = DHT_bootstrap_from_address(m->dht, argv[argvoffset + 1], |
114 | DHT_bootstrap(m->dht, bootstrap_ip_port, hex_string_to_bin(argv[3])); | 123 | ipv6enabled, port, bootstrap_key); |
124 | free(bootstrap_key); | ||
125 | if (!res) { | ||
126 | printf("Failed to convert \"%s\" into an IP address. Exiting...\n", argv[argvoffset + 1]); | ||
127 | exit(1); | ||
128 | } | ||
115 | } else { | 129 | } else { |
116 | FILE *file = fopen(argv[1], "rb"); | 130 | FILE *file = fopen(argv[argvoffset + 1], "rb"); |
117 | |||
118 | if ( file == NULL ) { | 131 | if ( file == NULL ) { |
132 | printf("Failed to open \"%s\" - does it exist?\n", argv[argvoffset + 1]); | ||
119 | return 1; | 133 | return 1; |
120 | } | 134 | } |
121 | 135 | ||
diff --git a/testing/misc_tools.c b/testing/misc_tools.c index c4dce1bb..824200d8 100644 --- a/testing/misc_tools.c +++ b/testing/misc_tools.c | |||
@@ -46,3 +46,36 @@ unsigned char *hex_string_to_bin(char hex_string[]) | |||
46 | 46 | ||
47 | return val; | 47 | return val; |
48 | } | 48 | } |
49 | |||
50 | |||
51 | int cmdline_parsefor_ipv46(int argc, char **argv, uint8_t *ipv6enabled) | ||
52 | { | ||
53 | int argvoffset = 0, argi; | ||
54 | for(argi = 1; argi < argc; argi++) | ||
55 | if (!strncasecmp(argv[argi], "--ipv", 5)) { | ||
56 | if (argv[argi][5] && !argv[argi][6]) { | ||
57 | char c = argv[argi][5]; | ||
58 | if (c == '4') | ||
59 | *ipv6enabled = 0; | ||
60 | else if (c == '6') | ||
61 | *ipv6enabled = 1; | ||
62 | else { | ||
63 | printf("Invalid argument: %s. Try --ipv4 or --ipv6!\n", argv[argi]); | ||
64 | return -1; | ||
65 | } | ||
66 | } | ||
67 | else { | ||
68 | printf("Invalid argument: %s. Try --ipv4 or --ipv6!\n", argv[argi]); | ||
69 | return -1; | ||
70 | } | ||
71 | |||
72 | if (argvoffset != argi - 1) { | ||
73 | printf("Argument must come first: %s.\n", argv[argi]); | ||
74 | return -1; | ||
75 | } | ||
76 | |||
77 | argvoffset++; | ||
78 | } | ||
79 | |||
80 | return argvoffset; | ||
81 | }; | ||
diff --git a/testing/nTox.c b/testing/nTox.c index 438468bd..1e83f507 100644 --- a/testing/nTox.c +++ b/testing/nTox.c | |||
@@ -537,6 +537,17 @@ void print_help(void) | |||
537 | 537 | ||
538 | int main(int argc, char *argv[]) | 538 | int main(int argc, char *argv[]) |
539 | { | 539 | { |
540 | if (argc < 4) { | ||
541 | printf("Usage: %s [--ipv4|--ipv6] IP PORT KEY [-f keyfile]\n", argv[0]); | ||
542 | exit(0); | ||
543 | } | ||
544 | |||
545 | /* let user override default by cmdline */ | ||
546 | uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */ | ||
547 | int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled); | ||
548 | if (argvoffset < 0) | ||
549 | exit(1); | ||
550 | |||
540 | int on = 0; | 551 | int on = 0; |
541 | int c = 0; | 552 | int c = 0; |
542 | int i = 0; | 553 | int i = 0; |
@@ -544,29 +555,18 @@ int main(int argc, char *argv[]) | |||
544 | char idstring[200] = {0}; | 555 | char idstring[200] = {0}; |
545 | Tox *m; | 556 | Tox *m; |
546 | 557 | ||
547 | if (argc < 4) { | 558 | if ((argc == 2) && !strcmp(argv[1], "-h")) { |
548 | printf("[!] Usage: %s [IP] [port] [public_key] <keyfile>\n", argv[0]); | 559 | print_help(); |
549 | exit(0); | 560 | exit(0); |
550 | } | 561 | } |
551 | 562 | ||
552 | for (i = 0; i < argc; i++) { | 563 | /* [-f keyfile] MUST be last two arguments, no point in walking over the list |
553 | if (argv[i] == NULL) { | 564 | * especially not a good idea to accept it anywhere in the middle */ |
554 | break; | 565 | if (argc > argvoffset + 3) |
555 | } else if (argv[i][0] == '-') { | 566 | if (!strcmp(argv[argc - 2], "-f")) |
556 | if (argv[i][1] == 'h') { | 567 | filename = argv[argc - 1]; |
557 | print_help(); | ||
558 | exit(0); | ||
559 | } else if (argv[i][1] == 'f') { | ||
560 | if (argv[i + 1] != NULL) | ||
561 | filename = argv[i + 1]; | ||
562 | else { | ||
563 | fputs("[!] you passed '-f' without giving an argument!\n", stderr); | ||
564 | } | ||
565 | } | ||
566 | } | ||
567 | } | ||
568 | 568 | ||
569 | m = tox_new(); | 569 | m = tox_new(ipv6enabled); |
570 | 570 | ||
571 | if ( !m ) { | 571 | if ( !m ) { |
572 | fputs("Failed to allocate Messenger datastructure", stderr); | 572 | fputs("Failed to allocate Messenger datastructure", stderr); |
@@ -590,20 +590,18 @@ int main(int argc, char *argv[]) | |||
590 | new_lines(idstring); | 590 | new_lines(idstring); |
591 | strcpy(line, ""); | 591 | strcpy(line, ""); |
592 | 592 | ||
593 | tox_IP_Port bootstrap_ip_port; | 593 | uint16_t port = htons(atoi(argv[argvoffset + 2])); |
594 | bootstrap_ip_port.port = htons(atoi(argv[2])); | 594 | unsigned char *binary_string = hex_string_to_bin(argv[argvoffset + 3]); |
595 | int resolved_address = resolve_addr(argv[1]); | 595 | int res = tox_bootstrap_from_address(m, argv[argvoffset + 1], ipv6enabled, port, binary_string); |
596 | free(binary_string); | ||
596 | 597 | ||
597 | if (resolved_address != 0) | 598 | if (!res) { |
598 | bootstrap_ip_port.ip.i = resolved_address; | 599 | printf("Failed to convert \"%s\" into an IP address. Exiting...\n", argv[argvoffset + 1]); |
599 | else | 600 | endwin(); |
600 | exit(1); | 601 | exit(1); |
602 | } | ||
601 | 603 | ||
602 | unsigned char *binary_string = hex_string_to_bin(argv[3]); | ||
603 | tox_bootstrap(m, bootstrap_ip_port, binary_string); | ||
604 | free(binary_string); | ||
605 | nodelay(stdscr, TRUE); | 604 | nodelay(stdscr, TRUE); |
606 | |||
607 | while (1) { | 605 | while (1) { |
608 | if (on == 0 && tox_isconnected(m)) { | 606 | if (on == 0 && tox_isconnected(m)) { |
609 | new_lines("[i] connected to DHT\n[i] define username with /n"); | 607 | new_lines("[i] connected to DHT\n[i] define username with /n"); |
diff --git a/toxcore/DHT.c b/toxcore/DHT.c index e2d91256..a5f0c1ab 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | #include "DHT.h" | 30 | #include "DHT.h" |
31 | #include "network.h" | ||
31 | #include "ping.h" | 32 | #include "ping.h" |
32 | #include "misc_tools.h" | 33 | #include "misc_tools.h" |
33 | 34 | ||
@@ -115,11 +116,6 @@ static int client_id_cmp(ClientPair p1, ClientPair p2) | |||
115 | return c; | 116 | return c; |
116 | } | 117 | } |
117 | 118 | ||
118 | static int ipport_equal(IP_Port a, IP_Port b) | ||
119 | { | ||
120 | return (a.ip.uint32 == b.ip.uint32) && (a.port == b.port); | ||
121 | } | ||
122 | |||
123 | static int id_equal(uint8_t *a, uint8_t *b) | 119 | static int id_equal(uint8_t *a, uint8_t *b) |
124 | { | 120 | { |
125 | return memcmp(a, b, CLIENT_ID_SIZE) == 0; | 121 | return memcmp(a, b, CLIENT_ID_SIZE) == 0; |
@@ -142,20 +138,23 @@ static int client_in_list(Client_data *list, uint32_t length, uint8_t *client_id | |||
142 | uint32_t i; | 138 | uint32_t i; |
143 | uint64_t temp_time = unix_time(); | 139 | uint64_t temp_time = unix_time(); |
144 | 140 | ||
145 | for (i = 0; i < length; ++i) { | 141 | /* if client_id is in list, find it and maybe overwrite ip_port */ |
146 | /* If ip_port is assigned to a different client_id replace it */ | 142 | for (i = 0; i < length; ++i) |
147 | if (ipport_equal(list[i].ip_port, ip_port)) { | 143 | if (id_equal(list[i].client_id, client_id)) { |
148 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); | 144 | /* Refresh the client timestamp. */ |
145 | list[i].timestamp = temp_time; | ||
146 | list[i].ip_port = ip_port; | ||
147 | return 1; | ||
149 | } | 148 | } |
150 | 149 | ||
151 | if (id_equal(list[i].client_id, client_id)) { | 150 | /* client_id not in list yet: find ip_port to overwrite */ |
151 | for (i = 0; i < length; ++i) | ||
152 | if (ipport_equal(&list[i].ip_port, &ip_port)) { | ||
152 | /* Refresh the client timestamp. */ | 153 | /* Refresh the client timestamp. */ |
153 | list[i].timestamp = temp_time; | 154 | list[i].timestamp = temp_time; |
154 | list[i].ip_port.ip.uint32 = ip_port.ip.uint32; | 155 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); |
155 | list[i].ip_port.port = ip_port.port; | ||
156 | return 1; | 156 | return 1; |
157 | } | 157 | } |
158 | } | ||
159 | 158 | ||
160 | return 0; | 159 | return 0; |
161 | } | 160 | } |
@@ -197,18 +196,37 @@ static int friend_number(DHT *dht, uint8_t *client_id) | |||
197 | * | 196 | * |
198 | * TODO: For the love of based Allah make this function cleaner and much more efficient. | 197 | * TODO: For the love of based Allah make this function cleaner and much more efficient. |
199 | */ | 198 | */ |
200 | static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list) | 199 | static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family) |
201 | { | 200 | { |
202 | uint32_t i, j, k; | 201 | uint32_t i, j, k; |
203 | uint64_t temp_time = unix_time(); | 202 | uint64_t temp_time = unix_time(); |
204 | int num_nodes = 0, closest, tout, inlist; | 203 | int num_nodes = 0, closest, tout, inlist, ipv46x; |
205 | 204 | ||
206 | for (i = 0; i < LCLIENT_LIST; ++i) { | 205 | for (i = 0; i < LCLIENT_LIST; ++i) { |
207 | tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT); | 206 | tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT); |
208 | inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id); | 207 | inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id); |
209 | 208 | ||
209 | /* | ||
210 | * NET_PACKET_SEND_NODES sends ONLY AF_INET | ||
211 | * NET_PACKET_SEND_NODES_EX sends ALL BUT AF_INET (i.e. AF_INET6), | ||
212 | * it could send both, but then a) packet size is an issue and | ||
213 | * b) duplicates the traffic (NET_PACKET_SEND_NODES has to be | ||
214 | * sent anyways for backwards compatibility) | ||
215 | * we COULD send ALL as NET_PACKET_SEND_NODES_EX if we KNEW that the | ||
216 | * partner node understands - that's true if *they* are on IPv6 | ||
217 | */ | ||
218 | #ifdef TOX_ENABLE_IPV6 | ||
219 | ipv46x = 0; | ||
220 | if (sa_family == AF_INET) | ||
221 | ipv46x = dht->close_clientlist[i].ip_port.ip.family != AF_INET; | ||
222 | else | ||
223 | ipv46x = dht->close_clientlist[i].ip_port.ip.family == AF_INET; | ||
224 | #else | ||
225 | ipv46x = sa_family != AF_INET; | ||
226 | #endif | ||
227 | |||
210 | /* If node isn't good or is already in list. */ | 228 | /* If node isn't good or is already in list. */ |
211 | if (tout || inlist) | 229 | if (tout || inlist || ipv46x) |
212 | continue; | 230 | continue; |
213 | 231 | ||
214 | if (num_nodes < MAX_SENT_NODES) { | 232 | if (num_nodes < MAX_SENT_NODES) { |
@@ -247,8 +265,18 @@ static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list | |||
247 | MAX_SENT_NODES, | 265 | MAX_SENT_NODES, |
248 | dht->friends_list[i].client_list[j].client_id); | 266 | dht->friends_list[i].client_list[j].client_id); |
249 | 267 | ||
268 | #ifdef TOX_ENABLE_IPV6 | ||
269 | ipv46x = 0; | ||
270 | if (sa_family == AF_INET) | ||
271 | ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family != AF_INET; | ||
272 | else | ||
273 | ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family == AF_INET; | ||
274 | #else | ||
275 | ipv46x = sa_family != AF_INET; | ||
276 | #endif | ||
277 | |||
250 | /* If node isn't good or is already in list. */ | 278 | /* If node isn't good or is already in list. */ |
251 | if (tout || inlist) | 279 | if (tout || inlist || ipv46x) |
252 | continue; | 280 | continue; |
253 | 281 | ||
254 | if (num_nodes < MAX_SENT_NODES) { | 282 | if (num_nodes < MAX_SENT_NODES) { |
@@ -301,7 +329,7 @@ static int replace_bad( Client_data *list, | |||
301 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); | 329 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); |
302 | list[i].ip_port = ip_port; | 330 | list[i].ip_port = ip_port; |
303 | list[i].timestamp = temp_time; | 331 | list[i].timestamp = temp_time; |
304 | list[i].ret_ip_port.ip.uint32 = 0; | 332 | ip_reset(&list[i].ret_ip_port.ip); |
305 | list[i].ret_ip_port.port = 0; | 333 | list[i].ret_ip_port.port = 0; |
306 | list[i].ret_timestamp = 0; | 334 | list[i].ret_timestamp = 0; |
307 | return 0; | 335 | return 0; |
@@ -349,7 +377,7 @@ static int replace_good( Client_data *list, | |||
349 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); | 377 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); |
350 | list[i].ip_port = ip_port; | 378 | list[i].ip_port = ip_port; |
351 | list[i].timestamp = temp_time; | 379 | list[i].timestamp = temp_time; |
352 | list[i].ret_ip_port.ip.uint32 = 0; | 380 | ip_reset(&list[i].ret_ip_port.ip); |
353 | list[i].ret_ip_port.port = 0; | 381 | list[i].ret_ip_port.port = 0; |
354 | list[i].ret_timestamp = 0; | 382 | list[i].ret_timestamp = 0; |
355 | return 0; | 383 | return 0; |
@@ -447,13 +475,13 @@ static int is_gettingnodes(DHT *dht, IP_Port ip_port, uint64_t ping_id) | |||
447 | if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) { | 475 | if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) { |
448 | pinging = 0; | 476 | pinging = 0; |
449 | 477 | ||
450 | if (ip_port.ip.uint32 != 0 && ipport_equal(dht->send_nodes[i].ip_port, ip_port)) | 478 | if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id) |
451 | ++pinging; | 479 | ++pinging; |
452 | 480 | ||
453 | if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id) | 481 | if (ip_isset(&ip_port.ip) && ipport_equal(&dht->send_nodes[i].ip_port, &ip_port)) |
454 | ++pinging; | 482 | ++pinging; |
455 | 483 | ||
456 | if (pinging == (ping_id != 0) + (ip_port.ip.uint32 != 0)) | 484 | if (pinging == (ping_id != 0) + (ip_isset(&ip_port.ip) != 0)) |
457 | return 1; | 485 | return 1; |
458 | } | 486 | } |
459 | } | 487 | } |
@@ -518,44 +546,65 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli | |||
518 | memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); | 546 | memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); |
519 | memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); | 547 | memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); |
520 | 548 | ||
521 | return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, sizeof(data)); | 549 | return sendpacket(dht->c->lossless_udp->net, ip_port, data, sizeof(data)); |
522 | } | 550 | } |
523 | 551 | ||
524 | /* Send a send nodes response. */ | 552 | /* Send a send nodes response. */ |
553 | /* because of BINARY compatibility, the Node_format MUST BE Node4_format, | ||
554 | * IPv6 nodes are sent in a different message */ | ||
525 | static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) | 555 | static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) |
526 | { | 556 | { |
527 | /* Check if packet is going to be sent to ourself. */ | 557 | /* Check if packet is going to be sent to ourself. */ |
528 | if (id_equal(public_key, dht->c->self_public_key)) | 558 | if (id_equal(public_key, dht->c->self_public_key)) |
529 | return -1; | 559 | return -1; |
530 | 560 | ||
561 | size_t Node4_format_size = sizeof(Node4_format); | ||
531 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) | 562 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) |
532 | + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; | 563 | + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING]; |
533 | 564 | ||
534 | Node_format nodes_list[MAX_SENT_NODES]; | 565 | Node_format nodes_list[MAX_SENT_NODES]; |
535 | int num_nodes = get_close_nodes(dht, client_id, nodes_list); | 566 | int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET); |
536 | 567 | ||
537 | if (num_nodes == 0) | 568 | if (num_nodes == 0) |
538 | return 0; | 569 | return 0; |
539 | 570 | ||
540 | uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; | 571 | uint8_t plain[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES]; |
541 | uint8_t encrypt[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; | 572 | uint8_t encrypt[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING]; |
542 | uint8_t nonce[crypto_box_NONCEBYTES]; | 573 | uint8_t nonce[crypto_box_NONCEBYTES]; |
543 | random_nonce(nonce); | 574 | random_nonce(nonce); |
544 | 575 | ||
545 | memcpy(plain, &ping_id, sizeof(ping_id)); | 576 | memcpy(plain, &ping_id, sizeof(ping_id)); |
546 | memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format)); | 577 | #ifdef TOX_ENABLE_IPV6 |
578 | Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); | ||
579 | int i, num_nodes_ok = 0; | ||
580 | for(i = 0; i < num_nodes; i++) | ||
581 | if (nodes_list[i].ip_port.ip.family == AF_INET) { | ||
582 | memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE); | ||
583 | nodes4_list[num_nodes_ok].ip_port.ip.uint32 = nodes_list[i].ip_port.ip.ip4.uint32; | ||
584 | nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port; | ||
585 | |||
586 | num_nodes_ok++; | ||
587 | } | ||
588 | |||
589 | if (num_nodes_ok < num_nodes) { | ||
590 | /* shouldn't happen */ | ||
591 | num_nodes = num_nodes_ok; | ||
592 | } | ||
593 | #else | ||
594 | memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node4_format_size); | ||
595 | #endif | ||
547 | 596 | ||
548 | int len = encrypt_data( public_key, | 597 | int len = encrypt_data( public_key, |
549 | dht->c->self_secret_key, | 598 | dht->c->self_secret_key, |
550 | nonce, | 599 | nonce, |
551 | plain, | 600 | plain, |
552 | sizeof(ping_id) + num_nodes * sizeof(Node_format), | 601 | sizeof(ping_id) + num_nodes * Node4_format_size, |
553 | encrypt ); | 602 | encrypt ); |
554 | 603 | ||
555 | if (len == -1) | 604 | if (len == -1) |
556 | return -1; | 605 | return -1; |
557 | 606 | ||
558 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING) | 607 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING) |
559 | return -1; | 608 | return -1; |
560 | 609 | ||
561 | data[0] = NET_PACKET_SEND_NODES; | 610 | data[0] = NET_PACKET_SEND_NODES; |
@@ -563,8 +612,56 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl | |||
563 | memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); | 612 | memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); |
564 | memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); | 613 | memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); |
565 | 614 | ||
566 | return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); | 615 | return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); |
616 | } | ||
617 | |||
618 | #ifdef TOX_ENABLE_IPV6 | ||
619 | /* Send a send nodes response: message for IPv6 nodes */ | ||
620 | static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) | ||
621 | { | ||
622 | /* Check if packet is going to be sent to ourself. */ | ||
623 | if (id_equal(public_key, dht->c->self_public_key)) | ||
624 | return -1; | ||
625 | |||
626 | size_t Node_format_size = sizeof(Node_format); | ||
627 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) | ||
628 | + Node_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING]; | ||
629 | |||
630 | Node_format nodes_list[MAX_SENT_NODES]; | ||
631 | int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET6); | ||
632 | |||
633 | if (num_nodes == 0) | ||
634 | return 0; | ||
635 | |||
636 | uint8_t plain[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES]; | ||
637 | uint8_t encrypt[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING]; | ||
638 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
639 | random_nonce(nonce); | ||
640 | |||
641 | memcpy(plain, &ping_id, sizeof(ping_id)); | ||
642 | memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node_format_size); | ||
643 | |||
644 | int len = encrypt_data( public_key, | ||
645 | dht->c->self_secret_key, | ||
646 | nonce, | ||
647 | plain, | ||
648 | sizeof(ping_id) + num_nodes * Node_format_size, | ||
649 | encrypt ); | ||
650 | |||
651 | if (len == -1) | ||
652 | return -1; | ||
653 | |||
654 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node_format_size + ENCRYPTION_PADDING) | ||
655 | return -1; | ||
656 | |||
657 | data[0] = NET_PACKET_SEND_NODES_IPV6; | ||
658 | memcpy(data + 1, dht->c->self_public_key, CLIENT_ID_SIZE); | ||
659 | memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); | ||
660 | memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); | ||
661 | |||
662 | return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); | ||
567 | } | 663 | } |
664 | #endif | ||
568 | 665 | ||
569 | static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 666 | static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) |
570 | { | 667 | { |
@@ -593,6 +690,9 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32 | |||
593 | 690 | ||
594 | memcpy(&ping_id, plain, sizeof(ping_id)); | 691 | memcpy(&ping_id, plain, sizeof(ping_id)); |
595 | sendnodes(dht, source, packet + 1, plain + sizeof(ping_id), ping_id); | 692 | sendnodes(dht, source, packet + 1, plain + sizeof(ping_id), ping_id); |
693 | #ifdef TOX_ENABLE_IPV6 | ||
694 | sendnodes_ipv6(dht, source, packet + 1, plain + sizeof(ping_id), ping_id); | ||
695 | #endif | ||
596 | 696 | ||
597 | //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */ | 697 | //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */ |
598 | 698 | ||
@@ -606,22 +706,23 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3 | |||
606 | uint32_t cid_size = 1 + CLIENT_ID_SIZE; | 706 | uint32_t cid_size = 1 + CLIENT_ID_SIZE; |
607 | cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; | 707 | cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; |
608 | 708 | ||
609 | if (length > (cid_size + sizeof(Node_format) * MAX_SENT_NODES) || | 709 | size_t Node4_format_size = sizeof(Node4_format); |
610 | ((length - cid_size) % sizeof(Node_format)) != 0 || | 710 | if (length > (cid_size + Node4_format_size * MAX_SENT_NODES) || |
611 | (length < cid_size + sizeof(Node_format))) | 711 | ((length - cid_size) % Node4_format_size) != 0 || |
712 | (length < cid_size + Node4_format_size)) | ||
612 | return 1; | 713 | return 1; |
613 | 714 | ||
614 | uint32_t num_nodes = (length - cid_size) / sizeof(Node_format); | 715 | uint32_t num_nodes = (length - cid_size) / Node4_format_size; |
615 | uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; | 716 | uint8_t plain[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES]; |
616 | 717 | ||
617 | int len = decrypt_data( | 718 | int len = decrypt_data( |
618 | packet + 1, | 719 | packet + 1, |
619 | dht->c->self_secret_key, | 720 | dht->c->self_secret_key, |
620 | packet + 1 + CLIENT_ID_SIZE, | 721 | packet + 1 + CLIENT_ID_SIZE, |
621 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, | 722 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, |
622 | sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain ); | 723 | sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING, plain ); |
623 | 724 | ||
624 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format)) | 725 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size) |
625 | return 1; | 726 | return 1; |
626 | 727 | ||
627 | memcpy(&ping_id, plain, sizeof(ping_id)); | 728 | memcpy(&ping_id, plain, sizeof(ping_id)); |
@@ -629,12 +730,78 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3 | |||
629 | if (!is_gettingnodes(dht, source, ping_id)) | 730 | if (!is_gettingnodes(dht, source, ping_id)) |
630 | return 1; | 731 | return 1; |
631 | 732 | ||
733 | uint32_t i; | ||
632 | Node_format nodes_list[MAX_SENT_NODES]; | 734 | Node_format nodes_list[MAX_SENT_NODES]; |
735 | |||
736 | #ifdef TOX_ENABLE_IPV6 | ||
737 | Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); | ||
738 | |||
739 | int num_nodes_ok = 0; | ||
740 | for(i = 0; i < num_nodes; i++) | ||
741 | if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != ~0)) { | ||
742 | memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE); | ||
743 | nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET; | ||
744 | nodes_list[num_nodes_ok].ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32; | ||
745 | nodes_list[num_nodes_ok].ip_port.port = nodes4_list[i].ip_port.port; | ||
746 | |||
747 | num_nodes_ok++; | ||
748 | } | ||
749 | |||
750 | if (num_nodes_ok < num_nodes) { | ||
751 | /* shouldn't happen */ | ||
752 | num_nodes = num_nodes_ok; | ||
753 | } | ||
754 | #else | ||
633 | memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); | 755 | memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); |
756 | #endif | ||
634 | 757 | ||
635 | addto_lists(dht, source, packet + 1); | 758 | addto_lists(dht, source, packet + 1); |
636 | 759 | ||
760 | for (i = 0; i < num_nodes; ++i) { | ||
761 | send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id); | ||
762 | returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); | ||
763 | } | ||
764 | |||
765 | return 0; | ||
766 | } | ||
767 | |||
768 | #ifdef TOX_ENABLE_IPV6 | ||
769 | static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length) | ||
770 | { | ||
771 | DHT *dht = object; | ||
772 | uint64_t ping_id; | ||
773 | uint32_t cid_size = 1 + CLIENT_ID_SIZE; | ||
774 | cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; | ||
775 | |||
776 | size_t Node_format_size = sizeof(Node4_format); | ||
777 | if (length > (cid_size + Node_format_size * MAX_SENT_NODES) || | ||
778 | ((length - cid_size) % Node_format_size) != 0 || | ||
779 | (length < cid_size + Node_format_size)) | ||
780 | return 1; | ||
781 | |||
782 | uint32_t num_nodes = (length - cid_size) / Node_format_size; | ||
783 | uint8_t plain[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES]; | ||
784 | |||
785 | int len = decrypt_data( | ||
786 | packet + 1, | ||
787 | dht->c->self_secret_key, | ||
788 | packet + 1 + CLIENT_ID_SIZE, | ||
789 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, | ||
790 | sizeof(ping_id) + num_nodes * Node_format_size + ENCRYPTION_PADDING, plain ); | ||
791 | |||
792 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node_format_size) | ||
793 | return 1; | ||
794 | |||
795 | memcpy(&ping_id, plain, sizeof(ping_id)); | ||
796 | |||
797 | if (!is_gettingnodes(dht, source, ping_id)) | ||
798 | return 1; | ||
799 | |||
637 | uint32_t i; | 800 | uint32_t i; |
801 | Node_format nodes_list[MAX_SENT_NODES]; | ||
802 | memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); | ||
803 | |||
804 | addto_lists(dht, source, packet + 1); | ||
638 | 805 | ||
639 | for (i = 0; i < num_nodes; ++i) { | 806 | for (i = 0; i < num_nodes; ++i) { |
640 | send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id); | 807 | send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id); |
@@ -643,6 +810,7 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3 | |||
643 | 810 | ||
644 | return 0; | 811 | return 0; |
645 | } | 812 | } |
813 | #endif | ||
646 | 814 | ||
647 | /*----------------------------------------------------------------------------------*/ | 815 | /*----------------------------------------------------------------------------------*/ |
648 | /*------------------------END of packet handling functions--------------------------*/ | 816 | /*------------------------END of packet handling functions--------------------------*/ |
@@ -703,27 +871,30 @@ int DHT_delfriend(DHT *dht, uint8_t *client_id) | |||
703 | } | 871 | } |
704 | 872 | ||
705 | /* TODO: Optimize this. */ | 873 | /* TODO: Optimize this. */ |
706 | IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id) | 874 | int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port) |
707 | { | 875 | { |
708 | uint32_t i, j; | 876 | uint32_t i, j; |
709 | uint64_t temp_time = unix_time(); | 877 | uint64_t temp_time = unix_time(); |
710 | IP_Port empty = {{{{0}}, 0, 0}}; | 878 | |
879 | ip_reset(&ip_port->ip); | ||
880 | ip_port->port = 0; | ||
711 | 881 | ||
712 | for (i = 0; i < dht->num_friends; ++i) { | 882 | for (i = 0; i < dht->num_friends; ++i) { |
713 | /* Equal */ | 883 | /* Equal */ |
714 | if (id_equal(dht->friends_list[i].client_id, client_id)) { | 884 | if (id_equal(dht->friends_list[i].client_id, client_id)) { |
715 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | 885 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { |
716 | if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id) | 886 | if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id) |
717 | && !is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) | 887 | && !is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) { |
718 | return dht->friends_list[i].client_list[j].ip_port; | 888 | *ip_port = dht->friends_list[i].client_list[j].ip_port; |
889 | return 1; | ||
890 | } | ||
719 | } | 891 | } |
720 | 892 | ||
721 | return empty; | 893 | return 0; |
722 | } | 894 | } |
723 | } | 895 | } |
724 | 896 | ||
725 | empty.ip.uint32 = 1; | 897 | return -1; |
726 | return empty; | ||
727 | } | 898 | } |
728 | 899 | ||
729 | /* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request | 900 | /* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request |
@@ -808,6 +979,36 @@ void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key) | |||
808 | getnodes(dht, ip_port, public_key, dht->c->self_public_key); | 979 | getnodes(dht, ip_port, public_key, dht->c->self_public_key); |
809 | send_ping_request(dht->ping, dht->c, ip_port, public_key); | 980 | send_ping_request(dht->ping, dht->c, ip_port, public_key); |
810 | } | 981 | } |
982 | int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled, | ||
983 | uint16_t port, uint8_t *public_key) | ||
984 | { | ||
985 | IP_Port ip_port_v64, ip_port_v4; | ||
986 | IP *ip_extra = NULL; | ||
987 | #ifdef TOX_ENABLE_IPV6 | ||
988 | ip_init(&ip_port_v64.ip, ipv6enabled); | ||
989 | if (ipv6enabled) { | ||
990 | ip_port_v64.ip.family = AF_UNSPEC; | ||
991 | ip_reset(&ip_port_v4.ip); | ||
992 | ip_extra = &ip_port_v4.ip; | ||
993 | } | ||
994 | #else | ||
995 | ip_init(&ip_port_v64.ip, 0); | ||
996 | #endif | ||
997 | |||
998 | if (addr_resolve_or_parse_ip(address, &ip_port_v64.ip, ip_extra)) { | ||
999 | ip_port_v64.port = port; | ||
1000 | DHT_bootstrap(dht, ip_port_v64, public_key); | ||
1001 | #ifdef TOX_ENABLE_IPV6 | ||
1002 | if ((ip_extra != NULL) && ip_isset(ip_extra)) { | ||
1003 | ip_port_v4.port = port; | ||
1004 | DHT_bootstrap(dht, ip_port_v4, public_key); | ||
1005 | } | ||
1006 | #endif | ||
1007 | return 1; | ||
1008 | } | ||
1009 | else | ||
1010 | return 0; | ||
1011 | } | ||
811 | 1012 | ||
812 | /* Send the given packet to node with client_id | 1013 | /* Send the given packet to node with client_id |
813 | * | 1014 | * |
@@ -819,7 +1020,7 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length) | |||
819 | 1020 | ||
820 | for (i = 0; i < LCLIENT_LIST; ++i) { | 1021 | for (i = 0; i < LCLIENT_LIST; ++i) { |
821 | if (id_equal(client_id, dht->close_clientlist[i].client_id)) | 1022 | if (id_equal(client_id, dht->close_clientlist[i].client_id)) |
822 | return sendpacket(dht->c->lossless_udp->net->sock, dht->close_clientlist[i].ip_port, packet, length); | 1023 | return sendpacket(dht->c->lossless_udp->net, dht->close_clientlist[i].ip_port, packet, length); |
823 | } | 1024 | } |
824 | 1025 | ||
825 | return -1; | 1026 | return -1; |
@@ -848,7 +1049,7 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) | |||
848 | client = &friend->client_list[i]; | 1049 | client = &friend->client_list[i]; |
849 | 1050 | ||
850 | /* If ip is not zero and node is good. */ | 1051 | /* If ip is not zero and node is good. */ |
851 | if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { | 1052 | if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { |
852 | 1053 | ||
853 | if (id_equal(client->client_id, friend->client_id)) | 1054 | if (id_equal(client->client_id, friend->client_id)) |
854 | return 0; | 1055 | return 0; |
@@ -890,8 +1091,8 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt | |||
890 | client = &friend->client_list[i]; | 1091 | client = &friend->client_list[i]; |
891 | 1092 | ||
892 | /* If ip is not zero and node is good. */ | 1093 | /* If ip is not zero and node is good. */ |
893 | if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { | 1094 | if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { |
894 | int retval = sendpacket(dht->c->lossless_udp->net->sock, client->ip_port, packet, length); | 1095 | int retval = sendpacket(dht->c->lossless_udp->net, client->ip_port, packet, length); |
895 | 1096 | ||
896 | if ((unsigned int)retval == length) | 1097 | if ((unsigned int)retval == length) |
897 | ++sent; | 1098 | ++sent; |
@@ -924,7 +1125,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint | |||
924 | client = &friend->client_list[i]; | 1125 | client = &friend->client_list[i]; |
925 | 1126 | ||
926 | /* If ip is not zero and node is good. */ | 1127 | /* If ip is not zero and node is good. */ |
927 | if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { | 1128 | if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { |
928 | ip_list[n] = client->ip_port; | 1129 | ip_list[n] = client->ip_port; |
929 | ++n; | 1130 | ++n; |
930 | } | 1131 | } |
@@ -933,7 +1134,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint | |||
933 | if (n < 1) | 1134 | if (n < 1) |
934 | return 0; | 1135 | return 0; |
935 | 1136 | ||
936 | int retval = sendpacket(dht->c->lossless_udp->net->sock, ip_list[rand() % n], packet, length); | 1137 | int retval = sendpacket(dht->c->lossless_udp->net, ip_list[rand() % n], packet, length); |
937 | 1138 | ||
938 | if ((unsigned int)retval == length) | 1139 | if ((unsigned int)retval == length) |
939 | return 1; | 1140 | return 1; |
@@ -1032,7 +1233,8 @@ static int handle_NATping(void *object, IP_Port source, uint8_t *source_pubkey, | |||
1032 | */ | 1233 | */ |
1033 | static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) | 1234 | static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) |
1034 | { | 1235 | { |
1035 | IP zero = {{0}}; | 1236 | IP zero; |
1237 | ip_reset(&zero); | ||
1036 | 1238 | ||
1037 | if (len > MAX_FRIEND_CLIENTS) | 1239 | if (len > MAX_FRIEND_CLIENTS) |
1038 | return zero; | 1240 | return zero; |
@@ -1042,7 +1244,7 @@ static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) | |||
1042 | 1244 | ||
1043 | for (i = 0; i < len; ++i) { | 1245 | for (i = 0; i < len; ++i) { |
1044 | for (j = 0; j < len; ++j) { | 1246 | for (j = 0; j < len; ++j) { |
1045 | if (ip_portlist[i].ip.uint32 == ip_portlist[j].ip.uint32) | 1247 | if (ip_equal(&ip_portlist[i].ip, &ip_portlist[j].ip)) |
1046 | ++numbers[i]; | 1248 | ++numbers[i]; |
1047 | } | 1249 | } |
1048 | 1250 | ||
@@ -1065,7 +1267,7 @@ static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t | |||
1065 | uint16_t num = 0; | 1267 | uint16_t num = 0; |
1066 | 1268 | ||
1067 | for (i = 0; i < len; ++i) { | 1269 | for (i = 0; i < len; ++i) { |
1068 | if (ip_portlist[i].ip.uint32 == ip.uint32) { | 1270 | if (ip_equal(&ip_portlist[i].ip, &ip)) { |
1069 | portlist[num] = ntohs(ip_portlist[i].port); | 1271 | portlist[num] = ntohs(ip_portlist[i].port); |
1070 | ++num; | 1272 | ++num; |
1071 | } | 1273 | } |
@@ -1085,7 +1287,9 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports, | |||
1085 | for (i = dht->friends_list[friend_num].punching_index; i != top; i++) { | 1287 | for (i = dht->friends_list[friend_num].punching_index; i != top; i++) { |
1086 | /* TODO: Improve port guessing algorithm. */ | 1288 | /* TODO: Improve port guessing algorithm. */ |
1087 | uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); | 1289 | uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); |
1088 | IP_Port pinging = {{ip, htons(port), 0}}; | 1290 | IP_Port pinging; |
1291 | ip_copy(&pinging.ip, &ip); | ||
1292 | pinging.port = htons(port); | ||
1089 | send_ping_request(dht->ping, dht->c, pinging, dht->friends_list[friend_num].client_id); | 1293 | send_ping_request(dht->ping, dht->c, pinging, dht->friends_list[friend_num].client_id); |
1090 | } | 1294 | } |
1091 | 1295 | ||
@@ -1115,8 +1319,7 @@ static void do_NAT(DHT *dht) | |||
1115 | dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { | 1319 | dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { |
1116 | 1320 | ||
1117 | IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); | 1321 | IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); |
1118 | 1322 | if (!ip_isset(&ip)) | |
1119 | if (ip.uint32 == 0) | ||
1120 | continue; | 1323 | continue; |
1121 | 1324 | ||
1122 | uint16_t port_list[MAX_FRIEND_CLIENTS]; | 1325 | uint16_t port_list[MAX_FRIEND_CLIENTS]; |
@@ -1145,16 +1348,15 @@ static void do_NAT(DHT *dht) | |||
1145 | */ | 1348 | */ |
1146 | int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port) | 1349 | int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port) |
1147 | { | 1350 | { |
1148 | if (ip_port.ip.uint32 == 0) | 1351 | if (!ip_isset(&ip_port.ip)) |
1149 | return -1; | 1352 | return -1; |
1150 | 1353 | ||
1151 | uint32_t i; | 1354 | uint32_t i; |
1152 | 1355 | ||
1153 | for (i = 0; i < MAX_TOPING; ++i) { | 1356 | for (i = 0; i < MAX_TOPING; ++i) { |
1154 | if (dht->toping[i].ip_port.ip.uint32 == 0) { | 1357 | if (!ip_isset(&dht->toping[i].ip_port.ip)) { |
1155 | memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); | 1358 | memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); |
1156 | dht->toping[i].ip_port.ip.uint32 = ip_port.ip.uint32; | 1359 | ipport_copy(&dht->toping[i].ip_port, &ip_port); |
1157 | dht->toping[i].ip_port.port = ip_port.port; | ||
1158 | return 0; | 1360 | return 0; |
1159 | } | 1361 | } |
1160 | } | 1362 | } |
@@ -1162,8 +1364,7 @@ int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port) | |||
1162 | for (i = 0; i < MAX_TOPING; ++i) { | 1364 | for (i = 0; i < MAX_TOPING; ++i) { |
1163 | if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) { | 1365 | if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) { |
1164 | memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); | 1366 | memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); |
1165 | dht->toping[i].ip_port.ip.uint32 = ip_port.ip.uint32; | 1367 | ipport_copy(&dht->toping[i].ip_port, &ip_port); |
1166 | dht->toping[i].ip_port.port = ip_port.port; | ||
1167 | return 0; | 1368 | return 0; |
1168 | } | 1369 | } |
1169 | } | 1370 | } |
@@ -1185,11 +1386,11 @@ static void do_toping(DHT *dht) | |||
1185 | uint32_t i; | 1386 | uint32_t i; |
1186 | 1387 | ||
1187 | for (i = 0; i < MAX_TOPING; ++i) { | 1388 | for (i = 0; i < MAX_TOPING; ++i) { |
1188 | if (dht->toping[i].ip_port.ip.uint32 == 0) | 1389 | if (!ip_isset(&dht->toping[i].ip_port.ip)) |
1189 | return; | 1390 | return; |
1190 | 1391 | ||
1191 | send_ping_request(dht->ping, dht->c, dht->toping[i].ip_port, dht->toping[i].client_id); | 1392 | send_ping_request(dht->ping, dht->c, dht->toping[i].ip_port, dht->toping[i].client_id); |
1192 | dht->toping[i].ip_port.ip.uint32 = 0; | 1393 | ip_reset(&dht->toping[i].ip_port.ip); |
1193 | } | 1394 | } |
1194 | } | 1395 | } |
1195 | 1396 | ||
@@ -1216,6 +1417,9 @@ DHT *new_DHT(Net_Crypto *c) | |||
1216 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, temp); | 1417 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, temp); |
1217 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, temp); | 1418 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, temp); |
1218 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, temp); | 1419 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, temp); |
1420 | #ifdef TOX_ENABLE_IPV6 | ||
1421 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, temp); | ||
1422 | #endif | ||
1219 | init_cryptopackets(temp); | 1423 | init_cryptopackets(temp); |
1220 | cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, temp); | 1424 | cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, temp); |
1221 | return temp; | 1425 | return temp; |
diff --git a/toxcore/DHT.h b/toxcore/DHT.h index e5122b5e..255074b0 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h | |||
@@ -75,10 +75,22 @@ typedef struct { | |||
75 | uint64_t NATping_timestamp; | 75 | uint64_t NATping_timestamp; |
76 | } DHT_Friend; | 76 | } DHT_Friend; |
77 | 77 | ||
78 | /* this must be kept even if IP_Port is expanded: wire compatibility */ | ||
79 | typedef struct { | ||
80 | uint8_t client_id[CLIENT_ID_SIZE]; | ||
81 | IP4_Port ip_port; | ||
82 | } Node4_format; | ||
83 | |||
78 | typedef struct { | 84 | typedef struct { |
79 | uint8_t client_id[CLIENT_ID_SIZE]; | 85 | uint8_t client_id[CLIENT_ID_SIZE]; |
80 | IP_Port ip_port; | 86 | IP_Port ip_port; |
81 | } Node_format; | 87 | } Node46_format; |
88 | |||
89 | #ifdef TOX_ENABLE_IPV6 | ||
90 | typedef Node46_format Node_format; | ||
91 | #else | ||
92 | typedef Node4_format Node_format; | ||
93 | #endif | ||
82 | 94 | ||
83 | typedef struct { | 95 | typedef struct { |
84 | IP_Port ip_port; | 96 | IP_Port ip_port; |
@@ -88,15 +100,15 @@ typedef struct { | |||
88 | 100 | ||
89 | /*----------------------------------------------------------------------------------*/ | 101 | /*----------------------------------------------------------------------------------*/ |
90 | typedef struct { | 102 | typedef struct { |
91 | Net_Crypto *c; | 103 | Net_Crypto *c; |
92 | Client_data close_clientlist[LCLIENT_LIST]; | 104 | Client_data close_clientlist[LCLIENT_LIST]; |
93 | DHT_Friend *friends_list; | 105 | DHT_Friend *friends_list; |
94 | uint16_t num_friends; | 106 | uint16_t num_friends; |
95 | Pinged send_nodes[LSEND_NODES_ARRAY]; | 107 | Pinged send_nodes[LSEND_NODES_ARRAY]; |
96 | Node_format toping[MAX_TOPING]; | 108 | Node_format toping[MAX_TOPING]; |
97 | uint64_t last_toping; | 109 | uint64_t last_toping; |
98 | uint64_t close_lastgetnodes; | 110 | uint64_t close_lastgetnodes; |
99 | void *ping; | 111 | void *ping; |
100 | } DHT; | 112 | } DHT; |
101 | /*----------------------------------------------------------------------------------*/ | 113 | /*----------------------------------------------------------------------------------*/ |
102 | 114 | ||
@@ -124,19 +136,45 @@ int DHT_delfriend(DHT *dht, uint8_t *client_id); | |||
124 | * ip must be 4 bytes long. | 136 | * ip must be 4 bytes long. |
125 | * port must be 2 bytes long. | 137 | * port must be 2 bytes long. |
126 | * | 138 | * |
139 | * !!! Signature changed !!! | ||
140 | * | ||
141 | * OLD: IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id); | ||
142 | * | ||
127 | * return ip if success. | 143 | * return ip if success. |
128 | * return ip of 0 if failure (This means the friend is either offline or we have not found him yet). | 144 | * return ip of 0 if failure (This means the friend is either offline or we have not found him yet). |
129 | * return ip of 1 if friend is not in list. | 145 | * return ip of 1 if friend is not in list. |
146 | * | ||
147 | * NEW: int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port); | ||
148 | * | ||
149 | * return -1, -- if client_id does NOT refer to a friend | ||
150 | * return 0, -- if client_id refers to a friend and we failed to find the friend (yet) | ||
151 | * return 1, ip if client_id refers to a friend and we found him | ||
130 | */ | 152 | */ |
131 | IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id); | 153 | int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port); |
132 | 154 | ||
133 | /* Run this function at least a couple times per second (It's the main loop). */ | 155 | /* Run this function at least a couple times per second (It's the main loop). */ |
134 | void do_DHT(DHT *dht); | 156 | void do_DHT(DHT *dht); |
135 | 157 | ||
136 | /* Use this function to bootstrap the client. | 158 | /* |
137 | * Sends a get nodes request to the given node with ip port and public_key. | 159 | * Use these two functions to bootstrap the client. |
160 | */ | ||
161 | /* Sends a "get nodes" request to the given node with ip, port and public_key | ||
162 | * to setup connections | ||
138 | */ | 163 | */ |
139 | void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key); | 164 | void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key); |
165 | /* Resolves address into an IP address. If successful, sends a "get nodes" | ||
166 | * request to the given node with ip, port and public_key to setup connections | ||
167 | * | ||
168 | * address can be a hostname or an IP address (IPv4 or IPv6). | ||
169 | * if ipv6enabled is 0 (zero), the resolving sticks STRICTLY to IPv4 addresses | ||
170 | * if ipv6enabled is not 0 (zero), the resolving looks for IPv6 addresses first, | ||
171 | * then IPv4 addresses. | ||
172 | * | ||
173 | * returns 1 if the address could be converted into an IP address | ||
174 | * returns 0 otherwise | ||
175 | */ | ||
176 | int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled, | ||
177 | uint16_t port, uint8_t *public_key); | ||
140 | 178 | ||
141 | /* Add nodes to the toping list. | 179 | /* Add nodes to the toping list. |
142 | * All nodes in this list are pinged every TIME_TOPING seconds | 180 | * All nodes in this list are pinged every TIME_TOPING seconds |
diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c index 1980cd93..c50fe65d 100644 --- a/toxcore/LAN_discovery.c +++ b/toxcore/LAN_discovery.c | |||
@@ -71,7 +71,7 @@ static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, uint8_t * d | |||
71 | sock_holder = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr; | 71 | sock_holder = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr; |
72 | if (sock_holder != NULL) { | 72 | if (sock_holder != NULL) { |
73 | IP_Port ip_port = {{{{sock_holder->sin_addr.s_addr}}, port, 0}}; | 73 | IP_Port ip_port = {{{{sock_holder->sin_addr.s_addr}}, port, 0}}; |
74 | sendpacket(net->sock, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES); | 74 | sendpacket(net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES); |
75 | } | 75 | } |
76 | } | 76 | } |
77 | 77 | ||
@@ -81,10 +81,42 @@ static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, uint8_t * d | |||
81 | #endif | 81 | #endif |
82 | 82 | ||
83 | /* Return the broadcast ip. */ | 83 | /* Return the broadcast ip. */ |
84 | static IP broadcast_ip(void) | 84 | static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast) |
85 | { | 85 | { |
86 | IP ip; | 86 | IP ip; |
87 | ip.uint32 = ~0; | 87 | ip_reset(&ip); |
88 | |||
89 | #ifdef TOX_ENABLE_IPV6 | ||
90 | if (family_socket == AF_INET6) { | ||
91 | if (family_broadcast == AF_INET6) { | ||
92 | ip.family = AF_INET6; | ||
93 | /* FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */ | ||
94 | /* FE80::*: MUST be exact, for that we would need to look over all | ||
95 | * interfaces and check in which status they are */ | ||
96 | ip.ip6.s6_addr[ 0] = 0xFF; | ||
97 | ip.ip6.s6_addr[ 1] = 0x02; | ||
98 | ip.ip6.s6_addr[15] = 0x01; | ||
99 | } | ||
100 | else if (family_broadcast == AF_INET) { | ||
101 | ip.family = AF_INET6; | ||
102 | ip.ip6.s6_addr32[0] = 0; | ||
103 | ip.ip6.s6_addr32[1] = 0; | ||
104 | ip.ip6.s6_addr32[2] = htonl(0xFFFF); | ||
105 | ip.ip6.s6_addr32[3] = INADDR_BROADCAST; | ||
106 | } | ||
107 | } | ||
108 | else if (family_socket == AF_INET) { | ||
109 | if (family_broadcast == AF_INET) { | ||
110 | ip.family = AF_INET; | ||
111 | ip.ip4.uint32 = INADDR_BROADCAST; | ||
112 | } | ||
113 | } | ||
114 | #else | ||
115 | if (family_socket == AF_INET) | ||
116 | if (family_broadcast == AF_INET) | ||
117 | ip.uint32 = INADDR_BROADCAST; | ||
118 | #endif | ||
119 | |||
88 | return ip; | 120 | return ip; |
89 | } | 121 | } |
90 | 122 | ||
@@ -93,21 +125,50 @@ static IP broadcast_ip(void) | |||
93 | */ | 125 | */ |
94 | static int LAN_ip(IP ip) | 126 | static int LAN_ip(IP ip) |
95 | { | 127 | { |
96 | if (ip.uint8[0] == 127) /* Loopback. */ | 128 | #ifdef TOX_ENABLE_IPV6 |
97 | return 0; | 129 | if (ip.family == AF_INET) { |
98 | 130 | IP4 ip4 = ip.ip4; | |
99 | if (ip.uint8[0] == 10) /* 10.0.0.0 to 10.255.255.255 range. */ | 131 | #else |
100 | return 0; | 132 | IP4 ip4 = ip; |
101 | 133 | #endif | |
102 | if (ip.uint8[0] == 172 && ip.uint8[1] >= 16 && ip.uint8[1] <= 31) /* 172.16.0.0 to 172.31.255.255 range. */ | 134 | /* Loopback. */ |
103 | return 0; | 135 | if (ip4.uint8[0] == 127) |
104 | 136 | return 0; | |
105 | if (ip.uint8[0] == 192 && ip.uint8[1] == 168) /* 192.168.0.0 to 192.168.255.255 range. */ | 137 | |
106 | return 0; | 138 | /* 10.0.0.0 to 10.255.255.255 range. */ |
107 | 139 | if (ip4.uint8[0] == 10) | |
108 | if (ip.uint8[0] == 169 && ip.uint8[1] == 254 && ip.uint8[2] != 0 | 140 | return 0; |
109 | && ip.uint8[2] != 255)/* 169.254.1.0 to 169.254.254.255 range. */ | 141 | |
110 | return 0; | 142 | /* 172.16.0.0 to 172.31.255.255 range. */ |
143 | if (ip4.uint8[0] == 172 && ip4.uint8[1] >= 16 && ip4.uint8[1] <= 31) | ||
144 | return 0; | ||
145 | |||
146 | /* 192.168.0.0 to 192.168.255.255 range. */ | ||
147 | if (ip4.uint8[0] == 192 && ip4.uint8[1] == 168) | ||
148 | return 0; | ||
149 | |||
150 | /* 169.254.1.0 to 169.254.254.255 range. */ | ||
151 | if (ip4.uint8[0] == 169 && ip4.uint8[1] == 254 && ip4.uint8[2] != 0 | ||
152 | && ip4.uint8[2] != 255) | ||
153 | return 0; | ||
154 | #ifdef TOX_ENABLE_IPV6 | ||
155 | } | ||
156 | else if (ip.family == AF_INET6) { | ||
157 | /* autogenerated for each interface: FE80::* (up to FEBF::*) | ||
158 | /* FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */ | ||
159 | if (((ip.ip6.s6_addr[0] == 0xFF) && (ip.ip6.s6_addr[1] < 3) && (ip.ip6.s6_addr[15] == 1)) || | ||
160 | ((ip.ip6.s6_addr[0] == 0xFE) && ((ip.ip6.s6_addr[1] & 0xC0) == 0x80))) | ||
161 | return 0; | ||
162 | |||
163 | /* embedded IPv4-in-IPv6 */ | ||
164 | if (!ip.ip6.s6_addr32[0] && !ip.ip6.s6_addr32[1] && ip.ip6.s6_addr32[2] == htonl(0xFFFF)) { | ||
165 | IP ip4; | ||
166 | ip4.family = AF_INET; | ||
167 | ip4.ip4.uint32 = ip.ip6.s6_addr32[3]; | ||
168 | return LAN_ip(ip4); | ||
169 | } | ||
170 | } | ||
171 | #endif | ||
111 | 172 | ||
112 | return -1; | 173 | return -1; |
113 | } | 174 | } |
@@ -132,11 +193,34 @@ int send_LANdiscovery(uint16_t port, Net_Crypto *c) | |||
132 | uint8_t data[crypto_box_PUBLICKEYBYTES + 1]; | 193 | uint8_t data[crypto_box_PUBLICKEYBYTES + 1]; |
133 | data[0] = NET_PACKET_LAN_DISCOVERY; | 194 | data[0] = NET_PACKET_LAN_DISCOVERY; |
134 | memcpy(data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES); | 195 | memcpy(data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES); |
196 | |||
135 | #ifdef __linux | 197 | #ifdef __linux |
136 | send_broadcasts(c->lossless_udp->net, port, data, 1 + crypto_box_PUBLICKEYBYTES); | 198 | send_broadcasts(c->lossless_udp->net, port, data, 1 + crypto_box_PUBLICKEYBYTES); |
137 | #endif | 199 | #endif |
138 | IP_Port ip_port = {{broadcast_ip(), port, 0}}; | 200 | |
139 | return sendpacket(c->lossless_udp->net->sock, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES); | 201 | int res = -1; |
202 | IP_Port ip_port; | ||
203 | ip_port.port = port; | ||
204 | |||
205 | #ifdef TOX_ENABLE_IPV6 | ||
206 | /* IPv6 multicast */ | ||
207 | if (c->lossless_udp->net->family == AF_INET6) { | ||
208 | ip_port.ip = broadcast_ip(AF_INET6, AF_INET6); | ||
209 | if (ip_isset(&ip_port.ip)) | ||
210 | if (sendpacket(c->lossless_udp->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES) > 0) | ||
211 | res = 1; | ||
212 | } | ||
213 | |||
214 | /* IPv4 broadcast (has to be IPv4-in-IPv6 mapping if socket is AF_INET6 */ | ||
215 | ip_port.ip = broadcast_ip(c->lossless_udp->net->family, AF_INET); | ||
216 | #else | ||
217 | ip_port.ip = broadcast_ip(AF_INET, AF_INET); | ||
218 | #endif | ||
219 | if (ip_isset(&ip_port.ip)) | ||
220 | if (sendpacket(c->lossless_udp->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES)) | ||
221 | res = 1; | ||
222 | |||
223 | return res; | ||
140 | } | 224 | } |
141 | 225 | ||
142 | 226 | ||
diff --git a/toxcore/LAN_discovery.h b/toxcore/LAN_discovery.h index 78990936..a0789956 100644 --- a/toxcore/LAN_discovery.h +++ b/toxcore/LAN_discovery.h | |||
@@ -35,6 +35,8 @@ | |||
35 | #include <linux/netdevice.h> | 35 | #include <linux/netdevice.h> |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | /* standard interval in seconds between LAN discovery packet sending. */ | ||
39 | #define LAN_DISCOVERY_INTERVAL 60 | ||
38 | 40 | ||
39 | /* Send a LAN discovery pcaket to the broadcast address with port port. */ | 41 | /* Send a LAN discovery pcaket to the broadcast address with port port. */ |
40 | int send_LANdiscovery(uint16_t port, Net_Crypto *c); | 42 | int send_LANdiscovery(uint16_t port, Net_Crypto *c); |
diff --git a/toxcore/Lossless_UDP.c b/toxcore/Lossless_UDP.c index fbb473e7..ca874562 100644 --- a/toxcore/Lossless_UDP.c +++ b/toxcore/Lossless_UDP.c | |||
@@ -44,9 +44,7 @@ | |||
44 | int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port) | 44 | int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port) |
45 | { | 45 | { |
46 | tox_array_for_each(&ludp->connections, Connection, tmp) { | 46 | tox_array_for_each(&ludp->connections, Connection, tmp) { |
47 | if (tmp->ip_port.ip.uint32 == ip_port.ip.uint32 && | 47 | if (tmp-> status > 0 && ipport_equal(&tmp->ip_port, &ip_port)) { |
48 | tmp->ip_port.port == ip_port.port && | ||
49 | tmp->status > 0) { | ||
50 | return tmp_i; | 48 | return tmp_i; |
51 | } | 49 | } |
52 | } | 50 | } |
@@ -61,17 +59,49 @@ int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port) | |||
61 | * | 59 | * |
62 | * TODO: make this better | 60 | * TODO: make this better |
63 | */ | 61 | */ |
64 | static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source) | 62 | |
63 | static uint8_t randtable_initget(Lossless_UDP *ludp, uint32_t index, uint8_t value) | ||
65 | { | 64 | { |
66 | uint32_t id = 0, i; | 65 | if (ludp->randtable[index][value] == 0) |
66 | ludp->randtable[index][value] = random_int(); | ||
67 | 67 | ||
68 | for (i = 0; i < 6; ++i) { | 68 | return ludp->randtable[index][value]; |
69 | if (ludp->randtable[i][source.uint8[i]] == 0) | 69 | } |
70 | ludp->randtable[i][source.uint8[i]] = random_int(); | ||
71 | 70 | ||
72 | id ^= ludp->randtable[i][source.uint8[i]]; | 71 | static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source) |
72 | { | ||
73 | uint32_t id = 0, i = 0; | ||
74 | |||
75 | uint8_t *uint8; | ||
76 | uint8 = (uint8_t *)&source.port; | ||
77 | id ^= randtable_initget(ludp, i, *uint8); | ||
78 | i++, uint8++; | ||
79 | id ^= randtable_initget(ludp, i, *uint8); | ||
80 | i++; | ||
81 | |||
82 | #ifdef TOX_ENABLE_IPV6 | ||
83 | if (source.ip.family == AF_INET) | ||
84 | { | ||
85 | IP4 ip4 = source.ip.ip4; | ||
86 | #else | ||
87 | IP4 ip4 = source.ip; | ||
88 | #endif | ||
89 | int k; | ||
90 | for (k = 0; k < 4; k++) { | ||
91 | id ^= randtable_initget(ludp, i++, ip4.uint8[k]); | ||
92 | } | ||
93 | #ifdef TOX_ENABLE_IPV6 | ||
73 | } | 94 | } |
74 | 95 | ||
96 | if (source.ip.family == AF_INET6) | ||
97 | { | ||
98 | int k; | ||
99 | for (k = 0; k < 16; k++) { | ||
100 | id ^= randtable_initget(ludp, i++, source.ip.ip6.s6_addr[k]); | ||
101 | } | ||
102 | } | ||
103 | #endif | ||
104 | |||
75 | /* id can't be zero. */ | 105 | /* id can't be zero. */ |
76 | if (id == 0) | 106 | if (id == 0) |
77 | id = 1; | 107 | id = 1; |
@@ -290,7 +320,9 @@ IP_Port connection_ip(Lossless_UDP *ludp, int connection_id) | |||
290 | if ((unsigned int)connection_id < ludp->connections.len) | 320 | if ((unsigned int)connection_id < ludp->connections.len) |
291 | return tox_array_get(&ludp->connections, connection_id, Connection).ip_port; | 321 | return tox_array_get(&ludp->connections, connection_id, Connection).ip_port; |
292 | 322 | ||
293 | IP_Port zero = {{{{0}}, 0, 0}}; | 323 | IP_Port zero; |
324 | ip_reset(&zero.ip); | ||
325 | zero.port = 0; | ||
294 | return zero; | 326 | return zero; |
295 | } | 327 | } |
296 | 328 | ||
@@ -429,7 +461,7 @@ static int send_handshake(Lossless_UDP *ludp, IP_Port ip_port, uint32_t handshak | |||
429 | temp = htonl(handshake_id2); | 461 | temp = htonl(handshake_id2); |
430 | memcpy(packet + 5, &temp, 4); | 462 | memcpy(packet + 5, &temp, 4); |
431 | 463 | ||
432 | return sendpacket(ludp->net->sock, ip_port, packet, sizeof(packet)); | 464 | return sendpacket(ludp->net, ip_port, packet, sizeof(packet)); |
433 | } | 465 | } |
434 | 466 | ||
435 | static int send_SYNC(Lossless_UDP *ludp, int connection_id) | 467 | static int send_SYNC(Lossless_UDP *ludp, int connection_id) |
@@ -456,7 +488,7 @@ static int send_SYNC(Lossless_UDP *ludp, int connection_id) | |||
456 | index += 4; | 488 | index += 4; |
457 | memcpy(packet + index, requested, 4 * number); | 489 | memcpy(packet + index, requested, 4 * number); |
458 | 490 | ||
459 | return sendpacket(ludp->net->sock, ip_port, packet, (number * 4 + 4 + 4 + 2)); | 491 | return sendpacket(ludp->net, ip_port, packet, (number * 4 + 4 + 4 + 2)); |
460 | 492 | ||
461 | } | 493 | } |
462 | 494 | ||
@@ -471,7 +503,7 @@ static int send_data_packet(Lossless_UDP *ludp, int connection_id, uint32_t pack | |||
471 | temp = htonl(packet_num); | 503 | temp = htonl(packet_num); |
472 | memcpy(packet + 1, &temp, 4); | 504 | memcpy(packet + 1, &temp, 4); |
473 | memcpy(packet + 5, connection->sendbuffer[index].data, connection->sendbuffer[index].size); | 505 | memcpy(packet + 5, connection->sendbuffer[index].data, connection->sendbuffer[index].size); |
474 | return sendpacket(ludp->net->sock, connection->ip_port, packet, 1 + 4 + connection->sendbuffer[index].size); | 506 | return sendpacket(ludp->net, connection->ip_port, packet, 1 + 4 + connection->sendbuffer[index].size); |
475 | } | 507 | } |
476 | 508 | ||
477 | /* Sends 1 data packet. */ | 509 | /* Sends 1 data packet. */ |
diff --git a/toxcore/Lossless_UDP.h b/toxcore/Lossless_UDP.h index 20471b0a..f0ce0e87 100644 --- a/toxcore/Lossless_UDP.h +++ b/toxcore/Lossless_UDP.h | |||
@@ -123,7 +123,13 @@ typedef struct { | |||
123 | tox_array connections; | 123 | tox_array connections; |
124 | 124 | ||
125 | /* Table of random numbers used in handshake_id. */ | 125 | /* Table of random numbers used in handshake_id. */ |
126 | #ifdef TOX_ENABLE_IPV6 | ||
127 | /* IPv6 (16) + port (2)*/ | ||
128 | uint32_t randtable[18][256]; | ||
129 | #else | ||
130 | /* IPv4 (4) + port (2) */ | ||
126 | uint32_t randtable[6][256]; | 131 | uint32_t randtable[6][256]; |
132 | #endif | ||
127 | 133 | ||
128 | } Lossless_UDP; | 134 | } Lossless_UDP; |
129 | 135 | ||
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 177b8eb0..656b384b 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c | |||
@@ -811,19 +811,18 @@ static void do_allgroupchats(Messenger *m) | |||
811 | 811 | ||
812 | /* Interval in seconds between LAN discovery packet sending. */ | 812 | /* Interval in seconds between LAN discovery packet sending. */ |
813 | #define LAN_DISCOVERY_INTERVAL 60 | 813 | #define LAN_DISCOVERY_INTERVAL 60 |
814 | #define PORT 33445 | ||
815 | 814 | ||
816 | /* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */ | 815 | /* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */ |
817 | static void LANdiscovery(Messenger *m) | 816 | static void LANdiscovery(Messenger *m) |
818 | { | 817 | { |
819 | if (m->last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time()) { | 818 | if (m->last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time()) { |
820 | send_LANdiscovery(htons(PORT), m->net_crypto); | 819 | send_LANdiscovery(htons(TOX_PORT_DEFAULT), m->net_crypto); |
821 | m->last_LANdiscovery = unix_time(); | 820 | m->last_LANdiscovery = unix_time(); |
822 | } | 821 | } |
823 | } | 822 | } |
824 | 823 | ||
825 | /* Run this at startup. */ | 824 | /* Run this at startup. */ |
826 | Messenger *initMessenger(void) | 825 | Messenger *initMessenger(uint8_t ipv6enabled) |
827 | { | 826 | { |
828 | Messenger *m = calloc(1, sizeof(Messenger)); | 827 | Messenger *m = calloc(1, sizeof(Messenger)); |
829 | 828 | ||
@@ -831,8 +830,8 @@ Messenger *initMessenger(void) | |||
831 | return NULL; | 830 | return NULL; |
832 | 831 | ||
833 | IP ip; | 832 | IP ip; |
834 | ip.uint32 = 0; | 833 | ip_init(&ip, ipv6enabled); |
835 | m->net = new_networking(ip, PORT); | 834 | m->net = new_networking(ip, TOX_PORT_DEFAULT); |
836 | 835 | ||
837 | if (m->net == NULL) { | 836 | if (m->net == NULL) { |
838 | free(m); | 837 | free(m); |
@@ -916,11 +915,12 @@ void doFriends(Messenger *m) | |||
916 | } | 915 | } |
917 | } | 916 | } |
918 | 917 | ||
919 | IP_Port friendip = DHT_getfriendip(m->dht, m->friendlist[i].client_id); | 918 | IP_Port friendip; |
919 | int friendok = DHT_getfriendip(m->dht, m->friendlist[i].client_id, &friendip); | ||
920 | 920 | ||
921 | switch (is_cryptoconnected(m->net_crypto, m->friendlist[i].crypt_connection_id)) { | 921 | switch (is_cryptoconnected(m->net_crypto, m->friendlist[i].crypt_connection_id)) { |
922 | case 0: | 922 | case 0: |
923 | if (friendip.ip.uint32 > 1) | 923 | if (friendok == 1) |
924 | m->friendlist[i].crypt_connection_id = crypto_connect(m->net_crypto, m->friendlist[i].client_id, friendip); | 924 | m->friendlist[i].crypt_connection_id = crypto_connect(m->net_crypto, m->friendlist[i].client_id, friendip); |
925 | 925 | ||
926 | break; | 926 | break; |
@@ -1138,19 +1138,23 @@ void Messenger_save(Messenger *m, uint8_t *data) | |||
1138 | { | 1138 | { |
1139 | save_keys(m->net_crypto, data); | 1139 | save_keys(m->net_crypto, data); |
1140 | data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; | 1140 | data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; |
1141 | |||
1141 | uint32_t nospam = get_nospam(&(m->fr)); | 1142 | uint32_t nospam = get_nospam(&(m->fr)); |
1142 | memcpy(data, &nospam, sizeof(nospam)); | 1143 | memcpy(data, &nospam, sizeof(nospam)); |
1143 | data += sizeof(nospam); | 1144 | data += sizeof(nospam); |
1145 | |||
1144 | uint32_t size = DHT_size(m->dht); | 1146 | uint32_t size = DHT_size(m->dht); |
1145 | memcpy(data, &size, sizeof(size)); | 1147 | memcpy(data, &size, sizeof(size)); |
1146 | data += sizeof(size); | 1148 | data += sizeof(size); |
1147 | DHT_save(m->dht, data); | 1149 | DHT_save(m->dht, data); |
1148 | data += size; | 1150 | data += size; |
1151 | |||
1149 | size = sizeof(Friend) * m->numfriends; | 1152 | size = sizeof(Friend) * m->numfriends; |
1150 | memcpy(data, &size, sizeof(size)); | 1153 | memcpy(data, &size, sizeof(size)); |
1151 | data += sizeof(size); | 1154 | data += sizeof(size); |
1152 | memcpy(data, m->friendlist, sizeof(Friend) * m->numfriends); | 1155 | memcpy(data, m->friendlist, sizeof(Friend) * m->numfriends); |
1153 | data += size; | 1156 | data += size; |
1157 | |||
1154 | uint16_t small_size = m->name_length; | 1158 | uint16_t small_size = m->name_length; |
1155 | memcpy(data, &small_size, sizeof(small_size)); | 1159 | memcpy(data, &small_size, sizeof(small_size)); |
1156 | data += sizeof(small_size); | 1160 | data += sizeof(small_size); |
@@ -1163,59 +1167,69 @@ int Messenger_load(Messenger *m, uint8_t *data, uint32_t length) | |||
1163 | if (length == ~((uint32_t)0)) | 1167 | if (length == ~((uint32_t)0)) |
1164 | return -1; | 1168 | return -1; |
1165 | 1169 | ||
1166 | if (length < crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 3) | 1170 | /* BLOCK1: PUBKEY, SECKEY, NOSPAM, SIZE */ |
1171 | if (length < crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 2) | ||
1167 | return -1; | 1172 | return -1; |
1168 | 1173 | ||
1169 | length -= crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 3; | ||
1170 | load_keys(m->net_crypto, data); | 1174 | load_keys(m->net_crypto, data); |
1171 | data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; | 1175 | data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; |
1176 | length -= crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; | ||
1177 | |||
1172 | uint32_t nospam; | 1178 | uint32_t nospam; |
1173 | memcpy(&nospam, data, sizeof(nospam)); | 1179 | memcpy(&nospam, data, sizeof(nospam)); |
1174 | set_nospam(&(m->fr), nospam); | 1180 | set_nospam(&(m->fr), nospam); |
1175 | data += sizeof(nospam); | 1181 | data += sizeof(nospam); |
1182 | length -= sizeof(nospam); | ||
1183 | |||
1176 | uint32_t size; | 1184 | uint32_t size; |
1177 | memcpy(&size, data, sizeof(size)); | 1185 | memcpy(&size, data, sizeof(size)); |
1178 | data += sizeof(size); | 1186 | data += sizeof(size); |
1187 | length -= sizeof(size); | ||
1179 | 1188 | ||
1180 | if (length < size) | 1189 | if (length < size) |
1181 | return -1; | 1190 | return -1; |
1182 | 1191 | ||
1192 | if (DHT_load(m->dht, data, size) == -1) | ||
1193 | fprintf(stderr, "Data file: Something wicked happened to the stored connections...\n"); | ||
1194 | |||
1195 | /* go on, friends still might be intact */ | ||
1196 | |||
1197 | data += size; | ||
1183 | length -= size; | 1198 | length -= size; |
1184 | 1199 | ||
1185 | if (DHT_load(m->dht, data, size) == -1) | 1200 | if (length < sizeof(size)) |
1186 | return -1; | 1201 | return -1; |
1187 | 1202 | ||
1188 | data += size; | ||
1189 | memcpy(&size, data, sizeof(size)); | 1203 | memcpy(&size, data, sizeof(size)); |
1190 | data += sizeof(size); | 1204 | data += sizeof(size); |
1205 | length -= sizeof(size); | ||
1191 | 1206 | ||
1192 | if (length < size || size % sizeof(Friend) != 0) | 1207 | if (length < size) |
1193 | return -1; | 1208 | return -1; |
1194 | 1209 | ||
1195 | Friend *temp = malloc(size); | 1210 | if (!(size % sizeof(Friend))) { |
1196 | memcpy(temp, data, size); | 1211 | uint16_t num = size / sizeof(Friend); |
1197 | 1212 | Friend temp[num]; | |
1198 | uint16_t num = size / sizeof(Friend); | 1213 | memcpy(temp, data, size); |
1199 | 1214 | ||
1200 | uint32_t i; | 1215 | uint32_t i; |
1201 | 1216 | for (i = 0; i < num; ++i) { | |
1202 | for (i = 0; i < num; ++i) { | 1217 | if (temp[i].status >= 3) { |
1203 | if (temp[i].status >= 3) { | 1218 | int fnum = m_addfriend_norequest(m, temp[i].client_id); |
1204 | int fnum = m_addfriend_norequest(m, temp[i].client_id); | 1219 | setfriendname(m, fnum, temp[i].name, temp[i].name_length); |
1205 | setfriendname(m, fnum, temp[i].name, temp[i].name_length); | 1220 | /* set_friend_statusmessage(fnum, temp[i].statusmessage, temp[i].statusmessage_length); */ |
1206 | /* set_friend_statusmessage(fnum, temp[i].statusmessage, temp[i].statusmessage_length); */ | 1221 | } else if (temp[i].status != 0) { |
1207 | } else if (temp[i].status != 0) { | 1222 | /* TODO: This is not a good way to do this. */ |
1208 | /* TODO: This is not a good way to do this. */ | 1223 | uint8_t address[FRIEND_ADDRESS_SIZE]; |
1209 | uint8_t address[FRIEND_ADDRESS_SIZE]; | 1224 | memcpy(address, temp[i].client_id, crypto_box_PUBLICKEYBYTES); |
1210 | memcpy(address, temp[i].client_id, crypto_box_PUBLICKEYBYTES); | 1225 | memcpy(address + crypto_box_PUBLICKEYBYTES, &(temp[i].friendrequest_nospam), sizeof(uint32_t)); |
1211 | memcpy(address + crypto_box_PUBLICKEYBYTES, &(temp[i].friendrequest_nospam), sizeof(uint32_t)); | 1226 | uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); |
1212 | uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); | 1227 | memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), &checksum, sizeof(checksum)); |
1213 | memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), &checksum, sizeof(checksum)); | 1228 | m_addfriend(m, address, temp[i].info, temp[i].info_size); |
1214 | m_addfriend(m, address, temp[i].info, temp[i].info_size); | 1229 | } |
1215 | } | 1230 | } |
1216 | } | 1231 | } |
1217 | 1232 | ||
1218 | free(temp); | ||
1219 | data += size; | 1233 | data += size; |
1220 | length -= size; | 1234 | length -= size; |
1221 | 1235 | ||
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 7649a779..b7032bbd 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h | |||
@@ -373,7 +373,7 @@ void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, in | |||
373 | * return allocated instance of Messenger on success. | 373 | * return allocated instance of Messenger on success. |
374 | * return 0 if there are problems. | 374 | * return 0 if there are problems. |
375 | */ | 375 | */ |
376 | Messenger *initMessenger(void); | 376 | Messenger *initMessenger(uint8_t ipv6enabled); |
377 | 377 | ||
378 | /* Run this before closing shop | 378 | /* Run this before closing shop |
379 | * Free all datastructures. | 379 | * Free all datastructures. |
diff --git a/toxcore/friend_requests.c b/toxcore/friend_requests.c index b01015c4..c821d998 100644 --- a/toxcore/friend_requests.c +++ b/toxcore/friend_requests.c | |||
@@ -50,18 +50,22 @@ int send_friendrequest(DHT *dht, uint8_t *public_key, uint32_t nospam_num, uint8 | |||
50 | if (len == -1) | 50 | if (len == -1) |
51 | return -1; | 51 | return -1; |
52 | 52 | ||
53 | IP_Port ip_port = DHT_getfriendip(dht, public_key); | 53 | IP_Port ip_port; |
54 | int friendok = DHT_getfriendip(dht, public_key, &ip_port); | ||
54 | 55 | ||
55 | if (ip_port.ip.uint32 == 1) | 56 | // not a friend |
57 | if (friendok == -1) | ||
56 | return -1; | 58 | return -1; |
57 | 59 | ||
58 | if (ip_port.ip.uint32 != 0) { | 60 | // is a friend and we know how to reach him |
59 | if (sendpacket(dht->c->lossless_udp->net->sock, ip_port, packet, len) != -1) | 61 | if (friendok == 1) { |
62 | if (sendpacket(dht->c->lossless_udp->net, ip_port, packet, len) != -1) | ||
60 | return 0; | 63 | return 0; |
61 | 64 | ||
62 | return -1; | 65 | return -1; |
63 | } | 66 | } |
64 | 67 | ||
68 | // is a friend, we DON'T know how to reach him | ||
65 | int num = route_tofriend(dht, public_key, packet, len); | 69 | int num = route_tofriend(dht, public_key, packet, len); |
66 | 70 | ||
67 | if (num == 0) | 71 | if (num == 0) |
diff --git a/toxcore/group_chats.c b/toxcore/group_chats.c index 1e5309ad..f37c6a9c 100644 --- a/toxcore/group_chats.c +++ b/toxcore/group_chats.c | |||
@@ -189,7 +189,7 @@ static int send_groupchatpacket(Group_Chat *chat, IP_Port ip_port, uint8_t *publ | |||
189 | if (len == -1) | 189 | if (len == -1) |
190 | return -1; | 190 | return -1; |
191 | 191 | ||
192 | if (sendpacket(chat->net->sock, ip_port, packet, len) == len) | 192 | if (sendpacket(chat->net, ip_port, packet, len) == len) |
193 | return 0; | 193 | return 0; |
194 | 194 | ||
195 | return -1; | 195 | return -1; |
@@ -208,7 +208,7 @@ static uint8_t sendto_allpeers(Group_Chat *chat, uint8_t *data, uint16_t length, | |||
208 | uint64_t temp_time = unix_time(); | 208 | uint64_t temp_time = unix_time(); |
209 | 209 | ||
210 | for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { | 210 | for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { |
211 | if (chat->close[i].ip_port.ip.uint32 != 0 && chat->close[i].last_recv + BAD_NODE_TIMEOUT > temp_time) { | 211 | if (ip_isset(&chat->close[i].ip_port.ip) && chat->close[i].last_recv + BAD_NODE_TIMEOUT > temp_time) { |
212 | if (send_groupchatpacket(chat, chat->close[i].ip_port, chat->close[i].client_id, data, length, request_id) == 0) | 212 | if (send_groupchatpacket(chat, chat->close[i].ip_port, chat->close[i].client_id, data, length, request_id) == 0) |
213 | ++sent; | 213 | ++sent; |
214 | } | 214 | } |
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index a182bb53..b6f08fe4 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c | |||
@@ -439,7 +439,7 @@ int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port) | |||
439 | if (id != -1) { | 439 | if (id != -1) { |
440 | IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id].number); | 440 | IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id].number); |
441 | 441 | ||
442 | if (c_ip.ip.uint32 == ip_port.ip.uint32 && c_ip.port == ip_port.port) | 442 | if (ipport_equal(&c_ip, &ip_port)) |
443 | return -1; | 443 | return -1; |
444 | } | 444 | } |
445 | 445 | ||
diff --git a/toxcore/network.c b/toxcore/network.c index ed3dff8a..39483b42 100644 --- a/toxcore/network.c +++ b/toxcore/network.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | #include "network.h" | 28 | #include "network.h" |
29 | #include "util.h" | ||
29 | 30 | ||
30 | /* return current UNIX time in microseconds (us). */ | 31 | /* return current UNIX time in microseconds (us). */ |
31 | uint64_t current_time(void) | 32 | uint64_t current_time(void) |
@@ -61,17 +62,76 @@ uint32_t random_int(void) | |||
61 | #endif | 62 | #endif |
62 | } | 63 | } |
63 | 64 | ||
65 | #ifdef LOGGING | ||
66 | static void loglogdata(char *message, uint8_t *buffer, size_t buflen, IP_Port *ip_port, ssize_t res); | ||
67 | #endif | ||
68 | |||
64 | /* Basic network functions: | 69 | /* Basic network functions: |
65 | * Function to send packet(data) of length length to ip_port. | 70 | * Function to send packet(data) of length length to ip_port. |
66 | */ | 71 | */ |
67 | #ifdef WIN32 | 72 | int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t length) |
68 | int sendpacket(unsigned int sock, IP_Port ip_port, uint8_t *data, uint32_t length) | 73 | { |
74 | #ifdef TOX_ENABLE_IPV6 | ||
75 | /* socket AF_INET, but target IP NOT: can't send */ | ||
76 | if ((net->family == AF_INET) && (ip_port.ip.family != AF_INET)) | ||
77 | return 0; | ||
78 | #endif | ||
79 | |||
80 | struct sockaddr_storage addr; | ||
81 | size_t addrsize = 0; | ||
82 | |||
83 | #ifdef TOX_ENABLE_IPV6 | ||
84 | if (ip_port.ip.family == AF_INET) { | ||
85 | if (net->family == AF_INET6) { | ||
86 | /* must convert to IPV4-in-IPV6 address */ | ||
87 | addrsize = sizeof(struct sockaddr_in6); | ||
88 | struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; | ||
89 | addr6->sin6_family = AF_INET6; | ||
90 | addr6->sin6_port = ip_port.port; | ||
91 | |||
92 | /* there should be a macro for this in a standards compliant | ||
93 | * environment, not found */ | ||
94 | addr6->sin6_addr.s6_addr32[0] = 0; | ||
95 | addr6->sin6_addr.s6_addr32[1] = 0; | ||
96 | addr6->sin6_addr.s6_addr32[2] = htonl(0xFFFF); | ||
97 | addr6->sin6_addr.s6_addr32[3] = ip_port.ip.ip4.uint32; | ||
98 | |||
99 | addr6->sin6_flowinfo = 0; | ||
100 | addr6->sin6_scope_id = 0; | ||
101 | } | ||
102 | else { | ||
103 | IP4 ip4 = ip_port.ip.ip4; | ||
69 | #else | 104 | #else |
70 | int sendpacket(int sock, IP_Port ip_port, uint8_t *data, uint32_t length) | 105 | IP4 ip4 = ip_port.ip; |
71 | #endif | 106 | #endif |
72 | { | 107 | addrsize = sizeof(struct sockaddr_in); |
73 | ADDR addr = {AF_INET, ip_port.port, ip_port.ip, {0}}; | 108 | struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr; |
74 | return sendto(sock, (char *) data, length, 0, (struct sockaddr *)&addr, sizeof(addr)); | 109 | addr4->sin_family = AF_INET; |
110 | addr4->sin_addr = ip4.in_addr; | ||
111 | addr4->sin_port = ip_port.port; | ||
112 | #ifdef TOX_ENABLE_IPV6 | ||
113 | } | ||
114 | } | ||
115 | else if (ip_port.ip.family == AF_INET6) { | ||
116 | addrsize = sizeof(struct sockaddr_in6); | ||
117 | struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; | ||
118 | addr6->sin6_family = AF_INET6; | ||
119 | addr6->sin6_port = ip_port.port; | ||
120 | addr6->sin6_addr = ip_port.ip.ip6; | ||
121 | |||
122 | addr6->sin6_flowinfo = 0; | ||
123 | addr6->sin6_scope_id = 0; | ||
124 | } else { | ||
125 | /* unknown address type*/ | ||
126 | return 0; | ||
127 | } | ||
128 | #endif | ||
129 | |||
130 | int res = sendto(net->sock, (char *) data, length, 0, (struct sockaddr *)&addr, addrsize); | ||
131 | #ifdef LOGGING | ||
132 | loglogdata("O=>", data, length, &ip_port, res); | ||
133 | #endif | ||
134 | return res; | ||
75 | } | 135 | } |
76 | 136 | ||
77 | /* Function to receive data | 137 | /* Function to receive data |
@@ -80,13 +140,9 @@ int sendpacket(int sock, IP_Port ip_port, uint8_t *data, uint32_t length) | |||
80 | * Packet length is put into length. | 140 | * Packet length is put into length. |
81 | * Dump all empty packets. | 141 | * Dump all empty packets. |
82 | */ | 142 | */ |
83 | #ifdef WIN32 | 143 | static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t *length) |
84 | static int receivepacket(unsigned int sock, IP_Port *ip_port, uint8_t *data, uint32_t *length) | ||
85 | #else | ||
86 | static int receivepacket(int sock, IP_Port *ip_port, uint8_t *data, uint32_t *length) | ||
87 | #endif | ||
88 | { | 144 | { |
89 | ADDR addr; | 145 | struct sockaddr_storage addr; |
90 | #ifdef WIN32 | 146 | #ifdef WIN32 |
91 | int addrlen = sizeof(addr); | 147 | int addrlen = sizeof(addr); |
92 | #else | 148 | #else |
@@ -94,11 +150,45 @@ static int receivepacket(int sock, IP_Port *ip_port, uint8_t *data, uint32_t *le | |||
94 | #endif | 150 | #endif |
95 | (*(int32_t *)length) = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen); | 151 | (*(int32_t *)length) = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen); |
96 | 152 | ||
97 | if (*(int32_t *)length <= 0) | 153 | if (*(int32_t *)length <= 0) { |
154 | #ifdef LOGGING | ||
155 | if ((length < 0) && (errno != EWOULDBLOCK)) { | ||
156 | sprintf(logbuffer, "Unexpected error reading from socket: %u, %s\n", errno, strerror(errno)); | ||
157 | loglog(logbuffer); | ||
158 | } | ||
159 | #endif | ||
98 | return -1; /* Nothing received or empty packet. */ | 160 | return -1; /* Nothing received or empty packet. */ |
161 | } | ||
162 | |||
163 | #ifdef TOX_ENABLE_IPV6 | ||
164 | if (addr.ss_family == AF_INET) { | ||
165 | struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr; | ||
166 | ip_port->ip.family = addr_in->sin_family; | ||
167 | ip_port->ip.ip4.in_addr = addr_in->sin_addr; | ||
168 | ip_port->port = addr_in->sin_port; | ||
169 | } | ||
170 | else if (addr.ss_family == AF_INET6) { | ||
171 | struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr; | ||
172 | ip_port->ip.family = addr_in6->sin6_family; | ||
173 | ip_port->ip.ip6 = addr_in6->sin6_addr; | ||
174 | ip_port->port = addr_in6->sin6_port; | ||
175 | } | ||
176 | else | ||
177 | return -1; | ||
178 | #else | ||
179 | if (addr.ss_family == AF_INET) { | ||
180 | struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr; | ||
181 | ip_port->ip.in_addr = addr_in->sin_addr; | ||
182 | ip_port->port = addr_in->sin_port; | ||
183 | } | ||
184 | else | ||
185 | return -1; | ||
186 | #endif | ||
187 | |||
188 | #ifdef LOGGING | ||
189 | loglogdata("=>O", data, MAX_UDP_PACKET_SIZE, ip_port, *length); | ||
190 | #endif | ||
99 | 191 | ||
100 | ip_port->ip = addr.ip; | ||
101 | ip_port->port = addr.port; | ||
102 | return 0; | 192 | return 0; |
103 | } | 193 | } |
104 | 194 | ||
@@ -117,13 +207,20 @@ void networking_poll(Networking_Core *net) | |||
117 | while (receivepacket(net->sock, &ip_port, data, &length) != -1) { | 207 | while (receivepacket(net->sock, &ip_port, data, &length) != -1) { |
118 | if (length < 1) continue; | 208 | if (length < 1) continue; |
119 | 209 | ||
120 | if (!(net->packethandlers[data[0]].function)) continue; | 210 | if (!(net->packethandlers[data[0]].function)) { |
211 | #ifdef LOGGING | ||
212 | sprintf(logbuffer, "[%02u] -- Packet has no handler.\n", data[0]); | ||
213 | loglog(logbuffer); | ||
214 | #endif | ||
215 | continue; | ||
216 | } | ||
121 | 217 | ||
122 | net->packethandlers[data[0]].function(net->packethandlers[data[0]].object, ip_port, data, length); | 218 | net->packethandlers[data[0]].function(net->packethandlers[data[0]].object, ip_port, data, length); |
123 | } | 219 | } |
124 | } | 220 | } |
125 | 221 | ||
126 | uint8_t at_startup_ran; | 222 | |
223 | uint8_t at_startup_ran = 0; | ||
127 | static int at_startup(void) | 224 | static int at_startup(void) |
128 | { | 225 | { |
129 | if (at_startup_ran != 0) | 226 | if (at_startup_ran != 0) |
@@ -162,16 +259,31 @@ static void at_shutdown(void) | |||
162 | */ | 259 | */ |
163 | Networking_Core *new_networking(IP ip, uint16_t port) | 260 | Networking_Core *new_networking(IP ip, uint16_t port) |
164 | { | 261 | { |
262 | #ifdef TOX_ENABLE_IPV6 | ||
263 | /* maybe check for invalid IPs like 224+.x.y.z? if there is any IP set ever */ | ||
264 | if (ip.family != AF_INET && ip.family != AF_INET6) { | ||
265 | fprintf(stderr, "Invalid address family: %u\n", ip.family); | ||
266 | return NULL; | ||
267 | } | ||
268 | #endif | ||
269 | |||
165 | if (at_startup() != 0) | 270 | if (at_startup() != 0) |
166 | return NULL; | 271 | return NULL; |
167 | 272 | ||
168 | /* Initialize our socket. */ | ||
169 | Networking_Core *temp = calloc(1, sizeof(Networking_Core)); | 273 | Networking_Core *temp = calloc(1, sizeof(Networking_Core)); |
170 | |||
171 | if (temp == NULL) | 274 | if (temp == NULL) |
172 | return NULL; | 275 | return NULL; |
173 | 276 | ||
174 | temp->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); | 277 | #ifdef TOX_ENABLE_IPV6 |
278 | temp->family = ip.family; | ||
279 | #else | ||
280 | temp->family = AF_INET; | ||
281 | #endif | ||
282 | temp->port = 0; | ||
283 | |||
284 | /* Initialize our socket. */ | ||
285 | /* add log message what we're creating */ | ||
286 | temp->sock = socket(temp->family, SOCK_DGRAM, IPPROTO_UDP); | ||
175 | 287 | ||
176 | /* Check for socket error. */ | 288 | /* Check for socket error. */ |
177 | #ifdef WIN32 | 289 | #ifdef WIN32 |
@@ -184,6 +296,7 @@ Networking_Core *new_networking(IP ip, uint16_t port) | |||
184 | #else | 296 | #else |
185 | 297 | ||
186 | if (temp->sock < 0) { | 298 | if (temp->sock < 0) { |
299 | fprintf(stderr, "Failed to get a scoket?! %u, %s\n", errno, strerror(errno)); | ||
187 | free(temp); | 300 | free(temp); |
188 | return NULL; | 301 | return NULL; |
189 | } | 302 | } |
@@ -204,7 +317,7 @@ Networking_Core *new_networking(IP ip, uint16_t port) | |||
204 | return -1; | 317 | return -1; |
205 | */ | 318 | */ |
206 | 319 | ||
207 | /* Enable broadcast on socket. */ | 320 | /* Enable broadcast on socket */ |
208 | int broadcast = 1; | 321 | int broadcast = 1; |
209 | setsockopt(temp->sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast)); | 322 | setsockopt(temp->sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast)); |
210 | 323 | ||
@@ -218,10 +331,128 @@ Networking_Core *new_networking(IP ip, uint16_t port) | |||
218 | fcntl(temp->sock, F_SETFL, O_NONBLOCK, 1); | 331 | fcntl(temp->sock, F_SETFL, O_NONBLOCK, 1); |
219 | #endif | 332 | #endif |
220 | 333 | ||
221 | /* Bind our socket to port PORT and address 0.0.0.0 */ | 334 | #ifdef LOGGING |
222 | ADDR addr = {AF_INET, htons(port), ip, {0}}; | 335 | loginit(ntohs(port)); |
223 | bind(temp->sock, (struct sockaddr *)&addr, sizeof(addr)); | 336 | #endif |
224 | return temp; | 337 | |
338 | /* Bind our socket to port PORT and the given IP address (usually 0.0.0.0 or ::) */ | ||
339 | uint16_t *portptr = NULL; | ||
340 | struct sockaddr_storage addr; | ||
341 | size_t addrsize; | ||
342 | #ifdef TOX_ENABLE_IPV6 | ||
343 | if (temp->family == AF_INET) | ||
344 | { | ||
345 | IP4 ip4 = ip.ip4; | ||
346 | #else | ||
347 | IP4 ip4 = ip; | ||
348 | #endif | ||
349 | addrsize = sizeof(struct sockaddr_in); | ||
350 | struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr; | ||
351 | addr4->sin_family = AF_INET; | ||
352 | addr4->sin_port = 0; | ||
353 | addr4->sin_addr = ip4.in_addr; | ||
354 | |||
355 | portptr = &addr4->sin_port; | ||
356 | #ifdef TOX_ENABLE_IPV6 | ||
357 | } | ||
358 | else if (temp->family == AF_INET6) | ||
359 | { | ||
360 | addrsize = sizeof(struct sockaddr_in6); | ||
361 | struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; | ||
362 | addr6->sin6_family = AF_INET6; | ||
363 | addr6->sin6_port = 0; | ||
364 | addr6->sin6_addr = ip.ip6; | ||
365 | |||
366 | addr6->sin6_flowinfo = 0; | ||
367 | addr6->sin6_scope_id = 0; | ||
368 | |||
369 | portptr = &addr6->sin6_port; | ||
370 | } | ||
371 | else | ||
372 | return NULL; | ||
373 | |||
374 | if (ip.family == AF_INET6) { | ||
375 | char ipv6only = 0; | ||
376 | int res = setsockopt(temp->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, sizeof(ipv6only)); | ||
377 | #ifdef LOGGING | ||
378 | if (res < 0) { | ||
379 | sprintf(logbuffer, "Failed to enable dual-stack on IPv6 socket, won't be able to receive from/send to IPv4 addresses. (%u, %s)\n", | ||
380 | errno, strerror(errno)); | ||
381 | loglog(logbuffer); | ||
382 | } | ||
383 | else | ||
384 | loglog("Embedded IPv4 addresses enabled successfully.\n"); | ||
385 | #endif | ||
386 | |||
387 | /* multicast local nodes */ | ||
388 | struct ipv6_mreq mreq; | ||
389 | memset(&mreq, 0, sizeof(mreq)); | ||
390 | mreq.ipv6mr_multiaddr.s6_addr[ 0] = 0xFF; | ||
391 | mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02; | ||
392 | mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01; | ||
393 | mreq.ipv6mr_interface = 0; | ||
394 | res = setsockopt(temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); | ||
395 | #ifdef LOGGING | ||
396 | if (res < 0) { | ||
397 | sprintf(logbuffer, "Failed to activate local multicast membership. (%u, %s)\n", | ||
398 | errno, strerror(errno)); | ||
399 | loglog(logbuffer); | ||
400 | } | ||
401 | else | ||
402 | loglog("Local multicast group FF02::1 joined successfully.\n"); | ||
403 | #endif | ||
404 | } | ||
405 | #endif | ||
406 | |||
407 | /* a hanging program or a different user might block the standard port; | ||
408 | * as long as it isn't a parameter coming from the commandline, | ||
409 | * try a few ports after it, to see if we can find a "free" one | ||
410 | * | ||
411 | * if we go on without binding, the first sendto() automatically binds to | ||
412 | * a free port chosen by the system (i.e. anything from 1024 to 65535) | ||
413 | * | ||
414 | * returning NULL after bind fails has both advantages and disadvantages: | ||
415 | * advantage: | ||
416 | * we can rely on getting the port in the range 33445..33450, which | ||
417 | * enables us to tell joe user to open their firewall to a small range | ||
418 | * | ||
419 | * disadvantage: | ||
420 | * some clients might not test return of tox_new(), blindly assuming that | ||
421 | * it worked ok (which it did previously without a successful bind) | ||
422 | */ | ||
423 | uint16_t port_to_try = port; | ||
424 | *portptr = htons(port_to_try); | ||
425 | int tries, res; | ||
426 | for(tries = TOX_PORTRANGE_FROM; tries <= TOX_PORTRANGE_TO; tries++) | ||
427 | { | ||
428 | res = bind(temp->sock, (struct sockaddr *)&addr, addrsize); | ||
429 | if (!res) | ||
430 | { | ||
431 | temp->port = *portptr; | ||
432 | #ifdef LOGGING | ||
433 | sprintf(logbuffer, "Bound successfully to %s:%u.\n", ip_ntoa(&ip), ntohs(temp->port)); | ||
434 | loglog(logbuffer); | ||
435 | #endif | ||
436 | /* errno isn't reset on success, only set on failure, the failed | ||
437 | * binds with parallel clients yield a -EPERM to the outside if | ||
438 | * errno isn't cleared here */ | ||
439 | if (tries > 0) | ||
440 | errno = 0; | ||
441 | |||
442 | return temp; | ||
443 | } | ||
444 | |||
445 | port_to_try++; | ||
446 | if (port_to_try > TOX_PORTRANGE_TO) | ||
447 | port_to_try = TOX_PORTRANGE_FROM; | ||
448 | |||
449 | *portptr = htons(port_to_try); | ||
450 | } | ||
451 | |||
452 | fprintf(stderr, "Failed to bind socket: %u, %s (IP/Port: %s:%u\n", errno, | ||
453 | strerror(errno), ip_ntoa(&ip), port); | ||
454 | free(temp); | ||
455 | return NULL; | ||
225 | } | 456 | } |
226 | 457 | ||
227 | /* Function to cleanup networking stuff. */ | 458 | /* Function to cleanup networking stuff. */ |
@@ -235,3 +466,389 @@ void kill_networking(Networking_Core *net) | |||
235 | free(net); | 466 | free(net); |
236 | return; | 467 | return; |
237 | } | 468 | } |
469 | |||
470 | /* ip_equal | ||
471 | * compares two IPAny structures | ||
472 | * unset means unequal | ||
473 | * | ||
474 | * returns 0 when not equal or when uninitialized | ||
475 | */ | ||
476 | int ip_equal(IP *a, IP *b) | ||
477 | { | ||
478 | if (!a || !b) | ||
479 | return 0; | ||
480 | |||
481 | #ifdef TOX_ENABLE_IPV6 | ||
482 | if (a->family == AF_INET) | ||
483 | return (a->ip4.in_addr.s_addr == b->ip4.in_addr.s_addr); | ||
484 | |||
485 | if (a->family == AF_INET6) | ||
486 | return IN6_ARE_ADDR_EQUAL(&a->ip6, &b->ip6); | ||
487 | |||
488 | return 0; | ||
489 | #else | ||
490 | return (a->uint32 == b->uint32); | ||
491 | #endif | ||
492 | }; | ||
493 | |||
494 | /* ipport_equal | ||
495 | * compares two IPAny_Port structures | ||
496 | * unset means unequal | ||
497 | * | ||
498 | * returns 0 when not equal or when uninitialized | ||
499 | */ | ||
500 | int ipport_equal(IP_Port *a, IP_Port *b) | ||
501 | { | ||
502 | if (!a || !b) | ||
503 | return 0; | ||
504 | |||
505 | if (!a->port || (a->port != b->port)) | ||
506 | return 0; | ||
507 | |||
508 | return ip_equal(&a->ip, &b->ip); | ||
509 | }; | ||
510 | |||
511 | /* nulls out ip */ | ||
512 | void ip_reset(IP *ip) | ||
513 | { | ||
514 | if (!ip) | ||
515 | return; | ||
516 | |||
517 | #ifdef TOX_ENABLE_IPV6 | ||
518 | memset(ip, 0, sizeof(IP)); | ||
519 | #else | ||
520 | ip->uint32 = 0; | ||
521 | #endif | ||
522 | }; | ||
523 | |||
524 | /* nulls out ip, sets family according to flag */ | ||
525 | void ip_init(IP *ip, uint8_t ipv6enabled) | ||
526 | { | ||
527 | if (!ip) | ||
528 | return; | ||
529 | |||
530 | #ifdef TOX_ENABLE_IPV6 | ||
531 | memset(ip, 0, sizeof(IP)); | ||
532 | ip->family = ipv6enabled ? AF_INET6 : AF_INET; | ||
533 | #else | ||
534 | ip->uint32 = 0; | ||
535 | #endif | ||
536 | }; | ||
537 | |||
538 | /* checks if ip is valid */ | ||
539 | int ip_isset(IP *ip) | ||
540 | { | ||
541 | if (!ip) | ||
542 | return 0; | ||
543 | |||
544 | #ifdef TOX_ENABLE_IPV6 | ||
545 | return (ip->family != 0); | ||
546 | #else | ||
547 | return (ip->uint32 != 0); | ||
548 | #endif | ||
549 | }; | ||
550 | |||
551 | /* checks if ip is valid */ | ||
552 | int ipport_isset(IP_Port *ipport) | ||
553 | { | ||
554 | if (!ipport) | ||
555 | return 0; | ||
556 | |||
557 | if (!ipport->port) | ||
558 | return 0; | ||
559 | |||
560 | return ip_isset(&ipport->ip); | ||
561 | }; | ||
562 | |||
563 | /* copies an ip structure (careful about direction!) */ | ||
564 | void ip_copy(IP *target, IP *source) | ||
565 | { | ||
566 | if (!source || !target) | ||
567 | return; | ||
568 | |||
569 | memcpy(target, source, sizeof(IP)); | ||
570 | }; | ||
571 | |||
572 | /* copies an ip_port structure (careful about direction!) */ | ||
573 | void ipport_copy(IP_Port *target, IP_Port *source) | ||
574 | { | ||
575 | if (!source || !target) | ||
576 | return; | ||
577 | |||
578 | memcpy(target, source, sizeof(IP_Port)); | ||
579 | }; | ||
580 | |||
581 | /* ip_ntoa | ||
582 | * converts ip into a string | ||
583 | * uses a static buffer, so mustn't used multiple times in the same output | ||
584 | */ | ||
585 | /* there would be INET6_ADDRSTRLEN, but it might be too short for the error message */ | ||
586 | static char addresstext[96]; | ||
587 | const char *ip_ntoa(IP *ip) | ||
588 | { | ||
589 | if (ip) { | ||
590 | #ifdef TOX_ENABLE_IPV6 | ||
591 | if (ip->family == AF_INET) { | ||
592 | addresstext[0] = 0; | ||
593 | struct in_addr *addr = (struct in_addr *)&ip->ip4; | ||
594 | inet_ntop(ip->family, addr, addresstext, sizeof(addresstext)); | ||
595 | } | ||
596 | else if (ip->family == AF_INET6) { | ||
597 | addresstext[0] = '['; | ||
598 | struct in6_addr *addr = (struct in6_addr *)&ip->ip6; | ||
599 | inet_ntop(ip->family, addr, &addresstext[1], sizeof(addresstext) - 3); | ||
600 | size_t len = strlen(addresstext); | ||
601 | addresstext[len] = ']'; | ||
602 | addresstext[len + 1] = 0; | ||
603 | } | ||
604 | else | ||
605 | snprintf(addresstext, sizeof(addresstext), "(IP invalid, family %u)", ip->family); | ||
606 | #else | ||
607 | addresstext[0] = 0; | ||
608 | struct in_addr *addr = (struct in_addr *)&ip; | ||
609 | inet_ntop(AF_INET, addr, addresstext, sizeof(addresstext)); | ||
610 | #endif | ||
611 | } | ||
612 | else | ||
613 | snprintf(addresstext, sizeof(addresstext), "(IP invalid: NULL)"); | ||
614 | |||
615 | addresstext[INET6_ADDRSTRLEN + 2] = 0; | ||
616 | return addresstext; | ||
617 | }; | ||
618 | |||
619 | /* | ||
620 | * addr_parse_ip | ||
621 | * directly parses the input into an IP structure | ||
622 | * tries IPv4 first, then IPv6 | ||
623 | * | ||
624 | * input | ||
625 | * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6) | ||
626 | * | ||
627 | * output | ||
628 | * IP: family and the value is set on success | ||
629 | * | ||
630 | * returns 1 on success, 0 on failure | ||
631 | */ | ||
632 | |||
633 | int addr_parse_ip(const char *address, IP *to) | ||
634 | { | ||
635 | if (!address || !to) | ||
636 | return 0; | ||
637 | |||
638 | #ifdef TOX_ENABLE_IPV6 | ||
639 | struct in_addr addr4; | ||
640 | if (1 == inet_pton(AF_INET, address, &addr4)) { | ||
641 | to->family = AF_INET; | ||
642 | to->ip4.in_addr = addr4; | ||
643 | return 1; | ||
644 | }; | ||
645 | |||
646 | struct in6_addr addr6; | ||
647 | if (1 == inet_pton(AF_INET6, address, &addr6)) { | ||
648 | to->family = AF_INET6; | ||
649 | to->ip6 = addr6; | ||
650 | return 1; | ||
651 | }; | ||
652 | #else | ||
653 | struct in_addr addr4; | ||
654 | if (1 == inet_pton(AF_INET, address, &addr4)) { | ||
655 | to->in_addr = addr4; | ||
656 | return 1; | ||
657 | }; | ||
658 | #endif | ||
659 | |||
660 | return 0; | ||
661 | }; | ||
662 | |||
663 | /* | ||
664 | * addr_resolve(): | ||
665 | * uses getaddrinfo to resolve an address into an IP address | ||
666 | * uses the first IPv4/IPv6 addresses returned by getaddrinfo | ||
667 | * | ||
668 | * input | ||
669 | * address: a hostname (or something parseable to an IP address) | ||
670 | * to: to.family MUST be initialized, either set to a specific IP version | ||
671 | * (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both | ||
672 | * IP versions are acceptable | ||
673 | * extra can be NULL and is only set in special circumstances, see returns | ||
674 | * | ||
675 | * returns in *to a valid IPAny (v4/v6), | ||
676 | * prefers v6 if ip.family was AF_UNSPEC and both available | ||
677 | * returns in *extra an IPv4 address, if family was AF_UNSPEC and *to is AF_INET6 | ||
678 | * returns 0 on failure | ||
679 | */ | ||
680 | |||
681 | int addr_resolve(const char *address, IP *to, IP *extra) | ||
682 | { | ||
683 | if (!address || !to) | ||
684 | return 0; | ||
685 | |||
686 | sa_family_t family; | ||
687 | #ifdef TOX_ENABLE_IPV6 | ||
688 | family = to->family; | ||
689 | #else | ||
690 | family = AF_INET; | ||
691 | #endif | ||
692 | |||
693 | struct addrinfo *server = NULL; | ||
694 | struct addrinfo *walker = NULL; | ||
695 | struct addrinfo hints; | ||
696 | int rc; | ||
697 | |||
698 | memset(&hints, 0, sizeof(hints)); | ||
699 | hints.ai_family = family; | ||
700 | hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses. | ||
701 | |||
702 | #ifdef __WIN32__ | ||
703 | WSADATA wsa_data; | ||
704 | |||
705 | /* CLEANUP: really not the best place to put this */ | ||
706 | rc = WSAStartup(MAKEWORD(2, 2), &wsa_data); | ||
707 | |||
708 | if (rc != 0) { | ||
709 | return 0; | ||
710 | } | ||
711 | |||
712 | #endif | ||
713 | |||
714 | rc = getaddrinfo(address, NULL, &hints, &server); | ||
715 | // Lookup failed. | ||
716 | if (rc != 0) { | ||
717 | #ifdef __WIN32__ | ||
718 | WSACleanup(); | ||
719 | #endif | ||
720 | return 0; | ||
721 | } | ||
722 | |||
723 | #ifdef TOX_ENABLE_IPV6 | ||
724 | IP4 ip4; | ||
725 | memset(&ip4, 0, sizeof(ip4)); | ||
726 | IP6 ip6; | ||
727 | memset(&ip6, 0, sizeof(ip6)); | ||
728 | #endif | ||
729 | |||
730 | walker = server; | ||
731 | while (walker && (rc != 3)) { | ||
732 | if (family != AF_UNSPEC) { | ||
733 | if (walker->ai_family == family) { | ||
734 | if (family == AF_INET) { | ||
735 | if (walker->ai_addrlen == sizeof(struct sockaddr_in)) { | ||
736 | struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr; | ||
737 | #ifdef TOX_ENABLE_IPV6 | ||
738 | to->ip4.in_addr = addr->sin_addr; | ||
739 | #else | ||
740 | to->in_addr = addr->sin_addr; | ||
741 | #endif | ||
742 | rc = 3; | ||
743 | } | ||
744 | } | ||
745 | #ifdef TOX_ENABLE_IPV6 | ||
746 | else if (family == AF_INET6) { | ||
747 | if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) { | ||
748 | struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr; | ||
749 | to->ip6 = addr->sin6_addr; | ||
750 | rc = 3; | ||
751 | } | ||
752 | } | ||
753 | #endif | ||
754 | } | ||
755 | } | ||
756 | #ifdef TOX_ENABLE_IPV6 | ||
757 | else { | ||
758 | if (walker->ai_family == AF_INET) { | ||
759 | if (walker->ai_addrlen == sizeof(struct sockaddr_in)) { | ||
760 | struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr; | ||
761 | ip4.in_addr = addr->sin_addr; | ||
762 | rc |= 1; | ||
763 | } | ||
764 | } | ||
765 | else if (walker->ai_family == AF_INET6) { | ||
766 | if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) { | ||
767 | struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr; | ||
768 | ip6 = addr->sin6_addr; | ||
769 | rc |= 2; | ||
770 | } | ||
771 | } | ||
772 | } | ||
773 | #endif | ||
774 | |||
775 | walker = walker->ai_next; | ||
776 | } | ||
777 | |||
778 | #ifdef TOX_ENABLE_IPV6 | ||
779 | if (to->family == AF_UNSPEC) { | ||
780 | if (rc & 2) { | ||
781 | to->family = AF_INET6; | ||
782 | to->ip6 = ip6; | ||
783 | if ((rc & 1) && (extra != NULL)) { | ||
784 | extra->family = AF_INET; | ||
785 | extra->ip4 = ip4; | ||
786 | } | ||
787 | } | ||
788 | else if (rc & 1) { | ||
789 | to->family = AF_INET; | ||
790 | to->ip4 = ip4; | ||
791 | } | ||
792 | else | ||
793 | rc = 0; | ||
794 | } | ||
795 | #endif | ||
796 | |||
797 | |||
798 | freeaddrinfo(server); | ||
799 | #ifdef __WIN32__ | ||
800 | WSACleanup(); | ||
801 | #endif | ||
802 | return rc; | ||
803 | } | ||
804 | |||
805 | /* | ||
806 | * addr_resolve_or_parse_ip | ||
807 | * resolves string into an IP address | ||
808 | * | ||
809 | * address: a hostname (or something parseable to an IP address) | ||
810 | * to: to.family MUST be initialized, either set to a specific IP version | ||
811 | * (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both | ||
812 | * IP versions are acceptable | ||
813 | * extra can be NULL and is only set in special circumstances, see returns | ||
814 | * | ||
815 | * returns in *tro a matching address (IPv6 or IPv4) | ||
816 | * returns in *extra, if not NULL, an IPv4 address, if to->family was AF_UNSPEC | ||
817 | * returns 1 on success | ||
818 | * returns 0 on failure | ||
819 | */ | ||
820 | int addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra) | ||
821 | { | ||
822 | if (!addr_resolve(address, to, extra)) | ||
823 | if (!addr_parse_ip(address, to)) | ||
824 | return 0; | ||
825 | |||
826 | return 1; | ||
827 | }; | ||
828 | |||
829 | #ifdef LOGGING | ||
830 | static void loglogdata(char *message, uint8_t *buffer, size_t buflen, IP_Port *ip_port, ssize_t res) | ||
831 | { | ||
832 | if (res < 0) | ||
833 | snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %3u%c %s:%u (%u: %s) | %04x%04x\n", | ||
834 | buffer[0], message, buflen < 999 ? buflen : 999, 'E', | ||
835 | ip_ntoa(&ip_port->ip), ntohs(ip_port->port), errno, | ||
836 | strerror(errno), buflen > 4 ? ntohl(*(uint32_t *)&buffer[1]) : 0, | ||
837 | buflen > 7 ? ntohl(*(uint32_t *)(&buffer[5])) : 0); | ||
838 | else if ((res > 0) && (res <= buflen)) | ||
839 | snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %3u%c %s:%u (%u: %s) | %04x%04x\n", | ||
840 | buffer[0], message, res < 999 ? res : 999, res < buflen ? '<' : '=', | ||
841 | ip_ntoa(&ip_port->ip), ntohs(ip_port->port), 0, | ||
842 | "OK", buflen > 4 ? ntohl(*(uint32_t *)&buffer[1]) : 0, | ||
843 | buflen > 7 ? ntohl(*(uint32_t *)(&buffer[5])) : 0); | ||
844 | else /* empty or overwrite */ | ||
845 | snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %u%c%u %s:%u (%u: %s) | %04x%04x\n", | ||
846 | buffer[0], message, res, !res ? '0' : '>', buflen, | ||
847 | ip_ntoa(&ip_port->ip), ntohs(ip_port->port), 0, | ||
848 | "OK", buflen > 4 ? ntohl(*(uint32_t *)&buffer[1]) : 0, | ||
849 | buflen > 7 ? ntohl(*(uint32_t *)(&buffer[5])) : 0); | ||
850 | |||
851 | logbuffer[sizeof(logbuffer) - 1] = 0; | ||
852 | loglog(logbuffer); | ||
853 | } | ||
854 | #endif | ||
diff --git a/toxcore/network.h b/toxcore/network.h index 98307e5b..12a48868 100644 --- a/toxcore/network.h +++ b/toxcore/network.h | |||
@@ -39,17 +39,22 @@ | |||
39 | #include <windows.h> | 39 | #include <windows.h> |
40 | #include <ws2tcpip.h> | 40 | #include <ws2tcpip.h> |
41 | 41 | ||
42 | typedef unsigned int sock_t; | ||
43 | |||
42 | #else // Linux includes | 44 | #else // Linux includes |
43 | 45 | ||
44 | #include <fcntl.h> | 46 | #include <fcntl.h> |
45 | #include <sys/socket.h> | 47 | #include <sys/socket.h> |
46 | #include <netinet/in.h> | 48 | #include <netinet/in.h> |
49 | #include <arpa/inet.h> | ||
47 | #include <errno.h> | 50 | #include <errno.h> |
48 | #include <sys/time.h> | 51 | #include <sys/time.h> |
49 | #include <sys/types.h> | 52 | #include <sys/types.h> |
50 | #include <netdb.h> | 53 | #include <netdb.h> |
51 | #include <unistd.h> | 54 | #include <unistd.h> |
52 | 55 | ||
56 | typedef int sock_t; | ||
57 | |||
53 | #endif | 58 | #endif |
54 | 59 | ||
55 | #ifndef VANILLA_NACL | 60 | #ifndef VANILLA_NACL |
@@ -66,7 +71,8 @@ | |||
66 | #define NET_PACKET_PING_REQUEST 0 /* Ping request packet ID. */ | 71 | #define NET_PACKET_PING_REQUEST 0 /* Ping request packet ID. */ |
67 | #define NET_PACKET_PING_RESPONSE 1 /* Ping response packet ID. */ | 72 | #define NET_PACKET_PING_RESPONSE 1 /* Ping response packet ID. */ |
68 | #define NET_PACKET_GET_NODES 2 /* Get nodes request packet ID. */ | 73 | #define NET_PACKET_GET_NODES 2 /* Get nodes request packet ID. */ |
69 | #define NET_PACKET_SEND_NODES 3 /* Send nodes response packet ID. */ | 74 | #define NET_PACKET_SEND_NODES 3 /* Send nodes response packet ID for IPv4 addresses. */ |
75 | #define NET_PACKET_SEND_NODES_IPV6 4 /* Send nodes response packet ID for other addresses. */ | ||
70 | #define NET_PACKET_HANDSHAKE 16 /* Handshake packet ID. */ | 76 | #define NET_PACKET_HANDSHAKE 16 /* Handshake packet ID. */ |
71 | #define NET_PACKET_SYNC 17 /* SYNC packet ID. */ | 77 | #define NET_PACKET_SYNC 17 /* SYNC packet ID. */ |
72 | #define NET_PACKET_DATA 18 /* Data packet ID. */ | 78 | #define NET_PACKET_DATA 18 /* Data packet ID. */ |
@@ -74,6 +80,10 @@ | |||
74 | #define NET_PACKET_LAN_DISCOVERY 33 /* LAN discovery packet ID. */ | 80 | #define NET_PACKET_LAN_DISCOVERY 33 /* LAN discovery packet ID. */ |
75 | #define NET_PACKET_GROUP_CHATS 48 /* Group chats packet ID. */ | 81 | #define NET_PACKET_GROUP_CHATS 48 /* Group chats packet ID. */ |
76 | 82 | ||
83 | #define TOX_PORTRANGE_FROM 33445 | ||
84 | #define TOX_PORTRANGE_TO 33455 | ||
85 | #define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM | ||
86 | |||
77 | /* Current time, unix format */ | 87 | /* Current time, unix format */ |
78 | #define unix_time() ((uint64_t)time(NULL)) | 88 | #define unix_time() ((uint64_t)time(NULL)) |
79 | 89 | ||
@@ -82,27 +92,118 @@ typedef union { | |||
82 | uint8_t uint8[4]; | 92 | uint8_t uint8[4]; |
83 | uint16_t uint16[2]; | 93 | uint16_t uint16[2]; |
84 | uint32_t uint32; | 94 | uint32_t uint32; |
85 | } IP; | 95 | struct in_addr in_addr; |
96 | } IP4; | ||
97 | |||
98 | typedef struct in6_addr IP6; | ||
99 | |||
100 | typedef struct { | ||
101 | sa_family_t family; | ||
102 | union { | ||
103 | IP4 ip4; | ||
104 | IP6 ip6; | ||
105 | }; | ||
106 | } IPAny; | ||
86 | 107 | ||
87 | typedef union { | 108 | typedef union { |
88 | struct { | 109 | struct { |
89 | IP ip; | 110 | IP4 ip; |
90 | uint16_t port; | 111 | uint16_t port; |
91 | /* Not used for anything right now. */ | 112 | /* Not used for anything right now. */ |
92 | uint16_t padding; | 113 | uint16_t padding; |
93 | }; | 114 | }; |
94 | uint8_t uint8[8]; | 115 | uint8_t uint8[8]; |
95 | } IP_Port; | 116 | } IP4_Port; |
96 | 117 | ||
118 | /* will replace IP_Port as soon as the complete infrastructure is in place | ||
119 | * removed the unused union and padding also */ | ||
97 | typedef struct { | 120 | typedef struct { |
98 | int16_t family; | 121 | IPAny ip; |
99 | uint16_t port; | 122 | uint16_t port; |
100 | IP ip; | 123 | } IPAny_Port; |
101 | uint8_t zeroes[8]; | 124 | |
102 | #ifdef ENABLE_IPV6 | 125 | #undef TOX_ENABLE_IPV6 |
103 | uint8_t zeroes2[12]; | 126 | /* #define TOX_ENABLE_IPV6 */ |
127 | #ifdef TOX_ENABLE_IPV6 | ||
128 | #define TOX_ENABLE_IPV6_DEFAULT 1 | ||
129 | typedef IPAny IP; | ||
130 | typedef IPAny_Port IP_Port; | ||
131 | #else | ||
132 | #define TOX_ENABLE_IPV6_DEFAULT 0 | ||
133 | typedef IP4 IP; | ||
134 | typedef IP4_Port IP_Port; | ||
104 | #endif | 135 | #endif |
105 | } ADDR; | 136 | |
137 | /* ip_ntoa | ||
138 | * converts ip into a string | ||
139 | * uses a static buffer, so mustn't used multiple times in the same output | ||
140 | */ | ||
141 | const char *ip_ntoa(IP *ip); | ||
142 | |||
143 | /* ip_equal | ||
144 | * compares two IPAny structures | ||
145 | * unset means unequal | ||
146 | * | ||
147 | * returns 0 when not equal or when uninitialized | ||
148 | */ | ||
149 | int ip_equal(IP *a, IP *b); | ||
150 | |||
151 | /* ipport_equal | ||
152 | * compares two IPAny_Port structures | ||
153 | * unset means unequal | ||
154 | * | ||
155 | * returns 0 when not equal or when uninitialized | ||
156 | */ | ||
157 | int ipport_equal(IP_Port *a, IP_Port *b); | ||
158 | |||
159 | /* nulls out ip */ | ||
160 | void ip_reset(IP *ip); | ||
161 | /* nulls out ip, sets family according to flag */ | ||
162 | void ip_init(IP *ip, uint8_t ipv6enabled); | ||
163 | /* checks if ip is valid */ | ||
164 | int ip_isset(IP *ip); | ||
165 | /* checks if ip is valid */ | ||
166 | int ipport_isset(IP_Port *ipport); | ||
167 | /* copies an ip structure */ | ||
168 | void ip_copy(IP *target, IP *source); | ||
169 | /* copies an ip_port structure */ | ||
170 | void ipport_copy(IP_Port *target, IP_Port *source); | ||
171 | |||
172 | /* | ||
173 | * addr_resolve(): | ||
174 | * uses getaddrinfo to resolve an address into an IP address | ||
175 | * uses the first IPv4/IPv6 addresses returned by getaddrinfo | ||
176 | * | ||
177 | * input | ||
178 | * address: a hostname (or something parseable to an IP address) | ||
179 | * to: to.family MUST be initialized, either set to a specific IP version | ||
180 | * (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both | ||
181 | * IP versions are acceptable | ||
182 | * extra can be NULL and is only set in special circumstances, see returns | ||
183 | * | ||
184 | * returns in *to a valid IPAny (v4/v6), | ||
185 | * prefers v6 if ip.family was AF_UNSPEC and both available | ||
186 | * returns in *extra an IPv4 address, if family was AF_UNSPEC and *to is AF_INET6 | ||
187 | * returns 0 on failure | ||
188 | */ | ||
189 | int addr_resolve(const char *address, IP *to, IP *extra); | ||
190 | |||
191 | /* | ||
192 | * addr_resolve_or_parse_ip | ||
193 | * resolves string into an IP address | ||
194 | * | ||
195 | * address: a hostname (or something parseable to an IP address) | ||
196 | * to: to.family MUST be initialized, either set to a specific IP version | ||
197 | * (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both | ||
198 | * IP versions are acceptable | ||
199 | * extra can be NULL and is only set in special circumstances, see returns | ||
200 | * | ||
201 | * returns in *tro a matching address (IPv6 or IPv4) | ||
202 | * returns in *extra, if not NULL, an IPv4 address, if to->family was AF_UNSPEC | ||
203 | * returns 1 on success | ||
204 | * returns 0 on failure | ||
205 | */ | ||
206 | int addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra); | ||
106 | 207 | ||
107 | /* Function to receive data, ip and port of sender is put into ip_port. | 208 | /* Function to receive data, ip and port of sender is put into ip_port. |
108 | * Packet data is put into data. | 209 | * Packet data is put into data. |
@@ -117,13 +218,11 @@ typedef struct { | |||
117 | 218 | ||
118 | typedef struct { | 219 | typedef struct { |
119 | Packet_Handles packethandlers[256]; | 220 | Packet_Handles packethandlers[256]; |
120 | /* Our UDP socket. */ | ||
121 | #ifdef WIN32 | ||
122 | unsigned int sock; | ||
123 | #else | ||
124 | int sock; | ||
125 | #endif | ||
126 | 221 | ||
222 | /* Our UDP socket. */ | ||
223 | sa_family_t family; | ||
224 | uint16_t port; | ||
225 | sock_t sock; | ||
127 | } Networking_Core; | 226 | } Networking_Core; |
128 | 227 | ||
129 | /* return current time in milleseconds since the epoch. */ | 228 | /* return current time in milleseconds since the epoch. */ |
@@ -137,12 +236,7 @@ uint32_t random_int(void); | |||
137 | /* Basic network functions: */ | 236 | /* Basic network functions: */ |
138 | 237 | ||
139 | /* Function to send packet(data) of length length to ip_port. */ | 238 | /* Function to send packet(data) of length length to ip_port. */ |
140 | #ifdef WIN32 | 239 | int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t length); |
141 | int sendpacket(unsigned int sock, IP_Port ip_port, uint8_t *data, uint32_t length); | ||
142 | #else | ||
143 | int sendpacket(int sock, IP_Port ip_port, uint8_t *data, uint32_t length); | ||
144 | #endif | ||
145 | |||
146 | 240 | ||
147 | /* Function to call when packet beginning with byte is received. */ | 241 | /* Function to call when packet beginning with byte is received. */ |
148 | void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object); | 242 | void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object); |
@@ -163,5 +257,4 @@ Networking_Core *new_networking(IP ip, uint16_t port); | |||
163 | /* Function to cleanup networking stuff (doesn't do much right now). */ | 257 | /* Function to cleanup networking stuff (doesn't do much right now). */ |
164 | void kill_networking(Networking_Core *net); | 258 | void kill_networking(Networking_Core *net); |
165 | 259 | ||
166 | |||
167 | #endif | 260 | #endif |
diff --git a/toxcore/ping.c b/toxcore/ping.c index 3b39d911..49e0dba9 100644 --- a/toxcore/ping.c +++ b/toxcore/ping.c | |||
@@ -100,7 +100,8 @@ bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: Repl | |||
100 | { | 100 | { |
101 | PING *png = ping; | 101 | PING *png = ping; |
102 | 102 | ||
103 | if (ipp.ip.uint32 == 0 && ping_id == 0) | 103 | /* shouldn't that be an OR ? */ |
104 | if (!ip_isset(&ipp.ip) && ping_id == 0) | ||
104 | return false; | 105 | return false; |
105 | 106 | ||
106 | size_t i, id; | 107 | size_t i, id; |
@@ -111,7 +112,8 @@ bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: Repl | |||
111 | id = (png->pos_pings + i) % PING_NUM_MAX; | 112 | id = (png->pos_pings + i) % PING_NUM_MAX; |
112 | 113 | ||
113 | /* ping_id = 0 means match any id. */ | 114 | /* ping_id = 0 means match any id. */ |
114 | if ((ipp_eq(png->pings[id].ipp, ipp) || ipp.ip.uint32 == 0) && (png->pings[id].id == ping_id || ping_id == 0)) { | 115 | if ((!ip_isset(&ipp.ip) || ipport_equal(&png->pings[id].ipp, &ipp)) && |
116 | (png->pings[id].id == ping_id || ping_id == 0)) { | ||
115 | return true; | 117 | return true; |
116 | } | 118 | } |
117 | } | 119 | } |
@@ -147,7 +149,7 @@ int send_ping_request(void *ping, Net_Crypto *c, IP_Port ipp, uint8_t *client_id | |||
147 | if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) | 149 | if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) |
148 | return 1; | 150 | return 1; |
149 | 151 | ||
150 | return sendpacket(c->lossless_udp->net->sock, ipp, pk, sizeof(pk)); | 152 | return sendpacket(c->lossless_udp->net, ipp, pk, sizeof(pk)); |
151 | } | 153 | } |
152 | 154 | ||
153 | int send_ping_response(Net_Crypto *c, IP_Port ipp, uint8_t *client_id, uint64_t ping_id) | 155 | int send_ping_response(Net_Crypto *c, IP_Port ipp, uint8_t *client_id, uint64_t ping_id) |
@@ -172,7 +174,7 @@ int send_ping_response(Net_Crypto *c, IP_Port ipp, uint8_t *client_id, uint64_t | |||
172 | if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) | 174 | if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) |
173 | return 1; | 175 | return 1; |
174 | 176 | ||
175 | return sendpacket(c->lossless_udp->net->sock, ipp, pk, sizeof(pk)); | 177 | return sendpacket(c->lossless_udp->net, ipp, pk, sizeof(pk)); |
176 | } | 178 | } |
177 | 179 | ||
178 | int handle_ping_request(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 180 | int handle_ping_request(void *object, IP_Port source, uint8_t *packet, uint32_t length) |
diff --git a/toxcore/tox.c b/toxcore/tox.c index 54bbd9f0..3eb80d22 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c | |||
@@ -366,14 +366,20 @@ void tox_callback_connectionstatus(void *tox, void (*function)(Messenger *tox, i | |||
366 | m_callback_connectionstatus(m, function, userdata); | 366 | m_callback_connectionstatus(m, function, userdata); |
367 | } | 367 | } |
368 | 368 | ||
369 | /* Use this function to bootstrap the client. | 369 | /* Use these functions to bootstrap the client. |
370 | * Sends a get nodes request to the given node with ip port and public_key. | 370 | * Sends a get nodes request to the given node with ip port and public_key. |
371 | */ | 371 | */ |
372 | void tox_bootstrap(void *tox, IP_Port ip_port, uint8_t *public_key) | 372 | void tox_bootstrap_from_ip(void *tox, IP_Port ip_port, uint8_t *public_key) |
373 | { | 373 | { |
374 | Messenger *m = tox; | 374 | Messenger *m = tox; |
375 | DHT_bootstrap(m->dht, ip_port, public_key); | 375 | DHT_bootstrap(m->dht, ip_port, public_key); |
376 | } | 376 | } |
377 | int tox_bootstrap_from_address(void *tox, const char *address, | ||
378 | uint8_t ipv6enabled, uint16_t port, uint8_t *public_key) | ||
379 | { | ||
380 | Messenger *m = tox; | ||
381 | return DHT_bootstrap_from_address(m->dht, address, ipv6enabled, port, public_key); | ||
382 | }; | ||
377 | 383 | ||
378 | /* return 0 if we are not connected to the DHT. | 384 | /* return 0 if we are not connected to the DHT. |
379 | * return 1 if we are. | 385 | * return 1 if we are. |
@@ -389,9 +395,9 @@ int tox_isconnected(void *tox) | |||
389 | * return allocated instance of tox on success. | 395 | * return allocated instance of tox on success. |
390 | * return 0 if there are problems. | 396 | * return 0 if there are problems. |
391 | */ | 397 | */ |
392 | void *tox_new(void) | 398 | void *tox_new(uint8_t ipv6enabled) |
393 | { | 399 | { |
394 | return initMessenger(); | 400 | return initMessenger(ipv6enabled); |
395 | } | 401 | } |
396 | 402 | ||
397 | /* Run this before closing shop. | 403 | /* Run this before closing shop. |
diff --git a/toxcore/tox.h b/toxcore/tox.h index 811e798b..2fddfab4 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h | |||
@@ -26,6 +26,22 @@ | |||
26 | 26 | ||
27 | #include <stdint.h> | 27 | #include <stdint.h> |
28 | 28 | ||
29 | #ifdef WIN32 | ||
30 | #ifndef WINVER | ||
31 | //Windows XP | ||
32 | #define WINVER 0x0501 | ||
33 | #endif | ||
34 | |||
35 | #include <winsock2.h> | ||
36 | #include <windows.h> | ||
37 | #include <ws2tcpip.h> | ||
38 | |||
39 | #else | ||
40 | |||
41 | #include <netinet/ip.h> | ||
42 | |||
43 | #endif | ||
44 | |||
29 | #ifdef __cplusplus | 45 | #ifdef __cplusplus |
30 | extern "C" { | 46 | extern "C" { |
31 | #endif | 47 | #endif |
@@ -36,19 +52,56 @@ extern "C" { | |||
36 | 52 | ||
37 | #define TOX_FRIEND_ADDRESS_SIZE (TOX_CLIENT_ID_SIZE + sizeof(uint32_t) + sizeof(uint16_t)) | 53 | #define TOX_FRIEND_ADDRESS_SIZE (TOX_CLIENT_ID_SIZE + sizeof(uint32_t) + sizeof(uint16_t)) |
38 | 54 | ||
55 | #define TOX_PORTRANGE_FROM 33445 | ||
56 | #define TOX_PORTRANGE_TO 33455 | ||
57 | #define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM | ||
39 | 58 | ||
40 | typedef union { | 59 | typedef union { |
41 | uint8_t c[4]; | 60 | uint8_t c[4]; |
42 | uint16_t s[2]; | 61 | uint16_t s[2]; |
43 | uint32_t i; | 62 | uint32_t i; |
44 | } tox_IP; | 63 | } tox_IP4; |
64 | |||
65 | |||
66 | typedef struct in6_addr tox_IP6; | ||
67 | |||
68 | typedef struct { | ||
69 | sa_family_t family; | ||
70 | union { | ||
71 | tox_IP4 ip4; | ||
72 | tox_IP6 ip6; | ||
73 | }; | ||
74 | } tox_IPAny; | ||
45 | 75 | ||
76 | typedef union { | ||
77 | struct { | ||
78 | tox_IP4 ip; | ||
79 | uint16_t port; | ||
80 | /* Not used for anything right now. */ | ||
81 | uint16_t padding; | ||
82 | }; | ||
83 | uint8_t uint8[8]; | ||
84 | } tox_IP4_Port; | ||
85 | |||
86 | /* will replace IP_Port as soon as the complete infrastructure is in place | ||
87 | * removed the unused union and padding also */ | ||
46 | typedef struct { | 88 | typedef struct { |
47 | tox_IP ip; | 89 | tox_IPAny ip; |
48 | uint16_t port; | 90 | uint16_t port; |
49 | /* Not used for anything right now. */ | 91 | } tox_IPAny_Port; |
50 | uint16_t padding; | 92 | |
51 | } tox_IP_Port; | 93 | #undef TOX_ENABLE_IPV6 |
94 | /* #define TOX_ENABLE_IPV6 */ | ||
95 | #ifdef TOX_ENABLE_IPV6 | ||
96 | #define TOX_ENABLE_IPV6_DEFAULT 1 | ||
97 | typedef tox_IPAny tox_IP; | ||
98 | typedef tox_IPAny_Port tox_IP_Port; | ||
99 | #else | ||
100 | #define TOX_ENABLE_IPV6_DEFAULT 0 | ||
101 | typedef tox_IP4 tox_IP; | ||
102 | typedef tox_IP4_Port tox_IP_Port; | ||
103 | #endif | ||
104 | |||
52 | 105 | ||
53 | /* Errors for m_addfriend | 106 | /* Errors for m_addfriend |
54 | * FAERR - Friend Add Error | 107 | * FAERR - Friend Add Error |
@@ -289,22 +342,46 @@ void tox_callback_read_receipt(Tox *tox, void (*function)(Tox *tox, int, uint32_ | |||
289 | */ | 342 | */ |
290 | void tox_callback_connectionstatus(Tox *tox, void (*function)(Tox *tox, int, uint8_t, void *), void *userdata); | 343 | void tox_callback_connectionstatus(Tox *tox, void (*function)(Tox *tox, int, uint8_t, void *), void *userdata); |
291 | 344 | ||
292 | /* Use this function to bootstrap the client. | 345 | /* |
293 | * Sends a get nodes request to the given node with ip port and public_key. | 346 | * Use these two functions to bootstrap the client. |
294 | */ | 347 | */ |
295 | void tox_bootstrap(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key); | 348 | /* Sends a "get nodes" request to the given node with ip, port and public_key |
349 | * to setup connections | ||
350 | */ | ||
351 | void tox_bootstrap_from_ip(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key); | ||
352 | /* Resolves address into an IP address. If successful, sends a "get nodes" | ||
353 | * request to the given node with ip, port and public_key to setup connections | ||
354 | * | ||
355 | * address can be a hostname or an IP address (IPv4 or IPv6). | ||
356 | * if ipv6enabled is 0 (zero), the resolving sticks STRICTLY to IPv4 addresses | ||
357 | * if ipv6enabled is not 0 (zero), the resolving looks for IPv6 addresses first, | ||
358 | * then IPv4 addresses. | ||
359 | * | ||
360 | * returns 1 if the address could be converted into an IP address | ||
361 | * returns 0 otherwise | ||
362 | */ | ||
363 | int tox_bootstrap_from_address(Tox *tox, const char *address, uint8_t ipv6enabled, | ||
364 | uint16_t port, uint8_t *public_key); | ||
296 | 365 | ||
297 | /* return 0 if we are not connected to the DHT. | 366 | /* return 0 if we are not connected to the DHT. |
298 | * return 1 if we are. | 367 | * return 1 if we are. |
299 | */ | 368 | */ |
300 | int tox_isconnected(Tox *tox); | 369 | int tox_isconnected(Tox *tox); |
301 | 370 | ||
302 | /* Run this at startup. | 371 | /* |
372 | * Run this function at startup. | ||
373 | * | ||
374 | * Initializes a tox structure | ||
375 | * The type of communication socket depends on ipv6enabled: | ||
376 | * If set to 0 (zero), creates an IPv4 socket which subsequently only allows | ||
377 | * IPv4 communication | ||
378 | * If set to anything else, creates an IPv6 socket which allows both IPv4 AND | ||
379 | * IPv6 communication | ||
303 | * | 380 | * |
304 | * return allocated instance of tox on success. | 381 | * return allocated instance of tox on success. |
305 | * return 0 if there are problems. | 382 | * return 0 if there are problems. |
306 | */ | 383 | */ |
307 | Tox *tox_new(void); | 384 | Tox *tox_new(uint8_t ipv6enabled); |
308 | 385 | ||
309 | /* Run this before closing shop. | 386 | /* Run this before closing shop. |
310 | * Free all datastructures. */ | 387 | * Free all datastructures. */ |
diff --git a/toxcore/util.c b/toxcore/util.c index 1728ea21..e751e9e4 100644 --- a/toxcore/util.c +++ b/toxcore/util.c | |||
@@ -10,11 +10,12 @@ | |||
10 | #endif | 10 | #endif |
11 | 11 | ||
12 | #include <time.h> | 12 | #include <time.h> |
13 | #include <stdint.h> | ||
14 | #include <stdbool.h> | ||
15 | 13 | ||
14 | /* for CLIENT_ID_SIZE */ | ||
16 | #include "DHT.h" | 15 | #include "DHT.h" |
17 | 16 | ||
17 | #include "util.h" | ||
18 | |||
18 | uint64_t now() | 19 | uint64_t now() |
19 | { | 20 | { |
20 | return time(NULL); | 21 | return time(NULL); |
@@ -32,11 +33,6 @@ uint64_t random_64b() | |||
32 | return r; | 33 | return r; |
33 | } | 34 | } |
34 | 35 | ||
35 | bool ipp_eq(IP_Port a, IP_Port b) | ||
36 | { | ||
37 | return (a.ip.uint32 == b.ip.uint32) && (a.port == b.port); | ||
38 | } | ||
39 | |||
40 | bool id_eq(uint8_t *dest, uint8_t *src) | 36 | bool id_eq(uint8_t *dest, uint8_t *src) |
41 | { | 37 | { |
42 | return memcmp(dest, src, CLIENT_ID_SIZE) == 0; | 38 | return memcmp(dest, src, CLIENT_ID_SIZE) == 0; |
@@ -46,3 +42,30 @@ void id_cpy(uint8_t *dest, uint8_t *src) | |||
46 | { | 42 | { |
47 | memcpy(dest, src, CLIENT_ID_SIZE); | 43 | memcpy(dest, src, CLIENT_ID_SIZE); |
48 | } | 44 | } |
45 | |||
46 | #ifdef LOGGING | ||
47 | char logbuffer[512]; | ||
48 | static FILE *logfile = NULL; | ||
49 | void loginit(uint16_t port) | ||
50 | { | ||
51 | if (logfile) | ||
52 | fclose(logfile); | ||
53 | |||
54 | sprintf(logbuffer, "%u-%u.log", ntohs(port), now()); | ||
55 | logfile = fopen(logbuffer, "w"); | ||
56 | }; | ||
57 | void loglog(char *text) | ||
58 | { | ||
59 | if (logfile) { | ||
60 | fprintf(logfile, text); | ||
61 | fflush(logfile); | ||
62 | } | ||
63 | }; | ||
64 | void logexit() | ||
65 | { | ||
66 | if (logfile) { | ||
67 | fclose(logfile); | ||
68 | logfile = NULL; | ||
69 | } | ||
70 | }; | ||
71 | #endif | ||
diff --git a/toxcore/util.h b/toxcore/util.h index 90a3c8e4..71be84ca 100644 --- a/toxcore/util.h +++ b/toxcore/util.h | |||
@@ -5,8 +5,24 @@ | |||
5 | * Copyright 2013 plutooo | 5 | * Copyright 2013 plutooo |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #ifndef __UTIL_H__ | ||
9 | #define __UTIL_H__ | ||
10 | |||
11 | #include <stdbool.h> | ||
12 | #include <stdint.h> | ||
13 | |||
8 | uint64_t now(); | 14 | uint64_t now(); |
9 | uint64_t random_64b(); | 15 | uint64_t random_64b(); |
10 | bool ipp_eq(IP_Port a, IP_Port b); | ||
11 | bool id_eq(uint8_t *dest, uint8_t *src); | 16 | bool id_eq(uint8_t *dest, uint8_t *src); |
12 | void id_cpy(uint8_t *dest, uint8_t *src); | 17 | void id_cpy(uint8_t *dest, uint8_t *src); |
18 | |||
19 | #undef LOGGING | ||
20 | /* #define LOGGING */ | ||
21 | #ifdef LOGGING | ||
22 | extern char logbuffer[512]; | ||
23 | void loginit(uint16_t port); | ||
24 | void loglog(char *text); | ||
25 | void logexit(); | ||
26 | #endif | ||
27 | |||
28 | #endif /* __UTIL_H__ */ | ||