summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md1
-rw-r--r--auto_tests/TCP_test.c143
-rw-r--r--auto_tests/crypto_test.c37
-rw-r--r--auto_tests/messenger_test.c27
-rw-r--r--auto_tests/network_test.c5
-rw-r--r--auto_tests/onion_test.c38
-rw-r--r--auto_tests/tox_test.c28
-rw-r--r--docs/Group-Chats.md8
-rw-r--r--docs/Prevent_Tracking.txt5
-rw-r--r--docs/TCP_Network.txt13
-rw-r--r--docs/Tox_middle_level_network_protocol.txt118
-rw-r--r--docs/av_api.md2
-rw-r--r--docs/updates/Crypto.md2
-rw-r--r--docs/updates/DHT.md20
-rw-r--r--m4/pkg.m42
-rw-r--r--other/bootstrap_daemon/conf22
-rw-r--r--other/bootstrap_daemon/tox_bootstrap_daemon.c301
-rw-r--r--other/bootstrap_daemon/tox_bootstrap_daemon.sh6
-rw-r--r--other/fun/cracker.c2
-rw-r--r--toxav/Makefile.inc1
-rwxr-xr-xtoxav/msi.c57
-rwxr-xr-xtoxav/msi.h11
-rwxr-xr-xtoxav/phone.c1460
-rw-r--r--toxcore/Messenger.c3
24 files changed, 2141 insertions, 171 deletions
diff --git a/README.md b/README.md
index f2745d67..853a747d 100644
--- a/README.md
+++ b/README.md
@@ -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
11Tox must use UDP simply because [hole punching](http://en.wikipedia.org/wiki/UDP_hole_punching) with TCP is not as reliable. 11Tox must use UDP simply because [hole punching](http://en.wikipedia.org/wiki/UDP_hole_punching) with TCP is not as reliable.
12However, 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
14Every 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. 15Every 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}
292END_TEST 292END_TEST
293 293
294static int response_callback_good;
295static uint8_t response_callback_connection_id;
296static uint8_t response_callback_public_key[crypto_box_PUBLICKEYBYTES];
297static 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}
307static int status_callback_good;
308static uint8_t status_callback_connection_id;
309static uint8_t status_callback_status;
310static 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}
323static int data_callback_good;
324static 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
343static int oob_data_callback_good;
344static uint8_t oob_pubkey[crypto_box_PUBLICKEYBYTES];
345static 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
294START_TEST(test_client) 364START_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}
324END_TEST 459END_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
19void rand_bytes(uint8_t *b, size_t blen) 13void 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
249START_TEST(test_large_data_symmetric) 243START_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}
277END_TEST 271END_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}
300END_TEST 299END_TEST
301 300
302START_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}
321END_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}
143END_TEST 142END_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
98uint64_t size_recv; 98uint64_t size_recv;
99uint8_t num;
99void write_file(Tox *m, int friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata) 100void 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
111START_TEST(test_few_clients) 116START_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)
284loop_top: 292loop_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.
21Get nodes (Request): 21Get nodes (Request):
22Packet contents: 22Packet 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```
26Valid replies: a send_nodes packet 26Valid replies: a send_nodes packet
27 27
28Send_nodes (response): 28Send_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
33Broadcast packet: 33Broadcast 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
7065 - action (/me) 7065 - 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
112The data in the previous packet is in format: [real public key of sender] 112The data in the previous packet is in format: [real public key of sender]
113encrypted 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)]] 113encrypted with real private key of the sender, the nonce in the data packet and
114the real public key of the receiver:[[uint8_t id][data (optional)]]
114 115
115Data sent to us: 116Data sent to us:
116announce response packet: 117announce response packet:
@@ -153,5 +154,5 @@ Data packets:
153 154
154To tell our friend what our DHT public key is so that he can connect to us we send a data packet 155To tell our friend what our DHT public key is so that he can connect to us we send a data packet
155with id 156 and the data being:[uint64_t (in network byte order) no_replay, the packet will only be 156with id 156 and the data being:[uint64_t (in network byte order) no_replay, the packet will only be
156accepted if this number is bigger than the last one recieved] [our dht public key][Node_Format * ( 157accepted if this number is bigger than the last one received] [our dht public key][Node_Format * (
157maximum of 8) nodes closest to us so that the friend can find us faster] 158maximum 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
81client sent the server the public key and the public key we sent to the client, 81client sent the server the public key and the public key we sent to the client,
82the next with base nonce + 1...) 82the next with base nonce + 1...)
83 83
84The connection is set to an unconfirmed state until a packet is recieved and 84The connection is set to an unconfirmed state until a packet is received and
85decrypted correctly using the information in the handshake. 85decrypted correctly using the information in the handshake.
86 86
87each packet sent to/from the server has an id (the first byte of the plain text 87each 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)]
1055 - ping response (pong) 1055 - 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)]
1076 - OOB send
108[uint8_t id (6)][destination public key (32 bytes)][data]
1097 - OOB recv
110[uint8_t id (7)][senders public key (32 bytes)][data]
1078 - onion packet (same format as initial onion packet (See: Prevent 1118 - onion packet (same format as initial onion packet (See: Prevent
108tracking.txt) but packet id is 8 instead of 128) 112tracking.txt) but packet id is 8 instead of 128)
1099 - onion packet response (same format as onion packet with id 142 but id is 9 1139 - 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
136Ping responses must have the same ping_id as the request. 140Ping responses must have the same ping_id as the request.
137 141
138If the server recieves a ping packet he must respond with a ping response. 142If the server receives a ping packet he must respond with a ping response.
139 143
140The server will send a ping packet to clients every 30 seconds, they have 30 144The server will send a ping packet to clients every 30 seconds, they have 30
141seconds to respond, if they don't the connection is deleted. 145seconds to respond, if they don't the connection is deleted.
142 146
147OOB send packets will be sent to the peer connected to the TCP server with the
148destination public key as a OOB recv packet. The client sending this packet has
149no way of knowing if the packet reached its destination.
150
151
143Client: 152Client:
144 153
145Implementation details coming soon. 154Implementation 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 @@
1The TCP client and TCP server part are in a state that can be considered
2feature complete. Why doesn't Tox support TCP yet even if those parts are
3complete?
4
5The answer is that a way to ensure a smooth switchover between the TCP and UDP
6needs to be added. If Tox first connects to the other user using TCP but then
7due to pure chance manages to connect using the faster direct UDP connection
8Tox must switch seamlessly from the TCP to the UDP connection without there
9being any data loss or the other user going offline and then back online. The
10transition must be seamless whatever both connected users are doing be it
11transferring files or simply chatting together.
12
13Possible evil/bad or simply TCP relays going offline must not impact the
14connection between both clients.
15
16Typically Tox will use more than one TCP relay to connect to other peers for
17maximum connection stability which means there must be a way for Tox to take
18advantage of multiple relays in a way that the user will never be aware if one
19of them goes offline/tries to slow down the connection/decides to corrupt
20packets/etc..
21
22To accomplish this Tox needs something between the low level protocol (TCP) and
23high level Tox messaging protocol hence the name middle level.
24
25The plan is to move some functionality from lossless_UDP to a higher level:
26more specifically the functionality for detecting which packets a peer is
27missing and the ability to request and send them again. lossless UDP uses plain
28text packets to request missing packets from the other peer while Tox is
29currently designed to kill the connection if any packet tampering is detected.
30This works very well when connecting directly with someone because if the
31attacker can modify packets it means he can kill your connection anyways. With
32TCP relays however that is not the case as such the packets used to request
33missing packets must be encrypted. If it is detected that a packet has been
34tampered, the connection must stay intact while the evil relay must be
35disconnected from and replaced with a good relay, the behavior must be the same
36as if the relay had just suddenly gone online. Of course something to protect
37from evil "friends" framing relays must also be implemented.
38
39Detailed implementation details:
40
41cookie request packet:
42[uint8_t 24][Senders DHT Public key (32 bytes)][Random nonce (24
43bytes)][Encrypted message containing: [Senders real public key (32
44bytes)][padding (32 bytes)][uint64_t number (must be sent
45back untouched in cookie response)]]
46Encrypted message is encrypted with sender DHT private key, recievers DHT
47public key and the nonce.
48
49cookie response packet:
50[uint8_t 25][Random nonce (24 bytes)][Encrypted message containing:
51[Cookie][uint64_t number (that was sent in the request)]]
52Encrypted message is encrypted with sender DHT private key, recievers DHT
53public key and the nonce.
54
55The Cookie should be basically:
56[nonce][encrypted data:[uint64_t time][Senders real public key (32
57bytes)][Senders dht public key (32 bytes)]]
58
59Handshake packet:
60[uint8_t 26][Cookie][nonce][Encrypted message containing: [random 24 bytes base
61nonce][session public key of the peer (32 bytes)][sha512 hash of the entire
62Cookie sitting outside the encrypted part][Other Cookie (used by the other to
63respond to the handshake packet)]]
64
65The handshake packet is encrypted using the real private key of the sender, the
66real private key of the receiver and the nonce.
67
68
69Alice wants to connect to bob.
70
71Alice sends a cookie request packet to bob and gets a cookie response back.
72
73Alice then generates a nonce and a temporary public/private keypair.
74
75Alice then takes that nonce and just generated private key, the obtained
76cookie, creates a new cookie and puts them in a handshake packet which she
77sends to bob.
78
79Bob gets the handshake packet, accepts the connection request, then generates a
80nonce and a temporary public/private keypair and sends a handshake packet back
81with this just generated information and with the cookie field being the Other
82Cookie contained in the received handshake.
83
84Both then use these temporary keys to generate the session key with which every
85data packet sent and received will be encrypted and decrypted. The nonce sent
86in 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
89Data packets:
90
91[uint8_t 27][uint16_t (in network byte order) the last 2 bytes of the nonce
92used to encrypt this][encrypted with the session key and a nonce:[plain data]]
93
94Plain data in the data packets:
95
96[uint32_t our recvbuffers buffer_start, (highest packet number handled +
971)][uint32_t packet number if lossless, our sendbuffer buffer_end if
98lossy][data]
99
100data ids:
1010: padding (skipped until we hit a non zero (data id) byte)
1021: packet request packet (lossy packet)
1032: connection kill packet (lossy packet) (tells the other that the connection is over)
104...
10516+: reserved for Messenger usage (lossless packets).
106
107packet request packet: [uint8_t (1)][uint8_t num][uint8_t num][uint8_t
108num]...[uint8_t num]
109
110the list of nums are a list of packet numbers the other is requesting.
111to get the real packet numbers from this list take the recvbuffers buffer_start
112from the packet, substract 1 to it and put it in packet_num then start from the
113beggining of the num list: if num is zero, add 255 to packet_num then do the
114next num. if num isn't zero, add its value to packet_num, note that the other
115has requested we send this packet again to them then continue to the next num in
116the 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
36How to handle msi session: 36How to handle msi session:
37Controling is done via callbacks and action handlers. 37Controlling is done via callbacks and action handlers.
38First register callbacks for every state/action received and make sure 38First register callbacks for every state/action received and make sure
39NOT TO PLACE SOMETHING LIKE LOOPS THAT TAKES A LOT OF TIME TO EXECUTE; every callback is being called 39NOT TO PLACE SOMETHING LIKE LOOPS THAT TAKES A LOT OF TIME TO EXECUTE; every callback is being called
40directly from event loop. You can find examples in phone.c. 40directly 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
75The 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. 75The 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
77Each node can route the request to the reciever if they are connected to him. This is to bypass bad NATs. 77Each 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
80Node format: 80Node 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```
84see also: DHT.h (Node4_format struct) 84see also: DHT.h (pack_nodes() and unpack_nodes())
85
86IPv6 Node format:
87see: DHT.h (Node_format struct)
88 85
89Valid queries and Responses: 86Valid queries and Responses:
90 87
91Ping(Request and response): 88Ping(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```
95ping_id = a random integer, the response must contain the exact same number as the request 92ping_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
98Get nodes (Request): 95Get nodes (Request):
99Packet contents: 96Packet 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```
103Valid replies: a send_nodes packet 100Valid replies: a send_nodes packet
104 101
105Send_nodes (response (for ipv4 addresses)): 102Send_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
110Send_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```
diff --git a/m4/pkg.m4 b/m4/pkg.m4
index f26f84c9..260e1fb9 100644
--- a/m4/pkg.m4
+++ b/m4/pkg.m4
@@ -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.
4port = 33445 4port = 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.
9keys_file_path = "/home/tom/.tox_bootstrap_daemon/keys" 9keys_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.
15pid_file_path = "/home/tom/.tox_bootstrap_daemon/pid" 15pid_file_path = "/home/tom/.tox_bootstrap_daemon/.tox_bootstrap_daemon.pid"
16 16
17// Enable IPv6. 17// Enable IPv6.
18enable_ipv6 = false 18enable_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.
21enable_lan_discovery = true 21enable_lan_discovery = true
22 22
23enable_tcp_relay = true
24
25// Tox uses 443, 3389 and 33445 ports by default, so it's highly recommended to keep
26// them.
27tcp_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.
31enable_motd = true
32
33motd = "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.
29bootstrap_nodes = ( 41bootstrap_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
124void 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
109int get_general_config(char *cfg_file_path, char **pid_file_path, char **keys_file_path, int *port, int *enable_ipv6, 217int 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
282next: 450next:
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
297void print_public_key(uint8_t *public_key) 465void 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
13PATH=/sbin:/usr/sbin:/bin:/usr/bin 13PATH=/sbin:/usr/sbin:/bin:/usr/bin
14DESC="Tox DHT bootstrap server daemon" 14DESC="Tox DHT bootstrap daemon"
15NAME=tox_bootstrap_daemon 15NAME=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
17USER=tom 17USER=tom
18CFG=/home/$USER/.$NAME/conf 18CFG=/home/$USER/.$NAME/conf
19DAEMON=/home/$USER/$NAME 19DAEMON=/home/$USER/.$NAME/$NAME
20DAEMON_ARGS="$CFG" 20DAEMON_ARGS="$CFG"
21PIDFILE=/home/$USER/.$NAME/pid 21PIDFILE=/home/$USER/.$NAME/."$NAME".pid
22SCRIPTNAME=/etc/init.d/$NAME 22SCRIPTNAME=/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)
32int main(int argc, char *argv[]) 32int 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
38endif \ No newline at end of file 37endif \ 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
87struct SDL_Surface *screen;
88
89typedef struct {
90 struct SDL_Overlay *bmp;
91 int width, height;
92} VideoPicture;
93
94
95typedef struct av_friend_s {
96 int _id;
97 int _active; /* 0=false; 1=true; */
98} av_friend_t;
99
100typedef 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;
131av_session_t *_phone;
132
133void 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}
152av_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
170void 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
181unsigned 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
193int 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
206char *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
232static 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/*
272int 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 *//*
286sws_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
289SDL_UnlockYUVOverlay(_phone->video_picture.bmp);
290SDL_Rect rect;
291rect.x = 0;
292rect.y = 0;
293rect.w = cs->video_decoder_ctx->width;
294rect.h = cs->video_decoder_ctx->height;
295SDL_DisplayYUVOverlay(_phone->video_picture.bmp, &rect);
296return 1;
297}
298*/
299#ifdef TOX_FFMPEG
300void *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
422void *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
458void 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
539void *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
635void *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
719ending:
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
738void *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
848int 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
917void 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}
932void callback_recv_ringing ( void *_arg )
933{
934 INFO ( "Ringing!" );
935}
936void 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}
945void 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
959void callback_recv_error ( void *_arg )
960{
961 /*MSISession* _session = _arg;
962
963 INFO( "Error: %s", _session->last_error_str ); */
964}
965
966void 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}
975void callback_call_canceled ( void *_arg )
976{
977 INFO ( "Call canceled!" );
978}
979void callback_call_rejected ( void *_arg )
980{
981 INFO ( "Call rejected!" );
982}
983void 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
1005void callback_requ_timeout ( void *_arg )
1006{
1007 INFO( "No answer! " );
1008}
1009
1010av_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
1116failed_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
1147int 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 */
1173void 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
1185void 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
1200int 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
1218int 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
1233void 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
1348void *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
1360int 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
1389int 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
1400int 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) {