summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--auto_tests/tox_test.c196
-rw-r--r--auto_tests/toxav_basic_test.c38
-rw-r--r--auto_tests/toxav_many_test.c18
-rw-r--r--other/apidsl/README.md2
-rw-r--r--other/apidsl/tox.in.h5
-rw-r--r--other/apidsl/toxav.in.h2
-rw-r--r--other/bootstrap_daemon/tox-bootstrapd.c3
-rw-r--r--testing/av_test.c29
-rw-r--r--testing/irc_syncbot.c20
-rw-r--r--toxav/audio.c2
-rw-r--r--toxav/audio.h4
-rw-r--r--toxav/msi.c2
-rw-r--r--toxav/msi.h8
-rw-r--r--toxav/toxav.c374
-rw-r--r--toxav/toxav.h820
-rw-r--r--toxav/video.c7
-rw-r--r--toxav/video.h4
-rw-r--r--toxcore/DHT.c4
-rw-r--r--toxcore/LAN_discovery.c37
-rw-r--r--toxcore/LAN_discovery.h3
-rw-r--r--toxcore/Messenger.c78
-rw-r--r--toxcore/Messenger.h9
-rw-r--r--toxcore/TCP_connection.c1
-rw-r--r--toxcore/TCP_server.h2
-rw-r--r--toxcore/crypto_core.h1
-rw-r--r--toxcore/friend_connection.c21
-rw-r--r--toxcore/friend_connection.h2
-rw-r--r--toxcore/list.c8
-rw-r--r--toxcore/list.h8
-rw-r--r--toxcore/net_crypto.c93
-rw-r--r--toxcore/net_crypto.h16
-rw-r--r--toxcore/network.c2
-rw-r--r--toxcore/onion.c4
-rw-r--r--toxcore/onion.h4
-rw-r--r--toxcore/onion_announce.h2
-rw-r--r--toxcore/onion_client.c15
-rw-r--r--toxcore/ping.c6
-rw-r--r--toxcore/tox.c132
-rw-r--r--toxcore/tox.h6
-rw-r--r--toxdns/toxdns.c27
40 files changed, 1314 insertions, 701 deletions
diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c
index 0dab2e69..40022b0a 100644
--- a/auto_tests/tox_test.c
+++ b/auto_tests/tox_test.c
@@ -332,6 +332,7 @@ START_TEST(test_one)
332 tox_self_set_name(tox1, name, sizeof(name), 0); 332 tox_self_set_name(tox1, name, sizeof(name), 0);
333 ck_assert_msg(tox_self_get_name_size(tox1) == sizeof(name), "Can't set name of TOX_MAX_NAME_LENGTH"); 333 ck_assert_msg(tox_self_get_name_size(tox1) == sizeof(name), "Can't set name of TOX_MAX_NAME_LENGTH");
334 334
335 tox_self_get_address(tox1, address);
335 size_t save_size = tox_get_savedata_size(tox1); 336 size_t save_size = tox_get_savedata_size(tox1);
336 uint8_t data[save_size]; 337 uint8_t data[save_size];
337 tox_get_savedata(tox1, data); 338 tox_get_savedata(tox1, data);
@@ -344,6 +345,9 @@ START_TEST(test_one)
344 345
345 ck_assert_msg(tox_self_get_name_size(tox2) == sizeof name, "Wrong name size."); 346 ck_assert_msg(tox_self_get_name_size(tox2) == sizeof name, "Wrong name size.");
346 347
348 uint8_t address2[TOX_ADDRESS_SIZE];
349 tox_self_get_address(tox2, address2);
350 ck_assert_msg(memcmp(address2, address, TOX_ADDRESS_SIZE) == 0, "Wrong address.");
347 uint8_t new_name[TOX_MAX_NAME_LENGTH] = { 0 }; 351 uint8_t new_name[TOX_MAX_NAME_LENGTH] = { 0 };
348 tox_self_get_name(tox2, new_name); 352 tox_self_get_name(tox2, new_name);
349 ck_assert_msg(memcmp(name, new_name, TOX_MAX_NAME_LENGTH) == 0, "Wrong name"); 353 ck_assert_msg(memcmp(name, new_name, TOX_MAX_NAME_LENGTH) == 0, "Wrong name");
@@ -809,6 +813,196 @@ loop_top:
809} 813}
810END_TEST 814END_TEST
811 815
816#define TCP_RELAY_PORT 33448
817
818START_TEST(test_many_clients_tcp)
819{
820 long long unsigned int cur_time = time(NULL);
821 Tox *toxes[NUM_TOXES];
822 uint32_t i, j;
823 uint32_t to_comp = 974536;
824
825 for (i = 0; i < NUM_TOXES; ++i) {
826 struct Tox_Options opts;
827 tox_options_default(&opts);
828
829 if (i == 0) {
830 opts.tcp_port = TCP_RELAY_PORT;
831 } else {
832 opts.udp_enabled = 0;
833 }
834
835 toxes[i] = tox_new(&opts, 0, 0, 0);
836 ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i);
837 tox_callback_friend_request(toxes[i], accept_friend_request, &to_comp);
838 uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
839 tox_self_get_dht_id(toxes[0], dpk);
840 ck_assert_msg(tox_add_tcp_relay(toxes[i], "::1", TCP_RELAY_PORT, dpk, 0), "add relay error");
841 ck_assert_msg(tox_bootstrap(toxes[i], "::1", 33445, dpk, 0), "Bootstrap error");
842 }
843
844 {
845 TOX_ERR_GET_PORT error;
846 ck_assert_msg(tox_self_get_udp_port(toxes[0], &error) == 33445, "First Tox instance did not bind to udp port 33445.\n");
847 ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
848 ck_assert_msg(tox_self_get_tcp_port(toxes[0], &error) == TCP_RELAY_PORT,
849 "First Tox instance did not bind to tcp port %u.\n", TCP_RELAY_PORT);
850 ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
851 }
852
853 struct {
854 uint16_t tox1;
855 uint16_t tox2;
856 } pairs[NUM_FRIENDS];
857
858 uint8_t address[TOX_ADDRESS_SIZE];
859
860 for (i = 0; i < NUM_FRIENDS; ++i) {
861loop_top:
862 pairs[i].tox1 = rand() % NUM_TOXES;
863 pairs[i].tox2 = (pairs[i].tox1 + rand() % (NUM_TOXES - 1) + 1) % NUM_TOXES;
864
865 for (j = 0; j < i; ++j) {
866 if (pairs[j].tox2 == pairs[i].tox1 && pairs[j].tox1 == pairs[i].tox2)
867 goto loop_top;
868 }
869
870 tox_self_get_address(toxes[pairs[i].tox1], address);
871
872 TOX_ERR_FRIEND_ADD test;
873 uint32_t num = tox_friend_add(toxes[pairs[i].tox2], address, (uint8_t *)"Gentoo", 7, &test);
874
875 if (test == TOX_ERR_FRIEND_ADD_ALREADY_SENT) {
876 goto loop_top;
877 }
878
879 ck_assert_msg(num != UINT32_MAX && test == TOX_ERR_FRIEND_ADD_OK, "Failed to add friend error code: %i", test);
880 }
881
882 while (1) {
883 uint16_t counter = 0;
884
885 for (i = 0; i < NUM_TOXES; ++i) {
886 for (j = 0; j < tox_self_get_friend_list_size(toxes[i]); ++j)
887 if (tox_friend_get_connection_status(toxes[i], j, 0) == TOX_CONNECTION_TCP)
888 ++counter;
889 }
890
891 if (counter == NUM_FRIENDS * 2) {
892 break;
893 }
894
895 for (i = 0; i < NUM_TOXES; ++i) {
896 tox_iterate(toxes[i]);
897 }
898
899 c_sleep(50);
900 }
901
902 for (i = 0; i < NUM_TOXES; ++i) {
903 tox_kill(toxes[i]);
904 }
905
906 printf("test_many_clients_tcp succeeded, took %llu seconds\n", time(NULL) - cur_time);
907}
908END_TEST
909
910#define NUM_TCP_RELAYS 3
911
912START_TEST(test_many_clients_tcp_b)
913{
914 long long unsigned int cur_time = time(NULL);
915 Tox *toxes[NUM_TOXES];
916 uint32_t i, j;
917 uint32_t to_comp = 974536;
918
919 for (i = 0; i < NUM_TOXES; ++i) {
920 struct Tox_Options opts;
921 tox_options_default(&opts);
922
923 if (i < NUM_TCP_RELAYS) {
924 opts.tcp_port = TCP_RELAY_PORT + i;
925 } else {
926 opts.udp_enabled = 0;
927 }
928
929 toxes[i] = tox_new(&opts, 0, 0, 0);
930 ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i);
931 tox_callback_friend_request(toxes[i], accept_friend_request, &to_comp);
932 uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
933 tox_self_get_dht_id(toxes[(i % NUM_TCP_RELAYS)], dpk);
934 ck_assert_msg(tox_add_tcp_relay(toxes[i], "::1", TCP_RELAY_PORT + (i % NUM_TCP_RELAYS), dpk, 0), "add relay error");
935 tox_self_get_dht_id(toxes[0], dpk);
936 ck_assert_msg(tox_bootstrap(toxes[i], "::1", 33445, dpk, 0), "Bootstrap error");
937 }
938
939 {
940 TOX_ERR_GET_PORT error;
941 ck_assert_msg(tox_self_get_udp_port(toxes[0], &error) == 33445, "First Tox instance did not bind to udp port 33445.\n");
942 ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
943 ck_assert_msg(tox_self_get_tcp_port(toxes[0], &error) == TCP_RELAY_PORT,
944 "First Tox instance did not bind to tcp port %u.\n", TCP_RELAY_PORT);
945 ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
946 }
947
948 struct {
949 uint16_t tox1;
950 uint16_t tox2;
951 } pairs[NUM_FRIENDS];
952
953 uint8_t address[TOX_ADDRESS_SIZE];
954
955 for (i = 0; i < NUM_FRIENDS; ++i) {
956loop_top:
957 pairs[i].tox1 = rand() % NUM_TOXES;
958 pairs[i].tox2 = (pairs[i].tox1 + rand() % (NUM_TOXES - 1) + 1) % NUM_TOXES;
959
960 for (j = 0; j < i; ++j) {
961 if (pairs[j].tox2 == pairs[i].tox1 && pairs[j].tox1 == pairs[i].tox2)
962 goto loop_top;
963 }
964
965 tox_self_get_address(toxes[pairs[i].tox1], address);
966
967 TOX_ERR_FRIEND_ADD test;
968 uint32_t num = tox_friend_add(toxes[pairs[i].tox2], address, (uint8_t *)"Gentoo", 7, &test);
969
970 if (test == TOX_ERR_FRIEND_ADD_ALREADY_SENT) {
971 goto loop_top;
972 }
973
974 ck_assert_msg(num != UINT32_MAX && test == TOX_ERR_FRIEND_ADD_OK, "Failed to add friend error code: %i", test);
975 }
976
977 while (1) {
978 uint16_t counter = 0;
979
980 for (i = 0; i < NUM_TOXES; ++i) {
981 for (j = 0; j < tox_self_get_friend_list_size(toxes[i]); ++j)
982 if (tox_friend_get_connection_status(toxes[i], j, 0) == TOX_CONNECTION_TCP)
983 ++counter;
984 }
985
986 if (counter == NUM_FRIENDS * 2) {
987 break;
988 }
989
990 for (i = 0; i < NUM_TOXES; ++i) {
991 tox_iterate(toxes[i]);
992 }
993
994 c_sleep(50);
995 }
996
997 for (i = 0; i < NUM_TOXES; ++i) {
998 tox_kill(toxes[i]);
999 }
1000
1001 printf("test_many_clients_tcp_b succeeded, took %llu seconds\n", time(NULL) - cur_time);
1002}
1003END_TEST
1004
1005
812#define NUM_GROUP_TOX 32 1006#define NUM_GROUP_TOX 32
813 1007
814void g_accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata) 1008void g_accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
@@ -996,6 +1190,8 @@ Suite *tox_suite(void)
996 DEFTESTCASE(one); 1190 DEFTESTCASE(one);
997 DEFTESTCASE_SLOW(few_clients, 50); 1191 DEFTESTCASE_SLOW(few_clients, 50);
998 DEFTESTCASE_SLOW(many_clients, 150); 1192 DEFTESTCASE_SLOW(many_clients, 150);
1193 DEFTESTCASE_SLOW(many_clients_tcp, 20);
1194 DEFTESTCASE_SLOW(many_clients_tcp_b, 20);
999 DEFTESTCASE_SLOW(many_group, 100); 1195 DEFTESTCASE_SLOW(many_group, 100);
1000 return s; 1196 return s;
1001} 1197}
diff --git a/auto_tests/toxav_basic_test.c b/auto_tests/toxav_basic_test.c
index 9f04dc11..79c5b724 100644
--- a/auto_tests/toxav_basic_test.c
+++ b/auto_tests/toxav_basic_test.c
@@ -66,8 +66,8 @@ void t_toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, vo
66} 66}
67void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number, 67void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number,
68 uint16_t width, uint16_t height, 68 uint16_t width, uint16_t height,
69 uint8_t const *y, uint8_t const *u, uint8_t const *v, 69 uint8_t const *y, uint8_t const *u, uint8_t const *v, uint8_t const *a,
70 int32_t ystride, int32_t ustride, int32_t vstride, 70 int32_t ystride, int32_t ustride, int32_t vstride, int32_t astride,
71 void *user_data) 71 void *user_data)
72{ 72{
73 (void) av; 73 (void) av;
@@ -185,13 +185,13 @@ START_TEST(test_AV_flows)
185 185
186 toxav_callback_call(AliceAV, t_toxav_call_cb, &AliceCC); 186 toxav_callback_call(AliceAV, t_toxav_call_cb, &AliceCC);
187 toxav_callback_call_state(AliceAV, t_toxav_call_state_cb, &AliceCC); 187 toxav_callback_call_state(AliceAV, t_toxav_call_state_cb, &AliceCC);
188 toxav_callback_receive_video_frame(AliceAV, t_toxav_receive_video_frame_cb, &AliceCC); 188 toxav_callback_video_receive_frame(AliceAV, t_toxav_receive_video_frame_cb, &AliceCC);
189 toxav_callback_receive_audio_frame(AliceAV, t_toxav_receive_audio_frame_cb, &AliceCC); 189 toxav_callback_audio_receive_frame(AliceAV, t_toxav_receive_audio_frame_cb, &AliceCC);
190 190
191 toxav_callback_call(BobAV, t_toxav_call_cb, &BobCC); 191 toxav_callback_call(BobAV, t_toxav_call_cb, &BobCC);
192 toxav_callback_call_state(BobAV, t_toxav_call_state_cb, &BobCC); 192 toxav_callback_call_state(BobAV, t_toxav_call_state_cb, &BobCC);
193 toxav_callback_receive_video_frame(BobAV, t_toxav_receive_video_frame_cb, &BobCC); 193 toxav_callback_video_receive_frame(BobAV, t_toxav_receive_video_frame_cb, &BobCC);
194 toxav_callback_receive_audio_frame(BobAV, t_toxav_receive_audio_frame_cb, &BobCC); 194 toxav_callback_audio_receive_frame(BobAV, t_toxav_receive_audio_frame_cb, &BobCC);
195 195
196 printf("Created 2 instances of ToxAV\n"); 196 printf("Created 2 instances of ToxAV\n");
197 printf("All set after %llu seconds!\n", time(NULL) - cur_time); 197 printf("All set after %llu seconds!\n", time(NULL) - cur_time);
@@ -214,7 +214,7 @@ START_TEST(test_AV_flows)
214 long long unsigned int start_time = time(NULL); \ 214 long long unsigned int start_time = time(NULL); \
215 \ 215 \
216 \ 216 \
217 while (BobCC.state != TOXAV_CALL_STATE_END) { \ 217 while (BobCC.state != TOXAV_CALL_STATE_FINISHED) { \
218 \ 218 \
219 if (BobCC.incoming) { \ 219 if (BobCC.incoming) { \
220 TOXAV_ERR_ANSWER rc; \ 220 TOXAV_ERR_ANSWER rc; \
@@ -228,7 +228,7 @@ START_TEST(test_AV_flows)
228 } else { \ 228 } else { \
229 /* TODO rtp */ \ 229 /* TODO rtp */ \
230 \ 230 \
231 if (time(NULL) - start_time == 5) { \ 231 if (time(NULL) - start_time >= 1) { \
232 \ 232 \
233 TOXAV_ERR_CALL_CONTROL rc; \ 233 TOXAV_ERR_CALL_CONTROL rc; \
234 toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc); \ 234 toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc); \
@@ -358,8 +358,10 @@ START_TEST(test_AV_flows)
358 /* At first try all stuff while in invalid state */ 358 /* At first try all stuff while in invalid state */
359 ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_PAUSE, NULL)); 359 ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_PAUSE, NULL));
360 ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_RESUME, NULL)); 360 ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_RESUME, NULL));
361 ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL)); 361 ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_MUTE_AUDIO, NULL));
362 ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_HIDE_VIDEO, NULL)); 362 ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_UNMUTE_AUDIO, NULL));
363 ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_HIDE_VIDEO, NULL));
364 ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_SHOW_VIDEO, NULL));
363 365
364 { 366 {
365 TOXAV_ERR_ANSWER rc; 367 TOXAV_ERR_ANSWER rc;
@@ -377,32 +379,32 @@ START_TEST(test_AV_flows)
377 printf("Pause and Resume\n"); 379 printf("Pause and Resume\n");
378 ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_PAUSE, NULL)); 380 ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_PAUSE, NULL));
379 iterate_tox(bootstrap, Alice, Bob); 381 iterate_tox(bootstrap, Alice, Bob);
380 ck_assert(BobCC.state == TOXAV_CALL_STATE_PAUSED); 382 ck_assert(BobCC.state == 0);
381 ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_RESUME, NULL)); 383 ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_RESUME, NULL));
382 iterate_tox(bootstrap, Alice, Bob); 384 iterate_tox(bootstrap, Alice, Bob);
383 ck_assert(BobCC.state & (TOXAV_CALL_STATE_SENDING_A | TOXAV_CALL_STATE_SENDING_V)); 385 ck_assert(BobCC.state & (TOXAV_CALL_STATE_SENDING_A | TOXAV_CALL_STATE_SENDING_V));
384 386
385 /* Mute/Unmute single */ 387 /* Mute/Unmute single */
386 printf("Mute/Unmute single\n"); 388 printf("Mute/Unmute single\n");
387 ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL)); 389 ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_MUTE_AUDIO, NULL));
388 iterate_tox(bootstrap, Alice, Bob); 390 iterate_tox(bootstrap, Alice, Bob);
389 ck_assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_A); 391 ck_assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_A);
390 ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL)); 392 ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_UNMUTE_AUDIO, NULL));
391 iterate_tox(bootstrap, Alice, Bob); 393 iterate_tox(bootstrap, Alice, Bob);
392 ck_assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_A); 394 ck_assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_A);
393 395
394 /* Mute/Unmute both */ 396 /* Mute/Unmute both */
395 printf("Mute/Unmute both\n"); 397 printf("Mute/Unmute both\n");
396 ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL)); 398 ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_MUTE_AUDIO, NULL));
397 iterate_tox(bootstrap, Alice, Bob); 399 iterate_tox(bootstrap, Alice, Bob);
398 ck_assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_A); 400 ck_assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_A);
399 ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_HIDE_VIDEO, NULL)); 401 ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_HIDE_VIDEO, NULL));
400 iterate_tox(bootstrap, Alice, Bob); 402 iterate_tox(bootstrap, Alice, Bob);
401 ck_assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_V); 403 ck_assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_V);
402 ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL)); 404 ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_UNMUTE_AUDIO, NULL));
403 iterate_tox(bootstrap, Alice, Bob); 405 iterate_tox(bootstrap, Alice, Bob);
404 ck_assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_A); 406 ck_assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_A);
405 ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_HIDE_VIDEO, NULL)); 407 ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_SHOW_VIDEO, NULL));
406 iterate_tox(bootstrap, Alice, Bob); 408 iterate_tox(bootstrap, Alice, Bob);
407 ck_assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_V); 409 ck_assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_V);
408 410
@@ -417,7 +419,7 @@ START_TEST(test_AV_flows)
417 } 419 }
418 420
419 iterate_tox(bootstrap, Alice, Bob); 421 iterate_tox(bootstrap, Alice, Bob);
420 ck_assert(BobCC.state == TOXAV_CALL_STATE_END); 422 ck_assert(BobCC.state == TOXAV_CALL_STATE_FINISHED);
421 423
422 printf("Success!\n"); 424 printf("Success!\n");
423 } 425 }
diff --git a/auto_tests/toxav_many_test.c b/auto_tests/toxav_many_test.c
index f913c9d3..a15acce3 100644
--- a/auto_tests/toxav_many_test.c
+++ b/auto_tests/toxav_many_test.c
@@ -63,8 +63,8 @@ void t_toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, vo
63} 63}
64void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number, 64void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number,
65 uint16_t width, uint16_t height, 65 uint16_t width, uint16_t height,
66 uint8_t const *y, uint8_t const *u, uint8_t const *v, 66 uint8_t const *y, uint8_t const *u, uint8_t const *v, uint8_t const *a,
67 int32_t ystride, int32_t ustride, int32_t vstride, 67 int32_t ystride, int32_t ustride, int32_t vstride, int32_t stride,
68 void *user_data) 68 void *user_data)
69{ 69{
70 (void) av; 70 (void) av;
@@ -115,8 +115,8 @@ ToxAV* setup_av_instance(Tox* tox, CallControl *CC)
115 115
116 toxav_callback_call(av, t_toxav_call_cb, CC); 116 toxav_callback_call(av, t_toxav_call_cb, CC);
117 toxav_callback_call_state(av, t_toxav_call_state_cb, CC); 117 toxav_callback_call_state(av, t_toxav_call_state_cb, CC);
118 toxav_callback_receive_video_frame(av, t_toxav_receive_video_frame_cb, CC); 118 toxav_callback_video_receive_frame(av, t_toxav_receive_video_frame_cb, CC);
119 toxav_callback_receive_audio_frame(av, t_toxav_receive_audio_frame_cb, CC); 119 toxav_callback_audio_receive_frame(av, t_toxav_receive_audio_frame_cb, CC);
120 120
121 return av; 121 return av;
122} 122}
@@ -161,22 +161,24 @@ void* call_thread(void* pd)
161 uint8_t video_y[800*600]; 161 uint8_t video_y[800*600];
162 uint8_t video_u[800*600 / 2]; 162 uint8_t video_u[800*600 / 2];
163 uint8_t video_v[800*600 / 2]; 163 uint8_t video_v[800*600 / 2];
164 uint8_t video_a[800*600];
164 165
165 memset(PCM, 0, sizeof(PCM)); 166 memset(PCM, 0, sizeof(PCM));
166 memset(video_y, 0, sizeof(video_y)); 167 memset(video_y, 0, sizeof(video_y));
167 memset(video_u, 0, sizeof(video_u)); 168 memset(video_u, 0, sizeof(video_u));
168 memset(video_v, 0, sizeof(video_v)); 169 memset(video_v, 0, sizeof(video_v));
170 memset(video_a, 0, sizeof(video_a));
169 171
170 time_t start_time = time(NULL); 172 time_t start_time = time(NULL);
171 while(time(NULL) - start_time < 4) { 173 while(time(NULL) - start_time < 4) {
172 toxav_iterate(AliceAV); 174 toxav_iterate(AliceAV);
173 toxav_iterate(BobAV); 175 toxav_iterate(BobAV);
174 176
175 toxav_send_audio_frame(AliceAV, friend_number, PCM, 960, 1, 48000, NULL); 177 toxav_audio_send_frame(AliceAV, friend_number, PCM, 960, 1, 48000, NULL);
176 toxav_send_audio_frame(BobAV, 0, PCM, 960, 1, 48000, NULL); 178 toxav_audio_send_frame(BobAV, 0, PCM, 960, 1, 48000, NULL);
177 179
178 toxav_send_video_frame(AliceAV, friend_number, 800, 600, video_y, video_u, video_v, NULL); 180 toxav_video_send_frame(AliceAV, friend_number, 800, 600, video_y, video_u, video_v, video_a, NULL);
179 toxav_send_video_frame(BobAV, 0, 800, 600, video_y, video_u, video_v, NULL); 181 toxav_video_send_frame(BobAV, 0, 800, 600, video_y, video_u, video_v, video_a, NULL);
180 182
181 c_sleep(10); 183 c_sleep(10);
182 } 184 }
diff --git a/other/apidsl/README.md b/other/apidsl/README.md
index c8241eb8..0b3e776d 100644
--- a/other/apidsl/README.md
+++ b/other/apidsl/README.md
@@ -4,7 +4,7 @@ with: https://github.com/iphydf/apidsl
4You can also use the following command if you can't install it: 4You can also use the following command if you can't install it:
5 5
6``` 6```
7cat tox.in.h | curl -X POST --data-binary @- https://criticism.herokuapp.com/apidsl > tox.h 7curl -X POST --data-binary @- https://criticism.herokuapp.com/apidsl < tox.in.h > tox.h
8``` 8```
9 9
10Note that the output must be passed through astyle with the config in 10Note that the output must be passed through astyle with the config in
diff --git a/other/apidsl/tox.in.h b/other/apidsl/tox.in.h
index 84a4a03e..dd47df23 100644
--- a/other/apidsl/tox.in.h
+++ b/other/apidsl/tox.in.h
@@ -411,6 +411,11 @@ static class options {
411 * The end port of the inclusive port range to attempt to use. 411 * The end port of the inclusive port range to attempt to use.
412 */ 412 */
413 uint16_t end_port; 413 uint16_t end_port;
414
415 /**
416 * The port to use for the TCP server. If 0, the tcp server is disabled.
417 */
418 uint16_t tcp_port;
414 } 419 }
415 420
416 421
diff --git a/other/apidsl/toxav.in.h b/other/apidsl/toxav.in.h
index 9de1e184..bcf554ac 100644
--- a/other/apidsl/toxav.in.h
+++ b/other/apidsl/toxav.in.h
@@ -622,4 +622,4 @@ namespace video {
622} 622}
623%{ 623%{
624#endif 624#endif
625%} \ No newline at end of file 625%}
diff --git a/other/bootstrap_daemon/tox-bootstrapd.c b/other/bootstrap_daemon/tox-bootstrapd.c
index 1bcae732..8b5e6a4b 100644
--- a/other/bootstrap_daemon/tox-bootstrapd.c
+++ b/other/bootstrap_daemon/tox-bootstrapd.c
@@ -105,6 +105,9 @@ int manage_keys(DHT *dht, char *keys_file_path)
105 105
106 keys_file = fopen(keys_file_path, "w"); 106 keys_file = fopen(keys_file_path, "w");
107 107
108 if (!keys_file)
109 return 0;
110
108 const size_t write_size = fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file); 111 const size_t write_size = fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file);
109 112
110 if (write_size != KEYS_SIZE) { 113 if (write_size != KEYS_SIZE) {
diff --git a/testing/av_test.c b/testing/av_test.c
index 0e7af66e..de973d91 100644
--- a/testing/av_test.c
+++ b/testing/av_test.c
@@ -134,10 +134,15 @@ void t_toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, vo
134} 134}
135void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number, 135void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number,
136 uint16_t width, uint16_t height, 136 uint16_t width, uint16_t height,
137 uint8_t const *y, uint8_t const *u, uint8_t const *v, 137 uint8_t const *y, uint8_t const *u, uint8_t const *v, uint8_t const *a,
138 int32_t ystride, int32_t ustride, int32_t vstride, 138 int32_t ystride, int32_t ustride, int32_t vstride, int32_t astride,
139 void *user_data) 139 void *user_data)
140{ 140{
141 ystride = abs(ystride);
142 ustride = abs(ustride);
143 vstride = abs(vstride);
144 astride = abs(astride);
145
141 uint16_t *img_data = malloc(height * width * 6); 146 uint16_t *img_data = malloc(height * width * 6);
142 147
143 unsigned long int i, j; 148 unsigned long int i, j;
@@ -278,18 +283,18 @@ void initialize_tox(Tox** bootstrap, ToxAV** AliceAV, CallControl* AliceCC, ToxA
278 /* Alice */ 283 /* Alice */
279 toxav_callback_call(*AliceAV, t_toxav_call_cb, AliceCC); 284 toxav_callback_call(*AliceAV, t_toxav_call_cb, AliceCC);
280 toxav_callback_call_state(*AliceAV, t_toxav_call_state_cb, AliceCC); 285 toxav_callback_call_state(*AliceAV, t_toxav_call_state_cb, AliceCC);
281 toxav_callback_receive_video_frame(*AliceAV, t_toxav_receive_video_frame_cb, AliceCC); 286 toxav_callback_video_receive_frame(*AliceAV, t_toxav_receive_video_frame_cb, AliceCC);
282 toxav_callback_receive_audio_frame(*AliceAV, t_toxav_receive_audio_frame_cb, AliceCC); 287 toxav_callback_audio_receive_frame(*AliceAV, t_toxav_receive_audio_frame_cb, AliceCC);
283 toxav_callback_audio_bit_rate_status(*AliceAV, t_toxav_audio_bit_rate_status_cb, AliceCC);
284 toxav_callback_video_bit_rate_status(*AliceAV, t_toxav_video_bit_rate_status_cb, AliceCC); 288 toxav_callback_video_bit_rate_status(*AliceAV, t_toxav_video_bit_rate_status_cb, AliceCC);
289 toxav_callback_audio_bit_rate_status(*AliceAV, t_toxav_audio_bit_rate_status_cb, AliceCC);
285 290
286 /* Bob */ 291 /* Bob */
287 toxav_callback_call(*BobAV, t_toxav_call_cb, BobCC); 292 toxav_callback_call(*BobAV, t_toxav_call_cb, BobCC);
288 toxav_callback_call_state(*BobAV, t_toxav_call_state_cb, BobCC); 293 toxav_callback_call_state(*BobAV, t_toxav_call_state_cb, BobCC);
289 toxav_callback_receive_video_frame(*BobAV, t_toxav_receive_video_frame_cb, BobCC); 294 toxav_callback_video_receive_frame(*BobAV, t_toxav_receive_video_frame_cb, BobCC);
290 toxav_callback_receive_audio_frame(*BobAV, t_toxav_receive_audio_frame_cb, BobCC); 295 toxav_callback_audio_receive_frame(*BobAV, t_toxav_receive_audio_frame_cb, BobCC);
291 toxav_callback_audio_bit_rate_status(*BobAV, t_toxav_audio_bit_rate_status_cb, BobCC);
292 toxav_callback_video_bit_rate_status(*BobAV, t_toxav_video_bit_rate_status_cb, BobCC); 296 toxav_callback_video_bit_rate_status(*BobAV, t_toxav_video_bit_rate_status_cb, BobCC);
297 toxav_callback_audio_bit_rate_status(*BobAV, t_toxav_audio_bit_rate_status_cb, BobCC);
293 298
294 299
295 printf("Created 2 instances of ToxAV\n"); 300 printf("Created 2 instances of ToxAV\n");
@@ -364,7 +369,7 @@ int send_opencv_img(ToxAV* av, uint32_t friend_number, const IplImage* img)
364 } 369 }
365 370
366 371
367 int rc = toxav_send_video_frame(av, friend_number, img->width, img->height, planes[0], planes[1], planes[2], NULL); 372 int rc = toxav_video_send_frame(av, friend_number, img->width, img->height, planes[0], planes[1], planes[2], NULL, NULL);
368 free(planes[0]); 373 free(planes[0]);
369 free(planes[1]); 374 free(planes[1]);
370 free(planes[2]); 375 free(planes[2]);
@@ -586,7 +591,7 @@ int main (int argc, char** argv)
586 err = Pa_StartStream(adout); 591 err = Pa_StartStream(adout);
587 assert(err == paNoError); 592 assert(err == paNoError);
588 593
589 toxav_set_audio_bit_rate(AliceAV, 0, 64, false, NULL); 594 toxav_audio_bit_rate_set(AliceAV, 0, 64, false, NULL);
590 595
591 /* Start write thread */ 596 /* Start write thread */
592 pthread_t t; 597 pthread_t t;
@@ -599,7 +604,7 @@ int main (int argc, char** argv)
599 int64_t count = sf_read_short(af_handle, PCM, frame_size); 604 int64_t count = sf_read_short(af_handle, PCM, frame_size);
600 if (count > 0) { 605 if (count > 0) {
601 TOXAV_ERR_SEND_FRAME rc; 606 TOXAV_ERR_SEND_FRAME rc;
602 if (toxav_send_audio_frame(AliceAV, 0, PCM, count/af_info.channels, af_info.channels, af_info.samplerate, &rc) == false) { 607 if (toxav_audio_send_frame(AliceAV, 0, PCM, count/af_info.channels, af_info.channels, af_info.samplerate, &rc) == false) {
603 printf("Error sending frame of size %ld: %d\n", count, rc); 608 printf("Error sending frame of size %ld: %d\n", count, rc);
604 } 609 }
605 } 610 }
@@ -691,7 +696,7 @@ int main (int argc, char** argv)
691 exit(1); 696 exit(1);
692 } 697 }
693 698
694 toxav_set_video_bit_rate(AliceAV, 0, 5000, false, NULL); 699 toxav_video_bit_rate_set(AliceAV, 0, 5000, false, NULL);
695 700
696 time_t start_time = time(NULL); 701 time_t start_time = time(NULL);
697 while(start_time + 90 > time(NULL)) { 702 while(start_time + 90 > time(NULL)) {
diff --git a/testing/irc_syncbot.c b/testing/irc_syncbot.c
index b879e4eb..2d326c4b 100644
--- a/testing/irc_syncbot.c
+++ b/testing/irc_syncbot.c
@@ -163,9 +163,15 @@ void send_irc_group(Tox *tox, uint8_t *msg, uint16_t len)
163 uint8_t req[len]; 163 uint8_t req[len];
164 unsigned int i; 164 unsigned int i;
165 165
166 unsigned int spaces = 0;
167
166 for (i = 0; i < (len - 1); ++i) { 168 for (i = 0; i < (len - 1); ++i) {
167 if (msg[i + 1] == ':') { 169 if (msg[i + 1] == ' ') {
168 break; 170 ++spaces;
171 } else {
172 if (spaces >= 3 && msg[i + 1] == ':') {
173 break;
174 }
169 } 175 }
170 176
171 req[i] = msg[i + 1]; 177 req[i] = msg[i + 1];
@@ -227,11 +233,6 @@ Tox *init_tox(int argc, char *argv[])
227 tox_callback_group_message(tox, &copy_groupmessage, 0); 233 tox_callback_group_message(tox, &copy_groupmessage, 0);
228 tox_callback_group_action(tox, &copy_groupmessage, 0); 234 tox_callback_group_action(tox, &copy_groupmessage, 0);
229 235
230 uint16_t port = atoi(argv[argvoffset + 2]);
231 unsigned char *binary_string = hex_string_to_bin(argv[argvoffset + 3]);
232 tox_bootstrap(tox, argv[argvoffset + 1], port, binary_string, 0);
233 free(binary_string);
234
235 char temp_id[128]; 236 char temp_id[128];
236 printf("\nEnter the address of irc_syncbots master (38 bytes HEX format):\n"); 237 printf("\nEnter the address of irc_syncbots master (38 bytes HEX format):\n");
237 238
@@ -239,6 +240,11 @@ Tox *init_tox(int argc, char *argv[])
239 exit (1); 240 exit (1);
240 } 241 }
241 242
243 uint16_t port = atoi(argv[argvoffset + 2]);
244 unsigned char *binary_string = hex_string_to_bin(argv[argvoffset + 3]);
245 tox_bootstrap(tox, argv[argvoffset + 1], port, binary_string, 0);
246 free(binary_string);
247
242 uint8_t *bin_id = hex_string_to_bin(temp_id); 248 uint8_t *bin_id = hex_string_to_bin(temp_id);
243 uint32_t num = tox_friend_add(tox, bin_id, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo") - 1, 0); 249 uint32_t num = tox_friend_add(tox, bin_id, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo") - 1, 0);
244 free(bin_id); 250 free(bin_id);
diff --git a/toxav/audio.c b/toxav/audio.c
index c592a7da..f6993a1d 100644
--- a/toxav/audio.c
+++ b/toxav/audio.c
@@ -38,7 +38,7 @@ bool reconfigure_audio_decoder(ACSession* ac, int32_t sampling_rate, int8_t chan
38 38
39 39
40 40
41ACSession* ac_new(ToxAV* av, uint32_t friend_number, toxav_receive_audio_frame_cb *cb, void *cb_data) 41ACSession* ac_new(ToxAV* av, uint32_t friend_number, toxav_audio_receive_frame_cb *cb, void *cb_data)
42{ 42{
43 ACSession *ac = calloc(sizeof(ACSession), 1); 43 ACSession *ac = calloc(sizeof(ACSession), 1);
44 44
diff --git a/toxav/audio.h b/toxav/audio.h
index c003bac0..9ef10ae4 100644
--- a/toxav/audio.h
+++ b/toxav/audio.h
@@ -61,13 +61,13 @@ typedef struct ACSession_s {
61 61
62 ToxAV* av; 62 ToxAV* av;
63 uint32_t friend_number; 63 uint32_t friend_number;
64 PAIR(toxav_receive_audio_frame_cb *, void *) acb; /* Audio frame receive callback */ 64 PAIR(toxav_audio_receive_frame_cb *, void *) acb; /* Audio frame receive callback */
65} ACSession; 65} ACSession;
66 66
67/* 67/*
68 * Create new Audio Codec session. 68 * Create new Audio Codec session.
69 */ 69 */
70ACSession* ac_new(ToxAV* av, uint32_t friend_number, toxav_receive_audio_frame_cb *cb, void *cb_data); 70ACSession* ac_new(ToxAV* av, uint32_t friend_number, toxav_audio_receive_frame_cb *cb, void *cb_data);
71/* 71/*
72 * Kill the Audio Codec session. 72 * Kill the Audio Codec session.
73 */ 73 */
diff --git a/toxav/msi.c b/toxav/msi.c
index 65b6c4e4..d3559160 100644
--- a/toxav/msi.c
+++ b/toxav/msi.c
@@ -683,7 +683,7 @@ void handle_push ( MSICall *call, const MSIMessage *msg )
683 683
684 /* Only act if capabilities changed */ 684 /* Only act if capabilities changed */
685 if ( call->peer_capabilities != msg->capabilities.value) { 685 if ( call->peer_capabilities != msg->capabilities.value) {
686 LOGGER_INFO("Friend is changing capabilities"); 686 LOGGER_INFO("Friend is changing capabilities to: %u", msg->capabilities.value);
687 687
688 call->peer_capabilities = msg->capabilities.value; 688 call->peer_capabilities = msg->capabilities.value;
689 if ( invoke_callback(call, msi_OnCapabilities) == -1 ) 689 if ( invoke_callback(call, msi_OnCapabilities) == -1 )
diff --git a/toxav/msi.h b/toxav/msi.h
index 4836ae89..59f32c1d 100644
--- a/toxav/msi.h
+++ b/toxav/msi.h
@@ -50,10 +50,10 @@ typedef enum {
50 * Supported capabilities 50 * Supported capabilities
51 */ 51 */
52typedef enum { 52typedef enum {
53 msi_CapSAudio = 1, /* sending audio */ 53 msi_CapSAudio = 4, /* sending audio */
54 msi_CapSVideo = 2, /* sending video */ 54 msi_CapSVideo = 8, /* sending video */
55 msi_CapRAudio = 4, /* receiving audio */ 55 msi_CapRAudio = 16, /* receiving audio */
56 msi_CapRVideo = 8, /* receiving video */ 56 msi_CapRVideo = 32, /* receiving video */
57} MSICapabilities; 57} MSICapabilities;
58 58
59 59
diff --git a/toxav/toxav.c b/toxav/toxav.c
index 5e32f196..7ce6b9bc 100644
--- a/toxav/toxav.c
+++ b/toxav/toxav.c
@@ -91,8 +91,8 @@ struct ToxAV {
91 91
92 PAIR(toxav_call_cb *, void*) ccb; /* Call callback */ 92 PAIR(toxav_call_cb *, void*) ccb; /* Call callback */
93 PAIR(toxav_call_state_cb *, void *) scb; /* Call state callback */ 93 PAIR(toxav_call_state_cb *, void *) scb; /* Call state callback */
94 PAIR(toxav_receive_audio_frame_cb *, void *) acb; /* Audio frame receive callback */ 94 PAIR(toxav_audio_receive_frame_cb *, void *) acb; /* Audio frame receive callback */
95 PAIR(toxav_receive_video_frame_cb *, void *) vcb; /* Video frame receive callback */ 95 PAIR(toxav_video_receive_frame_cb *, void *) vcb; /* Video frame receive callback */
96 PAIR(toxav_audio_bit_rate_status_cb *, void *) abcb; /* Audio bit rate control callback */ 96 PAIR(toxav_audio_bit_rate_status_cb *, void *) abcb; /* Audio bit rate control callback */
97 PAIR(toxav_video_bit_rate_status_cb *, void *) vbcb; /* Video bit rate control callback */ 97 PAIR(toxav_video_bit_rate_status_cb *, void *) vbcb; /* Video bit rate control callback */
98 98
@@ -122,6 +122,27 @@ void call_kill_transmission(ToxAVCall* call);
122void ba_set(ToxAvBitrateAdapter* ba, uint32_t bit_rate); 122void ba_set(ToxAvBitrateAdapter* ba, uint32_t bit_rate);
123bool ba_shoud_send_dummy(ToxAvBitrateAdapter* ba); 123bool ba_shoud_send_dummy(ToxAvBitrateAdapter* ba);
124 124
125uint32_t toxav_version_major(void)
126{
127 return 0;
128}
129uint32_t toxav_version_minor(void)
130{
131 return 0;
132}
133uint32_t toxav_version_patch(void)
134{
135 return 0;
136}
137bool toxav_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch)
138{
139 (void)major;
140 (void)minor;
141 (void)patch;
142
143 return 1;
144}
145
125ToxAV* toxav_new(Tox* tox, TOXAV_ERR_NEW* error) 146ToxAV* toxav_new(Tox* tox, TOXAV_ERR_NEW* error)
126{ 147{
127 TOXAV_ERR_NEW rc = TOXAV_ERR_NEW_OK; 148 TOXAV_ERR_NEW rc = TOXAV_ERR_NEW_OK;
@@ -204,7 +225,7 @@ void toxav_kill(ToxAV* av)
204 free(av); 225 free(av);
205} 226}
206 227
207Tox* toxav_get_tox(ToxAV* av) 228Tox* toxav_get_tox(const ToxAV* av)
208{ 229{
209 return (Tox*) av->m; 230 return (Tox*) av->m;
210} 231}
@@ -430,20 +451,14 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
430 goto END; 451 goto END;
431 } 452 }
432 453
433
434 ToxAVCall* call = call_get(av, friend_number); 454 ToxAVCall* call = call_get(av, friend_number);
435 if (call == NULL) { 455 if (call == NULL || (!call->active && control != TOXAV_CALL_CONTROL_CANCEL)) {
436 rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; 456 rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL;
437 goto END; 457 goto END;
438 } 458 }
439 459
440 switch (control) { 460 switch (control) {
441 case TOXAV_CALL_CONTROL_RESUME: { 461 case TOXAV_CALL_CONTROL_RESUME: {
442 if (!call->active) {
443 rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL;
444 goto END;
445 }
446
447 /* Only act if paused and had media transfer active before */ 462 /* Only act if paused and had media transfer active before */
448 if (call->msi_call->self_capabilities == 0 && 463 if (call->msi_call->self_capabilities == 0 &&
449 call->previous_self_capabilities ) { 464 call->previous_self_capabilities ) {
@@ -459,17 +474,12 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
459 rtp_start_receiving(call->audio.first); 474 rtp_start_receiving(call->audio.first);
460 rtp_start_receiving(call->video.first); 475 rtp_start_receiving(call->video.first);
461 } else { 476 } else {
462 rc = TOXAV_ERR_CALL_CONTROL_NOT_PAUSED; 477 rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION;
463 goto END; 478 goto END;
464 } 479 }
465 } break; 480 } break;
466 481
467 case TOXAV_CALL_CONTROL_PAUSE: { 482 case TOXAV_CALL_CONTROL_PAUSE: {
468 if (!call->active) {
469 rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL;
470 goto END;
471 }
472
473 /* Only act if not already paused */ 483 /* Only act if not already paused */
474 if (call->msi_call->self_capabilities) { 484 if (call->msi_call->self_capabilities) {
475 call->previous_self_capabilities = call->msi_call->self_capabilities; 485 call->previous_self_capabilities = call->msi_call->self_capabilities;
@@ -484,7 +494,7 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
484 rtp_stop_receiving(call->audio.first); 494 rtp_stop_receiving(call->audio.first);
485 rtp_stop_receiving(call->video.first); 495 rtp_stop_receiving(call->video.first);
486 } else { 496 } else {
487 rc = TOXAV_ERR_CALL_CONTROL_ALREADY_PAUSED; 497 rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION;
488 goto END; 498 goto END;
489 } 499 }
490 } break; 500 } break;
@@ -498,12 +508,7 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
498 call_remove(call); 508 call_remove(call);
499 } break; 509 } break;
500 510
501 case TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO: { 511 case TOXAV_CALL_CONTROL_MUTE_AUDIO: {
502 if (!call->active) {
503 rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL;
504 goto END;
505 }
506
507 if (call->msi_call->self_capabilities & msi_CapRAudio) { 512 if (call->msi_call->self_capabilities & msi_CapRAudio) {
508 if (msi_change_capabilities(call->msi_call, call-> 513 if (msi_change_capabilities(call->msi_call, call->
509 msi_call->self_capabilities ^ msi_CapRAudio) == -1) { 514 msi_call->self_capabilities ^ msi_CapRAudio) == -1) {
@@ -515,9 +520,13 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
515 520
516 rtp_stop_receiving(call->audio.first); 521 rtp_stop_receiving(call->audio.first);
517 } else { 522 } else {
518 /* This call was already muted so notify the friend that he can 523 rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION;
519 * start sending audio again 524 goto END;
520 */ 525 }
526 } break;
527
528 case TOXAV_CALL_CONTROL_UNMUTE_AUDIO: {
529 if (call->msi_call->self_capabilities ^ msi_CapRAudio) {
521 if (msi_change_capabilities(call->msi_call, call-> 530 if (msi_change_capabilities(call->msi_call, call->
522 msi_call->self_capabilities | msi_CapRAudio) == -1) { 531 msi_call->self_capabilities | msi_CapRAudio) == -1) {
523 /* The only reason for this function to fail is invalid state 532 /* The only reason for this function to fail is invalid state
@@ -527,15 +536,13 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
527 } 536 }
528 537
529 rtp_start_receiving(call->audio.first); 538 rtp_start_receiving(call->audio.first);
539 } else {
540 rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION;
541 goto END;
530 } 542 }
531 } break; 543 } break;
532 544
533 case TOXAV_CALL_CONTROL_TOGGLE_HIDE_VIDEO: { 545 case TOXAV_CALL_CONTROL_HIDE_VIDEO: {
534 if (!call->active) {
535 rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL;
536 goto END;
537 }
538
539 if (call->msi_call->self_capabilities & msi_CapRVideo) { 546 if (call->msi_call->self_capabilities & msi_CapRVideo) {
540 if (msi_change_capabilities(call->msi_call, call-> 547 if (msi_change_capabilities(call->msi_call, call->
541 msi_call->self_capabilities ^ msi_CapRVideo) == -1) { 548 msi_call->self_capabilities ^ msi_CapRVideo) == -1) {
@@ -547,9 +554,13 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
547 554
548 rtp_stop_receiving(call->video.first); 555 rtp_stop_receiving(call->video.first);
549 } else { 556 } else {
550 /* This call was already muted so notify the friend that he can 557 rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION;
551 * start sending video again 558 goto END;
552 */ 559 }
560 } break;
561
562 case TOXAV_CALL_CONTROL_SHOW_VIDEO: {
563 if (call->msi_call->self_capabilities ^ msi_CapRVideo) {
553 if (msi_change_capabilities(call->msi_call, call-> 564 if (msi_change_capabilities(call->msi_call, call->
554 msi_call->self_capabilities | msi_CapRVideo) == -1) { 565 msi_call->self_capabilities | msi_CapRVideo) == -1) {
555 /* The only reason for this function to fail is invalid state 566 /* The only reason for this function to fail is invalid state
@@ -558,7 +569,10 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
558 goto END; 569 goto END;
559 } 570 }
560 571
561 rtp_start_receiving(call->video.first); 572 rtp_start_receiving(call->audio.first);
573 } else {
574 rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION;
575 goto END;
562 } 576 }
563 } break; 577 } break;
564 } 578 }
@@ -572,26 +586,26 @@ END:
572 return rc == TOXAV_ERR_CALL_CONTROL_OK; 586 return rc == TOXAV_ERR_CALL_CONTROL_OK;
573} 587}
574 588
575void toxav_callback_video_bit_rate_status(ToxAV* av, toxav_video_bit_rate_status_cb* function, void* user_data) 589void toxav_callback_audio_bit_rate_status(ToxAV* av, toxav_audio_bit_rate_status_cb* function, void* user_data)
576{ 590{
577 pthread_mutex_lock(av->mutex); 591 pthread_mutex_lock(av->mutex);
578 av->vbcb.first = function; 592 av->abcb.first = function;
579 av->vbcb.second = user_data; 593 av->abcb.second = user_data;
580 pthread_mutex_unlock(av->mutex); 594 pthread_mutex_unlock(av->mutex);
581} 595}
582 596
583bool toxav_set_video_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t video_bit_rate, bool force, TOXAV_ERR_BIT_RATE* error) 597bool toxav_audio_bit_rate_set(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_SET_BIT_RATE* error)
584{ 598{
585 TOXAV_ERR_BIT_RATE rc = TOXAV_ERR_BIT_RATE_OK; 599 TOXAV_ERR_SET_BIT_RATE rc = TOXAV_ERR_SET_BIT_RATE_OK;
586 ToxAVCall* call; 600 ToxAVCall* call;
587 601
588 if (m_friend_exists(av->m, friend_number) == 0) { 602 if (m_friend_exists(av->m, friend_number) == 0) {
589 rc = TOXAV_ERR_BIT_RATE_FRIEND_NOT_FOUND; 603 rc = TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_FOUND;
590 goto END; 604 goto END;
591 } 605 }
592 606
593 if (video_bit_rate_invalid(video_bit_rate)) { 607 if (audio_bit_rate_invalid(audio_bit_rate)) {
594 rc = TOXAV_ERR_BIT_RATE_INVALID; 608 rc = TOXAV_ERR_SET_BIT_RATE_INVALID;
595 goto END; 609 goto END;
596 } 610 }
597 611
@@ -599,26 +613,27 @@ bool toxav_set_video_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t video_
599 call = call_get(av, friend_number); 613 call = call_get(av, friend_number);
600 if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) { 614 if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) {
601 pthread_mutex_unlock(av->mutex); 615 pthread_mutex_unlock(av->mutex);
602 rc = TOXAV_ERR_BIT_RATE_FRIEND_NOT_IN_CALL; 616 rc = TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_IN_CALL;
603 goto END; 617 goto END;
604 } 618 }
605 619
606 if (call->video_bit_rate == video_bit_rate || (call->vba.active && call->vba.bit_rate == video_bit_rate)) { 620 if (call->audio_bit_rate == audio_bit_rate || (call->aba.active && call->aba.bit_rate == audio_bit_rate)) {
607 pthread_mutex_unlock(av->mutex); 621 pthread_mutex_unlock(av->mutex);
608 goto END; 622 goto END;
609 } 623 }
610 624
625
611 pthread_mutex_lock(call->mutex); 626 pthread_mutex_lock(call->mutex);
612 627
613 if (video_bit_rate > call->video_bit_rate && !force) 628 if (audio_bit_rate > call->audio_bit_rate && !force)
614 ba_set(&call->vba, video_bit_rate); 629 ba_set(&call->aba, audio_bit_rate);
615 else { 630 else {
616 /* Cancel any previous non forceful bitrate change request */ 631 /* Cancel any previous non forceful bitrate change request */
617 memset(&call->vba, 0, sizeof(call->vba)); 632 memset(&call->aba, 0, sizeof(call->aba));
618 call->video_bit_rate = video_bit_rate; 633 call->audio_bit_rate = audio_bit_rate;
619 634
620 if (!force && av->vbcb.first) 635 if (!force && av->abcb.first)
621 av->vbcb.first (av, call->friend_number, true, video_bit_rate, av->vbcb.second); 636 av->abcb.first (av, call->friend_number, true, audio_bit_rate, av->abcb.second);
622 } 637 }
623 638
624 pthread_mutex_unlock(call->mutex); 639 pthread_mutex_unlock(call->mutex);
@@ -628,29 +643,29 @@ END:
628 if (error) 643 if (error)
629 *error = rc; 644 *error = rc;
630 645
631 return rc == TOXAV_ERR_BIT_RATE_OK; 646 return rc == TOXAV_ERR_SET_BIT_RATE_OK;
632} 647}
633 648
634void toxav_callback_audio_bit_rate_status(ToxAV* av, toxav_audio_bit_rate_status_cb* function, void* user_data) 649void toxav_callback_video_bit_rate_status(ToxAV* av, toxav_video_bit_rate_status_cb* function, void* user_data)
635{ 650{
636 pthread_mutex_lock(av->mutex); 651 pthread_mutex_lock(av->mutex);
637 av->abcb.first = function; 652 av->vbcb.first = function;
638 av->abcb.second = user_data; 653 av->vbcb.second = user_data;
639 pthread_mutex_unlock(av->mutex); 654 pthread_mutex_unlock(av->mutex);
640} 655}
641 656
642bool toxav_set_audio_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_BIT_RATE* error) 657bool toxav_video_bit_rate_set(ToxAV* av, uint32_t friend_number, uint32_t video_bit_rate, bool force, TOXAV_ERR_SET_BIT_RATE* error)
643{ 658{
644 TOXAV_ERR_BIT_RATE rc = TOXAV_ERR_BIT_RATE_OK; 659 TOXAV_ERR_SET_BIT_RATE rc = TOXAV_ERR_SET_BIT_RATE_OK;
645 ToxAVCall* call; 660 ToxAVCall* call;
646 661
647 if (m_friend_exists(av->m, friend_number) == 0) { 662 if (m_friend_exists(av->m, friend_number) == 0) {
648 rc = TOXAV_ERR_BIT_RATE_FRIEND_NOT_FOUND; 663 rc = TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_FOUND;
649 goto END; 664 goto END;
650 } 665 }
651 666
652 if (audio_bit_rate_invalid(audio_bit_rate)) { 667 if (video_bit_rate_invalid(video_bit_rate)) {
653 rc = TOXAV_ERR_BIT_RATE_INVALID; 668 rc = TOXAV_ERR_SET_BIT_RATE_INVALID;
654 goto END; 669 goto END;
655 } 670 }
656 671
@@ -658,27 +673,26 @@ bool toxav_set_audio_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t audio_
658 call = call_get(av, friend_number); 673 call = call_get(av, friend_number);
659 if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) { 674 if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) {
660 pthread_mutex_unlock(av->mutex); 675 pthread_mutex_unlock(av->mutex);
661 rc = TOXAV_ERR_BIT_RATE_FRIEND_NOT_IN_CALL; 676 rc = TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_IN_CALL;
662 goto END; 677 goto END;
663 } 678 }
664 679
665 if (call->audio_bit_rate == audio_bit_rate || (call->aba.active && call->aba.bit_rate == audio_bit_rate)) { 680 if (call->video_bit_rate == video_bit_rate || (call->vba.active && call->vba.bit_rate == video_bit_rate)) {
666 pthread_mutex_unlock(av->mutex); 681 pthread_mutex_unlock(av->mutex);
667 goto END; 682 goto END;
668 } 683 }
669 684
670
671 pthread_mutex_lock(call->mutex); 685 pthread_mutex_lock(call->mutex);
672 686
673 if (audio_bit_rate > call->audio_bit_rate && !force) 687 if (video_bit_rate > call->video_bit_rate && !force)
674 ba_set(&call->aba, audio_bit_rate); 688 ba_set(&call->vba, video_bit_rate);
675 else { 689 else {
676 /* Cancel any previous non forceful bitrate change request */ 690 /* Cancel any previous non forceful bitrate change request */
677 memset(&call->aba, 0, sizeof(call->aba)); 691 memset(&call->vba, 0, sizeof(call->vba));
678 call->audio_bit_rate = audio_bit_rate; 692 call->video_bit_rate = video_bit_rate;
679 693
680 if (!force && av->abcb.first) 694 if (!force && av->vbcb.first)
681 av->abcb.first (av, call->friend_number, true, audio_bit_rate, av->abcb.second); 695 av->vbcb.first (av, call->friend_number, true, video_bit_rate, av->vbcb.second);
682 } 696 }
683 697
684 pthread_mutex_unlock(call->mutex); 698 pthread_mutex_unlock(call->mutex);
@@ -688,10 +702,112 @@ END:
688 if (error) 702 if (error)
689 *error = rc; 703 *error = rc;
690 704
691 return rc == TOXAV_ERR_BIT_RATE_OK; 705 return rc == TOXAV_ERR_SET_BIT_RATE_OK;
692} 706}
693 707
694bool toxav_send_video_frame(ToxAV* av, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t* y, const uint8_t* u, const uint8_t* v, TOXAV_ERR_SEND_FRAME* error) 708bool toxav_audio_send_frame(ToxAV* av, uint32_t friend_number, const int16_t* pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, TOXAV_ERR_SEND_FRAME* error)
709{
710 TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK;
711 ToxAVCall* call;
712
713 if (m_friend_exists(av->m, friend_number) == 0) {
714 rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND;
715 goto END;
716 }
717
718 pthread_mutex_lock(av->mutex);
719 call = call_get(av, friend_number);
720 if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) {
721 pthread_mutex_unlock(av->mutex);
722 rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL;
723 goto END;
724 }
725
726 pthread_mutex_lock(call->mutex_audio);
727 pthread_mutex_unlock(av->mutex);
728
729 if ( pcm == NULL ) {
730 pthread_mutex_unlock(call->mutex_audio);
731 rc = TOXAV_ERR_SEND_FRAME_NULL;
732 goto END;
733 }
734
735 if ( channels > 2 ) {
736 pthread_mutex_unlock(call->mutex_audio);
737 rc = TOXAV_ERR_SEND_FRAME_INVALID;
738 goto END;
739 }
740
741 { /* Encode and send */
742 if (ac_reconfigure_encoder(call->audio.second, call->audio_bit_rate * 1000, sampling_rate, channels) != 0) {
743 pthread_mutex_unlock(call->mutex_audio);
744 rc = TOXAV_ERR_SEND_FRAME_INVALID;
745 goto END;
746 }
747
748 uint8_t dest[sample_count + sizeof(sampling_rate)]; /* This is more than enough always */
749
750 sampling_rate = htonl(sampling_rate);
751 memcpy(dest, &sampling_rate, sizeof(sampling_rate));
752 int vrc = opus_encode(call->audio.second->encoder, pcm, sample_count,
753 dest + sizeof(sampling_rate), sizeof(dest) - sizeof(sampling_rate));
754
755 if (vrc < 0) {
756 LOGGER_WARNING("Failed to encode frame %s", opus_strerror(vrc));
757 pthread_mutex_unlock(call->mutex_audio);
758 rc = TOXAV_ERR_SEND_FRAME_INVALID;
759 goto END;
760 }
761
762 if (rtp_send_data(call->audio.first, dest, vrc + sizeof(sampling_rate), false) != 0) {
763 LOGGER_WARNING("Failed to send audio packet");
764 rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED;
765 }
766
767
768 /* For bit rate measurement; send dummy packet */
769 if (ba_shoud_send_dummy(&call->aba)) {
770 sampling_rate = ntohl(sampling_rate);
771 if (ac_reconfigure_test_encoder(call->audio.second, call->audio_bit_rate * 1000, sampling_rate, channels) != 0) {
772 /* FIXME should the bit rate changing fail here? */
773 pthread_mutex_unlock(call->mutex_audio);
774 rc = TOXAV_ERR_SEND_FRAME_INVALID;
775 goto END;
776 }
777
778 sampling_rate = htonl(sampling_rate);
779 memcpy(dest, &sampling_rate, sizeof(sampling_rate));
780 vrc = opus_encode(call->audio.second->test_encoder, pcm, sample_count,
781 dest + sizeof(sampling_rate), sizeof(dest) - sizeof(sampling_rate));
782
783 if (vrc < 0) {
784 LOGGER_WARNING("Failed to encode frame %s", opus_strerror(vrc));
785 pthread_mutex_unlock(call->mutex_audio);
786 rc = TOXAV_ERR_SEND_FRAME_INVALID;
787 goto END;
788 }
789
790 if (rtp_send_data(call->audio.first, dest, vrc + sizeof(sampling_rate), true) != 0) {
791 LOGGER_WARNING("Failed to send audio packet");
792 rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED;
793 }
794
795 if (call->aba.end_time == (uint64_t) ~0)
796 call->aba.end_time = current_time_monotonic() + BITRATE_CHANGE_TESTING_TIME_MS;
797 }
798 }
799
800
801 pthread_mutex_unlock(call->mutex_audio);
802
803END:
804 if (error)
805 *error = rc;
806
807 return rc == TOXAV_ERR_SEND_FRAME_OK;
808}
809
810bool toxav_video_send_frame(ToxAV* av, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t* y, const uint8_t* u, const uint8_t* v, const uint8_t* a,TOXAV_ERR_SEND_FRAME* error)
695{ 811{
696 TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK; 812 TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK;
697 ToxAVCall* call; 813 ToxAVCall* call;
@@ -736,6 +852,10 @@ bool toxav_send_video_frame(ToxAV* av, uint32_t friend_number, uint16_t width, u
736 memcpy(img.planes[VPX_PLANE_U], u, (width/2) * (height/2)); 852 memcpy(img.planes[VPX_PLANE_U], u, (width/2) * (height/2));
737 memcpy(img.planes[VPX_PLANE_V], v, (width/2) * (height/2)); 853 memcpy(img.planes[VPX_PLANE_V], v, (width/2) * (height/2));
738 854
855 /* TODO LOL */
856 if (a && img.planes[VPX_PLANE_ALPHA])
857 memcpy(img.planes[VPX_PLANE_ALPHA], a, width * height);
858
739 int vrc = vpx_codec_encode(call->video.second->encoder, &img, 859 int vrc = vpx_codec_encode(call->video.second->encoder, &img,
740 call->video.second->frame_counter, 1, 0, MAX_ENCODE_TIME_US); 860 call->video.second->frame_counter, 1, 0, MAX_ENCODE_TIME_US);
741 861
@@ -856,109 +976,15 @@ END:
856 return rc == TOXAV_ERR_SEND_FRAME_OK; 976 return rc == TOXAV_ERR_SEND_FRAME_OK;
857} 977}
858 978
859bool toxav_send_audio_frame(ToxAV* av, uint32_t friend_number, const int16_t* pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, TOXAV_ERR_SEND_FRAME* error) 979void toxav_callback_audio_receive_frame(ToxAV* av, toxav_audio_receive_frame_cb* function, void* user_data)
860{ 980{
861 TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK;
862 ToxAVCall* call;
863
864 if (m_friend_exists(av->m, friend_number) == 0) {
865 rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND;
866 goto END;
867 }
868
869 pthread_mutex_lock(av->mutex); 981 pthread_mutex_lock(av->mutex);
870 call = call_get(av, friend_number); 982 av->acb.first = function;
871 if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) { 983 av->acb.second = user_data;
872 pthread_mutex_unlock(av->mutex);
873 rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL;
874 goto END;
875 }
876
877 pthread_mutex_lock(call->mutex_audio);
878 pthread_mutex_unlock(av->mutex); 984 pthread_mutex_unlock(av->mutex);
879
880 if ( pcm == NULL ) {
881 pthread_mutex_unlock(call->mutex_audio);
882 rc = TOXAV_ERR_SEND_FRAME_NULL;
883 goto END;
884 }
885
886 if ( channels > 2 ) {
887 pthread_mutex_unlock(call->mutex_audio);
888 rc = TOXAV_ERR_SEND_FRAME_INVALID;
889 goto END;
890 }
891
892 { /* Encode and send */
893 if (ac_reconfigure_encoder(call->audio.second, call->audio_bit_rate * 1000, sampling_rate, channels) != 0) {
894 pthread_mutex_unlock(call->mutex_audio);
895 rc = TOXAV_ERR_SEND_FRAME_INVALID;
896 goto END;
897 }
898
899 uint8_t dest[sample_count + sizeof(sampling_rate)]; /* This is more than enough always */
900
901 sampling_rate = htonl(sampling_rate);
902 memcpy(dest, &sampling_rate, sizeof(sampling_rate));
903 int vrc = opus_encode(call->audio.second->encoder, pcm, sample_count,
904 dest + sizeof(sampling_rate), sizeof(dest) - sizeof(sampling_rate));
905
906 if (vrc < 0) {
907 LOGGER_WARNING("Failed to encode frame %s", opus_strerror(vrc));
908 pthread_mutex_unlock(call->mutex_audio);
909 rc = TOXAV_ERR_SEND_FRAME_INVALID;
910 goto END;
911 }
912
913 if (rtp_send_data(call->audio.first, dest, vrc + sizeof(sampling_rate), false) != 0) {
914 LOGGER_WARNING("Failed to send audio packet");
915 rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED;
916 }
917
918
919 /* For bit rate measurement; send dummy packet */
920 if (ba_shoud_send_dummy(&call->aba)) {
921 sampling_rate = ntohl(sampling_rate);
922 if (ac_reconfigure_test_encoder(call->audio.second, call->audio_bit_rate * 1000, sampling_rate, channels) != 0) {
923 /* FIXME should the bit rate changing fail here? */
924 pthread_mutex_unlock(call->mutex_audio);
925 rc = TOXAV_ERR_SEND_FRAME_INVALID;
926 goto END;
927 }
928
929 sampling_rate = htonl(sampling_rate);
930 memcpy(dest, &sampling_rate, sizeof(sampling_rate));
931 vrc = opus_encode(call->audio.second->test_encoder, pcm, sample_count,
932 dest + sizeof(sampling_rate), sizeof(dest) - sizeof(sampling_rate));
933
934 if (vrc < 0) {
935 LOGGER_WARNING("Failed to encode frame %s", opus_strerror(vrc));
936 pthread_mutex_unlock(call->mutex_audio);
937 rc = TOXAV_ERR_SEND_FRAME_INVALID;
938 goto END;
939 }
940
941 if (rtp_send_data(call->audio.first, dest, vrc + sizeof(sampling_rate), true) != 0) {
942 LOGGER_WARNING("Failed to send audio packet");
943 rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED;
944 }
945
946 if (call->aba.end_time == (uint64_t) ~0)
947 call->aba.end_time = current_time_monotonic() + BITRATE_CHANGE_TESTING_TIME_MS;
948 }
949 }
950
951
952 pthread_mutex_unlock(call->mutex_audio);
953
954END:
955 if (error)
956 *error = rc;
957
958 return rc == TOXAV_ERR_SEND_FRAME_OK;
959} 985}
960 986
961void toxav_callback_receive_video_frame(ToxAV* av, toxav_receive_video_frame_cb* function, void* user_data) 987void toxav_callback_video_receive_frame(ToxAV* av, toxav_video_receive_frame_cb* function, void* user_data)
962{ 988{
963 pthread_mutex_lock(av->mutex); 989 pthread_mutex_lock(av->mutex);
964 av->vcb.first = function; 990 av->vcb.first = function;
@@ -966,14 +992,6 @@ void toxav_callback_receive_video_frame(ToxAV* av, toxav_receive_video_frame_cb*
966 pthread_mutex_unlock(av->mutex); 992 pthread_mutex_unlock(av->mutex);
967} 993}
968 994
969void toxav_callback_receive_audio_frame(ToxAV* av, toxav_receive_audio_frame_cb* function, void* user_data)
970{
971 pthread_mutex_lock(av->mutex);
972 av->acb.first = function;
973 av->acb.second = user_data;
974 pthread_mutex_unlock(av->mutex);
975}
976
977 995
978/******************************************************************************* 996/*******************************************************************************
979 * 997 *
diff --git a/toxav/toxav.h b/toxav/toxav.h
index b0e7e37d..c75f8bff 100644
--- a/toxav/toxav.h
+++ b/toxav/toxav.h
@@ -1,22 +1,22 @@
1/** toxav.h 1/* toxav.h
2 * 2 *
3 * Copyright (C) 2013-2015 Tox project All Rights Reserved. 3 * Copyright (C) 2013-2015 Tox project All Rights Reserved.
4 * 4 *
5 * This file is part of Tox. 5 * This file is part of Tox.
6 * 6 *
7 * Tox is free software: you can redistribute it and/or modify 7 * Tox is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or 9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version. 10 * (at your option) any later version.
11 * 11 *
12 * Tox is distributed in the hope that it will be useful, 12 * Tox is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details. 15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
19 * 16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */ 20 */
21 21
22#ifndef TOXAV_H 22#ifndef TOXAV_H
@@ -29,45 +29,175 @@
29#ifdef __cplusplus 29#ifdef __cplusplus
30extern "C" { 30extern "C" {
31#endif 31#endif
32
32/** \page av Public audio/video API for Tox clients. 33/** \page av Public audio/video API for Tox clients.
33 * 34 *
35 * This API can handle multiple calls. Each call has its state, in very rare
36 * occasions the library can change the state of the call without apps knowledge.
37 *
38 */
39/** \subsection events Events and callbacks
40 *
41 * As in Core API, events are handled by callbacks. One callback can be
42 * registered per event. All events have a callback function type named
43 * `toxav_{event}_cb` and a function to register it named `tox_callback_{event}`.
44 * Passing a NULL callback will result in no callback being registered for that
45 * event. Only one callback per event can be registered, so if a client needs
46 * multiple event listeners, it needs to implement the dispatch functionality
47 * itself. Unlike Core API, lack of some event handlers will cause the the
48 * library to drop calls before they are started. Hanging up call from a
49 * callback causes undefined behaviour.
50 *
51 */
52/** \subsection threading Threading implications
53 *
34 * Unlike the Core API, this API is fully thread-safe. The library will ensure 54 * Unlike the Core API, this API is fully thread-safe. The library will ensure
35 * the proper synchronisation of parallel calls. 55 * the proper synchronisation of parallel calls.
56 *
57 * A common way to run ToxAV (multiple or single instance) is to have a thread,
58 * separate from tox instance thread, running a simple toxav_iterate loop,
59 * sleeping for toxav_iteration_interval * milliseconds on each iteration.
60 *
36 */ 61 */
37/** 62/**
38 * The type of the Tox Audio/Video subsystem object. 63 * External Tox type.
39 */ 64 */
40typedef struct ToxAV ToxAV;
41#ifndef TOX_DEFINED 65#ifndef TOX_DEFINED
42#define TOX_DEFINED 66#define TOX_DEFINED
67typedef struct Tox Tox;
68#endif /* TOX_DEFINED */
69
43/** 70/**
44 * The type of a Tox instance. Repeated here so this file does not have a direct 71 * ToxAV.
45 * dependency on the Core interface.
46 */ 72 */
47typedef struct Tox Tox; 73/**
48#endif 74 * The ToxAV instance type. Each ToxAV instance can be bound to only one Tox
75 * instance, and Tox instance can have only one ToxAV instance. One must make
76 * sure to close ToxAV instance prior closing Tox instance otherwise undefined
77 * behaviour occurs. Upon closing of ToxAV instance, all active calls will be
78 * forcibly terminated without notifying peers.
79 *
80 */
81#ifndef TOXAV_DEFINED
82#define TOXAV_DEFINED
83typedef struct ToxAV ToxAV;
84#endif /* TOXAV_DEFINED */
85
86
87/*******************************************************************************
88 *
89 * :: API version
90 *
91 ******************************************************************************/
92
93
94
95/**
96 * The major version number. Incremented when the API or ABI changes in an
97 * incompatible way.
98 */
99#define TOXAV_VERSION_MAJOR 0u
100
101/**
102 * The minor version number. Incremented when functionality is added without
103 * breaking the API or ABI. Set to 0 when the major version number is
104 * incremented.
105 */
106#define TOXAV_VERSION_MINOR 0u
107
108/**
109 * The patch or revision number. Incremented when bugfixes are applied without
110 * changing any functionality or API or ABI.
111 */
112#define TOXAV_VERSION_PATCH 0u
113
114/**
115 * A macro to check at preprocessing time whether the client code is compatible
116 * with the installed version of ToxAV.
117 */
118#define TOXAV_VERSION_IS_API_COMPATIBLE(MAJOR, MINOR, PATCH) \
119 (TOXAV_VERSION_MAJOR == MAJOR && \
120 (TOXAV_VERSION_MINOR > MINOR || \
121 (TOXAV_VERSION_MINOR == MINOR && \
122 TOXAV_VERSION_PATCH >= PATCH)))
123
124/**
125 * A macro to make compilation fail if the client code is not compatible with
126 * the installed version of ToxAV.
127 */
128#define TOXAV_VERSION_REQUIRE(MAJOR, MINOR, PATCH) \
129 typedef char toxav_required_version[TOXAV_IS_COMPATIBLE(MAJOR, MINOR, PATCH) ? 1 : -1]
130
131/**
132 * A convenience macro to call toxav_version_is_compatible with the currently
133 * compiling API version.
134 */
135#define TOXAV_VERSION_IS_ABI_COMPATIBLE() \
136 toxav_version_is_compatible(TOXAV_VERSION_MAJOR, TOXAV_VERSION_MINOR, TOXAV_VERSION_PATCH)
137
138/**
139 * Return the major version number of the library. Can be used to display the
140 * ToxAV library version or to check whether the client is compatible with the
141 * dynamically linked version of ToxAV.
142 */
143uint32_t toxav_version_major(void);
144
145/**
146 * Return the minor version number of the library.
147 */
148uint32_t toxav_version_minor(void);
149
150/**
151 * Return the patch number of the library.
152 */
153uint32_t toxav_version_patch(void);
154
155/**
156 * Return whether the compiled library version is compatible with the passed
157 * version numbers.
158 */
159bool toxav_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch);
160
161
49/******************************************************************************* 162/*******************************************************************************
50 * 163 *
51 * :: Creation and destruction 164 * :: Creation and destruction
52 * 165 *
53 ******************************************************************************/ 166 ******************************************************************************/
167
168
169
54typedef enum TOXAV_ERR_NEW { 170typedef enum TOXAV_ERR_NEW {
55 TOXAV_ERR_NEW_OK, 171
56 TOXAV_ERR_NEW_NULL, 172 /**
57 /** 173 * The function returned successfully.
58 * Memory allocation failure while trying to allocate structures required for 174 */
59 * the A/V session. 175 TOXAV_ERR_NEW_OK,
60 */ 176
61 TOXAV_ERR_NEW_MALLOC, 177 /**
62 /** 178 * One of the arguments to the function was NULL when it was not expected.
63 * Attempted to create a second session for the same Tox instance. 179 */
64 */ 180 TOXAV_ERR_NEW_NULL,
65 TOXAV_ERR_NEW_MULTIPLE 181
182 /**
183 * Memory allocation failure while trying to allocate structures required for
184 * the A/V session.
185 */
186 TOXAV_ERR_NEW_MALLOC,
187
188 /**
189 * Attempted to create a second session for the same Tox instance.
190 */
191 TOXAV_ERR_NEW_MULTIPLE,
192
66} TOXAV_ERR_NEW; 193} TOXAV_ERR_NEW;
194
195
67/** 196/**
68 * Start new A/V session. There can only be only one session per Tox instance. 197 * Start new A/V session. There can only be only one session per Tox instance.
69 */ 198 */
70ToxAV *toxav_new(Tox *tox, TOXAV_ERR_NEW *error); 199ToxAV *toxav_new(Tox *tox, TOXAV_ERR_NEW *error);
200
71/** 201/**
72 * Releases all resources associated with the A/V session. 202 * Releases all resources associated with the A/V session.
73 * 203 *
@@ -75,62 +205,86 @@ ToxAV *toxav_new(Tox *tox, TOXAV_ERR_NEW *error);
75 * notifying peers. After calling this function, no other functions may be 205 * notifying peers. After calling this function, no other functions may be
76 * called and the av pointer becomes invalid. 206 * called and the av pointer becomes invalid.
77 */ 207 */
78void toxav_kill(ToxAV *av); 208void toxav_kill(ToxAV *toxAV);
209
79/** 210/**
80 * Returns the Tox instance the A/V object was created for. 211 * Returns the Tox instance the A/V object was created for.
81 */ 212 */
82Tox *toxav_get_tox(ToxAV *av); 213Tox *toxav_get_tox(const ToxAV *toxAV);
214
215
83/******************************************************************************* 216/*******************************************************************************
84 * 217 *
85 * :: A/V event loop 218 * :: A/V event loop
86 * 219 *
87 ******************************************************************************/ 220 ******************************************************************************/
221
222
223
88/** 224/**
89 * Returns the interval in milliseconds when the next toxav_iterate call should 225 * Returns the interval in milliseconds when the next toxav_iterate call should
90 * be. If no call is active at the moment, this function returns 200. 226 * be. If no call is active at the moment, this function returns 200.
91 */ 227 */
92uint32_t toxav_iteration_interval(ToxAV const *av); 228uint32_t toxav_iteration_interval(const ToxAV *toxAV);
229
93/** 230/**
94 * Main loop for the session. This function needs to be called in intervals of 231 * Main loop for the session. This function needs to be called in intervals of
95 * toxav_iteration_interval() milliseconds. It is best called in the separate 232 * toxav_iteration_interval() milliseconds. It is best called in the separate
96 * thread from tox_iterate. 233 * thread from tox_iterate.
97 */ 234 */
98void toxav_iterate(ToxAV *av); 235void toxav_iterate(ToxAV *toxAV);
236
237
99/******************************************************************************* 238/*******************************************************************************
100 * 239 *
101 * :: Call setup 240 * :: Call setup
102 * 241 *
103 ******************************************************************************/ 242 ******************************************************************************/
243
244
245
104typedef enum TOXAV_ERR_CALL { 246typedef enum TOXAV_ERR_CALL {
105 TOXAV_ERR_CALL_OK, 247
106 /** 248 /**
107 * A resource allocation error occurred while trying to create the structures 249 * The function returned successfully.
108 * required for the call. 250 */
109 */ 251 TOXAV_ERR_CALL_OK,
110 TOXAV_ERR_CALL_MALLOC, 252
111 /** 253 /**
112 * The friend number did not designate a valid friend. 254 * A resource allocation error occurred while trying to create the structures
113 */ 255 * required for the call.
114 TOXAV_ERR_CALL_FRIEND_NOT_FOUND, 256 */
115 /** 257 TOXAV_ERR_CALL_MALLOC,
116 * The friend was valid, but not currently connected. 258
117 */ 259 /**
118 TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED, 260 * The friend number did not designate a valid friend.
119 /** 261 */
120 * Attempted to call a friend while already in an audio or video call with 262 TOXAV_ERR_CALL_FRIEND_NOT_FOUND,
121 * them. 263
122 */ 264 /**
123 TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL, 265 * The friend was valid, but not currently connected.
124 /** 266 */
125 * Audio or video bit rate is invalid. 267 TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED,
126 */ 268
127 TOXAV_ERR_CALL_INVALID_BIT_RATE 269 /**
270 * Attempted to call a friend while already in an audio or video call with
271 * them.
272 */
273 TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL,
274
275 /**
276 * Audio or video bit rate is invalid.
277 */
278 TOXAV_ERR_CALL_INVALID_BIT_RATE,
279
128} TOXAV_ERR_CALL; 280} TOXAV_ERR_CALL;
281
282
129/** 283/**
130 * Call a friend. This will start ringing the friend. 284 * Call a friend. This will start ringing the friend.
131 * 285 *
132 * It is the client's responsibility to stop ringing after a certain timeout, 286 * It is the client's responsibility to stop ringing after a certain timeout,
133 * if such behaviour is desired. If the client does not stop ringing, the A/V 287 * if such behaviour is desired. If the client does not stop ringing, the
134 * library will not stop until the friend is disconnected. 288 * library will not stop until the friend is disconnected.
135 * 289 *
136 * @param friend_number The friend number of the friend that should be called. 290 * @param friend_number The friend number of the friend that should be called.
@@ -139,39 +293,57 @@ typedef enum TOXAV_ERR_CALL {
139 * @param video_bit_rate Video bit rate in Kb/sec. Set this to 0 to disable 293 * @param video_bit_rate Video bit rate in Kb/sec. Set this to 0 to disable
140 * video sending. 294 * video sending.
141 */ 295 */
142bool toxav_call(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL *error); 296bool toxav_call(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL *error);
297
143/** 298/**
144 * The function type for the `call` callback. 299 * The function type for the call callback.
300 *
301 * @param friend_number The friend number from which the call is incoming.
302 * @param audio_enabled True if friend is sending audio.
303 * @param video_enabled True if friend is sending video.
145 */ 304 */
146typedef void toxav_call_cb(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data); 305typedef void toxav_call_cb(ToxAV *toxAV, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data);
306
307
147/** 308/**
148 * Set the callback for the `call` event. Pass NULL to unset. 309 * Set the callback for the `call` event. Pass NULL to unset.
149 * 310 *
150 * This event is triggered when a call is received from a friend.
151 */ 311 */
152void toxav_callback_call(ToxAV *av, toxav_call_cb *function, void *user_data); 312void toxav_callback_call(ToxAV *toxAV, toxav_call_cb *callback, void *user_data);
313
153typedef enum TOXAV_ERR_ANSWER { 314typedef enum TOXAV_ERR_ANSWER {
154 TOXAV_ERR_ANSWER_OK, 315
155 /** 316 /**
156 * Failed to initialize codecs for call session. Note that codec initiation 317 * The function returned successfully.
157 * will fail if there is no receive callback registered for either audio or 318 */
158 * video. 319 TOXAV_ERR_ANSWER_OK,
159 */ 320
160 TOXAV_ERR_ANSWER_CODEC_INITIALIZATION, 321 /**
161 /** 322 * Failed to initialize codecs for call session. Note that codec initiation
162 * The friend number did not designate a valid friend. 323 * will fail if there is no receive callback registered for either audio or
163 */ 324 * video.
164 TOXAV_ERR_ANSWER_FRIEND_NOT_FOUND, 325 */
165 /** 326 TOXAV_ERR_ANSWER_CODEC_INITIALIZATION,
166 * The friend was valid, but they are not currently trying to initiate a call. 327
167 * This is also returned if this client is already in a call with the friend. 328 /**
168 */ 329 * The friend number did not designate a valid friend.
169 TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING, 330 */
170 /** 331 TOXAV_ERR_ANSWER_FRIEND_NOT_FOUND,
171 * Audio or video bit rate is invalid. 332
172 */ 333 /**
173 TOXAV_ERR_ANSWER_INVALID_BIT_RATE 334 * The friend was valid, but they are not currently trying to initiate a call.
335 * This is also returned if this client is already in a call with the friend.
336 */
337 TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING,
338
339 /**
340 * Audio or video bit rate is invalid.
341 */
342 TOXAV_ERR_ANSWER_INVALID_BIT_RATE,
343
174} TOXAV_ERR_ANSWER; 344} TOXAV_ERR_ANSWER;
345
346
175/** 347/**
176 * Accept an incoming call. 348 * Accept an incoming call.
177 * 349 *
@@ -184,113 +356,155 @@ typedef enum TOXAV_ERR_ANSWER {
184 * @param video_bit_rate Video bit rate in Kb/sec. Set this to 0 to disable 356 * @param video_bit_rate Video bit rate in Kb/sec. Set this to 0 to disable
185 * video sending. 357 * video sending.
186 */ 358 */
187bool toxav_answer(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER *error); 359bool toxav_answer(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER *error);
360
361
188/******************************************************************************* 362/*******************************************************************************
189 * 363 *
190 * :: Call state graph 364 * :: Call state graph
191 * 365 *
192 ******************************************************************************/ 366 ******************************************************************************/
367
368
369
193enum TOXAV_CALL_STATE { 370enum TOXAV_CALL_STATE {
194 /** 371
195 * The flag that marks that friend is sending audio. 372 /**
196 */ 373 * Set by the AV core if an error occurred on the remote end or if friend
197 TOXAV_CALL_STATE_SENDING_A = 1, 374 * timed out. This is the final state after which no more state
198 /** 375 * transitions can occur for the call. This call state will never be triggered
199 * The flag that marks that friend is sending video. 376 * in combination with other call states.
200 */ 377 */
201 TOXAV_CALL_STATE_SENDING_V = 2, 378 TOXAV_CALL_STATE_ERROR = 1,
202 /** 379
203 * The flag that marks that friend is receiving audio. 380 /**
204 */ 381 * The call has finished. This is the final state after which no more state
205 TOXAV_CALL_STATE_RECEIVING_A = 4, 382 * transitions can occur for the call. This call state will never be
206 /** 383 * triggered in combination with other call states.
207 * The flag that marks that friend is receiving video. 384 */
208 */ 385 TOXAV_CALL_STATE_FINISHED = 2,
209 TOXAV_CALL_STATE_RECEIVING_V = 8, 386
210 /** 387 /**
211 * The call has finished. This is the final state after which no more state 388 * The flag that marks that friend is sending audio.
212 * transitions can occur for the call. This call state will never be 389 */
213 * triggered in combination with other call states. 390 TOXAV_CALL_STATE_SENDING_A = 4,
214 */ 391
215 TOXAV_CALL_STATE_FINISHED = 16, 392 /**
216 /** 393 * The flag that marks that friend is sending video.
217 * Set by the AV core if an error occurred on the remote end. This call 394 */
218 * state will never be triggered in combination with other call states. 395 TOXAV_CALL_STATE_SENDING_V = 8,
219 */ 396
220 TOXAV_CALL_STATE_ERROR = 32768 397 /**
398 * The flag that marks that friend is receiving audio.
399 */
400 TOXAV_CALL_STATE_RECEIVING_A = 16,
401
402 /**
403 * The flag that marks that friend is receiving video.
404 */
405 TOXAV_CALL_STATE_RECEIVING_V = 32,
406
221}; 407};
408
409
222/** 410/**
223 * The function type for the `call_state` callback. 411 * The function type for the call_state callback.
224 * 412 *
225 * @param friend_number The friend number for which the call state changed. 413 * @param friend_number The friend number for which the call state changed.
226 * @param state The new call state. 414 * @param state The new call state which is guaranteed to be different than
415 * the previous state. The state is set to 0 when the call is paused.
227 */ 416 */
228typedef void toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_data); 417typedef void toxav_call_state_cb(ToxAV *toxAV, uint32_t friend_number, uint32_t state, void *user_data);
418
419
229/** 420/**
230 * Set the callback for the `call_state` event. Pass NULL to unset. 421 * Set the callback for the `call_state` event. Pass NULL to unset.
231 * 422 *
232 * This event is triggered when a call state transition occurs.
233 */ 423 */
234void toxav_callback_call_state(ToxAV *av, toxav_call_state_cb *function, void *user_data); 424void toxav_callback_call_state(ToxAV *toxAV, toxav_call_state_cb *callback, void *user_data);
425
426
235/******************************************************************************* 427/*******************************************************************************
236 * 428 *
237 * :: Call control 429 * :: Call control
238 * 430 *
239 ******************************************************************************/ 431 ******************************************************************************/
432
433
434
240typedef enum TOXAV_CALL_CONTROL { 435typedef enum TOXAV_CALL_CONTROL {
241 /** 436
242 * Resume a previously paused call. Only valid if the pause was caused by this 437 /**
243 * client, if not, this control is ignored. Not valid before the call is accepted. 438 * Resume a previously paused call. Only valid if the pause was caused by this
244 */ 439 * client, if not, this control is ignored. Not valid before the call is accepted.
245 TOXAV_CALL_CONTROL_RESUME, 440 */
246 /** 441 TOXAV_CALL_CONTROL_RESUME,
247 * Put a call on hold. Not valid before the call is accepted. 442
248 */ 443 /**
249 TOXAV_CALL_CONTROL_PAUSE, 444 * Put a call on hold. Not valid before the call is accepted.
250 /** 445 */
251 * Reject a call if it was not answered, yet. Cancel a call after it was 446 TOXAV_CALL_CONTROL_PAUSE,
252 * answered. 447
253 */ 448 /**
254 TOXAV_CALL_CONTROL_CANCEL, 449 * Reject a call if it was not answered, yet. Cancel a call after it was
255 /** 450 * answered.
256 * Request that the friend stops sending audio. Regardless of the friend's 451 */
257 * compliance, this will cause the `receive_audio_frame` event to stop being 452 TOXAV_CALL_CONTROL_CANCEL,
258 * triggered on receiving an audio frame from the friend. If the audio was 453
259 * already muted, calling this control will notify client to start sending 454 /**
260 * audio again. 455 * Request that the friend stops sending audio. Regardless of the friend's
261 */ 456 * compliance, this will cause the audio_receive_frame event to stop being
262 TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, 457 * triggered on receiving an audio frame from the friend.
263 /** 458 */
264 * Request that the friend stops sending video. Regardless of the friend's 459 TOXAV_CALL_CONTROL_MUTE_AUDIO,
265 * compliance, this will cause the `receive_video_frame` event to stop being 460
266 * triggered on receiving an video frame from the friend. If the video was 461 /**
267 * already hidden, calling this control will notify client to start sending 462 * Calling this control will notify client to start sending audio again.
268 * video again. 463 */
269 */ 464 TOXAV_CALL_CONTROL_UNMUTE_AUDIO,
270 TOXAV_CALL_CONTROL_TOGGLE_HIDE_VIDEO 465
466 /**
467 * Request that the friend stops sending video. Regardless of the friend's
468 * compliance, this will cause the video_receive_frame event to stop being
469 * triggered on receiving an video frame from the friend.
470 */
471 TOXAV_CALL_CONTROL_HIDE_VIDEO,
472
473 /**
474 * Calling this control will notify client to start sending video again.
475 */
476 TOXAV_CALL_CONTROL_SHOW_VIDEO,
477
271} TOXAV_CALL_CONTROL; 478} TOXAV_CALL_CONTROL;
479
480
272typedef enum TOXAV_ERR_CALL_CONTROL { 481typedef enum TOXAV_ERR_CALL_CONTROL {
273 TOXAV_ERR_CALL_CONTROL_OK, 482
274 /** 483 /**
275 * The friend_number passed did not designate a valid friend. 484 * The function returned successfully.
276 */ 485 */
277 TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_FOUND, 486 TOXAV_ERR_CALL_CONTROL_OK,
278 /** 487
279 * This client is currently not in a call with the friend. Before the call is 488 /**
280 * answered, only CANCEL is a valid control. 489 * The friend_number passed did not designate a valid friend.
281 */ 490 */
282 TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL, 491 TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_FOUND,
283 /** 492
284 * Attempted to resume a call that was not paused. 493 /**
285 */ 494 * This client is currently not in a call with the friend. Before the call is
286 TOXAV_ERR_CALL_CONTROL_NOT_PAUSED, 495 * answered, only CANCEL is a valid control.
287 /** 496 */
288 * The call was already paused on this client. It is valid to pause if the 497 TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL,
289 * other party paused the call. The call will resume after both parties sent 498
290 * the RESUME control. 499 /**
291 */ 500 * Happens if user tried to pause an already paused call or if trying to
292 TOXAV_ERR_CALL_CONTROL_ALREADY_PAUSED 501 * resume a call that is not paused.
502 */
503 TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION,
504
293} TOXAV_ERR_CALL_CONTROL; 505} TOXAV_ERR_CALL_CONTROL;
506
507
294/** 508/**
295 * Sends a call control command to a friend. 509 * Sends a call control command to a friend.
296 * 510 *
@@ -300,29 +514,44 @@ typedef enum TOXAV_ERR_CALL_CONTROL {
300 * 514 *
301 * @return true on success. 515 * @return true on success.
302 */ 516 */
303bool toxav_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL *error); 517bool toxav_call_control(ToxAV *toxAV, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL *error);
518
519
304/******************************************************************************* 520/*******************************************************************************
305 * 521 *
306 * :: Controlling bit rates 522 * :: Controlling bit rates
307 * 523 *
308 ******************************************************************************/ 524 ******************************************************************************/
309typedef enum TOXAV_ERR_BIT_RATE { 525
310 TOXAV_ERR_BIT_RATE_OK, 526
311 /** 527
312 * The bit rate passed was not one of the supported values. 528typedef enum TOXAV_ERR_SET_BIT_RATE {
313 */ 529
314 TOXAV_ERR_BIT_RATE_INVALID, 530 /**
315 /** 531 * The function returned successfully.
316 * The friend_number passed did not designate a valid friend. 532 */
317 */ 533 TOXAV_ERR_SET_BIT_RATE_OK,
318 TOXAV_ERR_BIT_RATE_FRIEND_NOT_FOUND, 534
319 /** 535 /**
320 * This client is currently not in a call with the friend. 536 * The bit rate passed was not one of the supported values.
321 */ 537 */
322 TOXAV_ERR_BIT_RATE_FRIEND_NOT_IN_CALL 538 TOXAV_ERR_SET_BIT_RATE_INVALID,
323} TOXAV_ERR_BIT_RATE; 539
324/** 540 /**
325 * The function type for the `audio_bit_rate_status` callback. 541 * The friend_number passed did not designate a valid friend.
542 */
543 TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_FOUND,
544
545 /**
546 * This client is currently not in a call with the friend.
547 */
548 TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_IN_CALL,
549
550} TOXAV_ERR_SET_BIT_RATE;
551
552
553/**
554 * The function type for the audio_bit_rate_status callback.
326 * 555 *
327 * @param friend_number The friend number of the friend for which to set the 556 * @param friend_number The friend number of the friend for which to set the
328 * audio bit rate. 557 * audio bit rate.
@@ -334,11 +563,15 @@ typedef enum TOXAV_ERR_BIT_RATE {
334 * or the non forceful change failed. 563 * or the non forceful change failed.
335 * @param bit_rate The bit rate in Kb/sec. 564 * @param bit_rate The bit rate in Kb/sec.
336 */ 565 */
337typedef void toxav_audio_bit_rate_status_cb(ToxAV *av, uint32_t friend_number, bool stable, uint32_t bit_rate, void *user_data); 566typedef void toxav_audio_bit_rate_status_cb(ToxAV *toxAV, uint32_t friend_number, bool stable, uint32_t bit_rate, void *user_data);
567
568
338/** 569/**
339 * Set the callback for the `audio_bit_rate_status` event. Pass NULL to unset. 570 * Set the callback for the `audio_bit_rate_status` event. Pass NULL to unset.
571 *
340 */ 572 */
341void toxav_callback_audio_bit_rate_status(ToxAV *av, toxav_audio_bit_rate_status_cb *function, void *user_data); 573void toxav_callback_audio_bit_rate_status(ToxAV *toxAV, toxav_audio_bit_rate_status_cb *callback, void *user_data);
574
342/** 575/**
343 * Set the audio bit rate to be used in subsequent audio frames. If the passed 576 * Set the audio bit rate to be used in subsequent audio frames. If the passed
344 * bit rate is the same as the current bit rate this function will return true 577 * bit rate is the same as the current bit rate this function will return true
@@ -351,12 +584,13 @@ void toxav_callback_audio_bit_rate_status(ToxAV *av, toxav_audio_bit_rate_status
351 * audio bit rate. 584 * audio bit rate.
352 * @param audio_bit_rate The new audio bit rate in Kb/sec. Set to 0 to disable 585 * @param audio_bit_rate The new audio bit rate in Kb/sec. Set to 0 to disable
353 * audio sending. 586 * audio sending.
354 * 587 * @param force True if the bit rate change is forceful.
355 * @see toxav_call for the valid bit rates. 588 *
356 */ 589 */
357bool toxav_set_audio_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_BIT_RATE *error); 590bool toxav_audio_bit_rate_set(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_SET_BIT_RATE *error);
591
358/** 592/**
359 * The function type for the `video_bit_rate_status` callback. 593 * The function type for the video_bit_rate_status callback.
360 * 594 *
361 * @param friend_number The friend number of the friend for which to set the 595 * @param friend_number The friend number of the friend for which to set the
362 * video bit rate. 596 * video bit rate.
@@ -368,79 +602,78 @@ bool toxav_set_audio_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t audio_
368 * or the non forceful change failed. 602 * or the non forceful change failed.
369 * @param bit_rate The bit rate in Kb/sec. 603 * @param bit_rate The bit rate in Kb/sec.
370 */ 604 */
371typedef void toxav_video_bit_rate_status_cb(ToxAV *av, uint32_t friend_number, bool stable, uint32_t bit_rate, void *user_data); 605typedef void toxav_video_bit_rate_status_cb(ToxAV *toxAV, uint32_t friend_number, bool stable, uint32_t bit_rate, void *user_data);
606
607
372/** 608/**
373 * Set the callback for the `video_bit_rate_status` event. Pass NULL to unset. 609 * Set the callback for the `video_bit_rate_status` event. Pass NULL to unset.
610 *
374 */ 611 */
375void toxav_callback_video_bit_rate_status(ToxAV *av, toxav_video_bit_rate_status_cb *function, void *user_data); 612void toxav_callback_video_bit_rate_status(ToxAV *toxAV, toxav_video_bit_rate_status_cb *callback, void *user_data);
613
376/** 614/**
377 * Set the video bit rate to be used in subsequent video frames. If the passed 615 * Set the video bit rate to be used in subsequent video frames. If the passed
378 * bit rate is the same as the current bit rate this function will return true 616 * bit rate is the same as the current bit rate this function will return true
379 * without calling a callback. If there is an active non forceful setup with the 617 * without calling a callback. If there is an active non forceful setup with the
380 * passed bit rate and the new set request is forceful, the bit rate is 618 * passed video bit rate and the new set request is forceful, the bit rate is
381 * forcefully set and the previous non forceful request is cancelled. The active 619 * forcefully set and the previous non forceful request is cancelled. The active
382 * non forceful setup will be canceled in favour of new non forceful setup. 620 * non forceful setup will be canceled in favour of new non forceful setup.
383 * 621 *
384 * @param friend_number The friend number of the friend for which to set the 622 * @param friend_number The friend number of the friend for which to set the
385 * video bit rate. 623 * video bit rate.
386 * @param video_bit_rate The new video bit rate in Kb/sec. Set to 0 to disable 624 * @param audio_bit_rate The new video bit rate in Kb/sec. Set to 0 to disable
387 * video sending. 625 * video sending.
388 * 626 * @param force True if the bit rate change is forceful.
389 * @see toxav_call for the valid bit rates. 627 *
390 */ 628 */
391bool toxav_set_video_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t video_bit_rate, bool force, TOXAV_ERR_BIT_RATE *error); 629bool toxav_video_bit_rate_set(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_SET_BIT_RATE *error);
630
631
392/******************************************************************************* 632/*******************************************************************************
393 * 633 *
394 * :: A/V sending 634 * :: A/V sending
395 * 635 *
396 ******************************************************************************/ 636 ******************************************************************************/
397/** 637
398 * Common error codes for the send_*_frame functions. 638
399 */ 639
400typedef enum TOXAV_ERR_SEND_FRAME { 640typedef enum TOXAV_ERR_SEND_FRAME {
401 TOXAV_ERR_SEND_FRAME_OK, 641
402 /** 642 /**
403 * In case of video, one of Y, U, or V was NULL. In case of audio, the samples 643 * The function returned successfully.
404 * data pointer was NULL. 644 */
405 */ 645 TOXAV_ERR_SEND_FRAME_OK,
406 TOXAV_ERR_SEND_FRAME_NULL, 646
407 /** 647 /**
408 * The friend_number passed did not designate a valid friend. 648 * In case of video, one of Y, U, or V was NULL. In case of audio, the samples
409 */ 649 * data pointer was NULL.
410 TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND, 650 */
411 /** 651 TOXAV_ERR_SEND_FRAME_NULL,
412 * This client is currently not in a call with the friend. 652
413 */ 653 /**
414 TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL, 654 * The friend_number passed did not designate a valid friend.
415 /** 655 */
416 * One of the frame parameters was invalid. E.g. the resolution may be too 656 TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND,
417 * small or too large, or the audio sampling rate may be unsupported. 657
418 */ 658 /**
419 TOXAV_ERR_SEND_FRAME_INVALID, 659 * This client is currently not in a call with the friend.
420 /** 660 */
421 * Failed to push frame through rtp interface. 661 TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL,
422 */ 662
423 TOXAV_ERR_SEND_FRAME_RTP_FAILED 663 /**
664 * One of the frame parameters was invalid. E.g. the resolution may be too
665 * small or too large, or the audio sampling rate may be unsupported.
666 */
667 TOXAV_ERR_SEND_FRAME_INVALID,
668
669 /**
670 * Failed to push frame through rtp interface.
671 */
672 TOXAV_ERR_SEND_FRAME_RTP_FAILED,
673
424} TOXAV_ERR_SEND_FRAME; 674} TOXAV_ERR_SEND_FRAME;
425/** 675
426 * Send a video frame to a friend. 676
427 *
428 * Y - plane should be of size: height * width
429 * U - plane should be of size: (height/2) * (width/2)
430 * V - plane should be of size: (height/2) * (width/2)
431 *
432 * @param friend_number The friend number of the friend to which to send a video
433 * frame.
434 * @param width Width of the frame in pixels.
435 * @param height Height of the frame in pixels.
436 * @param y Y (Luminance) plane data.
437 * @param u U (Chroma) plane data.
438 * @param v V (Chroma) plane data.
439 */
440bool toxav_send_video_frame(ToxAV *av, uint32_t friend_number,
441 uint16_t width, uint16_t height,
442 uint8_t const *y, uint8_t const *u, uint8_t const *v,
443 TOXAV_ERR_SEND_FRAME *error);
444/** 677/**
445 * Send an audio frame to a friend. 678 * Send an audio frame to a friend.
446 * 679 *
@@ -461,19 +694,56 @@ bool toxav_send_video_frame(ToxAV *av, uint32_t friend_number,
461 * @param sampling_rate Audio sampling rate used in this frame. Valid sampling 694 * @param sampling_rate Audio sampling rate used in this frame. Valid sampling
462 * rates are 8000, 12000, 16000, 24000, or 48000. 695 * rates are 8000, 12000, 16000, 24000, or 48000.
463 */ 696 */
464bool toxav_send_audio_frame(ToxAV *av, uint32_t friend_number, 697bool toxav_audio_send_frame(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, TOXAV_ERR_SEND_FRAME *error);
465 int16_t const *pcm, 698
466 size_t sample_count, 699/**
467 uint8_t channels, 700 * Send a video frame to a friend.
468 uint32_t sampling_rate, 701 *
469 TOXAV_ERR_SEND_FRAME *error); 702 * Y - plane should be of size: height * width
703 * U - plane should be of size: (height/2) * (width/2)
704 * V - plane should be of size: (height/2) * (width/2)
705 *
706 * @param friend_number The friend number of the friend to which to send a video
707 * frame.
708 * @param width Width of the frame in pixels.
709 * @param height Height of the frame in pixels.
710 * @param y Y (Luminance) plane data.
711 * @param u U (Chroma) plane data.
712 * @param v V (Chroma) plane data.
713 * @param a A (Alpha) plane data.
714 */
715bool toxav_video_send_frame(ToxAV *toxAV, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v, const uint8_t *a, TOXAV_ERR_SEND_FRAME *error);
716
717
470/******************************************************************************* 718/*******************************************************************************
471 * 719 *
472 * :: A/V receiving 720 * :: A/V receiving
473 * 721 *
474 ******************************************************************************/ 722 ******************************************************************************/
723
724
725
475/** 726/**
476 * The function type for the `receive_video_frame` callback. 727 * The function type for the audio_receive_frame callback.
728 *
729 * @param friend_number The friend number of the friend who sent an audio frame.
730 * @param pcm An array of audio samples (sample_count * channels elements).
731 * @param sample_count The number of audio samples per channel in the PCM array.
732 * @param channels Number of audio channels.
733 * @param sampling_rate Sampling rate used in this frame.
734 *
735 */
736typedef void toxav_audio_receive_frame_cb(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, void *user_data);
737
738
739/**
740 * Set the callback for the `audio_receive_frame` event. Pass NULL to unset.
741 *
742 */
743void toxav_callback_audio_receive_frame(ToxAV *toxAV, toxav_audio_receive_frame_cb *callback, void *user_data);
744
745/**
746 * The function type for the video_receive_frame callback.
477 * 747 *
478 * @param friend_number The friend number of the friend who sent a video frame. 748 * @param friend_number The friend number of the friend who sent a video frame.
479 * @param width Width of the frame in pixels. 749 * @param width Width of the frame in pixels.
@@ -482,44 +752,26 @@ bool toxav_send_audio_frame(ToxAV *av, uint32_t friend_number,
482 * @param u 752 * @param u
483 * @param v Plane data. 753 * @param v Plane data.
484 * The size of plane data is derived from width and height where 754 * The size of plane data is derived from width and height where
485 * Y = width * height, U = (width/2) * (height/2) and V = (width/2) * (height/2). 755 * Y = MAX(width, abs(ystride)) * height,
756 * U = MAX(width/2, abs(ustride)) * (height/2) and
757 * V = MAX(width/2, abs(vstride)) * (height/2).
758 * A = MAX(width, abs(astride)) * height.
486 * @param ystride 759 * @param ystride
487 * @param ustride 760 * @param ustride
488 * @param vstride Strides data. 761 * @param vstride
489 */ 762 * @param astride Strides data. Strides represent padding for each plane
490typedef void toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number, 763 * that may or may not be present. You must handle strides in
491 uint16_t width, uint16_t height, 764 * your image processing code. Strides are negative if the
492 uint8_t const *y, uint8_t const *u, uint8_t const *v, 765 * image is bottom-up hence why you MUST abs() it when
493 int32_t ystride, int32_t ustride, int32_t vstride, 766 * calculating plane buffer size.
494 void *user_data);
495/**
496 * Set the callback for the `receive_video_frame` event. Pass NULL to unset.
497 */ 767 */
498void toxav_callback_receive_video_frame(ToxAV *av, toxav_receive_video_frame_cb *function, void *user_data); 768typedef void toxav_video_receive_frame_cb(ToxAV *toxAV, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v, const uint8_t *a, int32_t ystride, int32_t ustride, int32_t vstride, int32_t astride, void *user_data);
769
770
499/** 771/**
500 * The function type for the `receive_audio_frame` callback. 772 * Set the callback for the `video_receive_frame` event. Pass NULL to unset.
501 *
502 * @param friend_number The friend number of the friend who sent an audio frame.
503 * @param pcm An array of audio samples (sample_count * channels elements).
504 * @param sample_count The number of audio samples per channel in the PCM array.
505 * @param channels Number of audio channels.
506 * @param sampling_rate Sampling rate used in this frame.
507 * 773 *
508 * @see toxav_send_audio_frame for the audio format.
509 */
510typedef void toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number,
511 int16_t const *pcm,
512 size_t sample_count,
513 uint8_t channels,
514 uint32_t sampling_rate,
515 void *user_data);
516/**
517 * Set the callback for the `receive_audio_frame` event. Pass NULL to unset.
518 */ 774 */
519void toxav_callback_receive_audio_frame(ToxAV *av, toxav_receive_audio_frame_cb *function, void *user_data); 775void toxav_callback_video_receive_frame(ToxAV *toxAV, toxav_video_receive_frame_cb *callback, void *user_data);
520 776
521#ifdef __cplusplus
522}
523#endif 777#endif
524
525#endif /* TOXAV_H */
diff --git a/toxav/video.c b/toxav/video.c
index fe57387f..690b3bd4 100644
--- a/toxav/video.c
+++ b/toxav/video.c
@@ -42,7 +42,7 @@ typedef struct { uint16_t size; uint8_t data[]; } Payload;
42bool create_video_encoder (vpx_codec_ctx_t* dest, int32_t bit_rate); 42bool create_video_encoder (vpx_codec_ctx_t* dest, int32_t bit_rate);
43 43
44 44
45VCSession* vc_new(ToxAV* av, uint32_t friend_number, toxav_receive_video_frame_cb* cb, void* cb_data, uint32_t mvfpsz) 45VCSession* vc_new(ToxAV* av, uint32_t friend_number, toxav_video_receive_frame_cb* cb, void* cb_data, uint32_t mvfpsz)
46{ 46{
47 VCSession *vc = calloc(sizeof(VCSession), 1); 47 VCSession *vc = calloc(sizeof(VCSession), 1);
48 48
@@ -141,8 +141,9 @@ void vc_do(VCSession* vc)
141 for (; dest; dest = vpx_codec_get_frame(vc->decoder, &iter)) { 141 for (; dest; dest = vpx_codec_get_frame(vc->decoder, &iter)) {
142 if (vc->vcb.first) 142 if (vc->vcb.first)
143 vc->vcb.first(vc->av, vc->friend_number, dest->d_w, dest->d_h, 143 vc->vcb.first(vc->av, vc->friend_number, dest->d_w, dest->d_h,
144 (const uint8_t*)dest->planes[0], (const uint8_t*)dest->planes[1], (const uint8_t*)dest->planes[2], 144 (const uint8_t*)dest->planes[0], (const uint8_t*)dest->planes[1],
145 dest->stride[0], dest->stride[1], dest->stride[2], vc->vcb.second); 145 (const uint8_t*)dest->planes[2], (const uint8_t*)dest->planes[3],
146 dest->stride[0], dest->stride[1], dest->stride[2], dest->stride[3], vc->vcb.second);
146 147
147 vpx_img_free(dest); 148 vpx_img_free(dest);
148 } 149 }
diff --git a/toxav/video.h b/toxav/video.h
index 8da15578..96d3205d 100644
--- a/toxav/video.h
+++ b/toxav/video.h
@@ -71,7 +71,7 @@ typedef struct VCSession_s {
71 ToxAV *av; 71 ToxAV *av;
72 uint32_t friend_number; 72 uint32_t friend_number;
73 73
74 PAIR(toxav_receive_video_frame_cb *, void *) vcb; /* Video frame receive callback */ 74 PAIR(toxav_video_receive_frame_cb *, void *) vcb; /* Video frame receive callback */
75 75
76 pthread_mutex_t queue_mutex[1]; 76 pthread_mutex_t queue_mutex[1];
77} VCSession; 77} VCSession;
@@ -79,7 +79,7 @@ typedef struct VCSession_s {
79/* 79/*
80 * Create new Video Codec session. 80 * Create new Video Codec session.
81 */ 81 */
82VCSession* vc_new(ToxAV* av, uint32_t friend_number, toxav_receive_video_frame_cb *cb, void *cb_data, uint32_t mvfpsz); 82VCSession* vc_new(ToxAV* av, uint32_t friend_number, toxav_video_receive_frame_cb *cb, void *cb_data, uint32_t mvfpsz);
83/* 83/*
84 * Kill the Video Codec session. 84 * Kill the Video Codec session.
85 */ 85 */
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index 9ebe11cf..8cd8852c 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -145,7 +145,7 @@ void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t
145 */ 145 */
146void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *client_id) 146void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *client_id)
147{ 147{
148 return get_shared_key(&dht->shared_keys_recv, shared_key, dht->self_secret_key, client_id); 148 get_shared_key(&dht->shared_keys_recv, shared_key, dht->self_secret_key, client_id);
149} 149}
150 150
151/* Copy shared_key to encrypt/decrypt DHT packet from client_id into shared_key 151/* Copy shared_key to encrypt/decrypt DHT packet from client_id into shared_key
@@ -153,7 +153,7 @@ void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *clien
153 */ 153 */
154void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *client_id) 154void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *client_id)
155{ 155{
156 return get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, client_id); 156 get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, client_id);
157} 157}
158 158
159void to_net_family(IP *ip) 159void to_net_family(IP *ip)
diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c
index dbce762e..5ab5b0e1 100644
--- a/toxcore/LAN_discovery.c
+++ b/toxcore/LAN_discovery.c
@@ -227,18 +227,43 @@ static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast)
227 return ip; 227 return ip;
228} 228}
229 229
230/* Is IP a local ip or not. */
231_Bool Local_ip(IP ip)
232{
233 if (ip.family == AF_INET) {
234 IP4 ip4 = ip.ip4;
235
236 /* Loopback. */
237 if (ip4.uint8[0] == 127)
238 return 1;
239 } else {
240 /* embedded IPv4-in-IPv6 */
241 if (IPV6_IPV4_IN_V6(ip.ip6)) {
242 IP ip4;
243 ip4.family = AF_INET;
244 ip4.ip4.uint32 = ip.ip6.uint32[3];
245 return Local_ip(ip4);
246 }
247
248 /* localhost in IPv6 (::1) */
249 if (ip.ip6.uint64[0] == 0 && ip.ip6.uint32[2] == 0 && ip.ip6.uint32[3] == htonl(1))
250 return 1;
251 }
252
253 return 0;
254}
255
230/* return 0 if ip is a LAN ip. 256/* return 0 if ip is a LAN ip.
231 * return -1 if it is not. 257 * return -1 if it is not.
232 */ 258 */
233int LAN_ip(IP ip) 259int LAN_ip(IP ip)
234{ 260{
261 if (Local_ip(ip))
262 return 0;
263
235 if (ip.family == AF_INET) { 264 if (ip.family == AF_INET) {
236 IP4 ip4 = ip.ip4; 265 IP4 ip4 = ip.ip4;
237 266
238 /* Loopback. */
239 if (ip4.uint8[0] == 127)
240 return 0;
241
242 /* 10.0.0.0 to 10.255.255.255 range. */ 267 /* 10.0.0.0 to 10.255.255.255 range. */
243 if (ip4.uint8[0] == 10) 268 if (ip4.uint8[0] == 10)
244 return 0; 269 return 0;
@@ -276,10 +301,6 @@ int LAN_ip(IP ip)
276 ip4.ip4.uint32 = ip.ip6.uint32[3]; 301 ip4.ip4.uint32 = ip.ip6.uint32[3];
277 return LAN_ip(ip4); 302 return LAN_ip(ip4);
278 } 303 }
279
280 /* localhost in IPv6 (::1) */
281 if (ip.ip6.uint64[0] == 0 && ip.ip6.uint32[2] == 0 && ip.ip6.uint32[3] == htonl(1))
282 return 0;
283 } 304 }
284 305
285 return -1; 306 return -1;
diff --git a/toxcore/LAN_discovery.h b/toxcore/LAN_discovery.h
index 5243bd93..358bea2f 100644
--- a/toxcore/LAN_discovery.h
+++ b/toxcore/LAN_discovery.h
@@ -40,6 +40,9 @@ void LANdiscovery_init(DHT *dht);
40/* Clear packet handlers. */ 40/* Clear packet handlers. */
41void LANdiscovery_kill(DHT *dht); 41void LANdiscovery_kill(DHT *dht);
42 42
43/* Is IP a local ip or not. */
44_Bool Local_ip(IP ip);
45
43/* checks if a given IP isn't routable 46/* checks if a given IP isn't routable
44 * 47 *
45 * return 0 if ip is a LAN ip. 48 * return 0 if ip is a LAN ip.
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index a7e0a9fe..dc0e605a 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -52,24 +52,6 @@ static uint8_t friend_not_valid(const Messenger *m, int32_t friendnumber)
52 return 1; 52 return 1;
53} 53}
54 54
55static int add_online_friend(Messenger *m, int32_t friendnumber)
56{
57 if (friend_not_valid(m, friendnumber))
58 return -1;
59
60 ++m->numonline_friends;
61 return 0;
62}
63
64
65static int remove_online_friend(Messenger *m, int32_t friendnumber)
66{
67 if (friend_not_valid(m, friendnumber))
68 return -1;
69
70 --m->numonline_friends;
71 return 0;
72}
73/* Set the size of the friend list to numfriends. 55/* Set the size of the friend list to numfriends.
74 * 56 *
75 * return -1 if realloc fails. 57 * return -1 if realloc fails.
@@ -399,9 +381,6 @@ int m_delfriend(Messenger *m, int32_t friendnumber)
399 if (friend_not_valid(m, friendnumber)) 381 if (friend_not_valid(m, friendnumber))
400 return -1; 382 return -1;
401 383
402 if (m->friendlist[friendnumber].status == FRIEND_ONLINE)
403 remove_online_friend(m, friendnumber);
404
405 clear_receipts(m, friendnumber); 384 clear_receipts(m, friendnumber);
406 remove_request_received(&(m->fr), m->friendlist[friendnumber].real_pk); 385 remove_request_received(&(m->fr), m->friendlist[friendnumber].real_pk);
407 friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, 0, 0, 0, 0, 0); 386 friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, 0, 0, 0, 0, 0);
@@ -884,10 +863,7 @@ static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, ui
884 if (is_online != was_online) { 863 if (is_online != was_online) {
885 if (was_online) { 864 if (was_online) {
886 break_files(m, friendnumber); 865 break_files(m, friendnumber);
887 remove_online_friend(m, friendnumber);
888 clear_receipts(m, friendnumber); 866 clear_receipts(m, friendnumber);
889 } else {
890 add_online_friend(m, friendnumber);
891 } 867 }
892 868
893 m->friendlist[friendnumber].status = status; 869 m->friendlist[friendnumber].status = status;
@@ -1831,6 +1807,27 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)
1831 return NULL; 1807 return NULL;
1832 } 1808 }
1833 1809
1810 if (options->tcp_server_port) {
1811 m->tcp_server = new_TCP_server(options->ipv6enabled, 1, &options->tcp_server_port, m->dht->self_public_key,
1812 m->dht->self_secret_key, m->onion);
1813
1814 if (m->tcp_server == NULL) {
1815 kill_friend_connections(m->fr_c);
1816 kill_onion(m->onion);
1817 kill_onion_announce(m->onion_a);
1818 kill_onion_client(m->onion_c);
1819 kill_DHT(m->dht);
1820 kill_net_crypto(m->net_crypto);
1821 kill_networking(m->net);
1822 free(m);
1823
1824 if (error)
1825 *error = MESSENGER_ERROR_TCP_SERVER;
1826
1827 return NULL;
1828 }
1829 }
1830
1834 m->options = *options; 1831 m->options = *options;
1835 friendreq_init(&(m->fr), m->fr_c); 1832 friendreq_init(&(m->fr), m->fr_c);
1836 set_nospam(&(m->fr), random_int()); 1833 set_nospam(&(m->fr), random_int());
@@ -1850,6 +1847,10 @@ void kill_messenger(Messenger *m)
1850 1847
1851 uint32_t i; 1848 uint32_t i;
1852 1849
1850 if (m->tcp_server) {
1851 kill_TCP_server(m->tcp_server);
1852 }
1853
1853 kill_friend_connections(m->fr_c); 1854 kill_friend_connections(m->fr_c);
1854 kill_onion(m->onion); 1855 kill_onion(m->onion);
1855 kill_onion_announce(m->onion_a); 1856 kill_onion_announce(m->onion_a);
@@ -2285,6 +2286,15 @@ void do_messenger(Messenger *m)
2285 for (i = 0; i < NUM_SAVED_TCP_RELAYS; ++i) { 2286 for (i = 0; i < NUM_SAVED_TCP_RELAYS; ++i) {
2286 add_tcp_relay(m->net_crypto, m->loaded_relays[i].ip_port, m->loaded_relays[i].public_key); 2287 add_tcp_relay(m->net_crypto, m->loaded_relays[i].ip_port, m->loaded_relays[i].public_key);
2287 } 2288 }
2289
2290 if (m->tcp_server) {
2291 /* Add self tcp server. */
2292 IP_Port local_ip_port;
2293 local_ip_port.port = m->options.tcp_server_port;
2294 local_ip_port.ip.family = AF_INET;
2295 local_ip_port.ip.ip4.uint32 = INADDR_LOOPBACK;
2296 add_tcp_relay(m->net_crypto, local_ip_port, m->tcp_server->public_key);
2297 }
2288 } 2298 }
2289 2299
2290 unix_time_update(); 2300 unix_time_update();
@@ -2294,6 +2304,10 @@ void do_messenger(Messenger *m)
2294 do_DHT(m->dht); 2304 do_DHT(m->dht);
2295 } 2305 }
2296 2306
2307 if (m->tcp_server) {
2308 do_TCP_server(m->tcp_server);
2309 }
2310
2297 do_net_crypto(m->net_crypto); 2311 do_net_crypto(m->net_crypto);
2298 do_onion_client(m->onion_c); 2312 do_onion_client(m->onion_c);
2299 do_friend_connections(m->fr_c); 2313 do_friend_connections(m->fr_c);
@@ -2622,13 +2636,11 @@ static int messenger_load_state_callback(void *outer, const uint8_t *data, uint3
2622 case MESSENGER_STATE_TYPE_NOSPAMKEYS: 2636 case MESSENGER_STATE_TYPE_NOSPAMKEYS:
2623 if (length == crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t)) { 2637 if (length == crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t)) {
2624 set_nospam(&(m->fr), *(uint32_t *)data); 2638 set_nospam(&(m->fr), *(uint32_t *)data);
2625 load_keys(m->net_crypto, &data[sizeof(uint32_t)]); 2639 load_secret_key(m->net_crypto, (&data[sizeof(uint32_t)]) + crypto_box_PUBLICKEYBYTES);
2626#ifdef ENABLE_ASSOC_DHT
2627 2640
2628 if (m->dht->assoc) 2641 if (memcmp((&data[sizeof(uint32_t)]), m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES) != 0) {
2629 Assoc_self_client_id_changed(m->dht->assoc, m->net_crypto->self_public_key); 2642 return -1;
2630 2643 }
2631#endif
2632 } else 2644 } else
2633 return -1; /* critical */ 2645 return -1; /* critical */
2634 2646
@@ -2738,12 +2750,6 @@ uint32_t count_friendlist(const Messenger *m)
2738 return ret; 2750 return ret;
2739} 2751}
2740 2752
2741/* Return the number of online friends in the instance m. */
2742uint32_t get_num_online_friends(const Messenger *m)
2743{
2744 return m->numonline_friends;
2745}
2746
2747/* Copy a list of valid friend IDs into the array out_list. 2753/* Copy a list of valid friend IDs into the array out_list.
2748 * If out_list is NULL, returns 0. 2754 * If out_list is NULL, returns 0.
2749 * Otherwise, returns the number of elements copied. 2755 * Otherwise, returns the number of elements copied.
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index 6943475f..26704dd1 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -27,7 +27,6 @@
27#define MESSENGER_H 27#define MESSENGER_H
28 28
29#include "friend_requests.h" 29#include "friend_requests.h"
30#include "LAN_discovery.h"
31#include "friend_connection.h" 30#include "friend_connection.h"
32 31
33#define MAX_NAME_LENGTH 128 32#define MAX_NAME_LENGTH 128
@@ -71,6 +70,7 @@ typedef struct {
71 uint8_t udp_disabled; 70 uint8_t udp_disabled;
72 TCP_Proxy_Info proxy_info; 71 TCP_Proxy_Info proxy_info;
73 uint16_t port_range[2]; 72 uint16_t port_range[2];
73 uint16_t tcp_server_port;
74} Messenger_Options; 74} Messenger_Options;
75 75
76 76
@@ -220,6 +220,7 @@ struct Messenger {
220 220
221 Friend_Connections *fr_c; 221 Friend_Connections *fr_c;
222 222
223 TCP_Server *tcp_server;
223 Friend_Requests fr; 224 Friend_Requests fr;
224 uint8_t name[MAX_NAME_LENGTH]; 225 uint8_t name[MAX_NAME_LENGTH];
225 uint16_t name_length; 226 uint16_t name_length;
@@ -232,8 +233,6 @@ struct Messenger {
232 Friend *friendlist; 233 Friend *friendlist;
233 uint32_t numfriends; 234 uint32_t numfriends;
234 235
235 uint32_t numonline_friends;
236
237#define NUM_SAVED_TCP_RELAYS 8 236#define NUM_SAVED_TCP_RELAYS 8
238 uint8_t has_added_relays; // If the first connection has occurred in do_messenger 237 uint8_t has_added_relays; // If the first connection has occurred in do_messenger
239 Node_format loaded_relays[NUM_SAVED_TCP_RELAYS]; // Relays loaded from config 238 Node_format loaded_relays[NUM_SAVED_TCP_RELAYS]; // Relays loaded from config
@@ -730,6 +729,7 @@ int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const
730enum { 729enum {
731 MESSENGER_ERROR_NONE, 730 MESSENGER_ERROR_NONE,
732 MESSENGER_ERROR_PORT, 731 MESSENGER_ERROR_PORT,
732 MESSENGER_ERROR_TCP_SERVER,
733 MESSENGER_ERROR_OTHER 733 MESSENGER_ERROR_OTHER
734}; 734};
735 735
@@ -772,9 +772,6 @@ int messenger_load(Messenger *m, const uint8_t *data, uint32_t length);
772 * for copy_friendlist. */ 772 * for copy_friendlist. */
773uint32_t count_friendlist(const Messenger *m); 773uint32_t count_friendlist(const Messenger *m);
774 774
775/* Return the number of online friends in the instance m. */
776uint32_t get_num_online_friends(const Messenger *m);
777
778/* Copy a list of valid friend IDs into the array out_list. 775/* Copy a list of valid friend IDs into the array out_list.
779 * If out_list is NULL, returns 0. 776 * If out_list is NULL, returns 0.
780 * Otherwise, returns the number of elements copied. 777 * Otherwise, returns the number of elements copied.
diff --git a/toxcore/TCP_connection.c b/toxcore/TCP_connection.c
index fe39dc52..b0b26d20 100644
--- a/toxcore/TCP_connection.c
+++ b/toxcore/TCP_connection.c
@@ -249,7 +249,6 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c
249 for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { 249 for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
250 uint32_t tcp_con_num = con_to->connections[i].tcp_connection; 250 uint32_t tcp_con_num = con_to->connections[i].tcp_connection;
251 uint8_t status = con_to->connections[i].status; 251 uint8_t status = con_to->connections[i].status;
252 uint8_t connection_id = con_to->connections[i].connection_id;
253 252
254 if (tcp_con_num && status == TCP_CONNECTIONS_STATUS_REGISTERED) { 253 if (tcp_con_num && status == TCP_CONNECTIONS_STATUS_REGISTERED) {
255 tcp_con_num -= 1; 254 tcp_con_num -= 1;
diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h
index 727c4b4e..ba3e7308 100644
--- a/toxcore/TCP_server.h
+++ b/toxcore/TCP_server.h
@@ -85,7 +85,7 @@ typedef struct TCP_Priority_List TCP_Priority_List;
85struct TCP_Priority_List { 85struct TCP_Priority_List {
86 TCP_Priority_List *next; 86 TCP_Priority_List *next;
87 uint16_t size, sent; 87 uint16_t size, sent;
88 uint8_t data[0]; 88 uint8_t data[];
89}; 89};
90 90
91typedef struct TCP_Secure_Connection { 91typedef struct TCP_Secure_Connection {
diff --git a/toxcore/crypto_core.h b/toxcore/crypto_core.h
index d7306a8a..eefb1d90 100644
--- a/toxcore/crypto_core.h
+++ b/toxcore/crypto_core.h
@@ -35,6 +35,7 @@
35#include <crypto_hash_sha512.h> 35#include <crypto_hash_sha512.h>
36#include <crypto_verify_16.h> 36#include <crypto_verify_16.h>
37#include <crypto_verify_32.h> 37#include <crypto_verify_32.h>
38#include <crypto_scalarmult_curve25519.h>
38#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) 39#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
39#endif 40#endif
40 41
diff --git a/toxcore/friend_connection.c b/toxcore/friend_connection.c
index c13ca949..1656def0 100644
--- a/toxcore/friend_connection.c
+++ b/toxcore/friend_connection.c
@@ -158,6 +158,15 @@ int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, IP_Port ip_
158 if (!friend_con) 158 if (!friend_con)
159 return -1; 159 return -1;
160 160
161 /* Local ip and same pk means that they are hosting a TCP relay. */
162 if (Local_ip(ip_port.ip) && memcmp(friend_con->dht_temp_pk, public_key, crypto_box_PUBLICKEYBYTES) == 0) {
163 if (friend_con->dht_ip_port.ip.family != 0) {
164 ip_port.ip = friend_con->dht_ip_port.ip;
165 } else {
166 friend_con->hosting_tcp_relay = 0;
167 }
168 }
169
161 unsigned int i; 170 unsigned int i;
162 171
163 uint16_t index = friend_con->tcp_relay_counter % FRIEND_MAX_STORED_TCP_RELAYS; 172 uint16_t index = friend_con->tcp_relay_counter % FRIEND_MAX_STORED_TCP_RELAYS;
@@ -265,9 +274,14 @@ static void dht_ip_callback(void *object, int32_t number, IP_Port ip_port)
265 friend_new_connection(fr_c, number); 274 friend_new_connection(fr_c, number);
266 } 275 }
267 276
268 set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port); 277 set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, 1);
269 friend_con->dht_ip_port = ip_port; 278 friend_con->dht_ip_port = ip_port;
270 friend_con->dht_ip_port_lastrecv = unix_time(); 279 friend_con->dht_ip_port_lastrecv = unix_time();
280
281 if (friend_con->hosting_tcp_relay) {
282 friend_add_tcp_relay(fr_c, number, ip_port, friend_con->dht_temp_pk);
283 friend_con->hosting_tcp_relay = 0;
284 }
271} 285}
272 286
273static void change_dht_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_public_key) 287static void change_dht_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_public_key)
@@ -317,6 +331,7 @@ static int handle_status(void *object, int number, uint8_t status)
317 331
318 friend_con->status = FRIENDCONN_STATUS_CONNECTING; 332 friend_con->status = FRIENDCONN_STATUS_CONNECTING;
319 friend_con->crypt_connection_id = -1; 333 friend_con->crypt_connection_id = -1;
334 friend_con->hosting_tcp_relay = 0;
320 } 335 }
321 336
322 if (call_cb) { 337 if (call_cb) {
@@ -458,7 +473,7 @@ static int handle_new_connections(void *object, New_Connection *n_c)
458 friend_con->crypt_connection_id = id; 473 friend_con->crypt_connection_id = id;
459 474
460 if (n_c->source.ip.family != AF_INET && n_c->source.ip.family != AF_INET6) { 475 if (n_c->source.ip.family != AF_INET && n_c->source.ip.family != AF_INET6) {
461 set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port); 476 set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0);
462 } else { 477 } else {
463 friend_con->dht_ip_port = n_c->source; 478 friend_con->dht_ip_port = n_c->source;
464 friend_con->dht_ip_port_lastrecv = unix_time(); 479 friend_con->dht_ip_port_lastrecv = unix_time();
@@ -796,7 +811,7 @@ void do_friend_connections(Friend_Connections *fr_c)
796 811
797 if (friend_con->dht_lock) { 812 if (friend_con->dht_lock) {
798 if (friend_new_connection(fr_c, i) == 0) { 813 if (friend_new_connection(fr_c, i) == 0) {
799 set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port); 814 set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0);
800 connect_to_saved_tcp_relays(fr_c, i, (MAX_FRIEND_TCP_CONNECTIONS / 2)); /* Only fill it half up. */ 815 connect_to_saved_tcp_relays(fr_c, i, (MAX_FRIEND_TCP_CONNECTIONS / 2)); /* Only fill it half up. */
801 } 816 }
802 } 817 }
diff --git a/toxcore/friend_connection.h b/toxcore/friend_connection.h
index baca4b76..32e947ac 100644
--- a/toxcore/friend_connection.h
+++ b/toxcore/friend_connection.h
@@ -96,6 +96,8 @@ typedef struct {
96 96
97 Node_format tcp_relays[FRIEND_MAX_STORED_TCP_RELAYS]; 97 Node_format tcp_relays[FRIEND_MAX_STORED_TCP_RELAYS];
98 uint16_t tcp_relay_counter; 98 uint16_t tcp_relay_counter;
99
100 _Bool hosting_tcp_relay;
99} Friend_Conn; 101} Friend_Conn;
100 102
101 103
diff --git a/toxcore/list.c b/toxcore/list.c
index 301e56f8..b97727f8 100644
--- a/toxcore/list.c
+++ b/toxcore/list.c
@@ -45,7 +45,7 @@
45 * < 0 : no match, returns index (return value is INDEX(index)) where 45 * < 0 : no match, returns index (return value is INDEX(index)) where
46 * the data should be inserted 46 * the data should be inserted
47 */ 47 */
48static int find(const BS_LIST *list, const void *data) 48static int find(const BS_LIST *list, const uint8_t *data)
49{ 49{
50 //should work well, but could be improved 50 //should work well, but could be improved
51 if (list->n == 0) { 51 if (list->n == 0) {
@@ -162,7 +162,7 @@ void bs_list_free(BS_LIST *list)
162 free(list->ids); 162 free(list->ids);
163} 163}
164 164
165int bs_list_find(const BS_LIST *list, const void *data) 165int bs_list_find(const BS_LIST *list, const uint8_t *data)
166{ 166{
167 int r = find(list, data); 167 int r = find(list, data);
168 168
@@ -174,7 +174,7 @@ int bs_list_find(const BS_LIST *list, const void *data)
174 return list->ids[r]; 174 return list->ids[r];
175} 175}
176 176
177int bs_list_add(BS_LIST *list, const void *data, int id) 177int bs_list_add(BS_LIST *list, const uint8_t *data, int id)
178{ 178{
179 //find where the new element should be inserted 179 //find where the new element should be inserted
180 //see: return value of find() 180 //see: return value of find()
@@ -214,7 +214,7 @@ int bs_list_add(BS_LIST *list, const void *data, int id)
214 return 1; 214 return 1;
215} 215}
216 216
217int bs_list_remove(BS_LIST *list, const void *data, int id) 217int bs_list_remove(BS_LIST *list, const uint8_t *data, int id)
218{ 218{
219 int i = find(list, data); 219 int i = find(list, data);
220 220
diff --git a/toxcore/list.h b/toxcore/list.h
index 03ac04dd..b04177e1 100644
--- a/toxcore/list.h
+++ b/toxcore/list.h
@@ -34,7 +34,7 @@ typedef struct {
34 uint32_t n; //number of elements 34 uint32_t n; //number of elements
35 uint32_t capacity; //number of elements memory is allocated for 35 uint32_t capacity; //number of elements memory is allocated for
36 uint32_t element_size; //size of the elements 36 uint32_t element_size; //size of the elements
37 void *data; //array of elements 37 uint8_t *data; //array of elements
38 int *ids; //array of element ids 38 int *ids; //array of element ids
39} BS_LIST; 39} BS_LIST;
40 40
@@ -56,7 +56,7 @@ void bs_list_free(BS_LIST *list);
56 * >= 0 : id associated with data 56 * >= 0 : id associated with data
57 * -1 : failure 57 * -1 : failure
58 */ 58 */
59int bs_list_find(const BS_LIST *list, const void *data); 59int bs_list_find(const BS_LIST *list, const uint8_t *data);
60 60
61/* Add an element with associated id to the list 61/* Add an element with associated id to the list
62 * 62 *
@@ -64,7 +64,7 @@ int bs_list_find(const BS_LIST *list, const void *data);
64 * 1 : success 64 * 1 : success
65 * 0 : failure (data already in list) 65 * 0 : failure (data already in list)
66 */ 66 */
67int bs_list_add(BS_LIST *list, const void *data, int id); 67int bs_list_add(BS_LIST *list, const uint8_t *data, int id);
68 68
69/* Remove element from the list 69/* Remove element from the list
70 * 70 *
@@ -72,7 +72,7 @@ int bs_list_add(BS_LIST *list, const void *data, int id);
72 * 1 : success 72 * 1 : success
73 * 0 : failure (element not found or id does not match) 73 * 0 : failure (element not found or id does not match)
74 */ 74 */
75int bs_list_remove(BS_LIST *list, const void *data, int id); 75int bs_list_remove(BS_LIST *list, const uint8_t *data, int id);
76 76
77/* Removes the memory overhead 77/* Removes the memory overhead
78 * 78 *
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c
index 0ed855bb..6d4f6a9b 100644
--- a/toxcore/net_crypto.c
+++ b/toxcore/net_crypto.c
@@ -676,6 +676,8 @@ static int handle_request_packet(Packets_Array *send_array, const uint8_t *data,
676 uint32_t i, n = 1; 676 uint32_t i, n = 1;
677 uint32_t requested = 0; 677 uint32_t requested = 0;
678 678
679 uint64_t temp_time = current_time_monotonic();
680
679 for (i = send_array->buffer_start; i != send_array->buffer_end; ++i) { 681 for (i = send_array->buffer_start; i != send_array->buffer_end; ++i) {
680 if (length == 0) 682 if (length == 0)
681 break; 683 break;
@@ -684,7 +686,11 @@ static int handle_request_packet(Packets_Array *send_array, const uint8_t *data,
684 686
685 if (n == data[0]) { 687 if (n == data[0]) {
686 if (send_array->buffer[num]) { 688 if (send_array->buffer[num]) {
687 send_array->buffer[num]->sent = 0; 689 uint64_t sent_time = send_array->buffer[num]->sent_time;
690
691 if ((sent_time + DEFAULT_PING_CONNECTION) < temp_time) {
692 send_array->buffer[num]->sent_time = 0;
693 }
688 } 694 }
689 695
690 ++data; 696 ++data;
@@ -788,12 +794,12 @@ static int reset_max_speed_reached(Net_Crypto *c, int crypt_connection_id)
788 uint8_t send_failed = 0; 794 uint8_t send_failed = 0;
789 795
790 if (ret == 1) { 796 if (ret == 1) {
791 if (!dt->sent) { 797 if (!dt->sent_time) {
792 if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, dt->data, 798 if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, dt->data,
793 dt->length) != 0) { 799 dt->length) != 0) {
794 send_failed = 1; 800 send_failed = 1;
795 } else { 801 } else {
796 dt->sent = 1; 802 dt->sent_time = current_time_monotonic();
797 } 803 }
798 } 804 }
799 } 805 }
@@ -831,7 +837,7 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, cons
831 } 837 }
832 838
833 Packet_Data dt; 839 Packet_Data dt;
834 dt.sent = 0; 840 dt.sent_time = 0;
835 dt.length = length; 841 dt.length = length;
836 memcpy(dt.data, data, length); 842 memcpy(dt.data, data, length);
837 pthread_mutex_lock(&conn->mutex); 843 pthread_mutex_lock(&conn->mutex);
@@ -849,7 +855,7 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, cons
849 Packet_Data *dt1 = NULL; 855 Packet_Data *dt1 = NULL;
850 856
851 if (get_data_pointer(&conn->send_array, &dt1, packet_num) == 1) 857 if (get_data_pointer(&conn->send_array, &dt1, packet_num) == 1)
852 dt1->sent = 1; 858 dt1->sent_time = current_time_monotonic();
853 } else { 859 } else {
854 conn->maximum_speed_reached = 1; 860 conn->maximum_speed_reached = 1;
855 LOGGER_ERROR("send_data_packet failed\n"); 861 LOGGER_ERROR("send_data_packet failed\n");
@@ -936,7 +942,7 @@ static int send_request_packet(Net_Crypto *c, int crypt_connection_id)
936 * return -1 on failure. 942 * return -1 on failure.
937 * return number of packets sent on success. 943 * return number of packets sent on success.
938 */ 944 */
939static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint16_t max_num) 945static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32_t max_num)
940{ 946{
941 if (max_num == 0) 947 if (max_num == 0)
942 return -1; 948 return -1;
@@ -946,6 +952,7 @@ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint16
946 if (conn == 0) 952 if (conn == 0)
947 return -1; 953 return -1;
948 954
955 uint64_t temp_time = current_time_monotonic();
949 uint32_t i, num_sent = 0, array_size = num_packets_array(&conn->send_array); 956 uint32_t i, num_sent = 0, array_size = num_packets_array(&conn->send_array);
950 957
951 for (i = 0; i < array_size; ++i) { 958 for (i = 0; i < array_size; ++i) {
@@ -959,13 +966,13 @@ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint16
959 continue; 966 continue;
960 } 967 }
961 968
962 if (dt->sent) { 969 if (dt->sent_time) {
963 continue; 970 continue;
964 } 971 }
965 972
966 if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, dt->data, 973 if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, dt->data,
967 dt->length) == 0) { 974 dt->length) == 0) {
968 dt->sent = 1; 975 dt->sent_time = temp_time;
969 ++num_sent; 976 ++num_sent;
970 } 977 }
971 978
@@ -1439,10 +1446,10 @@ static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id,
1439 1446
1440 if (source.ip.family == AF_INET || source.ip.family == AF_INET6) { 1447 if (source.ip.family == AF_INET || source.ip.family == AF_INET6) {
1441 if (!ipport_equal(&source, &conn->ip_port)) { 1448 if (!ipport_equal(&source, &conn->ip_port)) {
1442 if (!bs_list_add(&c->ip_port_list, &source, crypt_connection_id)) 1449 if (!bs_list_add(&c->ip_port_list, (uint8_t *)&source, crypt_connection_id))
1443 return -1; 1450 return -1;
1444 1451
1445 bs_list_remove(&c->ip_port_list, &conn->ip_port, crypt_connection_id); 1452 bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_port, crypt_connection_id);
1446 conn->ip_port = source; 1453 conn->ip_port = source;
1447 } 1454 }
1448 1455
@@ -1547,12 +1554,13 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c)
1547 return -1; 1554 return -1;
1548 1555
1549 pthread_mutex_lock(&c->tcp_mutex); 1556 pthread_mutex_lock(&c->tcp_mutex);
1550 conn->connection_number_tcp = new_tcp_connection_to(c->tcp_c, n_c->dht_public_key, crypt_connection_id); 1557 int connection_number_tcp = new_tcp_connection_to(c->tcp_c, n_c->dht_public_key, crypt_connection_id);
1551 pthread_mutex_unlock(&c->tcp_mutex); 1558 pthread_mutex_unlock(&c->tcp_mutex);
1552 1559
1553 if (conn->connection_number_tcp == -1) 1560 if (connection_number_tcp == -1)
1554 return -1; 1561 return -1;
1555 1562
1563 conn->connection_number_tcp = connection_number_tcp;
1556 memcpy(conn->public_key, n_c->public_key, crypto_box_PUBLICKEYBYTES); 1564 memcpy(conn->public_key, n_c->public_key, crypto_box_PUBLICKEYBYTES);
1557 memcpy(conn->recv_nonce, n_c->recv_nonce, crypto_box_NONCEBYTES); 1565 memcpy(conn->recv_nonce, n_c->recv_nonce, crypto_box_NONCEBYTES);
1558 memcpy(conn->peersessionpublic_key, n_c->peersessionpublic_key, crypto_box_PUBLICKEYBYTES); 1566 memcpy(conn->peersessionpublic_key, n_c->peersessionpublic_key, crypto_box_PUBLICKEYBYTES);
@@ -1600,12 +1608,13 @@ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const u
1600 return -1; 1608 return -1;
1601 1609
1602 pthread_mutex_lock(&c->tcp_mutex); 1610 pthread_mutex_lock(&c->tcp_mutex);
1603 conn->connection_number_tcp = new_tcp_connection_to(c->tcp_c, dht_public_key, crypt_connection_id); 1611 int connection_number_tcp = new_tcp_connection_to(c->tcp_c, dht_public_key, crypt_connection_id);
1604 pthread_mutex_unlock(&c->tcp_mutex); 1612 pthread_mutex_unlock(&c->tcp_mutex);
1605 1613
1606 if (conn->connection_number_tcp == -1) 1614 if (connection_number_tcp == -1)
1607 return -1; 1615 return -1;
1608 1616
1617 conn->connection_number_tcp = connection_number_tcp;
1609 memcpy(conn->public_key, real_public_key, crypto_box_PUBLICKEYBYTES); 1618 memcpy(conn->public_key, real_public_key, crypto_box_PUBLICKEYBYTES);
1610 random_nonce(conn->sent_nonce); 1619 random_nonce(conn->sent_nonce);
1611 crypto_box_keypair(conn->sessionpublic_key, conn->sessionsecret_key); 1620 crypto_box_keypair(conn->sessionpublic_key, conn->sessionsecret_key);
@@ -1632,10 +1641,12 @@ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const u
1632 1641
1633/* Set the direct ip of the crypto connection. 1642/* Set the direct ip of the crypto connection.
1634 * 1643 *
1644 * Connected is 0 if we are not sure we are connected to that person, 1 if we are sure.
1645 *
1635 * return -1 on failure. 1646 * return -1 on failure.
1636 * return 0 on success. 1647 * return 0 on success.
1637 */ 1648 */
1638int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port) 1649int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, _Bool connected)
1639{ 1650{
1640 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); 1651 Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
1641 1652
@@ -1656,10 +1667,16 @@ int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port)
1656 return -1; 1667 return -1;
1657 } 1668 }
1658 1669
1659 if (bs_list_add(&c->ip_port_list, &ip_port, crypt_connection_id)) { 1670 if (bs_list_add(&c->ip_port_list, (uint8_t *)&ip_port, crypt_connection_id)) {
1660 bs_list_remove(&c->ip_port_list, &conn->ip_port, crypt_connection_id); 1671 bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_port, crypt_connection_id);
1661 conn->ip_port = ip_port; 1672 conn->ip_port = ip_port;
1662 conn->direct_lastrecv_time = 0; 1673
1674 if (connected) {
1675 conn->direct_lastrecv_time = unix_time();
1676 } else {
1677 conn->direct_lastrecv_time = 0;
1678 }
1679
1663 return 0; 1680 return 0;
1664 } 1681 }
1665 } 1682 }
@@ -1931,7 +1948,7 @@ int nc_dht_pk_callback(Net_Crypto *c, int crypt_connection_id, void (*function)(
1931 */ 1948 */
1932static int crypto_id_ip_port(const Net_Crypto *c, IP_Port ip_port) 1949static int crypto_id_ip_port(const Net_Crypto *c, IP_Port ip_port)
1933{ 1950{
1934 return bs_list_find(&c->ip_port_list, &ip_port); 1951 return bs_list_find(&c->ip_port_list, (uint8_t *)&ip_port);
1935} 1952}
1936 1953
1937#define CRYPTO_MIN_PACKET_SIZE (1 + sizeof(uint16_t) + crypto_box_MACBYTES) 1954#define CRYPTO_MIN_PACKET_SIZE (1 + sizeof(uint16_t) + crypto_box_MACBYTES)
@@ -1983,7 +2000,14 @@ static int udp_handle_packet(void *object, IP_Port source, const uint8_t *packet
1983/* Ratio of recv queue size / recv packet rate (in seconds) times 2000/* Ratio of recv queue size / recv packet rate (in seconds) times
1984 * the number of ms between request packets to send at that ratio 2001 * the number of ms between request packets to send at that ratio
1985 */ 2002 */
1986#define REQUEST_PACKETS_COMPARE_CONSTANT (0.5 * 100.0) 2003#define REQUEST_PACKETS_COMPARE_CONSTANT (0.125 * 100.0)
2004
2005/* Multiplier for maximum allowed resends. */
2006#define PACKET_RESEND_MULTIPLIER 2
2007
2008/* Timeout for increasing speed after congestion event (in ms). */
2009#define CONGESTION_EVENT_TIMEOUT 4000
2010
1987static void send_crypto_packets(Net_Crypto *c) 2011static void send_crypto_packets(Net_Crypto *c)
1988{ 2012{
1989 uint32_t i; 2013 uint32_t i;
@@ -2061,7 +2085,11 @@ static void send_crypto_packets(Net_Crypto *c)
2061 double min_speed = 1000.0 * (((double)(total_sent)) / ((double)(CONGESTION_QUEUE_ARRAY_SIZE) * 2085 double min_speed = 1000.0 * (((double)(total_sent)) / ((double)(CONGESTION_QUEUE_ARRAY_SIZE) *
2062 PACKET_COUNTER_AVERAGE_INTERVAL)); 2086 PACKET_COUNTER_AVERAGE_INTERVAL));
2063 2087
2064 conn->packet_send_rate = min_speed * 1.2; 2088 if (conn->last_congestion_event + CONGESTION_EVENT_TIMEOUT < temp_time) {
2089 conn->packet_send_rate = min_speed * 1.2;
2090 } else {
2091 conn->packet_send_rate = min_speed;
2092 }
2065 2093
2066 if (conn->packet_send_rate < CRYPTO_PACKET_MIN_RATE) { 2094 if (conn->packet_send_rate < CRYPTO_PACKET_MIN_RATE) {
2067 conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; 2095 conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE;
@@ -2084,10 +2112,15 @@ static void send_crypto_packets(Net_Crypto *c)
2084 conn->last_packets_left_set = temp_time; 2112 conn->last_packets_left_set = temp_time;
2085 } 2113 }
2086 2114
2087 int ret = send_requested_packets(c, i, conn->packets_left); 2115 int ret = send_requested_packets(c, i, conn->packets_left * PACKET_RESEND_MULTIPLIER);
2088 2116
2089 if (ret != -1) { 2117 if (ret != -1) {
2090 conn->packets_left -= ret; 2118 if (ret < conn->packets_left) {
2119 conn->packets_left -= ret;
2120 } else {
2121 conn->last_congestion_event = temp_time;
2122 conn->packets_left = 0;
2123 }
2091 } 2124 }
2092 2125
2093 if (conn->packet_send_rate > CRYPTO_PACKET_MIN_RATE * 1.5) { 2126 if (conn->packet_send_rate > CRYPTO_PACKET_MIN_RATE * 1.5) {
@@ -2280,7 +2313,7 @@ int crypto_kill(Net_Crypto *c, int crypt_connection_id)
2280 kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp); 2313 kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp);
2281 pthread_mutex_unlock(&c->tcp_mutex); 2314 pthread_mutex_unlock(&c->tcp_mutex);
2282 2315
2283 bs_list_remove(&c->ip_port_list, &conn->ip_port, crypt_connection_id); 2316 bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_port, crypt_connection_id);
2284 clear_temp_packet(c, crypt_connection_id); 2317 clear_temp_packet(c, crypt_connection_id);
2285 clear_buffer(&conn->send_array); 2318 clear_buffer(&conn->send_array);
2286 clear_buffer(&conn->recv_array); 2319 clear_buffer(&conn->recv_array);
@@ -2326,6 +2359,8 @@ void new_keys(Net_Crypto *c)
2326 2359
2327/* Save the public and private keys to the keys array. 2360/* Save the public and private keys to the keys array.
2328 * Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES. 2361 * Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES.
2362 *
2363 * TODO: Save only secret key.
2329 */ 2364 */
2330void save_keys(const Net_Crypto *c, uint8_t *keys) 2365void save_keys(const Net_Crypto *c, uint8_t *keys)
2331{ 2366{
@@ -2333,13 +2368,13 @@ void save_keys(const Net_Crypto *c, uint8_t *keys)
2333 memcpy(keys + crypto_box_PUBLICKEYBYTES, c->self_secret_key, crypto_box_SECRETKEYBYTES); 2368 memcpy(keys + crypto_box_PUBLICKEYBYTES, c->self_secret_key, crypto_box_SECRETKEYBYTES);
2334} 2369}
2335 2370
2336/* Load the public and private keys from the keys array. 2371/* Load the secret key.
2337 * Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES. 2372 * Length must be crypto_box_SECRETKEYBYTES.
2338 */ 2373 */
2339void load_keys(Net_Crypto *c, const uint8_t *keys) 2374void load_secret_key(Net_Crypto *c, const uint8_t *sk)
2340{ 2375{
2341 memcpy(c->self_public_key, keys, crypto_box_PUBLICKEYBYTES); 2376 memcpy(c->self_secret_key, sk, crypto_box_SECRETKEYBYTES);
2342 memcpy(c->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES); 2377 crypto_scalarmult_curve25519_base(c->self_public_key, c->self_secret_key);
2343} 2378}
2344 2379
2345/* Run this to (re)initialize net_crypto. 2380/* Run this to (re)initialize net_crypto.
diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h
index 9eb5e2d3..56f43cc4 100644
--- a/toxcore/net_crypto.h
+++ b/toxcore/net_crypto.h
@@ -82,8 +82,11 @@
82 at the dT defined in net_crypto.c */ 82 at the dT defined in net_crypto.c */
83#define CONGESTION_QUEUE_ARRAY_SIZE 24 83#define CONGESTION_QUEUE_ARRAY_SIZE 24
84 84
85/* Connection ping in ms. TODO: calculate it per connection. */
86#define DEFAULT_PING_CONNECTION 50
87
85typedef struct { 88typedef struct {
86 _Bool sent; 89 uint64_t sent_time;
87 uint16_t length; 90 uint16_t length;
88 uint8_t data[MAX_CRYPTO_DATA_SIZE]; 91 uint8_t data[MAX_CRYPTO_DATA_SIZE];
89} Packet_Data; 92} Packet_Data;
@@ -146,6 +149,7 @@ typedef struct {
146 uint32_t last_sendqueue_size[CONGESTION_QUEUE_ARRAY_SIZE], last_sendqueue_counter; 149 uint32_t last_sendqueue_size[CONGESTION_QUEUE_ARRAY_SIZE], last_sendqueue_counter;
147 long signed int last_num_packets_sent[CONGESTION_QUEUE_ARRAY_SIZE]; 150 long signed int last_num_packets_sent[CONGESTION_QUEUE_ARRAY_SIZE];
148 uint32_t packets_sent; 151 uint32_t packets_sent;
152 uint64_t last_congestion_event;
149 153
150 /* TCP_connection connection_number */ 154 /* TCP_connection connection_number */
151 unsigned int connection_number_tcp; 155 unsigned int connection_number_tcp;
@@ -224,10 +228,12 @@ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const u
224 228
225/* Set the direct ip of the crypto connection. 229/* Set the direct ip of the crypto connection.
226 * 230 *
231 * Connected is 0 if we are not sure we are connected to that person, 1 if we are sure.
232 *
227 * return -1 on failure. 233 * return -1 on failure.
228 * return 0 on success. 234 * return 0 on success.
229 */ 235 */
230int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port); 236int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, _Bool connected);
231 237
232/* Set function to be called when connection with crypt_connection_id goes connects/disconnects. 238/* Set function to be called when connection with crypt_connection_id goes connects/disconnects.
233 * 239 *
@@ -378,10 +384,10 @@ void new_keys(Net_Crypto *c);
378 */ 384 */
379void save_keys(const Net_Crypto *c, uint8_t *keys); 385void save_keys(const Net_Crypto *c, uint8_t *keys);
380 386
381/* Load the public and private keys from the keys array. 387/* Load the secret key.
382 * Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES. 388 * Length must be crypto_box_SECRETKEYBYTES.
383 */ 389 */
384void load_keys(Net_Crypto *c, const uint8_t *keys); 390void load_secret_key(Net_Crypto *c, const uint8_t *sk);
385 391
386/* Create new instance of Net_Crypto. 392/* Create new instance of Net_Crypto.
387 * Sets all the global connection variables to their default values. 393 * Sets all the global connection variables to their default values.
diff --git a/toxcore/network.c b/toxcore/network.c
index e8787127..22ee4202 100644
--- a/toxcore/network.c
+++ b/toxcore/network.c
@@ -813,7 +813,7 @@ void ipport_copy(IP_Port *target, const IP_Port *source)
813 return; 813 return;
814 814
815 memcpy(target, source, sizeof(IP_Port)); 815 memcpy(target, source, sizeof(IP_Port));
816}; 816}
817 817
818/* ip_ntoa 818/* ip_ntoa
819 * converts ip into a string 819 * converts ip into a string
diff --git a/toxcore/onion.c b/toxcore/onion.c
index 48e4c769..cec178b9 100644
--- a/toxcore/onion.c
+++ b/toxcore/onion.c
@@ -104,7 +104,7 @@ static int ipport_unpack(IP_Port *target, const uint8_t *data, unsigned int data
104 104
105/* Create a new onion path. 105/* Create a new onion path.
106 * 106 *
107 * Create a new onion path out of nodes (nodes is a list of 3 nodes) 107 * Create a new onion path out of nodes (nodes is a list of ONION_PATH_LENGTH nodes)
108 * 108 *
109 * new_path must be an empty memory location of atleast Onion_Path size. 109 * new_path must be an empty memory location of atleast Onion_Path size.
110 * 110 *
@@ -148,7 +148,7 @@ int create_onion_path(const DHT *dht, Onion_Path *new_path, const Node_format *n
148 */ 148 */
149int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_Path *path) 149int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_Path *path)
150{ 150{
151 if (num_nodes < 3) 151 if (num_nodes < ONION_PATH_LENGTH)
152 return -1; 152 return -1;
153 153
154 nodes[0].ip_port = path->ip_port1; 154 nodes[0].ip_port = path->ip_port1;
diff --git a/toxcore/onion.h b/toxcore/onion.h
index b05d2c8c..2b270ea9 100644
--- a/toxcore/onion.h
+++ b/toxcore/onion.h
@@ -53,6 +53,8 @@ typedef struct {
53#define ONION_MAX_DATA_SIZE (ONION_MAX_PACKET_SIZE - (ONION_SEND_1 + 1)) 53#define ONION_MAX_DATA_SIZE (ONION_MAX_PACKET_SIZE - (ONION_SEND_1 + 1))
54#define ONION_RESPONSE_MAX_DATA_SIZE (ONION_MAX_PACKET_SIZE - (1 + ONION_RETURN_3)) 54#define ONION_RESPONSE_MAX_DATA_SIZE (ONION_MAX_PACKET_SIZE - (1 + ONION_RETURN_3))
55 55
56#define ONION_PATH_LENGTH 3
57
56typedef struct { 58typedef struct {
57 uint8_t shared_key1[crypto_box_BEFORENMBYTES]; 59 uint8_t shared_key1[crypto_box_BEFORENMBYTES];
58 uint8_t shared_key2[crypto_box_BEFORENMBYTES]; 60 uint8_t shared_key2[crypto_box_BEFORENMBYTES];
@@ -76,7 +78,7 @@ typedef struct {
76 78
77/* Create a new onion path. 79/* Create a new onion path.
78 * 80 *
79 * Create a new onion path out of nodes (nodes is a list of 3 nodes) 81 * Create a new onion path out of nodes (nodes is a list of ONION_PATH_LENGTH nodes)
80 * 82 *
81 * new_path must be an empty memory location of atleast Onion_Path size. 83 * new_path must be an empty memory location of atleast Onion_Path size.
82 * 84 *
diff --git a/toxcore/onion_announce.h b/toxcore/onion_announce.h
index 36ffe767..0e041e50 100644
--- a/toxcore/onion_announce.h
+++ b/toxcore/onion_announce.h
@@ -25,7 +25,7 @@
25 25
26#include "onion.h" 26#include "onion.h"
27 27
28#define ONION_ANNOUNCE_MAX_ENTRIES 64 28#define ONION_ANNOUNCE_MAX_ENTRIES 96
29#define ONION_ANNOUNCE_TIMEOUT 300 29#define ONION_ANNOUNCE_TIMEOUT 300
30#define ONION_PING_ID_SIZE crypto_hash_sha256_BYTES 30#define ONION_PING_ID_SIZE crypto_hash_sha256_BYTES
31 31
diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c
index ed328fb3..6575f632 100644
--- a/toxcore/onion_client.c
+++ b/toxcore/onion_client.c
@@ -190,7 +190,7 @@ static int is_path_used(const Onion_Client_Paths *onion_paths, const Node_format
190 continue; 190 continue;
191 } 191 }
192 192
193 if (ipport_equal(&onion_paths->paths[i].ip_port1, &nodes[2].ip_port)) { 193 if (ipport_equal(&onion_paths->paths[i].ip_port1, &nodes[ONION_PATH_LENGTH - 1].ip_port)) {
194 return i; 194 return i;
195 } 195 }
196 } 196 }
@@ -215,9 +215,9 @@ static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_pa
215 if ((onion_paths->last_path_success[pathnum] + ONION_PATH_TIMEOUT < onion_paths->last_path_used[pathnum] 215 if ((onion_paths->last_path_success[pathnum] + ONION_PATH_TIMEOUT < onion_paths->last_path_used[pathnum]
216 && onion_paths->last_path_used_times[pathnum] >= ONION_PATH_MAX_NO_RESPONSE_USES) 216 && onion_paths->last_path_used_times[pathnum] >= ONION_PATH_MAX_NO_RESPONSE_USES)
217 || is_timeout(onion_paths->path_creation_time[pathnum], ONION_PATH_MAX_LIFETIME)) { 217 || is_timeout(onion_paths->path_creation_time[pathnum], ONION_PATH_MAX_LIFETIME)) {
218 Node_format nodes[3]; 218 Node_format nodes[ONION_PATH_LENGTH];
219 219
220 if (random_nodes_path_onion(onion_c, nodes, 3) != 3) 220 if (random_nodes_path_onion(onion_c, nodes, ONION_PATH_LENGTH) != ONION_PATH_LENGTH)
221 return -1; 221 return -1;
222 222
223 int n = is_path_used(onion_paths, nodes); 223 int n = is_path_used(onion_paths, nodes);
@@ -267,13 +267,12 @@ static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, uint32_t
267 onion_paths->last_path_success[path_num % NUMBER_ONION_PATHS] = unix_time(); 267 onion_paths->last_path_success[path_num % NUMBER_ONION_PATHS] = unix_time();
268 onion_paths->last_path_used_times[path_num % NUMBER_ONION_PATHS] = 0; 268 onion_paths->last_path_used_times[path_num % NUMBER_ONION_PATHS] = 0;
269 269
270 unsigned int path_len = 3; 270 Node_format nodes[ONION_PATH_LENGTH];
271 Node_format nodes[path_len];
272 271
273 if (onion_path_to_nodes(nodes, path_len, &onion_paths->paths[path_num % NUMBER_ONION_PATHS]) == 0) { 272 if (onion_path_to_nodes(nodes, ONION_PATH_LENGTH, &onion_paths->paths[path_num % NUMBER_ONION_PATHS]) == 0) {
274 unsigned int i; 273 unsigned int i;
275 274
276 for (i = 0; i < path_len; ++i) { 275 for (i = 0; i < ONION_PATH_LENGTH; ++i) {
277 onion_add_path_node(onion_c, nodes[i].ip_port, nodes[i].public_key); 276 onion_add_path_node(onion_c, nodes[i].ip_port, nodes[i].public_key);
278 } 277 }
279 } 278 }
@@ -1205,7 +1204,7 @@ static void populate_path_nodes_tcp(Onion_Client *onion_c)
1205 unsigned int i; 1204 unsigned int i;
1206 1205
1207 for (i = 0; i < num_nodes; ++i) { 1206 for (i = 0; i < num_nodes; ++i) {
1208 onion_add_path_node(onion_c, nodes_list[i].ip_port, nodes_list[i].public_key); 1207 onion_add_bs_path_node(onion_c, nodes_list[i].ip_port, nodes_list[i].public_key);
1209 } 1208 }
1210} 1209}
1211 1210
diff --git a/toxcore/ping.c b/toxcore/ping.c
index 1c3564a3..2decca0a 100644
--- a/toxcore/ping.c
+++ b/toxcore/ping.c
@@ -304,16 +304,18 @@ void do_to_ping(PING *ping)
304 if (!ip_isset(&ping->to_ping[0].ip_port.ip)) 304 if (!ip_isset(&ping->to_ping[0].ip_port.ip))
305 return; 305 return;
306 306
307 ping->last_to_ping = unix_time();
308 uint32_t i; 307 uint32_t i;
309 308
310 for (i = 0; i < MAX_TO_PING; ++i) { 309 for (i = 0; i < MAX_TO_PING; ++i) {
311 if (!ip_isset(&ping->to_ping[i].ip_port.ip)) 310 if (!ip_isset(&ping->to_ping[i].ip_port.ip))
312 return; 311 break;
313 312
314 send_ping_request(ping, ping->to_ping[i].ip_port, ping->to_ping[i].public_key); 313 send_ping_request(ping, ping->to_ping[i].ip_port, ping->to_ping[i].public_key);
315 ip_reset(&ping->to_ping[i].ip_port.ip); 314 ip_reset(&ping->to_ping[i].ip_port.ip);
316 } 315 }
316
317 if (i != 0)
318 ping->last_to_ping = unix_time();
317} 319}
318 320
319 321
diff --git a/toxcore/tox.c b/toxcore/tox.c
index 848f81c7..de615768 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -152,6 +152,7 @@ Tox *tox_new(const struct Tox_Options *options, const uint8_t *data, size_t leng
152 m_options.udp_disabled = !options->udp_enabled; 152 m_options.udp_disabled = !options->udp_enabled;
153 m_options.port_range[0] = options->start_port; 153 m_options.port_range[0] = options->start_port;
154 m_options.port_range[1] = options->end_port; 154 m_options.port_range[1] = options->end_port;
155 m_options.tcp_server_port = options->tcp_port;
155 156
156 switch (options->proxy_type) { 157 switch (options->proxy_type) {
157 case TOX_PROXY_TYPE_HTTP: 158 case TOX_PROXY_TYPE_HTTP:
@@ -238,31 +239,6 @@ void tox_get_savedata(const Tox *tox, uint8_t *data)
238 } 239 }
239} 240}
240 241
241static int address_to_ip(Messenger *m, const char *address, IP_Port *ip_port, IP_Port *ip_port_v4)
242{
243 if (!addr_parse_ip(address, &ip_port->ip)) {
244 if (m->options.udp_disabled) { /* Disable DNS when udp is disabled. */
245 return -1;
246 }
247
248 IP *ip_extra = NULL;
249 ip_init(&ip_port->ip, m->options.ipv6enabled);
250
251 if (m->options.ipv6enabled && ip_port_v4) {
252 /* setup for getting BOTH: an IPv6 AND an IPv4 address */
253 ip_port->ip.family = AF_UNSPEC;
254 ip_reset(&ip_port_v4->ip);
255 ip_extra = &ip_port_v4->ip;
256 }
257
258 if (!addr_resolve(address, &ip_port->ip, ip_extra)) {
259 return -1;
260 }
261 }
262
263 return 0;
264}
265
266bool tox_bootstrap(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error) 242bool tox_bootstrap(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error)
267{ 243{
268 if (!address || !public_key) { 244 if (!address || !public_key) {
@@ -270,23 +246,53 @@ bool tox_bootstrap(Tox *tox, const char *address, uint16_t port, const uint8_t *
270 return 0; 246 return 0;
271 } 247 }
272 248
273 Messenger *m = tox; 249 if (port == 0) {
274 bool ret = tox_add_tcp_relay(tox, address, port, public_key, error); 250 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_PORT);
251 return 0;
252 }
275 253
276 if (!ret) { 254 struct addrinfo *root, *info;
255
256 if (getaddrinfo(address, NULL, NULL, &root) != 0) {
257 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
277 return 0; 258 return 0;
278 } 259 }
279 260
280 if (m->options.udp_disabled) { 261 info = root;
281 return ret; 262
282 } else { /* DHT only works on UDP. */ 263 unsigned int count = 0;
283 if (DHT_bootstrap_from_address(m->dht, address, m->options.ipv6enabled, htons(port), public_key) == 0) { 264
284 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST); 265 do {
285 return 0; 266 IP_Port ip_port;
267 ip_port.port = htons(port);
268 ip_port.ip.family = info->ai_family;
269
270 if (info->ai_socktype && info->ai_socktype != SOCK_DGRAM) {
271 continue;
272 }
273
274 if (info->ai_family == AF_INET) {
275 ip_port.ip.ip4.in_addr = ((struct sockaddr_in *)info->ai_addr)->sin_addr;
276 } else if (info->ai_family == AF_INET6) {
277 ip_port.ip.ip6.in6_addr = ((struct sockaddr_in6 *)info->ai_addr)->sin6_addr;
278 } else {
279 continue;
286 } 280 }
287 281
282 Messenger *m = tox;
283 onion_add_bs_path_node(m->onion_c, ip_port, public_key);
284 DHT_bootstrap(m->dht, ip_port, public_key);
285 ++count;
286 } while ((info = info->ai_next));
287
288 freeaddrinfo(root);
289
290 if (count) {
288 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK); 291 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK);
289 return 1; 292 return 1;
293 } else {
294 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
295 return 0;
290 } 296 }
291} 297}
292 298
@@ -298,25 +304,53 @@ bool tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8
298 return 0; 304 return 0;
299 } 305 }
300 306
301 Messenger *m = tox;
302 IP_Port ip_port, ip_port_v4;
303
304 if (port == 0) { 307 if (port == 0) {
305 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_PORT); 308 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_PORT);
306 return 0; 309 return 0;
307 } 310 }
308 311
309 if (address_to_ip(m, address, &ip_port, &ip_port_v4) == -1) { 312 struct addrinfo *root, *info;
313
314 if (getaddrinfo(address, NULL, NULL, &root) != 0) {
310 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST); 315 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
311 return 0; 316 return 0;
312 } 317 }
313 318
314 ip_port.port = htons(port); 319 info = root;
315 add_tcp_relay(m->net_crypto, ip_port, public_key);
316 onion_add_bs_path_node(m->onion_c, ip_port, public_key); //TODO: move this
317 320
318 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK); 321 unsigned int count = 0;
319 return 1; 322
323 do {
324 IP_Port ip_port;
325 ip_port.port = htons(port);
326 ip_port.ip.family = info->ai_family;
327
328 if (info->ai_socktype && info->ai_socktype != SOCK_STREAM) {
329 continue;
330 }
331
332 if (info->ai_family == AF_INET) {
333 ip_port.ip.ip4.in_addr = ((struct sockaddr_in *)info->ai_addr)->sin_addr;
334 } else if (info->ai_family == AF_INET6) {
335 ip_port.ip.ip6.in6_addr = ((struct sockaddr_in6 *)info->ai_addr)->sin6_addr;
336 } else {
337 continue;
338 }
339
340 Messenger *m = tox;
341 add_tcp_relay(m->net_crypto, ip_port, public_key);
342 ++count;
343 } while ((info = info->ai_next));
344
345 freeaddrinfo(root);
346
347 if (count) {
348 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK);
349 return 1;
350 } else {
351 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
352 return 0;
353 }
320} 354}
321 355
322TOX_CONNECTION tox_self_get_connection_status(const Tox *tox) 356TOX_CONNECTION tox_self_get_connection_status(const Tox *tox)
@@ -1205,9 +1239,15 @@ uint16_t tox_self_get_udp_port(const Tox *tox, TOX_ERR_GET_PORT *error)
1205 1239
1206uint16_t tox_self_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error) 1240uint16_t tox_self_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error)
1207{ 1241{
1208 /* TCP server not yet implemented in clients. */ 1242 const Messenger *m = tox;
1209 SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND); 1243
1210 return 0; 1244 if (m->tcp_server) {
1245 SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK);
1246 return m->options.tcp_server_port;
1247 } else {
1248 SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND);
1249 return 0;
1250 }
1211} 1251}
1212 1252
1213#include "tox_old_code.h" 1253#include "tox_old_code.h"
diff --git a/toxcore/tox.h b/toxcore/tox.h
index abd2f051..4afdf7c3 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -426,6 +426,12 @@ struct Tox_Options {
426 */ 426 */
427 uint16_t end_port; 427 uint16_t end_port;
428 428
429
430 /**
431 * The port to use for the TCP server. If 0, the tcp server is disabled.
432 */
433 uint16_t tcp_port;
434
429}; 435};
430 436
431 437
diff --git a/toxdns/toxdns.c b/toxdns/toxdns.c
index 186ea82b..f7df5df3 100644
--- a/toxdns/toxdns.c
+++ b/toxdns/toxdns.c
@@ -160,25 +160,14 @@ static int decode(uint8_t *dest, uint8_t *src)
160 while (*p) { 160 while (*p) {
161 uint8_t ch = *p++; 161 uint8_t ch = *p++;
162 162
163 switch (ch) { 163 if ('A' <= ch && ch <= 'Z') {
164 case 'A' ... 'Z': { 164 ch = ch - 'A';
165 ch = ch - 'A'; 165 } else if ('a' <= ch && ch <= 'z') {
166 break; 166 ch = ch - 'a';
167 } 167 } else if ('0' <= ch && ch <= '5') {
168 168 ch = ch - '0' + 26;
169 case 'a' ... 'z': { 169 } else {
170 ch = ch - 'a'; 170 return - 1;
171 break;
172 }
173
174 case '0' ... '5': {
175 ch = ch - '0' + 26;
176 break;
177 }
178
179 default: {
180 return - 1;
181 }
182 } 171 }
183 172
184 *op |= (ch << bits); 173 *op |= (ch << bits);