diff options
author | mannol <eniz_vukovic@hotmail.com> | 2014-05-20 00:27:02 +0200 |
---|---|---|
committer | mannol <eniz_vukovic@hotmail.com> | 2014-05-20 00:27:02 +0200 |
commit | c9f1c6882dbf986685e3a900dae516f06832393c (patch) | |
tree | 6529505163b9a0d4fd0cb6c4aac0a19c5a108fb1 | |
parent | a1f2a18ae4146ebea11fbd3f83df803b715813da (diff) | |
parent | fc19327dccedf7950377856c3b09a13f2b0f5911 (diff) |
Merge upstream fo real now?
-rw-r--r-- | README.md | 1 | ||||
-rw-r--r-- | auto_tests/TCP_test.c | 143 | ||||
-rw-r--r-- | auto_tests/crypto_test.c | 37 | ||||
-rw-r--r-- | auto_tests/messenger_test.c | 27 | ||||
-rw-r--r-- | auto_tests/network_test.c | 5 | ||||
-rw-r--r-- | auto_tests/onion_test.c | 38 | ||||
-rw-r--r-- | auto_tests/tox_test.c | 28 | ||||
-rw-r--r-- | docs/Group-Chats.md | 8 | ||||
-rw-r--r-- | docs/Prevent_Tracking.txt | 5 | ||||
-rw-r--r-- | docs/TCP_Network.txt | 13 | ||||
-rw-r--r-- | docs/Tox_middle_level_network_protocol.txt | 118 | ||||
-rw-r--r-- | docs/av_api.md | 2 | ||||
-rw-r--r-- | docs/updates/Crypto.md | 2 | ||||
-rw-r--r-- | docs/updates/DHT.md | 20 | ||||
-rw-r--r-- | m4/pkg.m4 | 2 | ||||
-rw-r--r-- | other/bootstrap_daemon/conf | 22 | ||||
-rw-r--r-- | other/bootstrap_daemon/tox_bootstrap_daemon.c | 301 | ||||
-rw-r--r-- | other/bootstrap_daemon/tox_bootstrap_daemon.sh | 6 | ||||
-rw-r--r-- | other/fun/cracker.c | 2 | ||||
-rw-r--r-- | toxav/Makefile.inc | 1 | ||||
-rwxr-xr-x | toxav/msi.c | 57 | ||||
-rwxr-xr-x | toxav/msi.h | 11 | ||||
-rwxr-xr-x | toxav/phone.c | 1460 | ||||
-rw-r--r-- | toxcore/Messenger.c | 3 |
24 files changed, 2141 insertions, 171 deletions
@@ -9,6 +9,7 @@ With the rise of governmental monitoring programs, Tox, a FOSS initiative, aims | |||
9 | ## The Complex Stuff: | 9 | ## The Complex Stuff: |
10 | ### UDP vs. TCP | 10 | ### UDP vs. TCP |
11 | Tox must use UDP simply because [hole punching](http://en.wikipedia.org/wiki/UDP_hole_punching) with TCP is not as reliable. | 11 | Tox must use UDP simply because [hole punching](http://en.wikipedia.org/wiki/UDP_hole_punching) with TCP is not as reliable. |
12 | However, Tox does use [TCP relays](https://github.com/irungentoo/ProjectTox-Core/blob/master/docs/TCP_Network.txt) as a fallback if it encounters a firewall that prevents UDP hole punching. | ||
12 | 13 | ||
13 | ### Connecting & Communicating | 14 | ### Connecting & Communicating |
14 | Every peer is represented as a [byte string][String] (the public key [Tox ID] of the peer). By using torrent-style DHT, peers can find the IP of other peers by using their Tox ID. Once the IP is obtained, peers can initiate a [secure](https://github.com/irungentoo/ProjectTox-Core/wiki/Crypto) connection with each other. Once the connection is made, peers can exchange messages, send files, start video chats, etc. using encrypted communications. | 15 | Every peer is represented as a [byte string][String] (the public key [Tox ID] of the peer). By using torrent-style DHT, peers can find the IP of other peers by using their Tox ID. Once the IP is obtained, peers can initiate a [secure](https://github.com/irungentoo/ProjectTox-Core/wiki/Crypto) connection with each other. Once the connection is made, peers can exchange messages, send files, start video chats, etc. using encrypted communications. |
diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c index de37bb97..ca5afd9a 100644 --- a/auto_tests/TCP_test.c +++ b/auto_tests/TCP_test.c | |||
@@ -89,7 +89,7 @@ START_TEST(test_basic) | |||
89 | uint8_t r_req[2 + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES]; | 89 | uint8_t r_req[2 + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES]; |
90 | uint16_t size = 1 + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES; | 90 | uint16_t size = 1 + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES; |
91 | size = htons(size); | 91 | size = htons(size); |
92 | ret = encrypt_data_fast(f_shared_key, f_nonce, r_req_p, 1 + crypto_box_PUBLICKEYBYTES, r_req + 2); | 92 | ret = encrypt_data_symmetric(f_shared_key, f_nonce, r_req_p, 1 + crypto_box_PUBLICKEYBYTES, r_req + 2); |
93 | increment_nonce(f_nonce); | 93 | increment_nonce(f_nonce); |
94 | memcpy(r_req, &size, 2); | 94 | memcpy(r_req, &size, 2); |
95 | uint32_t i; | 95 | uint32_t i; |
@@ -110,7 +110,7 @@ START_TEST(test_basic) | |||
110 | memcpy(&size, packet_resp, 2); | 110 | memcpy(&size, packet_resp, 2); |
111 | ck_assert_msg(ntohs(size) == 2 + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES, "Wrong packet size."); | 111 | ck_assert_msg(ntohs(size) == 2 + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES, "Wrong packet size."); |
112 | uint8_t packet_resp_plain[4096]; | 112 | uint8_t packet_resp_plain[4096]; |
113 | ret = decrypt_data_fast(f_shared_key, f_nonce_r, packet_resp + 2, recv_data_len - 2, packet_resp_plain); | 113 | ret = decrypt_data_symmetric(f_shared_key, f_nonce_r, packet_resp + 2, recv_data_len - 2, packet_resp_plain); |
114 | ck_assert_msg(ret != -1, "decryption failed"); | 114 | ck_assert_msg(ret != -1, "decryption failed"); |
115 | increment_nonce(f_nonce_r); | 115 | increment_nonce(f_nonce_r); |
116 | ck_assert_msg(packet_resp_plain[0] == 1, "wrong packet id %u", packet_resp_plain[0]); | 116 | ck_assert_msg(packet_resp_plain[0] == 1, "wrong packet id %u", packet_resp_plain[0]); |
@@ -179,7 +179,7 @@ int write_packet_TCP_secure_connection(struct sec_TCP_con *con, uint8_t *data, u | |||
179 | 179 | ||
180 | uint16_t c_length = htons(length + crypto_box_MACBYTES); | 180 | uint16_t c_length = htons(length + crypto_box_MACBYTES); |
181 | memcpy(packet, &c_length, sizeof(uint16_t)); | 181 | memcpy(packet, &c_length, sizeof(uint16_t)); |
182 | int len = encrypt_data_fast(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); | 182 | int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); |
183 | 183 | ||
184 | if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) | 184 | if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) |
185 | return -1; | 185 | return -1; |
@@ -194,7 +194,7 @@ int read_packet_sec_TCP(struct sec_TCP_con *con, uint8_t *data, uint16_t length) | |||
194 | { | 194 | { |
195 | int len; | 195 | int len; |
196 | ck_assert_msg((len = recv(con->sock, data, length, 0)) == length, "wrong len %i\n", len); | 196 | ck_assert_msg((len = recv(con->sock, data, length, 0)) == length, "wrong len %i\n", len); |
197 | ck_assert_msg((len = decrypt_data_fast(con->shared_key, con->recv_nonce, data + 2, length - 2, data)) != -1, | 197 | ck_assert_msg((len = decrypt_data_symmetric(con->shared_key, con->recv_nonce, data + 2, length - 2, data)) != -1, |
198 | "Decrypt failed"); | 198 | "Decrypt failed"); |
199 | increment_nonce(con->recv_nonce); | 199 | increment_nonce(con->recv_nonce); |
200 | return len; | 200 | return len; |
@@ -291,6 +291,76 @@ START_TEST(test_some) | |||
291 | } | 291 | } |
292 | END_TEST | 292 | END_TEST |
293 | 293 | ||
294 | static int response_callback_good; | ||
295 | static uint8_t response_callback_connection_id; | ||
296 | static uint8_t response_callback_public_key[crypto_box_PUBLICKEYBYTES]; | ||
297 | static int response_callback(void *object, uint8_t connection_id, uint8_t *public_key) | ||
298 | { | ||
299 | if (set_tcp_connection_number(object - 2, connection_id, 7) != 0) | ||
300 | return 1; | ||
301 | |||
302 | response_callback_connection_id = connection_id; | ||
303 | memcpy(response_callback_public_key, public_key, crypto_box_PUBLICKEYBYTES); | ||
304 | response_callback_good++; | ||
305 | return 0; | ||
306 | } | ||
307 | static int status_callback_good; | ||
308 | static uint8_t status_callback_connection_id; | ||
309 | static uint8_t status_callback_status; | ||
310 | static int status_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t status) | ||
311 | { | ||
312 | if (object != (void *)2) | ||
313 | return 1; | ||
314 | |||
315 | if (number != 7) | ||
316 | return 1; | ||
317 | |||
318 | status_callback_connection_id = connection_id; | ||
319 | status_callback_status = status; | ||
320 | status_callback_good++; | ||
321 | return 0; | ||
322 | } | ||
323 | static int data_callback_good; | ||
324 | static int data_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t *data, uint16_t length) | ||
325 | { | ||
326 | if (object != (void *)3) | ||
327 | return 1; | ||
328 | |||
329 | if (number != 7) | ||
330 | return 1; | ||
331 | |||
332 | if (length != 5) | ||
333 | return 1; | ||
334 | |||
335 | if (data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4 && data[4] == 5) { | ||
336 | data_callback_good++; | ||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | return 1; | ||
341 | } | ||
342 | |||
343 | static int oob_data_callback_good; | ||
344 | static uint8_t oob_pubkey[crypto_box_PUBLICKEYBYTES]; | ||
345 | static int oob_data_callback(void *object, uint8_t *public_key, uint8_t *data, uint16_t length) | ||
346 | { | ||
347 | if (object != (void *)4) | ||
348 | return 1; | ||
349 | |||
350 | if (length != 5) | ||
351 | return 1; | ||
352 | |||
353 | if (memcmp(public_key, oob_pubkey, crypto_box_PUBLICKEYBYTES) != 0) | ||
354 | return 1; | ||
355 | |||
356 | if (data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4 && data[4] == 5) { | ||
357 | oob_data_callback_good++; | ||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | return 1; | ||
362 | } | ||
363 | |||
294 | START_TEST(test_client) | 364 | START_TEST(test_client) |
295 | { | 365 | { |
296 | unix_time_update(); | 366 | unix_time_update(); |
@@ -320,6 +390,71 @@ START_TEST(test_client) | |||
320 | do_TCP_connection(conn); | 390 | do_TCP_connection(conn); |
321 | ck_assert_msg(conn->status == TCP_CLIENT_CONFIRMED, "Wrong status. Expected: %u, is: %u", TCP_CLIENT_CONFIRMED, | 391 | ck_assert_msg(conn->status == TCP_CLIENT_CONFIRMED, "Wrong status. Expected: %u, is: %u", TCP_CLIENT_CONFIRMED, |
322 | conn->status); | 392 | conn->status); |
393 | c_sleep(500); | ||
394 | do_TCP_connection(conn); | ||
395 | ck_assert_msg(conn->status == TCP_CLIENT_CONFIRMED, "Wrong status. Expected: %u, is: %u", TCP_CLIENT_CONFIRMED, | ||
396 | conn->status); | ||
397 | c_sleep(500); | ||
398 | do_TCP_connection(conn); | ||
399 | ck_assert_msg(conn->status == TCP_CLIENT_CONFIRMED, "Wrong status. Expected: %u, is: %u", TCP_CLIENT_CONFIRMED, | ||
400 | conn->status); | ||
401 | do_TCP_server(tcp_s); | ||
402 | c_sleep(50); | ||
403 | ck_assert_msg(conn->status == TCP_CLIENT_CONFIRMED, "Wrong status. Expected: %u, is: %u", TCP_CLIENT_CONFIRMED, | ||
404 | conn->status); | ||
405 | |||
406 | uint8_t f2_public_key[crypto_box_PUBLICKEYBYTES]; | ||
407 | uint8_t f2_secret_key[crypto_box_SECRETKEYBYTES]; | ||
408 | crypto_box_keypair(f2_public_key, f2_secret_key); | ||
409 | TCP_Client_Connection *conn2 = new_TCP_connection(ip_port_tcp_s, self_public_key, f2_public_key, f2_secret_key); | ||
410 | routing_response_handler(conn, response_callback, ((void *)conn) + 2); | ||
411 | routing_status_handler(conn, status_callback, (void *)2); | ||
412 | routing_data_handler(conn, data_callback, (void *)3); | ||
413 | oob_data_handler(conn, oob_data_callback, (void *)4); | ||
414 | oob_data_callback_good = response_callback_good = status_callback_good = data_callback_good = 0; | ||
415 | c_sleep(50); | ||
416 | do_TCP_connection(conn); | ||
417 | do_TCP_connection(conn2); | ||
418 | c_sleep(50); | ||
419 | do_TCP_server(tcp_s); | ||
420 | c_sleep(50); | ||
421 | do_TCP_connection(conn); | ||
422 | do_TCP_connection(conn2); | ||
423 | c_sleep(50); | ||
424 | uint8_t data[5] = {1, 2, 3, 4, 5}; | ||
425 | memcpy(oob_pubkey, f2_public_key, crypto_box_PUBLICKEYBYTES); | ||
426 | send_oob_packet(conn2, f_public_key, data, 5); | ||
427 | send_routing_request(conn, f2_public_key); | ||
428 | send_routing_request(conn2, f_public_key); | ||
429 | c_sleep(50); | ||
430 | do_TCP_server(tcp_s); | ||
431 | c_sleep(50); | ||
432 | do_TCP_connection(conn); | ||
433 | do_TCP_connection(conn2); | ||
434 | ck_assert_msg(oob_data_callback_good == 1, "oob callback not called"); | ||
435 | ck_assert_msg(response_callback_good == 1, "response callback not called"); | ||
436 | ck_assert_msg(memcmp(response_callback_public_key, f2_public_key, crypto_box_PUBLICKEYBYTES) == 0, "wrong public key"); | ||
437 | ck_assert_msg(status_callback_good == 1, "status callback not called"); | ||
438 | ck_assert_msg(status_callback_status == 2, "wrong status"); | ||
439 | ck_assert_msg(status_callback_connection_id == response_callback_connection_id, "connection ids not equal"); | ||
440 | c_sleep(50); | ||
441 | do_TCP_server(tcp_s); | ||
442 | ck_assert_msg(send_data(conn2, 0, data, 5) == 1, "send data failed"); | ||
443 | c_sleep(50); | ||
444 | do_TCP_server(tcp_s); | ||
445 | c_sleep(50); | ||
446 | do_TCP_connection(conn); | ||
447 | do_TCP_connection(conn2); | ||
448 | ck_assert_msg(data_callback_good == 1, "data callback not called"); | ||
449 | status_callback_good = 0; | ||
450 | send_disconnect_request(conn2, 0); | ||
451 | c_sleep(50); | ||
452 | do_TCP_server(tcp_s); | ||
453 | c_sleep(50); | ||
454 | do_TCP_connection(conn); | ||
455 | do_TCP_connection(conn2); | ||
456 | ck_assert_msg(status_callback_good == 1, "status callback not called"); | ||
457 | ck_assert_msg(status_callback_status == 1, "wrong status"); | ||
323 | } | 458 | } |
324 | END_TEST | 459 | END_TEST |
325 | 460 | ||
diff --git a/auto_tests/crypto_test.c b/auto_tests/crypto_test.c index 95cdefcd..252f7275 100644 --- a/auto_tests/crypto_test.c +++ b/auto_tests/crypto_test.c | |||
@@ -9,12 +9,6 @@ | |||
9 | #include <check.h> | 9 | #include <check.h> |
10 | #include <stdlib.h> | 10 | #include <stdlib.h> |
11 | #include <time.h> | 11 | #include <time.h> |
12 | #ifndef VANILLA_NACL | ||
13 | #include <sodium.h> | ||
14 | #else | ||
15 | #include <crypto_box.h> | ||
16 | #define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) | ||
17 | #endif | ||
18 | 12 | ||
19 | void rand_bytes(uint8_t *b, size_t blen) | 13 | void rand_bytes(uint8_t *b, size_t blen) |
20 | { | 14 | { |
@@ -126,12 +120,12 @@ START_TEST(test_fast_known) | |||
126 | ck_assert_msg(sizeof(test_c) == sizeof(c), "sanity check failed"); | 120 | ck_assert_msg(sizeof(test_c) == sizeof(c), "sanity check failed"); |
127 | ck_assert_msg(sizeof(test_m) == sizeof(m), "sanity check failed"); | 121 | ck_assert_msg(sizeof(test_m) == sizeof(m), "sanity check failed"); |
128 | 122 | ||
129 | clen = encrypt_data_fast(k, nonce, test_m, sizeof(test_m) / sizeof(unsigned char), c); | 123 | clen = encrypt_data_symmetric(k, nonce, test_m, sizeof(test_m) / sizeof(unsigned char), c); |
130 | 124 | ||
131 | ck_assert_msg(memcmp(test_c, c, sizeof(c)) == 0, "cyphertext doesn't match test vector"); | 125 | ck_assert_msg(memcmp(test_c, c, sizeof(c)) == 0, "cyphertext doesn't match test vector"); |
132 | ck_assert_msg(clen == sizeof(c) / sizeof(unsigned char), "wrong ciphertext length"); | 126 | ck_assert_msg(clen == sizeof(c) / sizeof(unsigned char), "wrong ciphertext length"); |
133 | 127 | ||
134 | mlen = decrypt_data_fast(k, nonce, test_c, sizeof(test_c) / sizeof(unsigned char), m); | 128 | mlen = decrypt_data_symmetric(k, nonce, test_c, sizeof(test_c) / sizeof(unsigned char), m); |
135 | 129 | ||
136 | ck_assert_msg(memcmp(test_m, m, sizeof(m)) == 0, "decrypted text doesn't match test vector"); | 130 | ck_assert_msg(memcmp(test_m, m, sizeof(m)) == 0, "decrypted text doesn't match test vector"); |
137 | ck_assert_msg(mlen == sizeof(m) / sizeof(unsigned char), "wrong plaintext length"); | 131 | ck_assert_msg(mlen == sizeof(m) / sizeof(unsigned char), "wrong plaintext length"); |
@@ -186,8 +180,8 @@ START_TEST(test_endtoend) | |||
186 | //Encrypt all four ways | 180 | //Encrypt all four ways |
187 | c1len = encrypt_data(pk2, sk1, n, m, mlen, c1); | 181 | c1len = encrypt_data(pk2, sk1, n, m, mlen, c1); |
188 | c2len = encrypt_data(pk1, sk2, n, m, mlen, c2); | 182 | c2len = encrypt_data(pk1, sk2, n, m, mlen, c2); |
189 | c3len = encrypt_data_fast(k1, n, m, mlen, c3); | 183 | c3len = encrypt_data_symmetric(k1, n, m, mlen, c3); |
190 | c4len = encrypt_data_fast(k2, n, m, mlen, c4); | 184 | c4len = encrypt_data_symmetric(k2, n, m, mlen, c4); |
191 | 185 | ||
192 | ck_assert_msg(c1len == c2len && c1len == c3len && c1len == c4len, "cyphertext lengths differ"); | 186 | ck_assert_msg(c1len == c2len && c1len == c3len && c1len == c4len, "cyphertext lengths differ"); |
193 | ck_assert_msg(c1len == mlen + (int)crypto_box_MACBYTES, "wrong cyphertext length"); | 187 | ck_assert_msg(c1len == mlen + (int)crypto_box_MACBYTES, "wrong cyphertext length"); |
@@ -197,8 +191,8 @@ START_TEST(test_endtoend) | |||
197 | //Decrypt all four ways | 191 | //Decrypt all four ways |
198 | m1len = decrypt_data(pk2, sk1, n, c1, c1len, m1); | 192 | m1len = decrypt_data(pk2, sk1, n, c1, c1len, m1); |
199 | m2len = decrypt_data(pk1, sk2, n, c1, c1len, m2); | 193 | m2len = decrypt_data(pk1, sk2, n, c1, c1len, m2); |
200 | m3len = decrypt_data_fast(k1, n, c1, c1len, m3); | 194 | m3len = decrypt_data_symmetric(k1, n, c1, c1len, m3); |
201 | m4len = decrypt_data_fast(k2, n, c1, c1len, m4); | 195 | m4len = decrypt_data_symmetric(k2, n, c1, c1len, m4); |
202 | 196 | ||
203 | ck_assert_msg(m1len == m2len && m1len == m3len && m1len == m4len, "decrypted text lengths differ"); | 197 | ck_assert_msg(m1len == m2len && m1len == m3len && m1len == m4len, "decrypted text lengths differ"); |
204 | ck_assert_msg(m1len == mlen, "wrong decrypted text length"); | 198 | ck_assert_msg(m1len == mlen, "wrong decrypted text length"); |
@@ -215,11 +209,11 @@ START_TEST(test_large_data) | |||
215 | 209 | ||
216 | unsigned char n[crypto_box_NONCEBYTES]; | 210 | unsigned char n[crypto_box_NONCEBYTES]; |
217 | 211 | ||
218 | unsigned char m1[MAX_DATA_SIZE - crypto_box_MACBYTES]; | 212 | unsigned char m1[MAX_CRYPTO_PACKET_SIZE - crypto_box_MACBYTES]; |
219 | unsigned char c1[sizeof(m1) + crypto_box_MACBYTES]; | 213 | unsigned char c1[sizeof(m1) + crypto_box_MACBYTES]; |
220 | unsigned char m1prime[sizeof(m1)]; | 214 | unsigned char m1prime[sizeof(m1)]; |
221 | 215 | ||
222 | unsigned char m2[MAX_DATA_SIZE]; | 216 | unsigned char m2[MAX_CRYPTO_PACKET_SIZE]; |
223 | unsigned char c2[sizeof(m2) + crypto_box_MACBYTES]; | 217 | unsigned char c2[sizeof(m2) + crypto_box_MACBYTES]; |
224 | 218 | ||
225 | int c1len, c2len; | 219 | int c1len, c2len; |
@@ -233,13 +227,13 @@ START_TEST(test_large_data) | |||
233 | //Generate key | 227 | //Generate key |
234 | rand_bytes(k, crypto_box_BEFORENMBYTES); | 228 | rand_bytes(k, crypto_box_BEFORENMBYTES); |
235 | 229 | ||
236 | c1len = encrypt_data_fast(k, n, m1, sizeof(m1), c1); | 230 | c1len = encrypt_data_symmetric(k, n, m1, sizeof(m1), c1); |
237 | c2len = encrypt_data_fast(k, n, m2, sizeof(m2), c2); | 231 | c2len = encrypt_data_symmetric(k, n, m2, sizeof(m2), c2); |
238 | 232 | ||
239 | ck_assert_msg(c1len == sizeof(m1) + crypto_box_MACBYTES, "could not encrypt max size"); | 233 | ck_assert_msg(c1len == sizeof(m1) + crypto_box_MACBYTES, "could not encrypt"); |
240 | ck_assert_msg(c2len == -1, "incorrectly succeeded encrypting massive size"); | 234 | ck_assert_msg(c2len == sizeof(m2) + crypto_box_MACBYTES, "could not encrypt"); |
241 | 235 | ||
242 | m1plen = decrypt_data_fast(k, n, c1, c1len, m1prime); | 236 | m1plen = decrypt_data_symmetric(k, n, c1, c1len, m1prime); |
243 | 237 | ||
244 | ck_assert_msg(m1plen == sizeof(m1), "decrypted text lengths differ"); | 238 | ck_assert_msg(m1plen == sizeof(m1), "decrypted text lengths differ"); |
245 | ck_assert_msg(memcmp(m1prime, m1, sizeof(m1)) == 0, "decrypted texts differ"); | 239 | ck_assert_msg(memcmp(m1prime, m1, sizeof(m1)) == 0, "decrypted texts differ"); |
@@ -248,9 +242,9 @@ END_TEST | |||
248 | 242 | ||
249 | START_TEST(test_large_data_symmetric) | 243 | START_TEST(test_large_data_symmetric) |
250 | { | 244 | { |
251 | unsigned char k[crypto_secretbox_KEYBYTES]; | 245 | unsigned char k[crypto_box_KEYBYTES]; |
252 | 246 | ||
253 | unsigned char n[crypto_secretbox_NONCEBYTES]; | 247 | unsigned char n[crypto_box_NONCEBYTES]; |
254 | 248 | ||
255 | unsigned char m1[16 * 16 * 16]; | 249 | unsigned char m1[16 * 16 * 16]; |
256 | unsigned char c1[sizeof(m1) + crypto_box_MACBYTES]; | 250 | unsigned char c1[sizeof(m1) + crypto_box_MACBYTES]; |
@@ -276,6 +270,7 @@ START_TEST(test_large_data_symmetric) | |||
276 | } | 270 | } |
277 | END_TEST | 271 | END_TEST |
278 | 272 | ||
273 | |||
279 | #define DEFTESTCASE(NAME) \ | 274 | #define DEFTESTCASE(NAME) \ |
280 | TCase *NAME = tcase_create(#NAME); \ | 275 | TCase *NAME = tcase_create(#NAME); \ |
281 | tcase_add_test(NAME, test_##NAME); \ | 276 | tcase_add_test(NAME, test_##NAME); \ |
diff --git a/auto_tests/messenger_test.c b/auto_tests/messenger_test.c index 5e5f7b06..7ab7d674 100644 --- a/auto_tests/messenger_test.c +++ b/auto_tests/messenger_test.c | |||
@@ -16,7 +16,6 @@ | |||
16 | 16 | ||
17 | #include "../testing/misc_tools.c" // hex_string_to_bin | 17 | #include "../testing/misc_tools.c" // hex_string_to_bin |
18 | #include "../toxcore/Messenger.h" | 18 | #include "../toxcore/Messenger.h" |
19 | #include "../toxcore/Lossless_UDP.h" | ||
20 | #include <sys/types.h> | 19 | #include <sys/types.h> |
21 | #include <stdint.h> | 20 | #include <stdint.h> |
22 | #include <string.h> | 21 | #include <string.h> |
@@ -46,7 +45,7 @@ START_TEST(test_m_sendmesage) | |||
46 | { | 45 | { |
47 | char *message = "h-hi :3"; | 46 | char *message = "h-hi :3"; |
48 | int good_len = strlen(message); | 47 | int good_len = strlen(message); |
49 | int bad_len = MAX_DATA_SIZE; | 48 | int bad_len = MAX_CRYPTO_PACKET_SIZE; |
50 | 49 | ||
51 | 50 | ||
52 | ck_assert(m_sendmessage(m, -1, (uint8_t *)message, good_len) == 0); | 51 | ck_assert(m_sendmessage(m, -1, (uint8_t *)message, good_len) == 0); |
@@ -127,7 +126,7 @@ START_TEST(test_m_addfriend) | |||
127 | 126 | ||
128 | int good_len = strlen(good_data); | 127 | int good_len = strlen(good_data); |
129 | int bad_len = strlen(bad_data); | 128 | int bad_len = strlen(bad_data); |
130 | int really_bad_len = (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES | 129 | int really_bad_len = (MAX_CRYPTO_PACKET_SIZE - crypto_box_PUBLICKEYBYTES |
131 | - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES | 130 | - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES |
132 | + crypto_box_ZEROBYTES + 100); */ | 131 | + crypto_box_ZEROBYTES + 100); */ |
133 | /* TODO: Update this properly to latest master | 132 | /* TODO: Update this properly to latest master |
@@ -299,27 +298,6 @@ START_TEST(test_messenger_state_saveloadsave) | |||
299 | } | 298 | } |
300 | END_TEST | 299 | END_TEST |
301 | 300 | ||
302 | START_TEST(test_messenger_state_saveload_encrypted) | ||
303 | { | ||
304 | uint8_t addr[FRIEND_ADDRESS_SIZE]; | ||
305 | getaddress(m, addr); | ||
306 | Messenger *m_temp = new_messenger(TOX_ENABLE_IPV6_DEFAULT); | ||
307 | |||
308 | size_t size = messenger_size_encrypted(m); | ||
309 | uint8_t buffer[size]; | ||
310 | messenger_save_encrypted(m, buffer, "Gentoo", sizeof("Gentoo")); | ||
311 | |||
312 | ck_assert_msg(messenger_load_encrypted(m_temp, buffer, size, "Ubuntu", sizeof("Ubuntu")) == -1, | ||
313 | "Bad password didn't make the function fail."); | ||
314 | ck_assert_msg(messenger_load_encrypted(m_temp, buffer, size, "Gentoo", sizeof("Gentoo")) == 0, | ||
315 | "Good password didn't make the function succeed."); | ||
316 | uint8_t addr1[FRIEND_ADDRESS_SIZE]; | ||
317 | getaddress(m_temp, addr1); | ||
318 | ck_assert_msg(memcmp(addr1, addr, FRIEND_ADDRESS_SIZE) == 0, "Didn't load messenger successfully"); | ||
319 | kill_messenger(m_temp); | ||
320 | } | ||
321 | END_TEST | ||
322 | |||
323 | #define DEFTESTCASE(NAME) \ | 301 | #define DEFTESTCASE(NAME) \ |
324 | TCase *tc_##NAME = tcase_create(#NAME); \ | 302 | TCase *tc_##NAME = tcase_create(#NAME); \ |
325 | tcase_add_test(tc_##NAME, test_##NAME); \ | 303 | tcase_add_test(tc_##NAME, test_##NAME); \ |
@@ -331,7 +309,6 @@ Suite *messenger_suite(void) | |||
331 | 309 | ||
332 | DEFTESTCASE(dht_state_saveloadsave); | 310 | DEFTESTCASE(dht_state_saveloadsave); |
333 | DEFTESTCASE(messenger_state_saveloadsave); | 311 | DEFTESTCASE(messenger_state_saveloadsave); |
334 | DEFTESTCASE(messenger_state_saveload_encrypted); | ||
335 | 312 | ||
336 | DEFTESTCASE(getself_name); | 313 | DEFTESTCASE(getself_name); |
337 | DEFTESTCASE(m_get_userstatus_size); | 314 | DEFTESTCASE(m_get_userstatus_size); |
diff --git a/auto_tests/network_test.c b/auto_tests/network_test.c index 3b4b50cd..afd90e7a 100644 --- a/auto_tests/network_test.c +++ b/auto_tests/network_test.c | |||
@@ -136,9 +136,8 @@ START_TEST(test_struct_sizes) | |||
136 | { | 136 | { |
137 | ck_assert_msg(sizeof(IP4) == 4, "sizeof(IP4): expected result 4, got %u.", sizeof(IP4)); | 137 | ck_assert_msg(sizeof(IP4) == 4, "sizeof(IP4): expected result 4, got %u.", sizeof(IP4)); |
138 | ck_assert_msg(sizeof(IP6) == 16, "sizeof(IP6): expected result 16, got %u.", sizeof(IP6)); | 138 | ck_assert_msg(sizeof(IP6) == 16, "sizeof(IP6): expected result 16, got %u.", sizeof(IP6)); |
139 | ck_assert_msg(sizeof(IP) == 20, "sizeof(IP): expected result 20, got %u.", sizeof(IP)); | 139 | ck_assert_msg(sizeof(IP) == 17, "sizeof(IP): expected result 17, got %u.", sizeof(IP)); |
140 | ck_assert_msg(sizeof(IP_Port) == 24, "sizeof(IP_Port): expected result 24, got %u.", sizeof(IP_Port)); | 140 | ck_assert_msg(sizeof(IP_Port) == 19, "sizeof(IP_Port): expected result 19, got %u.", sizeof(IP_Port)); |
141 | ck_assert_msg(sizeof(IP4_Port) == 8, "sizeof(IP4_Port): expected result 8, got %u.", sizeof(IP4_Port)); | ||
142 | } | 141 | } |
143 | END_TEST | 142 | END_TEST |
144 | 143 | ||
diff --git a/auto_tests/onion_test.c b/auto_tests/onion_test.c index 2f244693..4489a894 100644 --- a/auto_tests/onion_test.c +++ b/auto_tests/onion_test.c | |||
@@ -80,7 +80,7 @@ static int handle_test_3(void *object, IP_Port source, uint8_t *packet, uint32_t | |||
80 | 80 | ||
81 | uint8_t plain[1 + crypto_hash_sha256_BYTES]; | 81 | uint8_t plain[1 + crypto_hash_sha256_BYTES]; |
82 | //print_client_id(packet, length); | 82 | //print_client_id(packet, length); |
83 | int len = decrypt_data(test_3_pub_key, onion->dht->c->self_secret_key, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, | 83 | int len = decrypt_data(test_3_pub_key, onion->dht->self_secret_key, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, |
84 | packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES, | 84 | packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES, |
85 | 1 + crypto_hash_sha256_BYTES + crypto_box_MACBYTES, plain); | 85 | 1 + crypto_hash_sha256_BYTES + crypto_box_MACBYTES, plain); |
86 | 86 | ||
@@ -111,7 +111,7 @@ static int handle_test_4(void *object, IP_Port source, uint8_t *packet, uint32_t | |||
111 | if (memcmp(nonce, packet + 1, crypto_box_NONCEBYTES) != 0) | 111 | if (memcmp(nonce, packet + 1, crypto_box_NONCEBYTES) != 0) |
112 | return 1; | 112 | return 1; |
113 | 113 | ||
114 | int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion->dht->c->self_secret_key, packet + 1, | 114 | int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion->dht->self_secret_key, packet + 1, |
115 | packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, sizeof("Install gentoo") + crypto_box_MACBYTES, plain); | 115 | packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, sizeof("Install gentoo") + crypto_box_MACBYTES, plain); |
116 | 116 | ||
117 | if (len == -1) | 117 | if (len == -1) |
@@ -129,8 +129,8 @@ START_TEST(test_basic) | |||
129 | IP ip; | 129 | IP ip; |
130 | ip_init(&ip, 1); | 130 | ip_init(&ip, 1); |
131 | ip.ip6.uint8[15] = 1; | 131 | ip.ip6.uint8[15] = 1; |
132 | Onion *onion1 = new_onion(new_DHT(new_net_crypto(new_networking(ip, 34567)))); | 132 | Onion *onion1 = new_onion(new_DHT(new_networking(ip, 34567))); |
133 | Onion *onion2 = new_onion(new_DHT(new_net_crypto(new_networking(ip, 34568)))); | 133 | Onion *onion2 = new_onion(new_DHT(new_networking(ip, 34568))); |
134 | ck_assert_msg((onion1 != NULL) && (onion2 != NULL), "Onion failed initializing."); | 134 | ck_assert_msg((onion1 != NULL) && (onion2 != NULL), "Onion failed initializing."); |
135 | networking_registerhandler(onion2->net, 'I', &handle_test_1, onion2); | 135 | networking_registerhandler(onion2->net, 'I', &handle_test_1, onion2); |
136 | 136 | ||
@@ -176,26 +176,30 @@ START_TEST(test_basic) | |||
176 | ck_assert_msg((onion1_a != NULL) && (onion2_a != NULL), "Onion_Announce failed initializing."); | 176 | ck_assert_msg((onion1_a != NULL) && (onion2_a != NULL), "Onion_Announce failed initializing."); |
177 | uint8_t zeroes[64] = {0}; | 177 | uint8_t zeroes[64] = {0}; |
178 | randombytes(sb_data, sizeof(sb_data)); | 178 | randombytes(sb_data, sizeof(sb_data)); |
179 | uint64_t s; | ||
180 | memcpy(&s, sb_data, sizeof(uint64_t)); | ||
179 | memcpy(test_3_pub_key, nodes[3].client_id, crypto_box_PUBLICKEYBYTES); | 181 | memcpy(test_3_pub_key, nodes[3].client_id, crypto_box_PUBLICKEYBYTES); |
180 | ret = send_announce_request(onion1->net, &path, nodes[3], onion1->dht->c->self_public_key, | 182 | ret = send_announce_request(onion1->net, &path, nodes[3], onion1->dht->self_public_key, |
181 | onion1->dht->c->self_secret_key, | 183 | onion1->dht->self_secret_key, |
182 | zeroes, onion1->dht->c->self_public_key, onion1->dht->c->self_public_key, sb_data); | 184 | zeroes, onion1->dht->self_public_key, onion1->dht->self_public_key, s); |
183 | ck_assert_msg(ret == 0, "Failed to create/send onion announce_request packet."); | 185 | ck_assert_msg(ret == 0, "Failed to create/send onion announce_request packet."); |
184 | handled_test_3 = 0; | 186 | handled_test_3 = 0; |
185 | 187 | ||
186 | while (handled_test_3 == 0) { | 188 | while (handled_test_3 == 0) { |
187 | do_onion(onion1); | 189 | do_onion(onion1); |
188 | do_onion(onion2); | 190 | do_onion(onion2); |
191 | c_sleep(50); | ||
189 | } | 192 | } |
190 | 193 | ||
191 | randombytes(sb_data, sizeof(sb_data)); | 194 | randombytes(sb_data, sizeof(sb_data)); |
195 | memcpy(&s, sb_data, sizeof(uint64_t)); | ||
192 | memcpy(onion2_a->entries[1].public_key, onion2->dht->self_public_key, crypto_box_PUBLICKEYBYTES); | 196 | memcpy(onion2_a->entries[1].public_key, onion2->dht->self_public_key, crypto_box_PUBLICKEYBYTES); |
193 | onion2_a->entries[1].time = unix_time(); | 197 | onion2_a->entries[1].time = unix_time(); |
194 | networking_registerhandler(onion1->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_test_4, onion1); | 198 | networking_registerhandler(onion1->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_test_4, onion1); |
195 | send_announce_request(onion1->net, &path, nodes[3], onion1->dht->c->self_public_key, onion1->dht->c->self_secret_key, | 199 | send_announce_request(onion1->net, &path, nodes[3], onion1->dht->self_public_key, onion1->dht->self_secret_key, |
196 | test_3_ping_id, onion1->dht->c->self_public_key, onion1->dht->c->self_public_key, sb_data); | 200 | test_3_ping_id, onion1->dht->self_public_key, onion1->dht->self_public_key, s); |
197 | 201 | ||
198 | while (memcmp(onion2_a->entries[ONION_ANNOUNCE_MAX_ENTRIES - 2].public_key, onion1->dht->c->self_public_key, | 202 | while (memcmp(onion2_a->entries[ONION_ANNOUNCE_MAX_ENTRIES - 2].public_key, onion1->dht->self_public_key, |
199 | crypto_box_PUBLICKEYBYTES) != 0) { | 203 | crypto_box_PUBLICKEYBYTES) != 0) { |
200 | do_onion(onion1); | 204 | do_onion(onion1); |
201 | do_onion(onion2); | 205 | do_onion(onion2); |
@@ -203,12 +207,12 @@ START_TEST(test_basic) | |||
203 | } | 207 | } |
204 | 208 | ||
205 | c_sleep(1000); | 209 | c_sleep(1000); |
206 | Onion *onion3 = new_onion(new_DHT(new_net_crypto(new_networking(ip, 34569)))); | 210 | Onion *onion3 = new_onion(new_DHT(new_networking(ip, 34569))); |
207 | ck_assert_msg((onion3 != NULL), "Onion failed initializing."); | 211 | ck_assert_msg((onion3 != NULL), "Onion failed initializing."); |
208 | 212 | ||
209 | new_nonce(nonce); | 213 | new_nonce(nonce); |
210 | ret = send_data_request(onion3->net, &path, nodes[3].ip_port, onion1->dht->c->self_public_key, | 214 | ret = send_data_request(onion3->net, &path, nodes[3].ip_port, onion1->dht->self_public_key, |
211 | onion1->dht->c->self_public_key, | 215 | onion1->dht->self_public_key, |
212 | nonce, (uint8_t *)"Install gentoo", sizeof("Install gentoo")); | 216 | nonce, (uint8_t *)"Install gentoo", sizeof("Install gentoo")); |
213 | ck_assert_msg(ret == 0, "Failed to create/send onion data_request packet."); | 217 | ck_assert_msg(ret == 0, "Failed to create/send onion data_request packet."); |
214 | handled_test_4 = 0; | 218 | handled_test_4 = 0; |
@@ -233,10 +237,10 @@ Onions *new_onions(uint16_t port) | |||
233 | ip_init(&ip, 1); | 237 | ip_init(&ip, 1); |
234 | ip.ip6.uint8[15] = 1; | 238 | ip.ip6.uint8[15] = 1; |
235 | Onions *on = malloc(sizeof(Onions)); | 239 | Onions *on = malloc(sizeof(Onions)); |
236 | DHT *dht = new_DHT(new_net_crypto(new_networking(ip, port))); | 240 | DHT *dht = new_DHT(new_networking(ip, port)); |
237 | on->onion = new_onion(dht); | 241 | on->onion = new_onion(dht); |
238 | on->onion_a = new_onion_announce(dht); | 242 | on->onion_a = new_onion_announce(dht); |
239 | on->onion_c = new_onion_client(dht); | 243 | on->onion_c = new_onion_client(new_net_crypto(dht)); |
240 | 244 | ||
241 | if (on->onion && on->onion_a && on->onion_c) | 245 | if (on->onion && on->onion_a && on->onion_c) |
242 | return on; | 246 | return on; |
@@ -297,8 +301,8 @@ START_TEST(test_announce) | |||
297 | c_sleep(50); | 301 | c_sleep(50); |
298 | } | 302 | } |
299 | 303 | ||
300 | onion_addfriend(onions[7]->onion_c, onions[37]->onion->dht->c->self_public_key); | 304 | onion_addfriend(onions[7]->onion_c, onions[37]->onion_c->c->self_public_key); |
301 | int frnum = onion_addfriend(onions[37]->onion_c, onions[7]->onion->dht->c->self_public_key); | 305 | int frnum = onion_addfriend(onions[37]->onion_c, onions[7]->onion_c->c->self_public_key); |
302 | 306 | ||
303 | int ok = -1; | 307 | int ok = -1; |
304 | 308 | ||
diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 1e01aee7..9b63b35b 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c | |||
@@ -96,21 +96,26 @@ void file_print_control(Tox *m, int friendnumber, uint8_t send_recieve, uint8_t | |||
96 | } | 96 | } |
97 | 97 | ||
98 | uint64_t size_recv; | 98 | uint64_t size_recv; |
99 | uint8_t num; | ||
99 | void write_file(Tox *m, int friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata) | 100 | void write_file(Tox *m, int friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata) |
100 | { | 101 | { |
101 | if (*((uint32_t *)userdata) != 974536) | 102 | if (*((uint32_t *)userdata) != 974536) |
102 | return; | 103 | return; |
103 | 104 | ||
104 | uint8_t *f_data = malloc(length); | 105 | uint8_t *f_data = malloc(length); |
105 | memset(f_data, 6, length); | 106 | memset(f_data, num, length); |
107 | ++num; | ||
106 | 108 | ||
107 | if (memcmp(f_data, data, length) == 0) | 109 | if (memcmp(f_data, data, length) == 0) { |
108 | size_recv += length; | 110 | size_recv += length; |
111 | } else { | ||
112 | printf("FILE_CORRUPTED\n"); | ||
113 | } | ||
109 | } | 114 | } |
110 | 115 | ||
111 | START_TEST(test_few_clients) | 116 | START_TEST(test_few_clients) |
112 | { | 117 | { |
113 | long long unsigned int cur_time = time(NULL); | 118 | long long unsigned int con_time, cur_time = time(NULL); |
114 | Tox *tox1 = tox_new(TOX_ENABLE_IPV6_DEFAULT); | 119 | Tox *tox1 = tox_new(TOX_ENABLE_IPV6_DEFAULT); |
115 | Tox *tox2 = tox_new(TOX_ENABLE_IPV6_DEFAULT); | 120 | Tox *tox2 = tox_new(TOX_ENABLE_IPV6_DEFAULT); |
116 | Tox *tox3 = tox_new(TOX_ENABLE_IPV6_DEFAULT); | 121 | Tox *tox3 = tox_new(TOX_ENABLE_IPV6_DEFAULT); |
@@ -131,6 +136,7 @@ START_TEST(test_few_clients) | |||
131 | 136 | ||
132 | if (tox_isconnected(tox1) && tox_isconnected(tox2) && tox_isconnected(tox3) && off) { | 137 | if (tox_isconnected(tox1) && tox_isconnected(tox2) && tox_isconnected(tox3) && off) { |
133 | printf("Toxes are online, took %llu seconds\n", time(NULL) - cur_time); | 138 | printf("Toxes are online, took %llu seconds\n", time(NULL) - cur_time); |
139 | con_time = time(NULL); | ||
134 | off = 0; | 140 | off = 0; |
135 | } | 141 | } |
136 | 142 | ||
@@ -141,7 +147,7 @@ START_TEST(test_few_clients) | |||
141 | c_sleep(50); | 147 | c_sleep(50); |
142 | } | 148 | } |
143 | 149 | ||
144 | printf("tox clients connected\n"); | 150 | printf("tox clients connected took %llu seconds\n", time(NULL) - con_time); |
145 | to_compare = 974536; | 151 | to_compare = 974536; |
146 | tox_callback_friend_message(tox3, print_message, &to_compare); | 152 | tox_callback_friend_message(tox3, print_message, &to_compare); |
147 | tox_send_message(tox2, 0, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo")); | 153 | tox_send_message(tox2, 0, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo")); |
@@ -227,8 +233,8 @@ START_TEST(test_few_clients) | |||
227 | ck_assert_msg(fnum != -1, "tox_new_file_sender fail"); | 233 | ck_assert_msg(fnum != -1, "tox_new_file_sender fail"); |
228 | int fpiece_size = tox_file_data_size(tox2, 0); | 234 | int fpiece_size = tox_file_data_size(tox2, 0); |
229 | uint8_t *f_data = malloc(fpiece_size); | 235 | uint8_t *f_data = malloc(fpiece_size); |
230 | memset(f_data, 6, fpiece_size); | 236 | uint8_t num = 0; |
231 | 237 | memset(f_data, num, fpiece_size); | |
232 | while (1) { | 238 | while (1) { |
233 | file_sent = 0; | 239 | file_sent = 0; |
234 | tox_do(tox1); | 240 | tox_do(tox1); |
@@ -241,6 +247,8 @@ START_TEST(test_few_clients) | |||
241 | sendf_ok = 0; | 247 | sendf_ok = 0; |
242 | tox_file_send_control(tox2, 0, 0, fnum, TOX_FILECONTROL_FINISHED, NULL, 0); | 248 | tox_file_send_control(tox2, 0, 0, fnum, TOX_FILECONTROL_FINISHED, NULL, 0); |
243 | } | 249 | } |
250 | ++num; | ||
251 | memset(f_data, num, fpiece_size); | ||
244 | 252 | ||
245 | totalf_size -= fpiece_size; | 253 | totalf_size -= fpiece_size; |
246 | } | 254 | } |
@@ -284,6 +292,12 @@ START_TEST(test_many_clients) | |||
284 | loop_top: | 292 | loop_top: |
285 | pairs[i].tox1 = rand() % NUM_TOXES; | 293 | pairs[i].tox1 = rand() % NUM_TOXES; |
286 | pairs[i].tox2 = (pairs[i].tox1 + rand() % (NUM_TOXES - 1) + 1) % NUM_TOXES; | 294 | pairs[i].tox2 = (pairs[i].tox1 + rand() % (NUM_TOXES - 1) + 1) % NUM_TOXES; |
295 | |||
296 | for (j = 0; j < i; ++j) { | ||
297 | if (pairs[j].tox2 == pairs[i].tox1 && pairs[j].tox1 == pairs[i].tox2) | ||
298 | goto loop_top; | ||
299 | } | ||
300 | |||
287 | tox_get_address(toxes[pairs[i].tox1], address); | 301 | tox_get_address(toxes[pairs[i].tox1], address); |
288 | int test = tox_add_friend(toxes[pairs[i].tox2], address, (uint8_t *)"Gentoo", 7); | 302 | int test = tox_add_friend(toxes[pairs[i].tox2], address, (uint8_t *)"Gentoo", 7); |
289 | 303 | ||
@@ -331,7 +345,7 @@ Suite *tox_suite(void) | |||
331 | Suite *s = suite_create("Tox"); | 345 | Suite *s = suite_create("Tox"); |
332 | 346 | ||
333 | DEFTESTCASE_SLOW(few_clients, 50); | 347 | DEFTESTCASE_SLOW(few_clients, 50); |
334 | DEFTESTCASE_SLOW(many_clients, 300); | 348 | DEFTESTCASE_SLOW(many_clients, 150); |
335 | return s; | 349 | return s; |
336 | } | 350 | } |
337 | 351 | ||
diff --git a/docs/Group-Chats.md b/docs/Group-Chats.md index e318613d..5e00b550 100644 --- a/docs/Group-Chats.md +++ b/docs/Group-Chats.md | |||
@@ -21,18 +21,18 @@ See DHT, currently uses the IPv6 Node_format. | |||
21 | Get nodes (Request): | 21 | Get nodes (Request): |
22 | Packet contents: | 22 | Packet contents: |
23 | ``` | 23 | ``` |
24 | [char with a value of 48][Bob's (The reciever's) Public key (client_id) (32 bytes))][Alice's (The sender's) Public key (client_id) (32 bytes)][Random nonce (24 bytes)][Encrypted with the nonce, private key of the sender and public key of the reciever:[char with a value of 48][random 8 byte (ping_id)] | 24 | [char with a value of 48][Bob's (The receiver's) Public key (client_id) (32 bytes))][Alice's (The sender's) Public key (client_id) (32 bytes)][Random nonce (24 bytes)][Encrypted with the nonce, private key of the sender and public key of the receiver:[char with a value of 48][random 8 byte (ping_id)] |
25 | ``` | 25 | ``` |
26 | Valid replies: a send_nodes packet | 26 | Valid replies: a send_nodes packet |
27 | 27 | ||
28 | Send_nodes (response): | 28 | Send_nodes (response): |
29 | ``` | 29 | ``` |
30 | [char with a value of 48][Bob's (The reciever's) Public key (client_id) (32 bytes))][Alice's (The sender's) Public key (client_id) (32 bytes)][Random nonce (24 bytes)][Encrypted with the nonce, private key of the sender and public key of the reciever:[char with a value of 49][random 8 byte (ping_id)][Nodes in node format, length=40 * (number of nodes (maximum of 6 nodes)) bytes]] | 30 | [char with a value of 48][Bob's (The receiver's) Public key (client_id) (32 bytes))][Alice's (The sender's) Public key (client_id) (32 bytes)][Random nonce (24 bytes)][Encrypted with the nonce, private key of the sender and public key of the receiver:[char with a value of 49][random 8 byte (ping_id)][Nodes in node format, length=40 * (number of nodes (maximum of 6 nodes)) bytes]] |
31 | ``` | 31 | ``` |
32 | 32 | ||
33 | Broadcast packet: | 33 | Broadcast packet: |
34 | ``` | 34 | ``` |
35 | [char with a value of 48][Bob's (The reciever's) Public key (client_id) (32 bytes))][Alice's (The sender's) Public key (client_id) (32 bytes)][nonce][Encrypted with the nonce, private key of the sender and public key of the reciever:[char with a value of 50][Data to send to everyone]] | 35 | [char with a value of 48][Bob's (The receiver's) Public key (client_id) (32 bytes))][Alice's (The sender's) Public key (client_id) (32 bytes)][nonce][Encrypted with the nonce, private key of the sender and public key of the receiver:[char with a value of 50][Data to send to everyone]] |
36 | ``` | 36 | ``` |
37 | 37 | ||
38 | 38 | ||
@@ -68,4 +68,4 @@ Ban a peer | |||
68 | [uint8_t message[messagelen]] | 68 | [uint8_t message[messagelen]] |
69 | 69 | ||
70 | 65 - action (/me) | 70 | 65 - action (/me) |
71 | [uint8_t message[messagelen]] \ No newline at end of file | 71 | [uint8_t message[messagelen]] |
diff --git a/docs/Prevent_Tracking.txt b/docs/Prevent_Tracking.txt index c5f33e96..d170103f 100644 --- a/docs/Prevent_Tracking.txt +++ b/docs/Prevent_Tracking.txt | |||
@@ -110,7 +110,8 @@ encrypted with that temporary private key and the nonce and the public key from | |||
110 | (if Node D contains the ret data for the node, it sends the stuff in this packet as a data to route response packet to the right node) | 110 | (if Node D contains the ret data for the node, it sends the stuff in this packet as a data to route response packet to the right node) |
111 | 111 | ||
112 | The data in the previous packet is in format: [real public key of sender] | 112 | The data in the previous packet is in format: [real public key of sender] |
113 | encrypted with real private key of the sender, the nonce in the data packet and the real public key of the reciever:[[uint8_t id][data (optional)]] | 113 | encrypted with real private key of the sender, the nonce in the data packet and |
114 | the real public key of the receiver:[[uint8_t id][data (optional)]] | ||
114 | 115 | ||
115 | Data sent to us: | 116 | Data sent to us: |
116 | announce response packet: | 117 | announce response packet: |
@@ -153,5 +154,5 @@ Data packets: | |||
153 | 154 | ||
154 | To tell our friend what our DHT public key is so that he can connect to us we send a data packet | 155 | To tell our friend what our DHT public key is so that he can connect to us we send a data packet |
155 | with id 156 and the data being:[uint64_t (in network byte order) no_replay, the packet will only be | 156 | with id 156 and the data being:[uint64_t (in network byte order) no_replay, the packet will only be |
156 | accepted if this number is bigger than the last one recieved] [our dht public key][Node_Format * ( | 157 | accepted if this number is bigger than the last one received] [our dht public key][Node_Format * ( |
157 | maximum of 8) nodes closest to us so that the friend can find us faster] | 158 | maximum of 8) nodes closest to us so that the friend can find us faster] |
diff --git a/docs/TCP_Network.txt b/docs/TCP_Network.txt index 775ccc88..4bc2d433 100644 --- a/docs/TCP_Network.txt +++ b/docs/TCP_Network.txt | |||
@@ -81,7 +81,7 @@ received | |||
81 | client sent the server the public key and the public key we sent to the client, | 81 | client sent the server the public key and the public key we sent to the client, |
82 | the next with base nonce + 1...) | 82 | the next with base nonce + 1...) |
83 | 83 | ||
84 | The connection is set to an unconfirmed state until a packet is recieved and | 84 | The connection is set to an unconfirmed state until a packet is received and |
85 | decrypted correctly using the information in the handshake. | 85 | decrypted correctly using the information in the handshake. |
86 | 86 | ||
87 | each packet sent to/from the server has an id (the first byte of the plain text | 87 | each packet sent to/from the server has an id (the first byte of the plain text |
@@ -104,6 +104,10 @@ special ids and packets: | |||
104 | [uint8_t id (4)][uint64_t ping_id (0 is invalid)] | 104 | [uint8_t id (4)][uint64_t ping_id (0 is invalid)] |
105 | 5 - ping response (pong) | 105 | 5 - ping response (pong) |
106 | [uint8_t id (5)][uint64_t ping_id (0 is invalid)] | 106 | [uint8_t id (5)][uint64_t ping_id (0 is invalid)] |
107 | 6 - OOB send | ||
108 | [uint8_t id (6)][destination public key (32 bytes)][data] | ||
109 | 7 - OOB recv | ||
110 | [uint8_t id (7)][senders public key (32 bytes)][data] | ||
107 | 8 - onion packet (same format as initial onion packet (See: Prevent | 111 | 8 - onion packet (same format as initial onion packet (See: Prevent |
108 | tracking.txt) but packet id is 8 instead of 128) | 112 | tracking.txt) but packet id is 8 instead of 128) |
109 | 9 - onion packet response (same format as onion packet with id 142 but id is 9 | 113 | 9 - onion packet response (same format as onion packet with id 142 but id is 9 |
@@ -135,11 +139,16 @@ responses must be sent to the proper client. | |||
135 | 139 | ||
136 | Ping responses must have the same ping_id as the request. | 140 | Ping responses must have the same ping_id as the request. |
137 | 141 | ||
138 | If the server recieves a ping packet he must respond with a ping response. | 142 | If the server receives a ping packet he must respond with a ping response. |
139 | 143 | ||
140 | The server will send a ping packet to clients every 30 seconds, they have 30 | 144 | The server will send a ping packet to clients every 30 seconds, they have 30 |
141 | seconds to respond, if they don't the connection is deleted. | 145 | seconds to respond, if they don't the connection is deleted. |
142 | 146 | ||
147 | OOB send packets will be sent to the peer connected to the TCP server with the | ||
148 | destination public key as a OOB recv packet. The client sending this packet has | ||
149 | no way of knowing if the packet reached its destination. | ||
150 | |||
151 | |||
143 | Client: | 152 | Client: |
144 | 153 | ||
145 | Implementation details coming soon. | 154 | Implementation details coming soon. |
diff --git a/docs/Tox_middle_level_network_protocol.txt b/docs/Tox_middle_level_network_protocol.txt new file mode 100644 index 00000000..9941487b --- /dev/null +++ b/docs/Tox_middle_level_network_protocol.txt | |||
@@ -0,0 +1,118 @@ | |||
1 | The TCP client and TCP server part are in a state that can be considered | ||
2 | feature complete. Why doesn't Tox support TCP yet even if those parts are | ||
3 | complete? | ||
4 | |||
5 | The answer is that a way to ensure a smooth switchover between the TCP and UDP | ||
6 | needs to be added. If Tox first connects to the other user using TCP but then | ||
7 | due to pure chance manages to connect using the faster direct UDP connection | ||
8 | Tox must switch seamlessly from the TCP to the UDP connection without there | ||
9 | being any data loss or the other user going offline and then back online. The | ||
10 | transition must be seamless whatever both connected users are doing be it | ||
11 | transferring files or simply chatting together. | ||
12 | |||
13 | Possible evil/bad or simply TCP relays going offline must not impact the | ||
14 | connection between both clients. | ||
15 | |||
16 | Typically Tox will use more than one TCP relay to connect to other peers for | ||
17 | maximum connection stability which means there must be a way for Tox to take | ||
18 | advantage of multiple relays in a way that the user will never be aware if one | ||
19 | of them goes offline/tries to slow down the connection/decides to corrupt | ||
20 | packets/etc.. | ||
21 | |||
22 | To accomplish this Tox needs something between the low level protocol (TCP) and | ||
23 | high level Tox messaging protocol hence the name middle level. | ||
24 | |||
25 | The plan is to move some functionality from lossless_UDP to a higher level: | ||
26 | more specifically the functionality for detecting which packets a peer is | ||
27 | missing and the ability to request and send them again. lossless UDP uses plain | ||
28 | text packets to request missing packets from the other peer while Tox is | ||
29 | currently designed to kill the connection if any packet tampering is detected. | ||
30 | This works very well when connecting directly with someone because if the | ||
31 | attacker can modify packets it means he can kill your connection anyways. With | ||
32 | TCP relays however that is not the case as such the packets used to request | ||
33 | missing packets must be encrypted. If it is detected that a packet has been | ||
34 | tampered, the connection must stay intact while the evil relay must be | ||
35 | disconnected from and replaced with a good relay, the behavior must be the same | ||
36 | as if the relay had just suddenly gone online. Of course something to protect | ||
37 | from evil "friends" framing relays must also be implemented. | ||
38 | |||
39 | Detailed implementation details: | ||
40 | |||
41 | cookie request packet: | ||
42 | [uint8_t 24][Senders DHT Public key (32 bytes)][Random nonce (24 | ||
43 | bytes)][Encrypted message containing: [Senders real public key (32 | ||
44 | bytes)][padding (32 bytes)][uint64_t number (must be sent | ||
45 | back untouched in cookie response)]] | ||
46 | Encrypted message is encrypted with sender DHT private key, recievers DHT | ||
47 | public key and the nonce. | ||
48 | |||
49 | cookie response packet: | ||
50 | [uint8_t 25][Random nonce (24 bytes)][Encrypted message containing: | ||
51 | [Cookie][uint64_t number (that was sent in the request)]] | ||
52 | Encrypted message is encrypted with sender DHT private key, recievers DHT | ||
53 | public key and the nonce. | ||
54 | |||
55 | The Cookie should be basically: | ||
56 | [nonce][encrypted data:[uint64_t time][Senders real public key (32 | ||
57 | bytes)][Senders dht public key (32 bytes)]] | ||
58 | |||
59 | Handshake packet: | ||
60 | [uint8_t 26][Cookie][nonce][Encrypted message containing: [random 24 bytes base | ||
61 | nonce][session public key of the peer (32 bytes)][sha512 hash of the entire | ||
62 | Cookie sitting outside the encrypted part][Other Cookie (used by the other to | ||
63 | respond to the handshake packet)]] | ||
64 | |||
65 | The handshake packet is encrypted using the real private key of the sender, the | ||
66 | real private key of the receiver and the nonce. | ||
67 | |||
68 | |||
69 | Alice wants to connect to bob. | ||
70 | |||
71 | Alice sends a cookie request packet to bob and gets a cookie response back. | ||
72 | |||
73 | Alice then generates a nonce and a temporary public/private keypair. | ||
74 | |||
75 | Alice then takes that nonce and just generated private key, the obtained | ||
76 | cookie, creates a new cookie and puts them in a handshake packet which she | ||
77 | sends to bob. | ||
78 | |||
79 | Bob gets the handshake packet, accepts the connection request, then generates a | ||
80 | nonce and a temporary public/private keypair and sends a handshake packet back | ||
81 | with this just generated information and with the cookie field being the Other | ||
82 | Cookie contained in the received handshake. | ||
83 | |||
84 | Both then use these temporary keys to generate the session key with which every | ||
85 | data packet sent and received will be encrypted and decrypted. The nonce sent | ||
86 | in the handshake will be used to encrypt the first data packet sent, the nonce | ||
87 | + 1 the second, the nonce + 2 the third and so on. | ||
88 | |||
89 | Data packets: | ||
90 | |||
91 | [uint8_t 27][uint16_t (in network byte order) the last 2 bytes of the nonce | ||
92 | used to encrypt this][encrypted with the session key and a nonce:[plain data]] | ||
93 | |||
94 | Plain data in the data packets: | ||
95 | |||
96 | [uint32_t our recvbuffers buffer_start, (highest packet number handled + | ||
97 | 1)][uint32_t packet number if lossless, our sendbuffer buffer_end if | ||
98 | lossy][data] | ||
99 | |||
100 | data ids: | ||
101 | 0: padding (skipped until we hit a non zero (data id) byte) | ||
102 | 1: packet request packet (lossy packet) | ||
103 | 2: connection kill packet (lossy packet) (tells the other that the connection is over) | ||
104 | ... | ||
105 | 16+: reserved for Messenger usage (lossless packets). | ||
106 | |||
107 | packet request packet: [uint8_t (1)][uint8_t num][uint8_t num][uint8_t | ||
108 | num]...[uint8_t num] | ||
109 | |||
110 | the list of nums are a list of packet numbers the other is requesting. | ||
111 | to get the real packet numbers from this list take the recvbuffers buffer_start | ||
112 | from the packet, substract 1 to it and put it in packet_num then start from the | ||
113 | beggining of the num list: if num is zero, add 255 to packet_num then do the | ||
114 | next num. if num isn't zero, add its value to packet_num, note that the other | ||
115 | has requested we send this packet again to them then continue to the next num in | ||
116 | the list. | ||
117 | |||
118 | |||
diff --git a/docs/av_api.md b/docs/av_api.md index 17930144..2f536ade 100644 --- a/docs/av_api.md +++ b/docs/av_api.md | |||
@@ -34,7 +34,7 @@ msi_session_t* - pointer to a newly created msi session handler. | |||
34 | ###msi_session_t reference: | 34 | ###msi_session_t reference: |
35 | 35 | ||
36 | How to handle msi session: | 36 | How to handle msi session: |
37 | Controling is done via callbacks and action handlers. | 37 | Controlling is done via callbacks and action handlers. |
38 | First register callbacks for every state/action received and make sure | 38 | First register callbacks for every state/action received and make sure |
39 | NOT TO PLACE SOMETHING LIKE LOOPS THAT TAKES A LOT OF TIME TO EXECUTE; every callback is being called | 39 | NOT TO PLACE SOMETHING LIKE LOOPS THAT TAKES A LOT OF TIME TO EXECUTE; every callback is being called |
40 | directly from event loop. You can find examples in phone.c. | 40 | directly from event loop. You can find examples in phone.c. |
diff --git a/docs/updates/Crypto.md b/docs/updates/Crypto.md index a6c701d3..939c15e2 100644 --- a/docs/updates/Crypto.md +++ b/docs/updates/Crypto.md | |||
@@ -74,4 +74,4 @@ Crypto request packets | |||
74 | 74 | ||
75 | The encrypted message is encrypted with crypto_box() (using Bobs public key, Alice's private key and the nonce (randomly generated 24 bytes)) and is a message from Alice in which she tells Bob who she is. | 75 | The encrypted message is encrypted with crypto_box() (using Bobs public key, Alice's private key and the nonce (randomly generated 24 bytes)) and is a message from Alice in which she tells Bob who she is. |
76 | 76 | ||
77 | Each node can route the request to the reciever if they are connected to him. This is to bypass bad NATs. | 77 | Each node can route the request to the receiver if they are connected to him. This is to bypass bad NATs. |
diff --git a/docs/updates/DHT.md b/docs/updates/DHT.md index db825a3c..17db70ce 100644 --- a/docs/updates/DHT.md +++ b/docs/updates/DHT.md | |||
@@ -79,18 +79,15 @@ Protocol | |||
79 | 79 | ||
80 | Node format: | 80 | Node format: |
81 | ``` | 81 | ``` |
82 | [char array (node_id), length=32 bytes][ip (in network byte order), length=4 bytes][port (in network byte order), length=2 bytes][Padding , length=2 bytes] | 82 | [uint8_t family (2 == IPv4, 10 == IPv6, 130 == TCP IPv4, 138 == TCP IPv6)][ip (in network byte order), length=4 bytes if ipv4, 16 bytes if ipv6][port (in network byte order), length=2 bytes][char array (node_id), length=32 bytes] |
83 | ``` | 83 | ``` |
84 | see also: DHT.h (Node4_format struct) | 84 | see also: DHT.h (pack_nodes() and unpack_nodes()) |
85 | |||
86 | IPv6 Node format: | ||
87 | see: DHT.h (Node_format struct) | ||
88 | 85 | ||
89 | Valid queries and Responses: | 86 | Valid queries and Responses: |
90 | 87 | ||
91 | Ping(Request and response): | 88 | Ping(Request and response): |
92 | ``` | 89 | ``` |
93 | [byte with value: 00 for request, 01 for response][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender: [random 8 byte (ping_id)]] | 90 | [byte with value: 00 for request, 01 for response][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender: [1 byte type (0 for request, 1 for response)][random 8 byte (ping_id)]] |
94 | ``` | 91 | ``` |
95 | ping_id = a random integer, the response must contain the exact same number as the request | 92 | ping_id = a random integer, the response must contain the exact same number as the request |
96 | 93 | ||
@@ -98,16 +95,11 @@ ping_id = a random integer, the response must contain the exact same number as t | |||
98 | Get nodes (Request): | 95 | Get nodes (Request): |
99 | Packet contents: | 96 | Packet contents: |
100 | ``` | 97 | ``` |
101 | [byte with value: 02][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[char array: requested_node_id (node_id of which we want the ip), length=32 bytes][Encrypted data (must be sent back unmodified by in the response), length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]] | 98 | [byte with value: 02][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[char array: requested_node_id (node_id of which we want the ip), length=32 bytes][Sendback data (must be sent back unmodified by in the response), length=1 to NODES_ENCRYPTED_MESSAGE_LENGTH bytes]] |
102 | ``` | 99 | ``` |
103 | Valid replies: a send_nodes packet | 100 | Valid replies: a send_nodes packet |
104 | 101 | ||
105 | Send_nodes (response (for ipv4 addresses)): | 102 | Send_nodes (response (for all addresses)): |
106 | ``` | ||
107 | [byte with value: 03][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[Nodes in node format, length=40 * (number of nodes (maximum of 8 nodes)) bytes][Encrypted data, length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]] | ||
108 | ``` | ||
109 | |||
110 | Send_nodes_IPv6 (response (for ipv6 addresses)): | ||
111 | ``` | 103 | ``` |
112 | [byte with value: 04][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[Nodes in ipv6_node format, length=56 * (number of nodes (maximum of 8 nodes)) bytes][Encrypted data, length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]] | 104 | [byte with value: 04][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[uint8_t number of nodes in this packet][Nodes in node format, length=?? * (number of nodes (maximum of 8 nodes)) bytes][Sendback data, length=1 to NODES_ENCRYPTED_MESSAGE_LENGTH bytes]] |
113 | ``` | 105 | ``` |
@@ -53,7 +53,7 @@ fi[]dnl | |||
53 | # to PKG_CHECK_MODULES(), but does not set variables or print errors. | 53 | # to PKG_CHECK_MODULES(), but does not set variables or print errors. |
54 | # | 54 | # |
55 | # Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) | 55 | # Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) |
56 | # only at the first occurence in configure.ac, so if the first place | 56 | # only at the first occurrence in configure.ac, so if the first place |
57 | # it's called might be skipped (such as if it is within an "if", you | 57 | # it's called might be skipped (such as if it is within an "if", you |
58 | # have to call PKG_CHECK_EXISTS manually | 58 | # have to call PKG_CHECK_EXISTS manually |
59 | # -------------------------------------------------------------- | 59 | # -------------------------------------------------------------- |
diff --git a/other/bootstrap_daemon/conf b/other/bootstrap_daemon/conf index 28e638c1..c05beff1 100644 --- a/other/bootstrap_daemon/conf +++ b/other/bootstrap_daemon/conf | |||
@@ -3,16 +3,16 @@ | |||
3 | // Listening port. | 3 | // Listening port. |
4 | port = 33445 | 4 | port = 33445 |
5 | 5 | ||
6 | // The key file is like a password, so keep it where no one can read it. | 6 | // A key file is like a password, so keep it where no one can read it. |
7 | // The daemon should have permission to read/write to it. | 7 | // The daemon should have permission to read/write to it. |
8 | // Remember to replace the provided example with your own path. | 8 | // Remember to replace the provided example with your own path. |
9 | keys_file_path = "/home/tom/.tox_bootstrap_daemon/keys" | 9 | keys_file_path = "/home/tom/.tox_bootstrap_daemon/.tox_bootstrap_daemon.keys" |
10 | 10 | ||
11 | // The PID file written to by daemon. | 11 | // The PID file written to by daemon. |
12 | // Make sure that the user who runs the daemon has permissions to write to the | 12 | // Make sure that the user who runs the daemon has permissions to write to the |
13 | // PID file. | 13 | // PID file. |
14 | // Remember to replace the provided example with your own path. | 14 | // Remember to replace the provided example with your own path. |
15 | pid_file_path = "/home/tom/.tox_bootstrap_daemon/pid" | 15 | pid_file_path = "/home/tom/.tox_bootstrap_daemon/.tox_bootstrap_daemon.pid" |
16 | 16 | ||
17 | // Enable IPv6. | 17 | // Enable IPv6. |
18 | enable_ipv6 = false | 18 | enable_ipv6 = false |
@@ -20,6 +20,18 @@ enable_ipv6 = false | |||
20 | // Automatically bootstrap with nodes on local area network. | 20 | // Automatically bootstrap with nodes on local area network. |
21 | enable_lan_discovery = true | 21 | enable_lan_discovery = true |
22 | 22 | ||
23 | enable_tcp_relay = true | ||
24 | |||
25 | // Tox uses 443, 3389 and 33445 ports by default, so it's highly recommended to keep | ||
26 | // them. | ||
27 | tcp_relay_ports = [443, 3389, 33445] | ||
28 | |||
29 | // It's planned to use message of the day as a convenient method of checking | ||
30 | // whether a node is up or not, though there are other methods of doing that. | ||
31 | enable_motd = true | ||
32 | |||
33 | motd = "tox_bootstrap_daemon" | ||
34 | |||
23 | // Any number of nodes the daemon will bootstrap itself from. | 35 | // Any number of nodes the daemon will bootstrap itself from. |
24 | // Remember to replace the provided example with your own node list. | 36 | // Remember to replace the provided example with your own node list. |
25 | // There is a maintained list of bootstrap nodes on Tox's wiki, if you need it. | 37 | // There is a maintained list of bootstrap nodes on Tox's wiki, if you need it. |
@@ -28,8 +40,8 @@ enable_lan_discovery = true | |||
28 | // from anyone. | 40 | // from anyone. |
29 | bootstrap_nodes = ( | 41 | bootstrap_nodes = ( |
30 | { // Node 1 | 42 | { // Node 1 |
31 | // Any ipv4 or ipv6, depending if `enable_ipv6` is set or not, and also | 43 | // Any ipv4 or ipv6, depending on whether `enable_ipv6` is set or not, and |
32 | // any US-ASCII domain name. | 44 | // also any US-ASCII domain name. |
33 | address = "198.46.136.167" | 45 | address = "198.46.136.167" |
34 | port = 33445 | 46 | port = 33445 |
35 | public_key = "728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854" | 47 | public_key = "728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854" |
diff --git a/other/bootstrap_daemon/tox_bootstrap_daemon.c b/other/bootstrap_daemon/tox_bootstrap_daemon.c index 66f6436d..ceb4fded 100644 --- a/other/bootstrap_daemon/tox_bootstrap_daemon.c +++ b/other/bootstrap_daemon/tox_bootstrap_daemon.c | |||
@@ -21,37 +21,56 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <sys/types.h> | 24 | // system provided |
25 | #include <arpa/inet.h> | ||
26 | #include <syslog.h> | ||
25 | #include <sys/stat.h> | 27 | #include <sys/stat.h> |
28 | #include <sys/types.h> | ||
26 | #include <unistd.h> | 29 | #include <unistd.h> |
27 | #include <syslog.h> | ||
28 | 30 | ||
31 | // C | ||
29 | #include <stdio.h> | 32 | #include <stdio.h> |
30 | #include <stdlib.h> | 33 | #include <stdlib.h> |
31 | #include <libconfig.h> | ||
32 | #include <arpa/inet.h> | ||
33 | #include <string.h> | 34 | #include <string.h> |
34 | 35 | ||
36 | // 3rd party | ||
37 | #include <libconfig.h> | ||
38 | |||
39 | // ./configure | ||
35 | #ifdef HAVE_CONFIG_H | 40 | #ifdef HAVE_CONFIG_H |
36 | #include "config.h" | 41 | #include "config.h" |
37 | #endif | 42 | #endif |
38 | 43 | ||
39 | #include "../../toxcore/DHT.h" | 44 | // toxcore |
40 | #include "../../toxcore/friend_requests.h" | ||
41 | #include "../../toxcore/LAN_discovery.h" | 45 | #include "../../toxcore/LAN_discovery.h" |
46 | #include "../../toxcore/onion_announce.h" | ||
47 | #include "../../toxcore/TCP_server.h" | ||
48 | #include "../../toxcore/util.h" | ||
42 | 49 | ||
50 | // misc | ||
51 | #include "../bootstrap_node_packets.c" | ||
43 | #include "../../testing/misc_tools.c" | 52 | #include "../../testing/misc_tools.c" |
44 | 53 | ||
54 | |||
45 | #define DAEMON_NAME "tox_bootstrap_daemon" | 55 | #define DAEMON_NAME "tox_bootstrap_daemon" |
56 | #define DAEMON_VERSION_NUMBER 2014051800UL // yyyymmmddvv format: yyyy year, mm month, dd day, vv version change count for that day | ||
46 | 57 | ||
47 | #define SLEEP_TIME_MILLISECONDS 30 | 58 | #define SLEEP_TIME_MILLISECONDS 30 |
48 | #define sleep usleep(1000*SLEEP_TIME_MILLISECONDS) | 59 | #define sleep usleep(1000*SLEEP_TIME_MILLISECONDS) |
49 | 60 | ||
50 | #define DEFAULT_PID_FILE_PATH ".tox_bootstrap_daemon.pid" | 61 | #define DEFAULT_PID_FILE_PATH ".tox_bootstrap_daemon.pid" |
51 | #define DEFAULT_KEYS_FILE_PATH ".tox_bootstrap_daemon.keys" | 62 | #define DEFAULT_KEYS_FILE_PATH ".tox_bootstrap_daemon.keys" |
52 | #define DEFAULT_PORT 33445 | 63 | #define DEFAULT_PORT 33445 |
53 | #define DEFAULT_ENABLE_IPV6 0 // 1 - true, 0 - false | 64 | #define DEFAULT_ENABLE_IPV6 0 // 1 - true, 0 - false |
54 | #define DEFAULT_ENABLE_LAN_DISCOVERY 1 // 1 - true, 0 - false | 65 | #define DEFAULT_ENABLE_LAN_DISCOVERY 1 // 1 - true, 0 - false |
66 | #define DEFAULT_ENABLE_TCP_RELAY 1 // 1 - true, 0 - false | ||
67 | #define DEFAULT_TCP_RELAY_PORTS 443, 3389, 33445 // comma-separated list of ports. make sure to adjust DEFAULT_TCP_RELAY_PORTS_COUNT accordingly | ||
68 | #define DEFAULT_TCP_RELAY_PORTS_COUNT 3 | ||
69 | #define DEFAULT_ENABLE_MOTD 1 // 1 - true, 0 - false | ||
70 | #define DEFAULT_MOTD DAEMON_NAME | ||
71 | |||
72 | #define MIN_ALLOWED_PORT 1 | ||
73 | #define MAX_ALLOWED_PORT 65535 | ||
55 | 74 | ||
56 | 75 | ||
57 | // Uses the already existing key or creates one if it didn't exist | 76 | // Uses the already existing key or creates one if it didn't exist |
@@ -75,11 +94,12 @@ int manage_keys(DHT *dht, char *keys_file_path) | |||
75 | return 0; | 94 | return 0; |
76 | } | 95 | } |
77 | 96 | ||
78 | load_keys(dht->c, keys); | 97 | memcpy(dht->self_public_key, keys, crypto_box_PUBLICKEYBYTES); |
98 | memcpy(dht->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES); | ||
79 | } else { | 99 | } else { |
80 | // Otherwise save new keys | 100 | // Otherwise save new keys |
81 | new_keys(dht->c); | 101 | memcpy(keys, dht->self_public_key, crypto_box_PUBLICKEYBYTES); |
82 | save_keys(dht->c, keys); | 102 | memcpy(keys + crypto_box_PUBLICKEYBYTES, dht->self_secret_key, crypto_box_SECRETKEYBYTES); |
83 | 103 | ||
84 | keys_file = fopen(keys_file_path, "w"); | 104 | keys_file = fopen(keys_file_path, "w"); |
85 | 105 | ||
@@ -92,22 +112,111 @@ int manage_keys(DHT *dht, char *keys_file_path) | |||
92 | 112 | ||
93 | fclose(keys_file); | 113 | fclose(keys_file); |
94 | 114 | ||
95 | // We want our DHT public key to be the same as our internal one since this is a bootstrap node | ||
96 | memcpy(dht->self_public_key, dht->c->self_public_key, crypto_box_PUBLICKEYBYTES); | ||
97 | memcpy(dht->self_secret_key, dht->c->self_secret_key, crypto_box_SECRETKEYBYTES); | ||
98 | |||
99 | return 1; | 115 | return 1; |
100 | } | 116 | } |
101 | 117 | ||
118 | // Parses tcp relay ports from `cfg` and puts them into `tcp_relay_ports` array | ||
119 | // | ||
120 | // Supposed to be called from get_general_config only | ||
121 | // | ||
122 | // Important: iff `tcp_relay_port_count` > 0, then you are responsible for freeing `tcp_relay_ports` | ||
123 | |||
124 | void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int *tcp_relay_port_count) | ||
125 | { | ||
126 | const char *NAME_TCP_RELAY_PORTS = "tcp_relay_ports"; | ||
127 | |||
128 | *tcp_relay_port_count = 0; | ||
129 | |||
130 | config_setting_t *ports_array = config_lookup(cfg, NAME_TCP_RELAY_PORTS); | ||
131 | |||
132 | if (ports_array == NULL) { | ||
133 | syslog(LOG_WARNING, "No '%s' setting in the configuration file.\n", NAME_TCP_RELAY_PORTS); | ||
134 | syslog(LOG_WARNING, "Using default '%s':\n", NAME_TCP_RELAY_PORTS); | ||
135 | |||
136 | uint16_t default_ports[DEFAULT_TCP_RELAY_PORTS_COUNT] = {DEFAULT_TCP_RELAY_PORTS}; | ||
137 | |||
138 | int i; | ||
139 | |||
140 | for (i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; i ++) { | ||
141 | syslog(LOG_WARNING, "Port #%d: %u\n", i, default_ports[i]); | ||
142 | } | ||
143 | |||
144 | // similar procedure to the one of reading config file below | ||
145 | *tcp_relay_ports = malloc(DEFAULT_TCP_RELAY_PORTS_COUNT * sizeof(uint16_t)); | ||
146 | |||
147 | for (i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; i ++) { | ||
148 | |||
149 | (*tcp_relay_ports)[*tcp_relay_port_count] = default_ports[i]; | ||
150 | if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT || (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) { | ||
151 | syslog(LOG_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i, (*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); | ||
152 | continue; | ||
153 | } | ||
154 | |||
155 | (*tcp_relay_port_count) ++; | ||
156 | } | ||
157 | |||
158 | // the loop above skips invalid ports, so we adjust the allocated memory size | ||
159 | *tcp_relay_ports = realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t)); | ||
160 | |||
161 | return; | ||
162 | } | ||
163 | |||
164 | if (config_setting_is_array(ports_array) == CONFIG_FALSE) { | ||
165 | syslog(LOG_WARNING, "'%s' setting should be an array. Array syntax: 'setting = [value1, value2, ...]'.\n", NAME_TCP_RELAY_PORTS); | ||
166 | return; | ||
167 | } | ||
168 | |||
169 | int config_port_count = config_setting_length(ports_array); | ||
170 | if (config_port_count == 0) { | ||
171 | syslog(LOG_WARNING, "'%s' is empty.\n", NAME_TCP_RELAY_PORTS); | ||
172 | return; | ||
173 | } | ||
174 | |||
175 | *tcp_relay_ports = malloc(config_port_count * sizeof(uint16_t)); | ||
176 | |||
177 | config_setting_t *elem; | ||
178 | int i; | ||
179 | |||
180 | for (i = 0; i < config_port_count; i ++) { | ||
181 | |||
182 | elem = config_setting_get_elem(ports_array, i); | ||
183 | |||
184 | if (elem == NULL) { | ||
185 | // it's NULL if `ports_array` is not an array (we have that check ealier) or if `i` is out of range, which should not be | ||
186 | syslog(LOG_WARNING, "Port #%d: Something went wrong while parsing the port. Stopping reading ports.\n", i); | ||
187 | break; | ||
188 | } | ||
189 | |||
190 | if (config_setting_is_number(elem) == CONFIG_FALSE) { | ||
191 | syslog(LOG_WARNING, "Port #%d: Not a number. Skipping.\n", i); | ||
192 | continue; | ||
193 | } | ||
194 | |||
195 | (*tcp_relay_ports)[*tcp_relay_port_count] = config_setting_get_int(elem); | ||
196 | if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT || (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) { | ||
197 | syslog(LOG_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i, (*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); | ||
198 | continue; | ||
199 | } | ||
200 | |||
201 | (*tcp_relay_port_count) ++; | ||
202 | } | ||
203 | |||
204 | // the loop above skips invalid ports, so we adjust the allocated memory size | ||
205 | *tcp_relay_ports = realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t)); | ||
206 | } | ||
207 | |||
102 | // Gets general config options | 208 | // Gets general config options |
103 | // | 209 | // |
104 | // Important: you are responsible for freeing `pid_file_path` and `keys_file_path` | 210 | // Important: you are responsible for freeing `pid_file_path` and `keys_file_path` |
211 | // also, iff `tcp_relay_ports_count` > 0, then you are responsible for freeing `tcp_relay_ports` | ||
212 | // and also `motd` iff `enable_motd` is set | ||
105 | // | 213 | // |
106 | // returns 1 on success | 214 | // returns 1 on success |
107 | // 0 on failure, doesn't modify any data pointed by arguments | 215 | // 0 on failure, doesn't modify any data pointed by arguments |
108 | 216 | ||
109 | int get_general_config(char *cfg_file_path, char **pid_file_path, char **keys_file_path, int *port, int *enable_ipv6, | 217 | int get_general_config(char *cfg_file_path, char **pid_file_path, char **keys_file_path, int *port, int *enable_ipv6, |
110 | int *enable_lan_discovery) | 218 | int *enable_lan_discovery, int *enable_tcp_relay, uint16_t **tcp_relay_ports, int *tcp_relay_port_count, |
219 | int *enable_motd, char **motd) | ||
111 | { | 220 | { |
112 | config_t cfg; | 221 | config_t cfg; |
113 | 222 | ||
@@ -116,6 +225,9 @@ int get_general_config(char *cfg_file_path, char **pid_file_path, char **keys_fi | |||
116 | const char *NAME_KEYS_FILE_PATH = "keys_file_path"; | 225 | const char *NAME_KEYS_FILE_PATH = "keys_file_path"; |
117 | const char *NAME_ENABLE_IPV6 = "enable_ipv6"; | 226 | const char *NAME_ENABLE_IPV6 = "enable_ipv6"; |
118 | const char *NAME_ENABLE_LAN_DISCOVERY = "enable_lan_discovery"; | 227 | const char *NAME_ENABLE_LAN_DISCOVERY = "enable_lan_discovery"; |
228 | const char *NAME_ENABLE_TCP_RELAY = "enable_tcp_relay"; | ||
229 | const char *NAME_ENABLE_MOTD = "enable_motd"; | ||
230 | const char *NAME_MOTD = "motd"; | ||
119 | 231 | ||
120 | config_init(&cfg); | 232 | config_init(&cfg); |
121 | 233 | ||
@@ -172,6 +284,44 @@ int get_general_config(char *cfg_file_path, char **pid_file_path, char **keys_fi | |||
172 | *enable_lan_discovery = DEFAULT_ENABLE_LAN_DISCOVERY; | 284 | *enable_lan_discovery = DEFAULT_ENABLE_LAN_DISCOVERY; |
173 | } | 285 | } |
174 | 286 | ||
287 | // Get TCP relay option | ||
288 | if (config_lookup_bool(&cfg, NAME_ENABLE_TCP_RELAY, enable_tcp_relay) == CONFIG_FALSE) { | ||
289 | syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_TCP_RELAY); | ||
290 | syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_TCP_RELAY, | ||
291 | DEFAULT_ENABLE_TCP_RELAY ? "true" : "false"); | ||
292 | *enable_tcp_relay = DEFAULT_ENABLE_TCP_RELAY; | ||
293 | } | ||
294 | |||
295 | if (*enable_tcp_relay) { | ||
296 | parse_tcp_relay_ports_config(&cfg, tcp_relay_ports, tcp_relay_port_count); | ||
297 | } else { | ||
298 | *tcp_relay_port_count = 0; | ||
299 | } | ||
300 | |||
301 | // Get MOTD option | ||
302 | if (config_lookup_bool(&cfg, NAME_ENABLE_MOTD, enable_motd) == CONFIG_FALSE) { | ||
303 | syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_MOTD); | ||
304 | syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_MOTD, | ||
305 | DEFAULT_ENABLE_MOTD ? "true" : "false"); | ||
306 | *enable_motd = DEFAULT_ENABLE_MOTD; | ||
307 | } | ||
308 | |||
309 | if (*enable_motd) { | ||
310 | // Get MOTD | ||
311 | const char *tmp_motd; | ||
312 | |||
313 | if (config_lookup_string(&cfg, NAME_MOTD, &tmp_motd) == CONFIG_FALSE) { | ||
314 | syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_MOTD); | ||
315 | syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_MOTD, DEFAULT_MOTD); | ||
316 | tmp_motd = DEFAULT_MOTD; | ||
317 | } | ||
318 | size_t tmp_motd_length = strlen(tmp_motd) + 1; | ||
319 | size_t motd_length = tmp_motd_length > MAX_MOTD_LENGTH ? MAX_MOTD_LENGTH : tmp_motd_length; | ||
320 | *motd = malloc(motd_length); | ||
321 | strncpy(*motd, tmp_motd, motd_length); | ||
322 | (*motd)[motd_length - 1] = '\0'; | ||
323 | } | ||
324 | |||
175 | config_destroy(&cfg); | 325 | config_destroy(&cfg); |
176 | 326 | ||
177 | syslog(LOG_DEBUG, "Successfully read:\n"); | 327 | syslog(LOG_DEBUG, "Successfully read:\n"); |
@@ -181,6 +331,25 @@ int get_general_config(char *cfg_file_path, char **pid_file_path, char **keys_fi | |||
181 | syslog(LOG_DEBUG, "'%s': %s\n", NAME_ENABLE_IPV6, *enable_ipv6 ? "true" : "false"); | 331 | syslog(LOG_DEBUG, "'%s': %s\n", NAME_ENABLE_IPV6, *enable_ipv6 ? "true" : "false"); |
182 | syslog(LOG_DEBUG, "'%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, *enable_lan_discovery ? "true" : "false"); | 332 | syslog(LOG_DEBUG, "'%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, *enable_lan_discovery ? "true" : "false"); |
183 | 333 | ||
334 | syslog(LOG_DEBUG, "'%s': %s\n", NAME_ENABLE_TCP_RELAY, *enable_tcp_relay ? "true" : "false"); | ||
335 | // show info about tcp ports only if tcp relay is enabled | ||
336 | if (*enable_tcp_relay) { | ||
337 | if (*tcp_relay_port_count == 0) { | ||
338 | syslog(LOG_DEBUG, "No TCP ports could be read.\n"); | ||
339 | } else { | ||
340 | syslog(LOG_DEBUG, "Read %d TCP ports:\n", *tcp_relay_port_count); | ||
341 | int i; | ||
342 | for (i = 0; i < *tcp_relay_port_count; i ++) { | ||
343 | syslog(LOG_DEBUG, "Port #%d: %u\n", i, (*tcp_relay_ports)[i]); | ||
344 | } | ||
345 | } | ||
346 | } | ||
347 | |||
348 | syslog(LOG_DEBUG, "'%s': %s\n", NAME_ENABLE_MOTD, *enable_motd ? "true" : "false"); | ||
349 | if (*enable_motd) { | ||
350 | syslog(LOG_DEBUG, "'%s': %s\n", NAME_MOTD, *motd); | ||
351 | } | ||
352 | |||
184 | return 1; | 353 | return 1; |
185 | } | 354 | } |
186 | 355 | ||
@@ -255,15 +424,14 @@ int bootstrap_from_config(char *cfg_file_path, DHT *dht, int enable_ipv6) | |||
255 | } | 424 | } |
256 | 425 | ||
257 | // Process settings | 426 | // Process settings |
258 | if (strlen(bs_public_key) != 64) { | 427 | if (strlen(bs_public_key) != crypto_box_PUBLICKEYBYTES*2) { |
259 | syslog(LOG_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_PUBLIC_KEY, | 428 | syslog(LOG_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_PUBLIC_KEY, |
260 | bs_public_key); | 429 | bs_public_key); |
261 | goto next; | 430 | goto next; |
262 | } | 431 | } |
263 | 432 | ||
264 | // not (1 <= port <= 65535) | 433 | if (bs_port < MIN_ALLOWED_PORT || bs_port > MAX_ALLOWED_PORT) { |
265 | if (bs_port < 1 || bs_port > 65535) { | 434 | syslog(LOG_WARNING, "Bootstrap node #%d: Invalid '%s': %d, should be in [%d, %d]. Skipping the node.\n", i, NAME_PORT, bs_port, MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); |
266 | syslog(LOG_WARNING, "Bootstrap node #%d: Invalid '%s': %d. Skipping the node.\n", i, NAME_PORT, bs_port); | ||
267 | goto next; | 435 | goto next; |
268 | } | 436 | } |
269 | 437 | ||
@@ -280,9 +448,9 @@ int bootstrap_from_config(char *cfg_file_path, DHT *dht, int enable_ipv6) | |||
280 | syslog(LOG_DEBUG, "Successfully added bootstrap node #%d: %s:%d %s\n", i, bs_address, bs_port, bs_public_key); | 448 | syslog(LOG_DEBUG, "Successfully added bootstrap node #%d: %s:%d %s\n", i, bs_address, bs_port, bs_public_key); |
281 | 449 | ||
282 | next: | 450 | next: |
283 | // config_setting_lookup_string() allocates string inside and doesn't allow us to free it | 451 | // config_setting_lookup_string() allocates string inside and doesn't allow us to free it direcly |
284 | // so in order to reuse `bs_public_key` and `bs_address` we have to remove the element | 452 | // though it's freed when the element is removed, so we free it right away in order to keep memory |
285 | // which will cause libconfig to free allocated strings | 453 | // consumption minimal |
286 | config_setting_remove_elem(node_list, 0); | 454 | config_setting_remove_elem(node_list, 0); |
287 | i++; | 455 | i++; |
288 | } | 456 | } |
@@ -296,17 +464,13 @@ next: | |||
296 | 464 | ||
297 | void print_public_key(uint8_t *public_key) | 465 | void print_public_key(uint8_t *public_key) |
298 | { | 466 | { |
299 | char buffer[64 + 1]; | 467 | char buffer[2*crypto_box_PUBLICKEYBYTES + 1]; |
300 | int index = 0; | 468 | int index = 0; |
301 | 469 | ||
302 | int i; | 470 | int i; |
303 | 471 | ||
304 | for (i = 0; i < 32; i++) { | 472 | for (i = 0; i < crypto_box_PUBLICKEYBYTES; i++) { |
305 | if (public_key[i] < 16) { | 473 | index += sprintf(buffer + index, "%02hhX", public_key[i]); |
306 | index += sprintf(buffer + index, "0"); | ||
307 | } | ||
308 | |||
309 | index += sprintf(buffer + index, "%hhX", public_key[i]); | ||
310 | } | 474 | } |
311 | 475 | ||
312 | syslog(LOG_INFO, "Public Key: %s\n", buffer); | 476 | syslog(LOG_INFO, "Public Key: %s\n", buffer); |
@@ -318,6 +482,8 @@ int main(int argc, char *argv[]) | |||
318 | { | 482 | { |
319 | openlog(DAEMON_NAME, LOG_NOWAIT | LOG_PID, LOG_DAEMON); | 483 | openlog(DAEMON_NAME, LOG_NOWAIT | LOG_PID, LOG_DAEMON); |
320 | 484 | ||
485 | syslog(LOG_INFO, "Running \"%s\" version %lu.\n", DAEMON_NAME, DAEMON_VERSION_NUMBER); | ||
486 | |||
321 | if (argc < 2) { | 487 | if (argc < 2) { |
322 | syslog(LOG_ERR, "Please specify a path to a configuration file as the first argument. Exiting.\n"); | 488 | syslog(LOG_ERR, "Please specify a path to a configuration file as the first argument. Exiting.\n"); |
323 | return 1; | 489 | return 1; |
@@ -328,30 +494,33 @@ int main(int argc, char *argv[]) | |||
328 | int port; | 494 | int port; |
329 | int enable_ipv6; | 495 | int enable_ipv6; |
330 | int enable_lan_discovery; | 496 | int enable_lan_discovery; |
497 | int enable_tcp_relay; | ||
498 | uint16_t *tcp_relay_ports; | ||
499 | int tcp_relay_port_count; | ||
500 | int enable_motd; | ||
501 | char *motd; | ||
331 | 502 | ||
332 | if (get_general_config(cfg_file_path, &pid_file_path, &keys_file_path, &port, &enable_ipv6, &enable_lan_discovery)) { | 503 | if (get_general_config(cfg_file_path, &pid_file_path, &keys_file_path, &port, &enable_ipv6, &enable_lan_discovery, &enable_tcp_relay, &tcp_relay_ports, &tcp_relay_port_count, &enable_motd, &motd)) { |
333 | syslog(LOG_DEBUG, "General config read successfully\n"); | 504 | syslog(LOG_DEBUG, "General config read successfully\n"); |
334 | } else { | 505 | } else { |
335 | syslog(LOG_ERR, "Couldn't read config file: %s. Exiting.\n", cfg_file_path); | 506 | syslog(LOG_ERR, "Couldn't read config file: %s. Exiting.\n", cfg_file_path); |
336 | return 1; | 507 | return 1; |
337 | } | 508 | } |
338 | 509 | ||
339 | // not (1 <= port <= 65535) | 510 | if (port < MIN_ALLOWED_PORT || port > MAX_ALLOWED_PORT) { |
340 | if (port < 1 || port > 65535) { | 511 | syslog(LOG_ERR, "Invalid port: %d, should be in [%d, %d]. Exiting.\n", port, MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); |
341 | syslog(LOG_ERR, "Invalid port: %d, must be 1 <= port <= 65535. Exiting.\n", port); | ||
342 | return 1; | 512 | return 1; |
343 | } | 513 | } |
344 | 514 | ||
345 | // Check if the PID file exists | 515 | // Check if the PID file exists |
346 | if (fopen(pid_file_path, "r")) { | 516 | if (fopen(pid_file_path, "r")) { |
347 | syslog(LOG_ERR, "Another instance of the daemon is already running, PID file %s exists. Exiting.\n", pid_file_path); | 517 | syslog(LOG_ERR, "Another instance of the daemon is already running, PID file %s exists.\n", pid_file_path); |
348 | return 1; | ||
349 | } | 518 | } |
350 | 519 | ||
351 | IP ip; | 520 | IP ip; |
352 | ip_init(&ip, enable_ipv6); | 521 | ip_init(&ip, enable_ipv6); |
353 | 522 | ||
354 | DHT *dht = new_DHT(new_net_crypto(new_networking(ip, port))); | 523 | DHT *dht = new_DHT(new_networking(ip, port)); |
355 | 524 | ||
356 | if (dht == NULL) { | 525 | if (dht == NULL) { |
357 | syslog(LOG_ERR, "Couldn't initialize Tox DHT instance. Exiting.\n"); | 526 | syslog(LOG_ERR, "Couldn't initialize Tox DHT instance. Exiting.\n"); |
@@ -366,31 +535,58 @@ int main(int argc, char *argv[]) | |||
366 | return 1; | 535 | return 1; |
367 | } | 536 | } |
368 | 537 | ||
369 | if (enable_lan_discovery) { | 538 | if (enable_motd) { |
370 | LANdiscovery_init(dht); | 539 | if (bootstrap_set_callbacks(dht->net, DAEMON_VERSION_NUMBER, (uint8_t*)motd, strlen(motd) + 1) == 0) { |
540 | syslog(LOG_DEBUG, "Set MOTD successfully.\n"); | ||
541 | } else { | ||
542 | syslog(LOG_ERR, "Couldn't set MOTD: %s. Exiting.\n", motd); | ||
543 | return 1; | ||
544 | } | ||
545 | free(motd); | ||
371 | } | 546 | } |
372 | 547 | ||
373 | if (manage_keys(dht, keys_file_path)) { | 548 | if (manage_keys(dht, keys_file_path)) { |
374 | syslog(LOG_DEBUG, "Keys are managed successfully\n"); | 549 | syslog(LOG_DEBUG, "Keys are managed successfully.\n"); |
375 | } else { | 550 | } else { |
376 | syslog(LOG_ERR, "Couldn't read/write: %s. Exiting.\n", keys_file_path); | 551 | syslog(LOG_ERR, "Couldn't read/write: %s. Exiting.\n", keys_file_path); |
377 | return 1; | 552 | return 1; |
378 | } | 553 | } |
379 | 554 | ||
555 | TCP_Server *tcp_server = NULL; | ||
556 | |||
557 | if (enable_tcp_relay) { | ||
558 | if (tcp_relay_port_count == 0) { | ||
559 | syslog(LOG_ERR, "No TCP relay ports read. Exiting.\n"); | ||
560 | return 1; | ||
561 | } | ||
562 | |||
563 | tcp_server = new_TCP_server(enable_ipv6, tcp_relay_port_count, tcp_relay_ports, dht->self_public_key, dht->self_secret_key, onion); | ||
564 | |||
565 | // tcp_relay_port_count != 0 at this point | ||
566 | free(tcp_relay_ports); | ||
567 | |||
568 | if (tcp_server != NULL) { | ||
569 | syslog(LOG_DEBUG, "Initialized Tox TCP server successfully.\n"); | ||
570 | } else { | ||
571 | syslog(LOG_ERR, "Couldn't initialize Tox TCP server. Exiting.\n"); | ||
572 | return 1; | ||
573 | } | ||
574 | } | ||
575 | |||
380 | if (bootstrap_from_config(cfg_file_path, dht, enable_ipv6)) { | 576 | if (bootstrap_from_config(cfg_file_path, dht, enable_ipv6)) { |
381 | syslog(LOG_DEBUG, "List of bootstrap nodes read successfully\n"); | 577 | syslog(LOG_DEBUG, "List of bootstrap nodes read successfully.\n"); |
382 | } else { | 578 | } else { |
383 | syslog(LOG_ERR, "Couldn't read list of bootstrap nodes in %s. Exiting.\n", cfg_file_path); | 579 | syslog(LOG_ERR, "Couldn't read list of bootstrap nodes in %s. Exiting.\n", cfg_file_path); |
384 | return 1; | 580 | return 1; |
385 | } | 581 | } |
386 | 582 | ||
387 | print_public_key(dht->c->self_public_key); | 583 | print_public_key(dht->self_public_key); |
388 | 584 | ||
389 | // Write the PID file | 585 | // Write the PID file |
390 | FILE *pidf = fopen(pid_file_path, "w"); | 586 | FILE *pidf = fopen(pid_file_path, "a+"); |
391 | 587 | ||
392 | if (pidf == NULL) { | 588 | if (pidf == NULL) { |
393 | syslog(LOG_ERR, "Can't open the PID file for writing: %s. Exiting.\n", pid_file_path); | 589 | syslog(LOG_ERR, "Couldn't open the PID file for writing: %s. Exiting.\n", pid_file_path); |
394 | return 1; | 590 | return 1; |
395 | } | 591 | } |
396 | 592 | ||
@@ -407,7 +603,7 @@ int main(int argc, char *argv[]) | |||
407 | } | 603 | } |
408 | 604 | ||
409 | if (pid > 0) { | 605 | if (pid > 0) { |
410 | fprintf(pidf, "%d\n", pid); | 606 | fprintf(pidf, "%d ", pid); |
411 | fclose(pidf); | 607 | fclose(pidf); |
412 | syslog(LOG_DEBUG, "Forked successfully: PID: %d.\n", pid); | 608 | syslog(LOG_DEBUG, "Forked successfully: PID: %d.\n", pid); |
413 | return 0; | 609 | return 0; |
@@ -438,6 +634,11 @@ int main(int argc, char *argv[]) | |||
438 | 634 | ||
439 | int waiting_for_dht_connection = 1; | 635 | int waiting_for_dht_connection = 1; |
440 | 636 | ||
637 | if (enable_lan_discovery) { | ||
638 | LANdiscovery_init(dht); | ||
639 | syslog(LOG_DEBUG, "Initialized LAN discovery.\n"); | ||
640 | } | ||
641 | |||
441 | while (1) { | 642 | while (1) { |
442 | do_DHT(dht); | 643 | do_DHT(dht); |
443 | 644 | ||
@@ -446,6 +647,10 @@ int main(int argc, char *argv[]) | |||
446 | last_LANdiscovery = unix_time(); | 647 | last_LANdiscovery = unix_time(); |
447 | } | 648 | } |
448 | 649 | ||
650 | if (enable_tcp_relay) { | ||
651 | do_TCP_server(tcp_server); | ||
652 | } | ||
653 | |||
449 | networking_poll(dht->net); | 654 | networking_poll(dht->net); |
450 | 655 | ||
451 | if (waiting_for_dht_connection && DHT_isconnected(dht)) { | 656 | if (waiting_for_dht_connection && DHT_isconnected(dht)) { |
diff --git a/other/bootstrap_daemon/tox_bootstrap_daemon.sh b/other/bootstrap_daemon/tox_bootstrap_daemon.sh index 83d9a119..787498ec 100644 --- a/other/bootstrap_daemon/tox_bootstrap_daemon.sh +++ b/other/bootstrap_daemon/tox_bootstrap_daemon.sh | |||
@@ -11,14 +11,14 @@ | |||
11 | 11 | ||
12 | # PATH should only include /usr/* if it runs after the mountnfs.sh script | 12 | # PATH should only include /usr/* if it runs after the mountnfs.sh script |
13 | PATH=/sbin:/usr/sbin:/bin:/usr/bin | 13 | PATH=/sbin:/usr/sbin:/bin:/usr/bin |
14 | DESC="Tox DHT bootstrap server daemon" | 14 | DESC="Tox DHT bootstrap daemon" |
15 | NAME=tox_bootstrap_daemon | 15 | NAME=tox_bootstrap_daemon |
16 | # You may want to change USER if you are using it anywhere else | 16 | # You may want to change USER if you are using it anywhere else |
17 | USER=tom | 17 | USER=tom |
18 | CFG=/home/$USER/.$NAME/conf | 18 | CFG=/home/$USER/.$NAME/conf |
19 | DAEMON=/home/$USER/$NAME | 19 | DAEMON=/home/$USER/.$NAME/$NAME |
20 | DAEMON_ARGS="$CFG" | 20 | DAEMON_ARGS="$CFG" |
21 | PIDFILE=/home/$USER/.$NAME/pid | 21 | PIDFILE=/home/$USER/.$NAME/."$NAME".pid |
22 | SCRIPTNAME=/etc/init.d/$NAME | 22 | SCRIPTNAME=/etc/init.d/$NAME |
23 | 23 | ||
24 | # Exit if the package is not installed | 24 | # Exit if the package is not installed |
diff --git a/other/fun/cracker.c b/other/fun/cracker.c index 9921df31..7b7000de 100644 --- a/other/fun/cracker.c +++ b/other/fun/cracker.c | |||
@@ -32,7 +32,7 @@ void print_key(uint8_t *client_id) | |||
32 | int main(int argc, char *argv[]) | 32 | int main(int argc, char *argv[]) |
33 | { | 33 | { |
34 | if (argc < 2) { | 34 | if (argc < 2) { |
35 | printf("usage: ./cracker public_key(or beggining of one in hex format)\n"); | 35 | printf("usage: ./cracker public_key(or beginning of one in hex format)\n"); |
36 | return 0; | 36 | return 0; |
37 | } | 37 | } |
38 | 38 | ||
diff --git a/toxav/Makefile.inc b/toxav/Makefile.inc index 2d48d210..65098f1f 100644 --- a/toxav/Makefile.inc +++ b/toxav/Makefile.inc | |||
@@ -34,5 +34,4 @@ libtoxav_la_LIBADD = libtoxcore.la \ | |||
34 | $(PTHREAD_LIBS) \ | 34 | $(PTHREAD_LIBS) \ |
35 | $(AV_LIBS) | 35 | $(AV_LIBS) |
36 | 36 | ||
37 | |||
38 | endif \ No newline at end of file | 37 | endif \ No newline at end of file |
diff --git a/toxav/msi.c b/toxav/msi.c index aab13471..8e12e363 100755 --- a/toxav/msi.c +++ b/toxav/msi.c | |||
@@ -207,7 +207,22 @@ static inline__ const uint8_t *stringify_response ( MSIResponse response ) | |||
207 | } | 207 | } |
208 | 208 | ||
209 | 209 | ||
210 | <<<<<<< HEAD | ||
210 | 211 | ||
212 | ======= | ||
213 | #define ON_HEADER(iterator, header, descriptor, size_const) \ | ||
214 | ( memcmp(iterator, descriptor, size_const) == 0){ /* Okay */ \ | ||
215 | iterator += size_const; /* Set iterator at beginning of value part */ \ | ||
216 | if ( *iterator != value_byte ) { assert(0); return -1; }\ | ||
217 | iterator ++;\ | ||
218 | uint16_t _value_size = (uint16_t) *(iterator ) << 8 | \ | ||
219 | (uint16_t) *(iterator + 1); \ | ||
220 | header.header_value = calloc(sizeof(uint8_t), _value_size); \ | ||
221 | header.size = _value_size; \ | ||
222 | memcpy(header.header_value, iterator + 2, _value_size);\ | ||
223 | iterator = iterator + 2 + _value_size; /* set iterator at new header or end_byte */ \ | ||
224 | } | ||
225 | >>>>>>> upstream/master | ||
211 | 226 | ||
212 | /** | 227 | /** |
213 | * @brief Parse raw 'data' received from socket into MSIMessage struct. | 228 | * @brief Parse raw 'data' received from socket into MSIMessage struct. |
@@ -1085,11 +1100,11 @@ int handle_recv_start ( MSISession *session, MSICall* call, MSIMessage *msg ) | |||
1085 | 1100 | ||
1086 | call->state = call_active; | 1101 | call->state = call_active; |
1087 | 1102 | ||
1088 | call->key_peer = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES ); | 1103 | call->key_peer = calloc ( sizeof ( uint8_t ), crypto_box_KEYBYTES ); |
1089 | memcpy ( call->key_peer, msg->cryptokey.header_value, crypto_secretbox_KEYBYTES ); | 1104 | memcpy ( call->key_peer, msg->cryptokey.header_value, crypto_box_KEYBYTES ); |
1090 | 1105 | ||
1091 | call->nonce_peer = calloc ( sizeof ( uint8_t ), crypto_secretbox_NONCEBYTES ); | 1106 | call->nonce_peer = calloc ( sizeof ( uint8_t ), crypto_box_NONCEBYTES ); |
1092 | memcpy ( call->nonce_peer, msg->nonce.header_value, crypto_secretbox_NONCEBYTES ); | 1107 | memcpy ( call->nonce_peer, msg->nonce.header_value, crypto_box_NONCEBYTES ); |
1093 | 1108 | ||
1094 | flush_peer_type ( call, msg, 0 ); | 1109 | flush_peer_type ( call, msg, 0 ); |
1095 | 1110 | ||
@@ -1183,6 +1198,7 @@ int handle_recv_starting ( MSISession *session, MSICall* call, MSIMessage *msg ) | |||
1183 | } | 1198 | } |
1184 | 1199 | ||
1185 | /* Generate local key/nonce to send */ | 1200 | /* Generate local key/nonce to send */ |
1201 | <<<<<<< HEAD | ||
1186 | call->key_local = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES ); | 1202 | call->key_local = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES ); |
1187 | new_symmetric_key ( call->key_local ); | 1203 | new_symmetric_key ( call->key_local ); |
1188 | 1204 | ||
@@ -1195,13 +1211,33 @@ int handle_recv_starting ( MSISession *session, MSICall* call, MSIMessage *msg ) | |||
1195 | 1211 | ||
1196 | call->nonce_peer = calloc ( sizeof ( uint8_t ), crypto_secretbox_NONCEBYTES ); | 1212 | call->nonce_peer = calloc ( sizeof ( uint8_t ), crypto_secretbox_NONCEBYTES ); |
1197 | memcpy ( call->nonce_peer, msg->nonce.header_value, crypto_secretbox_NONCEBYTES ); | 1213 | memcpy ( call->nonce_peer, msg->nonce.header_value, crypto_secretbox_NONCEBYTES ); |
1214 | ======= | ||
1215 | session->call->key_local = calloc ( sizeof ( uint8_t ), crypto_box_KEYBYTES ); | ||
1216 | new_symmetric_key ( session->call->key_local ); | ||
1217 | |||
1218 | session->call->nonce_local = calloc ( sizeof ( uint8_t ), crypto_box_NONCEBYTES ); | ||
1219 | new_nonce ( session->call->nonce_local ); | ||
1220 | |||
1221 | /* Save peer key/nonce */ | ||
1222 | session->call->key_peer = calloc ( sizeof ( uint8_t ), crypto_box_KEYBYTES ); | ||
1223 | memcpy ( session->call->key_peer, msg->cryptokey.header_value, crypto_box_KEYBYTES ); | ||
1224 | |||
1225 | session->call->nonce_peer = calloc ( sizeof ( uint8_t ), crypto_box_NONCEBYTES ); | ||
1226 | memcpy ( session->call->nonce_peer, msg->nonce.header_value, crypto_box_NONCEBYTES ); | ||
1227 | >>>>>>> upstream/master | ||
1198 | 1228 | ||
1199 | call->state = call_active; | 1229 | call->state = call_active; |
1200 | 1230 | ||
1201 | MSIMessage *_msg_start = msi_new_message ( TYPE_REQUEST, stringify_request ( start ) ); | 1231 | MSIMessage *_msg_start = msi_new_message ( TYPE_REQUEST, stringify_request ( start ) ); |
1232 | <<<<<<< HEAD | ||
1202 | msi_msg_set_cryptokey ( _msg_start, call->key_local, crypto_secretbox_KEYBYTES ); | 1233 | msi_msg_set_cryptokey ( _msg_start, call->key_local, crypto_secretbox_KEYBYTES ); |
1203 | msi_msg_set_nonce ( _msg_start, call->nonce_local, crypto_secretbox_NONCEBYTES ); | 1234 | msi_msg_set_nonce ( _msg_start, call->nonce_local, crypto_secretbox_NONCEBYTES ); |
1204 | send_message ( session, call, _msg_start, msg->friend_id ); | 1235 | send_message ( session, call, _msg_start, msg->friend_id ); |
1236 | ======= | ||
1237 | msi_msg_set_cryptokey ( _msg_start, session->call->key_local, crypto_box_KEYBYTES ); | ||
1238 | msi_msg_set_nonce ( _msg_start, session->call->nonce_local, crypto_box_NONCEBYTES ); | ||
1239 | send_message ( session, _msg_start, msg->friend_id ); | ||
1240 | >>>>>>> upstream/master | ||
1205 | free_message ( _msg_start ); | 1241 | free_message ( _msg_start ); |
1206 | 1242 | ||
1207 | flush_peer_type ( call, msg, 0 ); | 1243 | flush_peer_type ( call, msg, 0 ); |
@@ -1593,6 +1629,7 @@ int msi_answer ( MSISession* session, int32_t call_index, MSICallType call_type | |||
1593 | 1629 | ||
1594 | /* Now set the local encryption key and pass it with STARTING message */ | 1630 | /* Now set the local encryption key and pass it with STARTING message */ |
1595 | 1631 | ||
1632 | <<<<<<< HEAD | ||
1596 | session->calls[call_index]->key_local = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES ); | 1633 | session->calls[call_index]->key_local = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES ); |
1597 | new_symmetric_key ( session->calls[call_index]->key_local ); | 1634 | new_symmetric_key ( session->calls[call_index]->key_local ); |
1598 | 1635 | ||
@@ -1601,6 +1638,16 @@ int msi_answer ( MSISession* session, int32_t call_index, MSICallType call_type | |||
1601 | 1638 | ||
1602 | msi_msg_set_cryptokey ( _msg_starting, session->calls[call_index]->key_local, crypto_secretbox_KEYBYTES ); | 1639 | msi_msg_set_cryptokey ( _msg_starting, session->calls[call_index]->key_local, crypto_secretbox_KEYBYTES ); |
1603 | msi_msg_set_nonce ( _msg_starting, session->calls[call_index]->nonce_local, crypto_secretbox_NONCEBYTES ); | 1640 | msi_msg_set_nonce ( _msg_starting, session->calls[call_index]->nonce_local, crypto_secretbox_NONCEBYTES ); |
1641 | ======= | ||
1642 | session->call->key_local = calloc ( sizeof ( uint8_t ), crypto_box_KEYBYTES ); | ||
1643 | new_symmetric_key ( session->call->key_local ); | ||
1644 | |||
1645 | session->call->nonce_local = calloc ( sizeof ( uint8_t ), crypto_box_NONCEBYTES ); | ||
1646 | new_nonce ( session->call->nonce_local ); | ||
1647 | |||
1648 | msi_msg_set_cryptokey ( _msg_starting, session->call->key_local, crypto_box_KEYBYTES ); | ||
1649 | msi_msg_set_nonce ( _msg_starting, session->call->nonce_local, crypto_box_NONCEBYTES ); | ||
1650 | >>>>>>> upstream/master | ||
1604 | 1651 | ||
1605 | send_message ( session, session->calls[call_index], _msg_starting, session->calls[call_index]->peers[session->calls[call_index]->peer_count - 1] ); | 1652 | send_message ( session, session->calls[call_index], _msg_starting, session->calls[call_index]->peers[session->calls[call_index]->peer_count - 1] ); |
1606 | free_message ( _msg_starting ); | 1653 | free_message ( _msg_starting ); |
@@ -1689,4 +1736,4 @@ int msi_stopcall ( MSISession* session, int32_t call_index ) | |||
1689 | terminate_call ( session, session->calls[call_index] ); | 1736 | terminate_call ( session, session->calls[call_index] ); |
1690 | 1737 | ||
1691 | return 0; | 1738 | return 0; |
1692 | } \ No newline at end of file | 1739 | } |
diff --git a/toxav/msi.h b/toxav/msi.h index e9e1b4d7..2d4929a6 100755 --- a/toxav/msi.h +++ b/toxav/msi.h | |||
@@ -72,21 +72,22 @@ typedef struct _MSICall { /* Call info structure */ | |||
72 | 72 | ||
73 | uint8_t id[CALL_ID_LEN]; /* Random value identifying the call */ | 73 | uint8_t id[CALL_ID_LEN]; /* Random value identifying the call */ |
74 | 74 | ||
75 | uint8_t *key_local; /* The key for encryption */ | 75 | uint8_t *key_local; /* The key for encryption */ |
76 | uint8_t *key_peer; /* The key for decryption */ | 76 | uint8_t *key_peer; /* The key for decryption */ |
77 | 77 | ||
78 | uint8_t *nonce_local; /* Local nonce */ | 78 | uint8_t *nonce_local; /* Local nonce */ |
79 | uint8_t *nonce_peer; /* Peer nonce */ | 79 | uint8_t *nonce_peer; /* Peer nonce */ |
80 | 80 | ||
81 | int ringing_tout_ms; /* Ringing timeout in ms */ | 81 | int ringing_tout_ms; /* Ringing timeout in ms */ |
82 | 82 | ||
83 | int request_timer_id; /* Timer id for outgoing request/action */ | 83 | int request_timer_id; /* Timer id for outgoing request/action */ |
84 | int ringing_timer_id; /* Timer id for ringing timeout */ | 84 | int ringing_timer_id; /* Timer id for ringing timeout */ |
85 | 85 | ||
86 | |||
86 | pthread_mutex_t mutex; /* It's to be assumed that call will have | 87 | pthread_mutex_t mutex; /* It's to be assumed that call will have |
87 | * separate thread so add mutex | 88 | * separate thread so add mutex |
88 | */ | 89 | */ |
89 | uint32_t *peers; | 90 | uint32_t *peers; |
90 | uint16_t peer_count; | 91 | uint16_t peer_count; |
91 | 92 | ||
92 | int32_t call_idx; /* Index of this call in MSISession */ | 93 | int32_t call_idx; /* Index of this call in MSISession */ |
diff --git a/toxav/phone.c b/toxav/phone.c new file mode 100755 index 00000000..74f743f7 --- /dev/null +++ b/toxav/phone.c | |||
@@ -0,0 +1,1460 @@ | |||
1 | /** phone.c | ||
2 | * | ||
3 | * NOTE NOTE NOTE NOTE NOTE NOTE | ||
4 | * | ||
5 | * This file is for testing/reference purposes only, hence | ||
6 | * it is _poorly_ designed and it does not fully reflect the | ||
7 | * quaility of msi nor rtp. Although toxmsi* and toxrtp* are tested | ||
8 | * there is always possibility of crashes. If crash occures, | ||
9 | * contact me ( mannol ) on either irc channel #tox-dev @ freenode.net:6667 | ||
10 | * or eniz_vukovic@hotmail.com | ||
11 | * | ||
12 | * NOTE NOTE NOTE NOTE NOTE NOTE | ||
13 | * | ||
14 | * Copyright (C) 2013 Tox project All Rights Reserved. | ||
15 | * | ||
16 | * This file is part of Tox. | ||
17 | * | ||
18 | * Tox is free software: you can redistribute it and/or modify | ||
19 | * it under the terms of the GNU General Public License as published by | ||
20 | * the Free Software Foundation, either version 3 of the License, or | ||
21 | * (at your option) any later version. | ||
22 | * | ||
23 | * Tox is distributed in the hope that it will be useful, | ||
24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
26 | * GNU General Public License for more details. | ||
27 | * | ||
28 | * You should have received a copy of the GNU General Public License | ||
29 | * along with Tox. If not, see <http://www.gnu.org/licenses/>. | ||
30 | * | ||
31 | */ | ||
32 | |||
33 | #ifdef HAVE_CONFIG_H | ||
34 | #include "config.h" | ||
35 | #endif /* HAVE_CONFIG_H */ | ||
36 | |||
37 | #define _BSD_SOURCE | ||
38 | |||
39 | #include <stdio.h> | ||
40 | #include <string.h> | ||
41 | #include <stdlib.h> | ||
42 | #include <stdarg.h> | ||
43 | #include <unistd.h> | ||
44 | #include <assert.h> | ||
45 | #include <math.h> | ||
46 | #include <pthread.h> | ||
47 | |||
48 | //#include "media.h" | ||
49 | #include "toxav.h" | ||
50 | #include "event.h" | ||
51 | #include "../toxcore/tox.h" | ||
52 | |||
53 | #define AUDIO_FRAME_SIZE (av_DefaultSettings.audio_sample_rate * av_DefaultSettings.audio_frame_duration / 1000) | ||
54 | |||
55 | #ifdef TOX_FFMPEG | ||
56 | /* Video encoding/decoding */ | ||
57 | #include <libavcodec/avcodec.h> | ||
58 | #include <libavformat/avformat.h> | ||
59 | #include <libswscale/swscale.h> | ||
60 | #include <libavdevice/avdevice.h> | ||
61 | #include <libavutil/opt.h> | ||
62 | #endif | ||
63 | |||
64 | #include <AL/al.h> | ||
65 | #include <AL/alc.h> | ||
66 | #include <SDL/SDL.h> | ||
67 | #include <SDL/SDL_thread.h> | ||
68 | |||
69 | /* the quit event for SDL */ | ||
70 | #define FF_QUIT_EVENT (SDL_USEREVENT + 2) | ||
71 | |||
72 | #ifdef __linux__ | ||
73 | #define VIDEO_DRIVER "video4linux2" | ||
74 | #define DEFAULT_WEBCAM "/dev/video0" | ||
75 | #endif | ||
76 | |||
77 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) | ||
78 | #define VIDEO_DRIVER "vfwcap" | ||
79 | #define DEFAULT_WEBCAM "0" | ||
80 | #endif | ||
81 | |||
82 | |||
83 | /* Define client version */ | ||
84 | #define _USERAGENT "v.0.3.0" | ||
85 | |||
86 | |||
87 | struct SDL_Surface *screen; | ||
88 | |||
89 | typedef struct { | ||
90 | struct SDL_Overlay *bmp; | ||
91 | int width, height; | ||
92 | } VideoPicture; | ||
93 | |||
94 | |||
95 | typedef struct av_friend_s { | ||
96 | int _id; | ||
97 | int _active; /* 0=false; 1=true; */ | ||
98 | } av_friend_t; | ||
99 | |||
100 | typedef struct av_session_s { | ||
101 | /* Encoding/decoding/capturing/playing */ | ||
102 | ToxAv *av; | ||
103 | |||
104 | VideoPicture video_picture; | ||
105 | struct ALCdevice *audio_capture_device; | ||
106 | |||
107 | /* context for converting image format to something SDL can use*/ | ||
108 | struct SwsContext *sws_SDL_r_ctx; | ||
109 | |||
110 | /* context for converting webcam image format to something the video encoder can use */ | ||
111 | struct SwsContext *sws_ctx; | ||
112 | |||
113 | /* Thread running control */ | ||
114 | int running_decaud, running_encaud, | ||
115 | running_decvid, running_encvid; | ||
116 | |||
117 | pthread_mutex_t _mutex; | ||
118 | |||
119 | Tox *_messenger; | ||
120 | av_friend_t *_friends; | ||
121 | int _friend_cout; | ||
122 | char _my_public_id[200]; | ||
123 | #ifdef TOX_FFMPEG | ||
124 | AVInputFormat *video_input_format; | ||
125 | AVFormatContext *video_format_ctx; | ||
126 | uint8_t video_stream; | ||
127 | AVCodecContext *webcam_decoder_ctx; | ||
128 | AVCodec *webcam_decoder; | ||
129 | #endif | ||
130 | } av_session_t; | ||
131 | av_session_t *_phone; | ||
132 | |||
133 | void av_allocate_friend(av_session_t *_phone, int _id, int _active) | ||
134 | { | ||
135 | static int _new_id = 0; | ||
136 | |||
137 | if ( !_phone->_friends ) { | ||
138 | _phone->_friends = calloc(sizeof(av_friend_t), 1); | ||
139 | _phone->_friend_cout = 1; | ||
140 | } else { | ||
141 | _phone->_friend_cout ++; | ||
142 | _phone->_friends = realloc(_phone->_friends, sizeof(av_friend_t) * _phone->_friend_cout); | ||
143 | } | ||
144 | |||
145 | if ( _id == -1 ) { | ||
146 | _phone->_friends->_id = _new_id; | ||
147 | _new_id ++; | ||
148 | } else _phone->_friends->_id = _id; | ||
149 | |||
150 | _phone->_friends->_active = _active; | ||
151 | } | ||
152 | av_friend_t *av_get_friend(av_session_t *_phone, int _id) | ||
153 | { | ||
154 | av_friend_t *_friends = _phone->_friends; | ||
155 | |||
156 | if ( !_friends ) return NULL; | ||
157 | |||
158 | int _it = 0; | ||
159 | |||
160 | for (; _it < _phone->_friend_cout; _it ++) | ||
161 | if ( _friends[_it]._id == _id ) | ||
162 | return _friends + _it; | ||
163 | |||
164 | return NULL; | ||
165 | } | ||
166 | |||
167 | |||
168 | /***************** MISC *****************/ | ||
169 | |||
170 | void INFO (const char *_format, ...) | ||
171 | { | ||
172 | printf("\r[!] "); | ||
173 | va_list _arg; | ||
174 | va_start (_arg, _format); | ||
175 | vfprintf (stdout, _format, _arg); | ||
176 | va_end (_arg); | ||
177 | printf("\n\r >> "); | ||
178 | fflush(stdout); | ||
179 | } | ||
180 | |||
181 | unsigned char *hex_string_to_bin(char hex_string[]) | ||
182 | { | ||
183 | size_t i, len = strlen(hex_string); | ||
184 | unsigned char *val = calloc(sizeof(unsigned char), len); | ||
185 | char *pos = hex_string; | ||
186 | |||
187 | for (i = 0; i < len; ++i, pos += 2) | ||
188 | sscanf(pos, "%2hhx", &val[i]); | ||
189 | |||
190 | return val; | ||
191 | } | ||
192 | |||
193 | int getinput( char *_buff, size_t _limit, int *_len ) | ||
194 | { | ||
195 | if ( fgets(_buff, _limit, stdin) == NULL ) | ||
196 | return -1; | ||
197 | |||
198 | *_len = strlen(_buff) - 1; | ||
199 | |||
200 | /* Get rid of newline */ | ||
201 | _buff[*_len] = '\0'; | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | char *trim_spaces ( char *buff ) | ||
207 | { | ||
208 | |||
209 | int _i = 0, _len = strlen(buff); | ||
210 | |||
211 | char *container = calloc(sizeof(char), _len); | ||
212 | int _ci = 0; | ||
213 | |||
214 | for ( ; _i < _len; _i++ ) { | ||
215 | while ( _i < _len && buff[_i] == ' ' ) | ||
216 | _i++; | ||
217 | |||
218 | if ( _i < _len ) { | ||
219 | container[_ci] = buff[_i]; | ||
220 | _ci ++; | ||
221 | } | ||
222 | } | ||
223 | |||
224 | memcpy( buff, container, _ci ); | ||
225 | buff[_ci] = '\0'; | ||
226 | free(container); | ||
227 | return buff; | ||
228 | } | ||
229 | |||
230 | #define FRADDR_TOSTR_CHUNK_LEN 8 | ||
231 | |||
232 | static void fraddr_to_str(uint8_t *id_bin, char *id_str) | ||
233 | { | ||
234 | uint i, delta = 0, pos_extra = 0, sum_extra = 0; | ||
235 | |||
236 | for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; i++) { | ||
237 | sprintf(&id_str[2 * i + delta], "%02hhX", id_bin[i]); | ||
238 | |||
239 | if ((i + 1) == TOX_CLIENT_ID_SIZE) | ||
240 | pos_extra = 2 * (i + 1) + delta; | ||
241 | |||
242 | if (i >= TOX_CLIENT_ID_SIZE) | ||
243 | sum_extra |= id_bin[i]; | ||
244 | |||
245 | if (!((i + 1) % FRADDR_TOSTR_CHUNK_LEN)) { | ||
246 | id_str[2 * (i + 1) + delta] = ' '; | ||
247 | delta++; | ||
248 | } | ||
249 | } | ||
250 | |||
251 | id_str[2 * i + delta] = 0; | ||
252 | |||
253 | if (!sum_extra) | ||
254 | id_str[pos_extra] = 0; | ||
255 | } | ||
256 | |||
257 | /********************************************* | ||
258 | ********************************************* | ||
259 | ********************************************* | ||
260 | ********************************************* | ||
261 | ********************************************* | ||
262 | ********************************************* | ||
263 | ********************************************* | ||
264 | ********************************************* | ||
265 | */ | ||
266 | |||
267 | |||
268 | /* | ||
269 | * How av stuff _should_ look like | ||
270 | */ | ||
271 | /* | ||
272 | int display_received_frame(av_session_t* _phone, vpx_image_t *image) | ||
273 | { | ||
274 | CodecState* cs = get_cs_temp(_phone->av); | ||
275 | AVPicture pict; | ||
276 | SDL_LockYUVOverlay(_phone->video_picture.bmp); | ||
277 | |||
278 | pict.data[0] = _phone->video_picture.bmp->pixels[0]; | ||
279 | pict.data[1] = _phone->video_picture.bmp->pixels[2]; | ||
280 | pict.data[2] = _phone->video_picture.bmp->pixels[1]; | ||
281 | pict.linesize[0] = _phone->video_picture.bmp->pitches[0]; | ||
282 | pict.linesize[1] = _phone->video_picture.bmp->pitches[2]; | ||
283 | pict.linesize[2] = _phone->video_picture.bmp->pitches[1]; | ||
284 | */ | ||
285 | /* Convert the image into YUV format that SDL uses *//* | ||
286 | sws_scale(_phone->sws_SDL_r_ctx, (uint8_t const * const *)r_video_frame->data, r_video_frame->linesize, 0, | ||
287 | cs->video_decoder_ctx->height, pict.data, pict.linesize ); | ||
288 | |||
289 | SDL_UnlockYUVOverlay(_phone->video_picture.bmp); | ||
290 | SDL_Rect rect; | ||
291 | rect.x = 0; | ||
292 | rect.y = 0; | ||
293 | rect.w = cs->video_decoder_ctx->width; | ||
294 | rect.h = cs->video_decoder_ctx->height; | ||
295 | SDL_DisplayYUVOverlay(_phone->video_picture.bmp, &rect); | ||
296 | return 1; | ||
297 | } | ||
298 | */ | ||
299 | #ifdef TOX_FFMPEG | ||
300 | void *encode_video_thread(void *arg) | ||
301 | { | ||
302 | INFO("Started encode video thread!"); | ||
303 | |||
304 | av_session_t *_phone = arg; | ||
305 | |||
306 | _phone->running_encvid = 1; | ||
307 | //CodecState *cs = get_cs_temp(_phone->av); | ||
308 | AVPacket pkt1, *packet = &pkt1; | ||
309 | //int p = 0; | ||
310 | //int got_packet; | ||
311 | int video_frame_finished; | ||
312 | AVFrame *s_video_frame; | ||
313 | AVFrame *webcam_frame; | ||
314 | s_video_frame = avcodec_alloc_frame(); | ||
315 | webcam_frame = avcodec_alloc_frame(); | ||
316 | //AVPacket enc_video_packet; | ||
317 | |||
318 | uint8_t *buffer; | ||
319 | int numBytes; | ||
320 | /* Determine required buffer size and allocate buffer */ | ||
321 | numBytes = avpicture_get_size(PIX_FMT_YUV420P, _phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height); | ||
322 | buffer = (uint8_t *)av_calloc(numBytes * sizeof(uint8_t), 1); | ||
323 | avpicture_fill((AVPicture *)s_video_frame, buffer, PIX_FMT_YUV420P, _phone->webcam_decoder_ctx->width, | ||
324 | _phone->webcam_decoder_ctx->height); | ||
325 | _phone->sws_ctx = sws_getContext(_phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height, | ||
326 | _phone->webcam_decoder_ctx->pix_fmt, _phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height, | ||
327 | PIX_FMT_YUV420P, | ||
328 | SWS_BILINEAR, NULL, NULL, NULL); | ||
329 | |||
330 | |||
331 | vpx_image_t *image = | ||
332 | vpx_img_alloc(NULL, VPX_IMG_FMT_I420, _phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height, 1); | ||
333 | |||
334 | //uint32_t frame_counter = 0; | ||
335 | while (_phone->running_encvid) { | ||
336 | |||
337 | if (av_read_frame(_phone->video_format_ctx, packet) < 0) { | ||
338 | printf("error reading frame\n"); | ||
339 | |||
340 | if (_phone->video_format_ctx->pb->error != 0) | ||
341 | break; | ||
342 | |||
343 | continue; | ||
344 | } | ||
345 | |||
346 | if (packet->stream_index == _phone->video_stream) { | ||
347 | if (avcodec_decode_video2(_phone->webcam_decoder_ctx, webcam_frame, &video_frame_finished, packet) < 0) { | ||
348 | printf("couldn't decode\n"); | ||
349 | continue; | ||
350 | } | ||
351 | |||
352 | av_free_packet(packet); | ||
353 | sws_scale(_phone->sws_ctx, (uint8_t const * const *)webcam_frame->data, webcam_frame->linesize, 0, | ||
354 | _phone->webcam_decoder_ctx->height, s_video_frame->data, s_video_frame->linesize); | ||
355 | /* create a new I-frame every 60 frames */ | ||
356 | //++p; | ||
357 | /* | ||
358 | if (p == 60) { | ||
359 | |||
360 | s_video_frame->pict_type = AV_PICTURE_TYPE_BI ; | ||
361 | } else if (p == 61) { | ||
362 | s_video_frame->pict_type = AV_PICTURE_TYPE_I ; | ||
363 | p = 0; | ||
364 | } else { | ||
365 | s_video_frame->pict_type = AV_PICTURE_TYPE_P ; | ||
366 | }*/ | ||
367 | |||
368 | if (video_frame_finished) { | ||
369 | memcpy(image->planes[VPX_PLANE_Y], s_video_frame->data[0], | ||
370 | s_video_frame->linesize[0] * _phone->webcam_decoder_ctx->height); | ||
371 | memcpy(image->planes[VPX_PLANE_U], s_video_frame->data[1], | ||
372 | s_video_frame->linesize[1] * _phone->webcam_decoder_ctx->height / 2); | ||
373 | memcpy(image->planes[VPX_PLANE_V], s_video_frame->data[2], | ||
374 | s_video_frame->linesize[2] * _phone->webcam_decoder_ctx->height / 2); | ||
375 | toxav_send_video (_phone->av, image); | ||
376 | //if (avcodec_encode_video2(cs->video_encoder_ctx, &enc_video_packet, s_video_frame, &got_packet) < 0) { | ||
377 | /*if (vpx_codec_encode(&cs->v_encoder, image, frame_counter, 1, 0, 0) != VPX_CODEC_OK) { | ||
378 | printf("could not encode video frame\n"); | ||
379 | continue; | ||
380 | } | ||
381 | ++frame_counter; | ||
382 | |||
383 | vpx_codec_iter_t iter = NULL; | ||
384 | vpx_codec_cx_pkt_t *pkt; | ||
385 | while( (pkt = vpx_codec_get_cx_data(&cs->v_encoder, &iter)) ) { | ||
386 | if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) | ||
387 | toxav_send_rtp_payload(_phone->av, TypeVideo, pkt->data.frame.buf, pkt->data.frame.sz); | ||
388 | }*/ | ||
389 | //if (!got_packet) { | ||
390 | // continue; | ||
391 | //} | ||
392 | |||
393 | //if (!enc_video_packet.data) fprintf(stderr, "video packet data is NULL\n"); | ||
394 | |||
395 | //toxav_send_rtp_payload(_phone->av, TypeVideo, enc_video_packet.data, enc_video_packet.size); | ||
396 | |||
397 | //av_free_packet(&enc_video_packet); | ||
398 | } | ||
399 | } else { | ||
400 | av_free_packet(packet); | ||
401 | } | ||
402 | } | ||
403 | |||
404 | vpx_img_free(image); | ||
405 | |||
406 | /* clean up codecs */ | ||
407 | //pthread_mutex_lock(&cs->ctrl_mutex); | ||
408 | av_free(buffer); | ||
409 | av_free(webcam_frame); | ||
410 | av_free(s_video_frame); | ||
411 | sws_freeContext(_phone->sws_ctx); | ||
412 | //avcodec_close(webcam_decoder_ctx); | ||
413 | //avcodec_close(cs->video_encoder_ctx); | ||
414 | //pthread_mutex_unlock(&cs->ctrl_mutex); | ||
415 | |||
416 | _phone->running_encvid = -1; | ||
417 | |||
418 | pthread_exit ( NULL ); | ||
419 | } | ||
420 | #endif | ||
421 | |||
422 | void *encode_audio_thread(void *arg) | ||
423 | { | ||
424 | INFO("Started encode audio thread!"); | ||
425 | av_session_t *_phone = arg; | ||
426 | _phone->running_encaud = 1; | ||
427 | |||
428 | int ret = 0; | ||
429 | int16_t frame[4096]; | ||
430 | int frame_size = AUDIO_FRAME_SIZE; | ||
431 | ALint sample = 0; | ||
432 | alcCaptureStart((ALCdevice *)_phone->audio_capture_device); | ||
433 | while (_phone->running_encaud) { | ||
434 | |||
435 | alcGetIntegerv((ALCdevice *)_phone->audio_capture_device, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &sample); | ||
436 | |||
437 | if (sample >= frame_size) { | ||
438 | alcCaptureSamples((ALCdevice *)_phone->audio_capture_device, frame, frame_size); | ||
439 | |||
440 | ret = toxav_send_audio(_phone->av, frame, frame_size); | ||
441 | |||
442 | if (ret < 0) printf("Could not encode or send audio packet\n"); | ||
443 | |||
444 | } else { | ||
445 | usleep(1000); | ||
446 | } | ||
447 | } | ||
448 | |||
449 | /* clean up codecs * | ||
450 | pthread_mutex_lock(&cs->ctrl_mutex);* / | ||
451 | alcCaptureStop((ALCdevice*)_phone->audio_capture_device); | ||
452 | alcCaptureCloseDevice((ALCdevice*)_phone->audio_capture_device); | ||
453 | / *pthread_mutex_unlock(&cs->ctrl_mutex);*/ | ||
454 | _phone->running_encaud = -1; | ||
455 | pthread_exit ( NULL ); | ||
456 | } | ||
457 | |||
458 | void convert_to_rgb(vpx_image_t *img, unsigned char *out) | ||
459 | { | ||
460 | const int w = img->d_w; | ||
461 | const int w2 = w / 2; | ||
462 | const int pstride = w * 3; | ||
463 | const int h = img->d_h; | ||
464 | const int h2 = h / 2; | ||
465 | |||
466 | const int strideY = img->stride[0]; | ||
467 | const int strideU = img->stride[1]; | ||
468 | const int strideV = img->stride[2]; | ||
469 | int posy, posx; | ||
470 | |||
471 | for (posy = 0; posy < h2; posy++) { | ||
472 | unsigned char *dst = out + pstride * (posy * 2); | ||
473 | unsigned char *dst2 = out + pstride * (posy * 2 + 1); | ||
474 | const unsigned char *srcY = img->planes[0] + strideY * posy * 2; | ||
475 | const unsigned char *srcY2 = img->planes[0] + strideY * (posy * 2 + 1); | ||
476 | const unsigned char *srcU = img->planes[1] + strideU * posy; | ||
477 | const unsigned char *srcV = img->planes[2] + strideV * posy; | ||
478 | |||
479 | for (posx = 0; posx < w2; posx++) { | ||
480 | unsigned char Y, U, V; | ||
481 | short R, G, B; | ||
482 | short iR, iG, iB; | ||
483 | |||
484 | U = *(srcU++); | ||
485 | V = *(srcV++); | ||
486 | iR = (351 * (V - 128)) / 256; | ||
487 | iG = - (179 * (V - 128)) / 256 - (86 * (U - 128)) / 256; | ||
488 | iB = (444 * (U - 128)) / 256; | ||
489 | |||
490 | Y = *(srcY++); | ||
491 | R = Y + iR ; | ||
492 | G = Y + iG ; | ||
493 | B = Y + iB ; | ||
494 | R = (R < 0 ? 0 : (R > 255 ? 255 : R)); | ||
495 | G = (G < 0 ? 0 : (G > 255 ? 255 : G)); | ||
496 | B = (B < 0 ? 0 : (B > 255 ? 255 : B)); | ||
497 | *(dst++) = R; | ||
498 | *(dst++) = G; | ||
499 | *(dst++) = B; | ||
500 | |||
501 | Y = *(srcY2++); | ||
502 | R = Y + iR ; | ||
503 | G = Y + iG ; | ||
504 | B = Y + iB ; | ||
505 | R = (R < 0 ? 0 : (R > 255 ? 255 : R)); | ||
506 | G = (G < 0 ? 0 : (G > 255 ? 255 : G)); | ||
507 | B = (B < 0 ? 0 : (B > 255 ? 255 : B)); | ||
508 | *(dst2++) = R; | ||
509 | *(dst2++) = G; | ||
510 | *(dst2++) = B; | ||
511 | |||
512 | Y = *(srcY++) ; | ||
513 | R = Y + iR ; | ||
514 | G = Y + iG ; | ||
515 | B = Y + iB ; | ||
516 | R = (R < 0 ? 0 : (R > 255 ? 255 : R)); | ||
517 | G = (G < 0 ? 0 : (G > 255 ? 255 : G)); | ||
518 | B = (B < 0 ? 0 : (B > 255 ? 255 : B)); | ||
519 | *(dst++) = R; | ||
520 | *(dst++) = G; | ||
521 | *(dst++) = B; | ||
522 | |||
523 | Y = *(srcY2++); | ||
524 | R = Y + iR ; | ||
525 | G = Y + iG ; | ||
526 | B = Y + iB ; | ||
527 | R = (R < 0 ? 0 : (R > 255 ? 255 : R)); | ||
528 | G = (G < 0 ? 0 : (G > 255 ? 255 : G)); | ||
529 | B = (B < 0 ? 0 : (B > 255 ? 255 : B)); | ||
530 | *(dst2++) = R; | ||
531 | *(dst2++) = G; | ||
532 | *(dst2++) = B; | ||
533 | } | ||
534 | } | ||
535 | } | ||
536 | |||
537 | #define mask32(BYTE) (*(uint32_t *)(uint8_t [4]){ [BYTE] = 0xff }) | ||
538 | |||
539 | void *decode_video_thread(void *arg) | ||
540 | { | ||
541 | INFO("Started decode video thread!"); | ||
542 | av_session_t *_phone = arg; | ||
543 | _phone->running_decvid = 1; | ||
544 | |||
545 | //CodecState *cs = get_cs_temp(_phone->av); | ||
546 | //cs->video_stream = 0; | ||
547 | |||
548 | //int recved_size; | ||
549 | //uint8_t dest[RTP_PAYLOAD_SIZE]; | ||
550 | |||
551 | //int dec_frame_finished; | ||
552 | //AVFrame *r_video_frame; | ||
553 | //r_video_frame = avcodec_alloc_frame(); | ||
554 | //AVPacket dec_video_packet; | ||
555 | //av_new_packet (&dec_video_packet, 65536); | ||
556 | int width = 0; | ||
557 | int height = 0; | ||
558 | |||
559 | while (_phone->running_decvid) { | ||
560 | //recved_size = toxav_recv_rtp_payload(_phone->av, TypeVideo, dest); | ||
561 | //if (recved_size) { | ||
562 | vpx_image_t *image = NULL; | ||
563 | |||
564 | if (toxav_recv_video(_phone->av, &image) == 0 && image) { | ||
565 | //memcpy(dec_video_packet.data, dest, recved_size); | ||
566 | //dec_video_packet.size = recved_size; | ||
567 | |||
568 | //avcodec_decode_video2(cs->video_decoder_ctx, r_video_frame, &dec_frame_finished, &dec_video_packet); | ||
569 | |||
570 | //if (dec_frame_finished) { | ||
571 | |||
572 | /* Check if size has changed */ | ||
573 | if (image->d_w != width || image->d_h != height) { | ||
574 | |||
575 | width = image->d_w; | ||
576 | height = image->d_h; | ||
577 | |||
578 | printf("w: %d h: %d \n", width, height); | ||
579 | |||
580 | screen = SDL_SetVideoMode(width, height, 0, 0); | ||
581 | |||
582 | //if (_phone->video_picture.bmp) | ||
583 | // SDL_FreeYUVOverlay(_phone->video_picture.bmp); | ||
584 | |||
585 | //_phone->video_picture.bmp = SDL_CreateYUVOverlay(width, height, SDL_YV12_OVERLAY, screen); | ||
586 | // _phone->sws_SDL_r_ctx = sws_getContext(width, height, cs->video_decoder_ctx->pix_fmt, width, height, PIX_FMT_YUV420P, | ||
587 | // SWS_BILINEAR, NULL, NULL, NULL); | ||
588 | } | ||
589 | |||
590 | uint8_t *rgb_image = malloc(width * height * 3); | ||
591 | convert_to_rgb(image, rgb_image); | ||
592 | SDL_Surface *img_surface = SDL_CreateRGBSurfaceFrom(rgb_image, width, height, 24, width * 3, mask32(0), mask32(1), | ||
593 | mask32(2), 0); | ||
594 | |||
595 | if (SDL_BlitSurface(img_surface, NULL, screen, NULL) == 0) | ||
596 | SDL_UpdateRect(screen, 0, 0, 0, 0); | ||
597 | |||
598 | /* | ||
599 | SDL_LockYUVOverlay(_phone->video_picture.bmp); | ||
600 | memcpy(_phone->video_picture.bmp->pixels[0], image->planes[VPX_PLANE_Y], _phone->video_picture.bmp->pitches[0] * height); | ||
601 | memcpy(_phone->video_picture.bmp->pixels[1], image->planes[VPX_PLANE_V], _phone->video_picture.bmp->pitches[1] * height / 2); | ||
602 | memcpy(_phone->video_picture.bmp->pixels[2], image->planes[VPX_PLANE_U], _phone->video_picture.bmp->pitches[2] * height / 2); | ||
603 | |||
604 | SDL_Rect rect; | ||
605 | rect.x = 0; | ||
606 | rect.y = 0; | ||
607 | rect.w = width; | ||
608 | rect.h = height; | ||
609 | SDL_DisplayYUVOverlay(_phone->video_picture.bmp, &rect);*/ | ||
610 | free(rgb_image); | ||
611 | //display_received_frame(_phone, image); | ||
612 | |||
613 | } //else { | ||
614 | |||
615 | /* TODO: request the sender to create a new i-frame immediately */ | ||
616 | //printf("Bad video packet\n"); | ||
617 | //} | ||
618 | //} | ||
619 | |||
620 | usleep(1000); | ||
621 | } | ||
622 | |||
623 | /* clean up codecs */ | ||
624 | //av_free(r_video_frame); | ||
625 | |||
626 | //pthread_mutex_lock(&cs->ctrl_mutex); | ||
627 | //avcodec_close(cs->video_decoder_ctx); | ||
628 | //pthread_mutex_unlock(&cs->ctrl_mutex); | ||
629 | |||
630 | _phone->running_decvid = -1; | ||
631 | |||
632 | pthread_exit ( NULL ); | ||
633 | } | ||
634 | |||
635 | void *decode_audio_thread(void *arg) | ||
636 | { | ||
637 | INFO("Started decode audio thread!"); | ||
638 | av_session_t *_phone = arg; | ||
639 | _phone->running_decaud = 1; | ||
640 | |||
641 | //int recved_size; | ||
642 | //uint8_t dest [RTP_PAYLOAD_SIZE]; | ||
643 | |||
644 | int frame_size = AUDIO_FRAME_SIZE; | ||
645 | //int data_size; | ||
646 | |||
647 | ALCdevice *dev; | ||
648 | ALCcontext *ctx; | ||
649 | ALuint source, *buffers; | ||
650 | dev = alcOpenDevice(NULL); | ||
651 | ctx = alcCreateContext(dev, NULL); | ||
652 | alcMakeContextCurrent(ctx); | ||
653 | int openal_buffers = 5; | ||
654 | |||
655 | buffers = calloc(sizeof(ALuint) * openal_buffers, 1); | ||
656 | alGenBuffers(openal_buffers, buffers); | ||
657 | alGenSources((ALuint)1, &source); | ||
658 | alSourcei(source, AL_LOOPING, AL_FALSE); | ||
659 | |||
660 | ALuint buffer; | ||
661 | ALint ready; | ||
662 | |||
663 | uint16_t zeros[frame_size]; | ||
664 | memset(zeros, 0, frame_size); | ||
665 | int16_t PCM[frame_size]; | ||
666 | |||
667 | int i; | ||
668 | |||
669 | for (i = 0; i < openal_buffers; ++i) { | ||
670 | alBufferData(buffers[i], AL_FORMAT_MONO16, zeros, frame_size, 48000); | ||
671 | } | ||
672 | |||
673 | alSourceQueueBuffers(source, openal_buffers, buffers); | ||
674 | alSourcePlay(source); | ||
675 | |||
676 | if (alGetError() != AL_NO_ERROR) { | ||
677 | fprintf(stderr, "Error starting audio\n"); | ||
678 | goto ending; | ||
679 | } | ||
680 | |||
681 | int dec_frame_len = 0; | ||
682 | |||
683 | while (_phone->running_decaud) { | ||
684 | |||
685 | alGetSourcei(source, AL_BUFFERS_PROCESSED, &ready); | ||
686 | |||
687 | if (ready <= 0) | ||
688 | continue; | ||
689 | |||
690 | dec_frame_len = toxav_recv_audio(_phone->av, frame_size, PCM); | ||
691 | |||
692 | /* Play the packet */ | ||
693 | if (dec_frame_len > 0) { | ||
694 | alSourceUnqueueBuffers(source, 1, &buffer); | ||
695 | alBufferData(buffer, AL_FORMAT_MONO16, PCM, dec_frame_len * 2 * 1, 48000); | ||
696 | int error = alGetError(); | ||
697 | |||
698 | if (error != AL_NO_ERROR) { | ||
699 | fprintf(stderr, "Error setting buffer %d\n", error); | ||
700 | break; | ||
701 | } | ||
702 | |||
703 | alSourceQueueBuffers(source, 1, &buffer); | ||
704 | |||
705 | if (alGetError() != AL_NO_ERROR) { | ||
706 | fprintf(stderr, "Error: could not buffer audio\n"); | ||
707 | break; | ||
708 | } | ||
709 | |||
710 | alGetSourcei(source, AL_SOURCE_STATE, &ready); | ||
711 | |||
712 | if (ready != AL_PLAYING) alSourcePlay(source); | ||
713 | } | ||
714 | |||
715 | usleep(1000); | ||
716 | } | ||
717 | |||
718 | |||
719 | ending: | ||
720 | /* clean up codecs */ | ||
721 | //pthread_mutex_lock(&cs->ctrl_mutex); | ||
722 | /* | ||
723 | alDeleteSources(1, &source); | ||
724 | alDeleteBuffers(openal_buffers, buffers); | ||
725 | alcMakeContextCurrent(NULL); | ||
726 | alcDestroyContext(ctx); | ||
727 | alcCloseDevice(dev); | ||
728 | */ | ||
729 | //pthread_mutex_unlock(&cs->ctrl_mutex); | ||
730 | |||
731 | _phone->running_decaud = -1; | ||
732 | |||
733 | pthread_exit ( NULL ); | ||
734 | } | ||
735 | |||
736 | |||
737 | |||
738 | void *one_threaded_audio(void *arg) | ||
739 | { | ||
740 | INFO("Started audio thread!"); | ||
741 | av_session_t *_phone = arg; | ||
742 | _phone->running_decaud = 1; | ||
743 | |||
744 | //int recved_size; | ||
745 | //uint8_t dest [RTP_PAYLOAD_SIZE]; | ||
746 | |||
747 | int frame_size = AUDIO_FRAME_SIZE; | ||
748 | |||
749 | int16_t frame[4096]; | ||
750 | ALint sample = 0; | ||
751 | alcCaptureStart((ALCdevice *)_phone->audio_capture_device); | ||
752 | |||
753 | ALCdevice *dev; | ||
754 | ALCcontext *ctx; | ||
755 | ALuint source, *buffers; | ||
756 | dev = alcOpenDevice(NULL); | ||
757 | ctx = alcCreateContext(dev, NULL); | ||
758 | alcMakeContextCurrent(ctx); | ||
759 | int openal_buffers = 5; | ||
760 | |||
761 | buffers = calloc(sizeof(ALuint) * openal_buffers, 1); | ||
762 | alGenBuffers(openal_buffers, buffers); | ||
763 | alGenSources((ALuint)1, &source); | ||
764 | alSourcei(source, AL_LOOPING, AL_FALSE); | ||
765 | |||
766 | ALuint buffer; | ||
767 | ALint ready; | ||
768 | |||
769 | uint16_t zeros[frame_size]; | ||
770 | memset(zeros, 0, frame_size); | ||
771 | int16_t PCM[frame_size]; | ||
772 | |||
773 | int i; | ||
774 | |||
775 | for (i = 0; i < openal_buffers; ++i) { | ||
776 | alBufferData(buffers[i], AL_FORMAT_MONO16, zeros, frame_size, 48000); | ||
777 | } | ||
778 | |||
779 | alSourceQueueBuffers(source, openal_buffers, buffers); | ||
780 | alSourcePlay(source); | ||
781 | |||
782 | if (alGetError() != AL_NO_ERROR) { | ||
783 | fprintf(stderr, "Error starting audio\n"); | ||
784 | goto ending; | ||
785 | } | ||
786 | |||
787 | int dec_frame_len; | ||
788 | |||
789 | while (_phone->running_decaud) { | ||
790 | |||
791 | // combo | ||
792 | alcGetIntegerv((ALCdevice *)_phone->audio_capture_device, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &sample); | ||
793 | |||
794 | // record and send | ||
795 | if (sample >= frame_size) { | ||
796 | alcCaptureSamples((ALCdevice *)_phone->audio_capture_device, frame, frame_size); | ||
797 | |||
798 | if (toxav_send_audio(_phone->av, frame, frame_size) < 0) | ||
799 | printf("Could not encode or send audio packet\n"); | ||
800 | |||
801 | } else { | ||
802 | usleep(5000); | ||
803 | } | ||
804 | |||
805 | // play received | ||
806 | |||
807 | alGetSourcei(source, AL_BUFFERS_PROCESSED, &ready); | ||
808 | |||
809 | if (ready <= 0) | ||
810 | continue; | ||
811 | |||
812 | dec_frame_len = toxav_recv_audio(_phone->av, frame_size, PCM); | ||
813 | |||
814 | /* Play the packet */ | ||
815 | if (dec_frame_len > 0) { | ||
816 | alSourceUnqueueBuffers(source, 1, &buffer); | ||
817 | alBufferData(buffer, AL_FORMAT_MONO16, PCM, dec_frame_len * 2 * 1, 48000); | ||
818 | int error = alGetError(); | ||
819 | |||
820 | if (error != AL_NO_ERROR) { | ||
821 | fprintf(stderr, "Error setting buffer %d\n", error); | ||
822 | break; | ||
823 | } | ||
824 | |||
825 | alSourceQueueBuffers(source, 1, &buffer); | ||
826 | |||
827 | if (alGetError() != AL_NO_ERROR) { | ||
828 | fprintf(stderr, "Error: could not buffer audio\n"); | ||
829 | break; | ||
830 | } | ||
831 | |||
832 | alGetSourcei(source, AL_SOURCE_STATE, &ready); | ||
833 | |||
834 | if (ready != AL_PLAYING) alSourcePlay(source); | ||
835 | } | ||
836 | |||
837 | usleep(1000); | ||
838 | } | ||
839 | |||
840 | |||
841 | ending: | ||
842 | _phone->running_decaud = -1; | ||
843 | |||
844 | pthread_exit ( NULL ); | ||
845 | } | ||
846 | |||
847 | |||
848 | int phone_startmedia_loop ( ToxAv *arg ) | ||
849 | { | ||
850 | if ( !arg ) { | ||
851 | return -1; | ||
852 | } | ||
853 | |||
854 | toxav_prepare_transmission(arg, 1); | ||
855 | |||
856 | /* | ||
857 | * Rise all threads | ||
858 | */ | ||
859 | #ifdef TOX_FFMPEG | ||
860 | |||
861 | /* Only checks for last peer */ | ||
862 | if ( toxav_get_peer_transmission_type(arg, 0) == TypeVideo && | ||
863 | 0 > event.rise(encode_video_thread, _phone) ) { | ||
864 | INFO("Error while starting encode_video_thread()"); | ||
865 | return -1; | ||
866 | } | ||
867 | |||
868 | #endif | ||
869 | |||
870 | /* Always send audio */ | ||
871 | /*if ( 0 > event.rise(encode_audio_thread, toxav_get_agent_handler(arg)) ) { | ||
872 | INFO("Error while starting encode_audio_thread()"); | ||
873 | return -1; | ||
874 | } */ | ||
875 | |||
876 | /* Only checks for last peer */ | ||
877 | if ( toxav_get_peer_transmission_type(arg, 0) == TypeVideo && | ||
878 | 0 > event.rise(decode_video_thread, _phone) ) { | ||
879 | INFO("Error while starting decode_video_thread()"); | ||
880 | return -1; | ||
881 | } | ||
882 | |||
883 | /*if ( 0 > event.rise(decode_audio_thread, toxav_get_agent_handler(arg)) ) { | ||
884 | INFO("Error while starting decode_audio_thread()"); | ||
885 | return -1; | ||
886 | } */ | ||
887 | |||
888 | |||
889 | /* One threaded audio */ | ||
890 | |||
891 | if ( 0 > event.rise(one_threaded_audio, _phone) ) { | ||
892 | INFO ("Shit-head"); | ||
893 | return -1; | ||
894 | } | ||
895 | |||
896 | return 0; | ||
897 | } | ||
898 | |||
899 | |||
900 | |||
901 | |||
902 | |||
903 | |||
904 | /********************************************* | ||
905 | ********************************************* | ||
906 | ********************************************* | ||
907 | ********************************************* | ||
908 | ********************************************* | ||
909 | ********************************************* | ||
910 | ********************************************* | ||
911 | ********************************************* | ||
912 | */ | ||
913 | |||
914 | |||
915 | /* Some example callbacks */ | ||
916 | |||
917 | void callback_recv_invite ( void *_arg ) | ||
918 | { | ||
919 | assert(_arg); | ||
920 | |||
921 | switch ( toxav_get_peer_transmission_type(_arg, 0) ) { | ||
922 | case TypeAudio: | ||
923 | INFO( "Incoming audio call!"); | ||
924 | break; | ||
925 | |||
926 | case TypeVideo: | ||
927 | INFO( "Incoming video call!"); | ||
928 | break; | ||
929 | } | ||
930 | |||
931 | } | ||
932 | void callback_recv_ringing ( void *_arg ) | ||
933 | { | ||
934 | INFO ( "Ringing!" ); | ||
935 | } | ||
936 | void callback_recv_starting ( void *_arg ) | ||
937 | { | ||
938 | if ( 0 != phone_startmedia_loop(_arg) ) { | ||
939 | INFO("Starting call failed!"); | ||
940 | } else { | ||
941 | INFO ("Call started! ( press h to hangup )"); | ||
942 | } | ||
943 | |||
944 | } | ||
945 | void callback_recv_ending ( void *_arg ) | ||
946 | { | ||
947 | INFO ( "Call ended!" ); | ||
948 | _phone->running_encaud = 0; | ||
949 | _phone->running_decaud = 0; | ||
950 | _phone->running_encvid = 0; | ||
951 | _phone->running_decvid = 0; | ||
952 | |||
953 | /* Wait until all threads are done */ | ||
954 | usleep(100000); | ||
955 | |||
956 | INFO ( "Call ended!" ); | ||
957 | } | ||
958 | |||
959 | void callback_recv_error ( void *_arg ) | ||
960 | { | ||
961 | /*MSISession* _session = _arg; | ||
962 | |||
963 | INFO( "Error: %s", _session->last_error_str ); */ | ||
964 | } | ||
965 | |||
966 | void callback_call_started ( void *_arg ) | ||
967 | { | ||
968 | if ( 0 != phone_startmedia_loop(_arg) ) { | ||
969 | INFO("Starting call failed!"); | ||
970 | } else { | ||
971 | INFO ("Call started! ( press h to hangup )"); | ||
972 | } | ||
973 | |||
974 | } | ||
975 | void callback_call_canceled ( void *_arg ) | ||
976 | { | ||
977 | INFO ( "Call canceled!" ); | ||
978 | } | ||
979 | void callback_call_rejected ( void *_arg ) | ||
980 | { | ||
981 | INFO ( "Call rejected!" ); | ||
982 | } | ||
983 | void callback_call_ended ( void *_arg ) | ||
984 | { | ||
985 | _phone->running_encaud = 0; | ||
986 | _phone->running_decaud = 0; | ||
987 | _phone->running_encvid = 0; | ||
988 | _phone->running_decvid = 0; | ||
989 | |||
990 | /* Wait until all threads are done | ||
991 | |||
992 | while ( _phone->running_encaud != -1 || | ||
993 | _phone->running_decaud != -1 || | ||
994 | _phone->running_encvid != -1 || | ||
995 | _phone->running_decvid != -1 ) | ||
996 | |||
997 | usleep(1000000);*/ | ||
998 | |||
999 | while (_phone->running_decaud != -1) usleep(1000000); | ||
1000 | |||
1001 | toxav_kill_transmission(_phone->av); | ||
1002 | INFO ( "Call ended!" ); | ||
1003 | } | ||
1004 | |||
1005 | void callback_requ_timeout ( void *_arg ) | ||
1006 | { | ||
1007 | INFO( "No answer! " ); | ||
1008 | } | ||
1009 | |||
1010 | av_session_t *av_init_session() | ||
1011 | { | ||
1012 | av_session_t *_retu = malloc(sizeof(av_session_t)); | ||
1013 | |||
1014 | /* Initialize our mutex */ | ||
1015 | pthread_mutex_init ( &_retu->_mutex, NULL ); | ||
1016 | |||
1017 | _retu->_messenger = tox_new(1); | ||
1018 | |||
1019 | if ( !_retu->_messenger ) { | ||
1020 | fprintf ( stderr, "tox_new() failed!\n" ); | ||
1021 | return NULL; | ||
1022 | } | ||
1023 | |||
1024 | _retu->_friends = NULL; | ||
1025 | |||
1026 | |||
1027 | const ALchar *_device_list = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); | ||
1028 | int i = 0; | ||
1029 | const ALchar *device_names[20]; | ||
1030 | |||
1031 | if ( _device_list ) { | ||
1032 | INFO("\nAvailable Capture Devices are:"); | ||
1033 | |||
1034 | while (*_device_list ) { | ||
1035 | device_names[i] = _device_list; | ||
1036 | INFO("%d) %s", i, device_names[i]); | ||
1037 | _device_list += strlen( _device_list ) + 1; | ||
1038 | ++i; | ||
1039 | } | ||
1040 | } | ||
1041 | |||
1042 | INFO("Enter capture device number"); | ||
1043 | |||
1044 | char dev[2]; | ||
1045 | char *left; | ||
1046 | char *warned_ = fgets(dev, 2, stdin); | ||
1047 | (void)warned_; | ||
1048 | long selection = strtol(dev, &left, 10); | ||
1049 | |||
1050 | if ( *left ) { | ||
1051 | printf("'%s' is not a number!", dev); | ||
1052 | fflush(stdout); | ||
1053 | exit(EXIT_FAILURE); | ||
1054 | } else { | ||
1055 | INFO("Selected: %d ( %s )", selection, device_names[selection]); | ||
1056 | } | ||
1057 | |||
1058 | _retu->audio_capture_device = | ||
1059 | (struct ALCdevice *)alcCaptureOpenDevice( | ||
1060 | device_names[selection], av_DefaultSettings.audio_sample_rate, AL_FORMAT_MONO16, AUDIO_FRAME_SIZE * 4); | ||
1061 | |||
1062 | |||
1063 | if (alcGetError((ALCdevice *)_retu->audio_capture_device) != AL_NO_ERROR) { | ||
1064 | printf("Could not start capture device! %d\n", alcGetError((ALCdevice *)_retu->audio_capture_device)); | ||
1065 | return 0; | ||
1066 | } | ||
1067 | |||
1068 | uint16_t height = 0, width = 0; | ||
1069 | #ifdef TOX_FFMPEG | ||
1070 | avdevice_register_all(); | ||
1071 | avcodec_register_all(); | ||
1072 | av_register_all(); | ||
1073 | |||
1074 | _retu->video_input_format = av_find_input_format(VIDEO_DRIVER); | ||
1075 | |||
1076 | if (avformat_open_input(&_retu->video_format_ctx, DEFAULT_WEBCAM, _retu->video_input_format, NULL) != 0) { | ||
1077 | fprintf(stderr, "Opening video_input_format failed!\n"); | ||
1078 | //return -1; | ||
1079 | goto failed_init_ffmpeg; | ||
1080 | } | ||
1081 | |||
1082 | avformat_find_stream_info(_retu->video_format_ctx, NULL); | ||
1083 | av_dump_format(_retu->video_format_ctx, 0, DEFAULT_WEBCAM, 0); | ||
1084 | |||
1085 | for (i = 0; i < _retu->video_format_ctx->nb_streams; ++i) { | ||
1086 | if (_retu->video_format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { | ||
1087 | _retu->video_stream = i; | ||
1088 | break; | ||
1089 | } | ||
1090 | } | ||
1091 | |||
1092 | _retu->webcam_decoder_ctx = _retu->video_format_ctx->streams[_retu->video_stream]->codec; | ||
1093 | _retu->webcam_decoder = avcodec_find_decoder(_retu->webcam_decoder_ctx->codec_id); | ||
1094 | |||
1095 | if (_retu->webcam_decoder == NULL) { | ||
1096 | fprintf(stderr, "Unsupported codec!\n"); | ||
1097 | //return -1; | ||
1098 | goto failed_init_ffmpeg; | ||
1099 | } | ||
1100 | |||
1101 | if (_retu->webcam_decoder_ctx == NULL) { | ||
1102 | fprintf(stderr, "Init webcam_decoder_ctx failed!\n"); | ||
1103 | //return -1; | ||
1104 | goto failed_init_ffmpeg; | ||
1105 | } | ||
1106 | |||
1107 | if (avcodec_open2(_retu->webcam_decoder_ctx, _retu->webcam_decoder, NULL) < 0) { | ||
1108 | fprintf(stderr, "Opening webcam decoder failed!\n"); | ||
1109 | //return -1; | ||
1110 | goto failed_init_ffmpeg; | ||
1111 | } | ||
1112 | |||
1113 | width = _retu->webcam_decoder_ctx->width; | ||
1114 | height = _retu->webcam_decoder_ctx->height; | ||
1115 | |||
1116 | failed_init_ffmpeg: ; | ||
1117 | #endif | ||
1118 | uint8_t _byte_address[TOX_FRIEND_ADDRESS_SIZE]; | ||
1119 | tox_get_address(_retu->_messenger, _byte_address ); | ||
1120 | fraddr_to_str( _byte_address, _retu->_my_public_id ); | ||
1121 | |||
1122 | ToxAvCodecSettings cs = av_DefaultSettings; | ||
1123 | cs.video_height = height; | ||
1124 | cs.video_width = width; | ||
1125 | _retu->av = toxav_new(_retu->_messenger, &cs); | ||
1126 | |||
1127 | /* ------------------ */ | ||
1128 | |||
1129 | toxav_register_callstate_callback(callback_call_started, av_OnStart, _retu->av); | ||
1130 | toxav_register_callstate_callback(callback_call_canceled, av_OnCancel, _retu->av); | ||
1131 | toxav_register_callstate_callback(callback_call_rejected, av_OnReject, _retu->av); | ||
1132 | toxav_register_callstate_callback(callback_call_ended, av_OnEnd, _retu->av); | ||
1133 | toxav_register_callstate_callback(callback_recv_invite, av_OnInvite, _retu->av); | ||
1134 | |||
1135 | toxav_register_callstate_callback(callback_recv_ringing, av_OnRinging, _retu->av); | ||
1136 | toxav_register_callstate_callback(callback_recv_starting, av_OnStarting, _retu->av); | ||
1137 | toxav_register_callstate_callback(callback_recv_ending, av_OnEnding, _retu->av); | ||
1138 | |||
1139 | toxav_register_callstate_callback(callback_recv_error, av_OnError, _retu->av); | ||
1140 | toxav_register_callstate_callback(callback_requ_timeout, av_OnRequestTimeout, _retu->av); | ||
1141 | |||
1142 | /* ------------------ */ | ||
1143 | |||
1144 | return _retu; | ||
1145 | } | ||
1146 | |||
1147 | int av_terminate_session(av_session_t *_phone) | ||
1148 | { | ||
1149 | _phone->running_decaud = 0; | ||
1150 | usleep(100000); /* Wait for tox_poll to end */ | ||
1151 | |||
1152 | toxav_kill(_phone->av); | ||
1153 | printf("\r[i] KILLED AV ARGH!\n"); | ||
1154 | |||
1155 | usleep(1000000); /* Wait for cancel request to be sent */ | ||
1156 | Tox *_p = _phone->_messenger; | ||
1157 | _phone->_messenger = NULL; | ||
1158 | tox_kill(_p); | ||
1159 | |||
1160 | |||
1161 | free(_phone->_friends); | ||
1162 | pthread_mutex_destroy ( &_phone->_mutex ); | ||
1163 | |||
1164 | free(_phone); | ||
1165 | |||
1166 | printf("\r[i] Quit!\n"); | ||
1167 | return 0; | ||
1168 | } | ||
1169 | |||
1170 | /****** AV HELPER FUNCTIONS ******/ | ||
1171 | |||
1172 | /* Auto accept friend request */ | ||
1173 | void av_friend_requ(Tox *_messenger, uint8_t *_public_key, uint8_t *_data, uint16_t _length, void *_userdata) | ||
1174 | { | ||
1175 | av_session_t *_phone = _userdata; | ||
1176 | av_allocate_friend (_phone, -1, 0); | ||
1177 | |||
1178 | INFO("Got friend request with message: %s", _data); | ||
1179 | |||
1180 | tox_add_friend_norequest(_phone->_messenger, _public_key); | ||
1181 | |||
1182 | INFO("Auto-accepted! Friend id: %d", _phone->_friends->_id ); | ||
1183 | } | ||
1184 | |||
1185 | void av_friend_active(Tox *_messenger, int _friendnumber, uint8_t *_string, uint16_t _length, void *_userdata) | ||
1186 | { | ||
1187 | av_session_t *_phone = _userdata; | ||
1188 | INFO("Friend no. %d is online", _friendnumber); | ||
1189 | |||
1190 | av_friend_t *_this_friend = av_get_friend(_phone, _friendnumber); | ||
1191 | |||
1192 | if ( !_this_friend ) { | ||
1193 | INFO("But it's not registered!"); | ||
1194 | return; | ||
1195 | } | ||
1196 | |||
1197 | (*_this_friend)._active = 1; | ||
1198 | } | ||
1199 | |||
1200 | int av_add_friend(av_session_t *_phone, char *_friend_hash) | ||
1201 | { | ||
1202 | trim_spaces(_friend_hash); | ||
1203 | |||
1204 | unsigned char *_bin_string = hex_string_to_bin(_friend_hash); | ||
1205 | int _number = tox_add_friend(_phone->_messenger, _bin_string, (uint8_t *)"Tox phone "_USERAGENT, | ||
1206 | sizeof("Tox phone "_USERAGENT)); | ||
1207 | free(_bin_string); | ||
1208 | |||
1209 | if ( _number >= 0) { | ||
1210 | INFO("Added friend as %d", _number ); | ||
1211 | av_allocate_friend(_phone, _number, 0); | ||
1212 | } else | ||
1213 | INFO("Unknown error %i", _number ); | ||
1214 | |||
1215 | return _number; | ||
1216 | } | ||
1217 | |||
1218 | int av_connect_to_dht(av_session_t *_phone, char *_dht_key, const char *_dht_addr, unsigned short _dht_port) | ||
1219 | { | ||
1220 | unsigned char *_binary_string = hex_string_to_bin(_dht_key); | ||
1221 | |||
1222 | uint16_t _port = htons(_dht_port); | ||
1223 | |||
1224 | int _if = tox_bootstrap_from_address(_phone->_messenger, _dht_addr, 1, _port, _binary_string ); | ||
1225 | |||
1226 | free(_binary_string); | ||
1227 | |||
1228 | return _if ? 0 : -1; | ||
1229 | } | ||
1230 | |||
1231 | /*********************************/ | ||
1232 | |||
1233 | void do_phone ( av_session_t *_phone ) | ||
1234 | { | ||
1235 | INFO("Welcome to tox_phone version: " _USERAGENT "\n" | ||
1236 | "Usage: \n" | ||
1237 | "f [pubkey] (add friend)\n" | ||
1238 | "c [a/v] (type) [friend] (friend id) (calls friend if online)\n" | ||
1239 | "h (if call is active hang up)\n" | ||
1240 | "a [a/v] (answer incoming call: a - audio / v - audio + video (audio is default))\n" | ||
1241 | "r (reject incoming call)\n" | ||
1242 | "q (quit)\n" | ||
1243 | "================================================================================" | ||
1244 | ); | ||
1245 | |||
1246 | while ( 1 ) { | ||
1247 | char _line [ 1500 ]; | ||
1248 | int _len; | ||
1249 | |||
1250 | if ( -1 == getinput(_line, 1500, &_len) ) { | ||
1251 | printf(" >> "); | ||
1252 | fflush(stdout); | ||
1253 | continue; | ||
1254 | } | ||
1255 | |||
1256 | if ( _len > 1 && _line[1] != ' ' && _line[1] != '\n' ) { | ||
1257 | INFO("Invalid input!"); | ||
1258 | continue; | ||
1259 | } | ||
1260 | |||
1261 | switch (_line[0]) { | ||
1262 | |||
1263 | case 'f': { | ||
1264 | char _id [128]; | ||
1265 | strncpy(_id, _line + 2, 128); | ||
1266 | |||
1267 | av_add_friend(_phone, _id); | ||
1268 | |||
1269 | } | ||
1270 | break; | ||
1271 | |||
1272 | case 'c': { | ||
1273 | ToxAvCallType _ctype; | ||
1274 | |||
1275 | if ( _len < 5 ) { | ||
1276 | INFO("Invalid input; usage: c a/v [friend]"); | ||
1277 | break; | ||
1278 | } else if ( _line[2] == 'a' || _line[2] != 'v' ) { /* default and audio */ | ||
1279 | _ctype = TypeAudio; | ||
1280 | } else { /* video */ | ||
1281 | _ctype = TypeVideo; | ||
1282 | } | ||
1283 | |||
1284 | char *_end; | ||
1285 | int _friend = strtol(_line + 4, &_end, 10); | ||
1286 | |||
1287 | if ( *_end ) { | ||
1288 | INFO("Friend num has to be numerical value"); | ||
1289 | break; | ||
1290 | } | ||
1291 | |||
1292 | if ( toxav_call(_phone->av, _friend, _ctype, 30) == ErrorAlreadyInCall ) { | ||
1293 | INFO("Already in a call"); | ||
1294 | break; | ||
1295 | } else INFO("Calling friend: %d!", _friend); | ||
1296 | |||
1297 | } | ||
1298 | break; | ||
1299 | |||
1300 | case 'h': { | ||
1301 | if ( toxav_hangup(_phone->av) == ErrorNoCall ) { | ||
1302 | INFO("No call!"); | ||
1303 | break; | ||
1304 | } else INFO("Hung up..."); | ||
1305 | |||
1306 | } | ||
1307 | break; | ||
1308 | |||
1309 | case 'a': { | ||
1310 | ToxAvError rc; | ||
1311 | |||
1312 | if ( _len > 1 && _line[2] == 'v' ) { | ||
1313 | rc = toxav_answer(_phone->av, TypeVideo); | ||
1314 | } else | ||
1315 | rc = toxav_answer(_phone->av, TypeAudio); | ||
1316 | |||
1317 | if ( rc == ErrorInvalidState ) { | ||
1318 | INFO("No call to answer!"); | ||
1319 | } | ||
1320 | |||
1321 | } | ||
1322 | break; | ||
1323 | |||
1324 | case 'r': { | ||
1325 | if ( toxav_reject(_phone->av, "User action") == ErrorInvalidState ) | ||
1326 | INFO("No state to cancel!"); | ||
1327 | else INFO("Call Rejected..."); | ||
1328 | |||
1329 | } | ||
1330 | break; | ||
1331 | |||
1332 | case 'q': { | ||
1333 | INFO("Quitting!"); | ||
1334 | return; | ||
1335 | } | ||
1336 | |||
1337 | case '\n': { | ||
1338 | } | ||
1339 | |||
1340 | default: { | ||
1341 | } break; | ||
1342 | |||
1343 | } | ||
1344 | |||
1345 | } | ||
1346 | } | ||
1347 | |||
1348 | void *tox_poll (void *_messenger_p) | ||
1349 | { | ||
1350 | Tox **_messenger = _messenger_p; | ||
1351 | |||
1352 | while ( *_messenger ) { | ||
1353 | tox_do(*_messenger); | ||
1354 | usleep(10000); | ||
1355 | } | ||
1356 | |||
1357 | pthread_exit(NULL); | ||
1358 | } | ||
1359 | |||
1360 | int av_wait_dht(av_session_t *_phone, int _wait_seconds, const char *_ip, char *_key, unsigned short _port) | ||
1361 | { | ||
1362 | if ( !_wait_seconds ) | ||
1363 | return -1; | ||
1364 | |||
1365 | int _waited = 0; | ||
1366 | |||
1367 | while ( !tox_isconnected(_phone->_messenger) ) { | ||
1368 | |||
1369 | if ( -1 == av_connect_to_dht(_phone, _key, _ip, _port) ) { | ||
1370 | INFO("Could not connect to: %s", _ip); | ||
1371 | av_terminate_session(_phone); | ||
1372 | return -1; | ||
1373 | } | ||
1374 | |||
1375 | if ( _waited >= _wait_seconds ) return 0; | ||
1376 | |||
1377 | printf("."); | ||
1378 | fflush(stdout); | ||
1379 | |||
1380 | _waited ++; | ||
1381 | usleep(1000000); | ||
1382 | } | ||
1383 | |||
1384 | int _r = _wait_seconds - _waited; | ||
1385 | return _r ? _r : 1; | ||
1386 | } | ||
1387 | /* ---------------------- */ | ||
1388 | |||
1389 | int print_help ( const char *_name ) | ||
1390 | { | ||
1391 | printf ( "Usage: %s [IP] [PORT] [KEY]\n" | ||
1392 | "\t[IP] (DHT ip)\n" | ||
1393 | "\t[PORT] (DHT port)\n" | ||
1394 | "\t[KEY] (DHT public key)\n" | ||
1395 | "P.S. Friends and key are stored in ./tox_phone.conf\n" | ||
1396 | , _name ); | ||
1397 | return 1; | ||
1398 | } | ||
1399 | |||
1400 | int main ( int argc, char *argv [] ) | ||
1401 | { | ||
1402 | if ( argc < 1 || argc < 4 ) | ||
1403 | return print_help(argv[0]); | ||
1404 | |||
1405 | char *_convertable; | ||
1406 | |||
1407 | |||
1408 | const char *_ip = argv[1]; | ||
1409 | char *_key = argv[3]; | ||
1410 | unsigned short _port = strtol(argv[2], &_convertable, 10); | ||
1411 | |||
1412 | if ( *_convertable ) { | ||
1413 | printf("Invalid port: cannot convert string to long: %s", _convertable); | ||
1414 | return 1; | ||
1415 | } | ||
1416 | |||
1417 | _phone = av_init_session(); | ||
1418 | |||
1419 | assert ( _phone ); | ||
1420 | |||
1421 | tox_callback_friend_request(_phone->_messenger, av_friend_requ, _phone); | ||
1422 | tox_callback_status_message(_phone->_messenger, av_friend_active, _phone); | ||
1423 | |||
1424 | |||
1425 | INFO("\r================================================================================\n" | ||
1426 | "[!] Trying dht@%s:%d" | ||
1427 | , _ip, _port); | ||
1428 | |||
1429 | /* Start tox protocol */ | ||
1430 | event.rise( tox_poll, &_phone->_messenger ); | ||
1431 | |||
1432 | /* Just clean one line */ | ||
1433 | printf("\r \r"); | ||
1434 | fflush(stdout); | ||
1435 | |||
1436 | int _r; | ||
1437 | int _wait_seconds = 5; | ||
1438 | |||
1439 | for ( _r = 0; _r == 0; _r = av_wait_dht(_phone, _wait_seconds, _ip, _key, _port) ) _wait_seconds --; | ||
1440 | |||
1441 | |||
1442 | if ( -1 == _r ) { | ||
1443 | INFO("Error while connecting to dht: %s:%d", _ip, _port); | ||
1444 | av_terminate_session(_phone); | ||
1445 | return 1; | ||
1446 | } | ||
1447 | |||
1448 | INFO("CONNECTED!\n" | ||
1449 | "================================================================================\n" | ||
1450 | "%s\n" | ||
1451 | "================================================================================" | ||
1452 | , trim_spaces(_phone->_my_public_id) ); | ||
1453 | |||
1454 | |||
1455 | do_phone (_phone); | ||
1456 | |||
1457 | av_terminate_session(_phone); | ||
1458 | |||
1459 | return 0; | ||
1460 | } | ||
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 28c8845a..4a9e5f7f 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c | |||
@@ -2048,6 +2048,7 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) | |||
2048 | if (m->friend_action) | 2048 | if (m->friend_action) |
2049 | (*m->friend_action)(m, i, action_terminated, action_length, m->friend_action_userdata); | 2049 | (*m->friend_action)(m, i, action_terminated, action_length, m->friend_action_userdata); |
2050 | 2050 | ||
2051 | |||
2051 | break; | 2052 | break; |
2052 | } | 2053 | } |
2053 | 2054 | ||
@@ -2207,7 +2208,7 @@ void do_friends(Messenger *m) | |||
2207 | m->friendlist[i].friendrequest_lastsent = temp_time; | 2208 | m->friendlist[i].friendrequest_lastsent = temp_time; |
2208 | } | 2209 | } |
2209 | } | 2210 | } |
2210 | 2211 | ||
2211 | if (m->friendlist[i].status == FRIEND_REQUESTED | 2212 | if (m->friendlist[i].status == FRIEND_REQUESTED |
2212 | || m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online. */ | 2213 | || m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online. */ |
2213 | if (m->friendlist[i].status == FRIEND_REQUESTED) { | 2214 | if (m->friendlist[i].status == FRIEND_REQUESTED) { |