diff options
author | mannol <eniz_vukovic@hotmail.com> | 2015-05-22 23:22:31 +0200 |
---|---|---|
committer | mannol <eniz_vukovic@hotmail.com> | 2015-05-22 23:22:31 +0200 |
commit | 3100042a2b78f4f80d23f67e6113797cd8fb5df0 (patch) | |
tree | c226f4b25002784d93f9bb6415be4b55b76cddd1 | |
parent | 62c40af1a0c557ba8c77583c972ae3af9af15cf1 (diff) | |
parent | 2ba076ac5cc6efb5eb41fb4aa6a77a151885f26c (diff) |
Updated with master
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 | } |
810 | END_TEST | 814 | END_TEST |
811 | 815 | ||
816 | #define TCP_RELAY_PORT 33448 | ||
817 | |||
818 | START_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) { | ||
861 | loop_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 | } | ||
908 | END_TEST | ||
909 | |||
910 | #define NUM_TCP_RELAYS 3 | ||
911 | |||
912 | START_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) { | ||
956 | loop_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 | } | ||
1003 | END_TEST | ||
1004 | |||
1005 | |||
812 | #define NUM_GROUP_TOX 32 | 1006 | #define NUM_GROUP_TOX 32 |
813 | 1007 | ||
814 | void g_accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata) | 1008 | void 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 | } |
67 | void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number, | 67 | void 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 | } |
64 | void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number, | 64 | void 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 | |||
4 | You can also use the following command if you can't install it: | 4 | You can also use the following command if you can't install it: |
5 | 5 | ||
6 | ``` | 6 | ``` |
7 | cat tox.in.h | curl -X POST --data-binary @- https://criticism.herokuapp.com/apidsl > tox.h | 7 | curl -X POST --data-binary @- https://criticism.herokuapp.com/apidsl < tox.in.h > tox.h |
8 | ``` | 8 | ``` |
9 | 9 | ||
10 | Note that the output must be passed through astyle with the config in | 10 | Note 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 | } |
135 | void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number, | 135 | void 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, ©_groupmessage, 0); | 233 | tox_callback_group_message(tox, ©_groupmessage, 0); |
228 | tox_callback_group_action(tox, ©_groupmessage, 0); | 234 | tox_callback_group_action(tox, ©_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 | ||
41 | ACSession* ac_new(ToxAV* av, uint32_t friend_number, toxav_receive_audio_frame_cb *cb, void *cb_data) | 41 | ACSession* 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 | */ |
70 | ACSession* ac_new(ToxAV* av, uint32_t friend_number, toxav_receive_audio_frame_cb *cb, void *cb_data); | 70 | ACSession* 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 | */ |
52 | typedef enum { | 52 | typedef 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); | |||
122 | void ba_set(ToxAvBitrateAdapter* ba, uint32_t bit_rate); | 122 | void ba_set(ToxAvBitrateAdapter* ba, uint32_t bit_rate); |
123 | bool ba_shoud_send_dummy(ToxAvBitrateAdapter* ba); | 123 | bool ba_shoud_send_dummy(ToxAvBitrateAdapter* ba); |
124 | 124 | ||
125 | uint32_t toxav_version_major(void) | ||
126 | { | ||
127 | return 0; | ||
128 | } | ||
129 | uint32_t toxav_version_minor(void) | ||
130 | { | ||
131 | return 0; | ||
132 | } | ||
133 | uint32_t toxav_version_patch(void) | ||
134 | { | ||
135 | return 0; | ||
136 | } | ||
137 | bool 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 | |||
125 | ToxAV* toxav_new(Tox* tox, TOXAV_ERR_NEW* error) | 146 | ToxAV* 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 | ||
207 | Tox* toxav_get_tox(ToxAV* av) | 228 | Tox* 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 | ||
575 | void toxav_callback_video_bit_rate_status(ToxAV* av, toxav_video_bit_rate_status_cb* function, void* user_data) | 589 | void 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 | ||
583 | bool toxav_set_video_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t video_bit_rate, bool force, TOXAV_ERR_BIT_RATE* error) | 597 | bool 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 | ||
634 | void toxav_callback_audio_bit_rate_status(ToxAV* av, toxav_audio_bit_rate_status_cb* function, void* user_data) | 649 | void 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 | ||
642 | bool toxav_set_audio_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_BIT_RATE* error) | 657 | bool 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 | ||
694 | bool 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) | 708 | bool 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 | |||
803 | END: | ||
804 | if (error) | ||
805 | *error = rc; | ||
806 | |||
807 | return rc == TOXAV_ERR_SEND_FRAME_OK; | ||
808 | } | ||
809 | |||
810 | bool 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 | ||
859 | bool 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) | 979 | void 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 | |||
954 | END: | ||
955 | if (error) | ||
956 | *error = rc; | ||
957 | |||
958 | return rc == TOXAV_ERR_SEND_FRAME_OK; | ||
959 | } | 985 | } |
960 | 986 | ||
961 | void toxav_callback_receive_video_frame(ToxAV* av, toxav_receive_video_frame_cb* function, void* user_data) | 987 | void 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 | ||
969 | void 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 |
30 | extern "C" { | 30 | extern "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 | */ |
40 | typedef struct ToxAV ToxAV; | ||
41 | #ifndef TOX_DEFINED | 65 | #ifndef TOX_DEFINED |
42 | #define TOX_DEFINED | 66 | #define TOX_DEFINED |
67 | typedef 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 | */ |
47 | typedef 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 | ||
83 | typedef 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 | */ | ||
143 | uint32_t toxav_version_major(void); | ||
144 | |||
145 | /** | ||
146 | * Return the minor version number of the library. | ||
147 | */ | ||
148 | uint32_t toxav_version_minor(void); | ||
149 | |||
150 | /** | ||
151 | * Return the patch number of the library. | ||
152 | */ | ||
153 | uint32_t toxav_version_patch(void); | ||
154 | |||
155 | /** | ||
156 | * Return whether the compiled library version is compatible with the passed | ||
157 | * version numbers. | ||
158 | */ | ||
159 | bool 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 | |||
54 | typedef enum TOXAV_ERR_NEW { | 170 | typedef 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 | */ |
70 | ToxAV *toxav_new(Tox *tox, TOXAV_ERR_NEW *error); | 199 | ToxAV *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 | */ |
78 | void toxav_kill(ToxAV *av); | 208 | void 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 | */ |
82 | Tox *toxav_get_tox(ToxAV *av); | 213 | Tox *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 | */ |
92 | uint32_t toxav_iteration_interval(ToxAV const *av); | 228 | uint32_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 | */ |
98 | void toxav_iterate(ToxAV *av); | 235 | void toxav_iterate(ToxAV *toxAV); |
236 | |||
237 | |||
99 | /******************************************************************************* | 238 | /******************************************************************************* |
100 | * | 239 | * |
101 | * :: Call setup | 240 | * :: Call setup |
102 | * | 241 | * |
103 | ******************************************************************************/ | 242 | ******************************************************************************/ |
243 | |||
244 | |||
245 | |||
104 | typedef enum TOXAV_ERR_CALL { | 246 | typedef 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 | */ |
142 | bool toxav_call(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL *error); | 296 | bool 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 | */ |
146 | typedef void toxav_call_cb(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data); | 305 | typedef 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 | */ |
152 | void toxav_callback_call(ToxAV *av, toxav_call_cb *function, void *user_data); | 312 | void toxav_callback_call(ToxAV *toxAV, toxav_call_cb *callback, void *user_data); |
313 | |||
153 | typedef enum TOXAV_ERR_ANSWER { | 314 | typedef 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 | */ |
187 | bool toxav_answer(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER *error); | 359 | bool 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 | |||
193 | enum TOXAV_CALL_STATE { | 370 | enum 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 | */ |
228 | typedef void toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_data); | 417 | typedef 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 | */ |
234 | void toxav_callback_call_state(ToxAV *av, toxav_call_state_cb *function, void *user_data); | 424 | void 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 | |||
240 | typedef enum TOXAV_CALL_CONTROL { | 435 | typedef 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 | |||
272 | typedef enum TOXAV_ERR_CALL_CONTROL { | 481 | typedef 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 | */ |
303 | bool toxav_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL *error); | 517 | bool 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 | ******************************************************************************/ |
309 | typedef 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. | 528 | typedef 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 | */ |
337 | typedef void toxav_audio_bit_rate_status_cb(ToxAV *av, uint32_t friend_number, bool stable, uint32_t bit_rate, void *user_data); | 566 | typedef 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 | */ |
341 | void toxav_callback_audio_bit_rate_status(ToxAV *av, toxav_audio_bit_rate_status_cb *function, void *user_data); | 573 | void 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 | */ |
357 | bool toxav_set_audio_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_BIT_RATE *error); | 590 | bool 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 | */ |
371 | typedef void toxav_video_bit_rate_status_cb(ToxAV *av, uint32_t friend_number, bool stable, uint32_t bit_rate, void *user_data); | 605 | typedef 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 | */ |
375 | void toxav_callback_video_bit_rate_status(ToxAV *av, toxav_video_bit_rate_status_cb *function, void *user_data); | 612 | void 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 | */ |
391 | bool toxav_set_video_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t video_bit_rate, bool force, TOXAV_ERR_BIT_RATE *error); | 629 | bool 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 | |
400 | typedef enum TOXAV_ERR_SEND_FRAME { | 640 | typedef 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 | */ | ||
440 | bool 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 | */ |
464 | bool toxav_send_audio_frame(ToxAV *av, uint32_t friend_number, | 697 | bool 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 | */ | ||
715 | bool 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 | */ | ||
736 | typedef 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 | */ | ||
743 | void 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 |
490 | typedef 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 | */ |
498 | void toxav_callback_receive_video_frame(ToxAV *av, toxav_receive_video_frame_cb *function, void *user_data); | 768 | typedef 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 | */ | ||
510 | typedef 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 | */ |
519 | void toxav_callback_receive_audio_frame(ToxAV *av, toxav_receive_audio_frame_cb *function, void *user_data); | 775 | void 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; | |||
42 | bool create_video_encoder (vpx_codec_ctx_t* dest, int32_t bit_rate); | 42 | bool create_video_encoder (vpx_codec_ctx_t* dest, int32_t bit_rate); |
43 | 43 | ||
44 | 44 | ||
45 | VCSession* vc_new(ToxAV* av, uint32_t friend_number, toxav_receive_video_frame_cb* cb, void* cb_data, uint32_t mvfpsz) | 45 | VCSession* 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 | */ |
82 | VCSession* vc_new(ToxAV* av, uint32_t friend_number, toxav_receive_video_frame_cb *cb, void *cb_data, uint32_t mvfpsz); | 82 | VCSession* 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 | */ |
146 | void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *client_id) | 146 | void 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 | */ |
154 | void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *client_id) | 154 | void 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 | ||
159 | void to_net_family(IP *ip) | 159 | void 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 | */ |
233 | int LAN_ip(IP ip) | 259 | int 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. */ |
41 | void LANdiscovery_kill(DHT *dht); | 41 | void 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 | ||
55 | static 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 | |||
65 | static 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. */ | ||
2742 | uint32_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 | |||
730 | enum { | 729 | enum { |
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. */ |
773 | uint32_t count_friendlist(const Messenger *m); | 773 | uint32_t count_friendlist(const Messenger *m); |
774 | 774 | ||
775 | /* Return the number of online friends in the instance m. */ | ||
776 | uint32_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; | |||
85 | struct TCP_Priority_List { | 85 | struct 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 | ||
91 | typedef struct TCP_Secure_Connection { | 91 | typedef 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 | ||
273 | static void change_dht_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_public_key) | 287 | static 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 | */ |
48 | static int find(const BS_LIST *list, const void *data) | 48 | static 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 | ||
165 | int bs_list_find(const BS_LIST *list, const void *data) | 165 | int 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 | ||
177 | int bs_list_add(BS_LIST *list, const void *data, int id) | 177 | int 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 | ||
217 | int bs_list_remove(BS_LIST *list, const void *data, int id) | 217 | int 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 | */ |
59 | int bs_list_find(const BS_LIST *list, const void *data); | 59 | int 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 | */ |
67 | int bs_list_add(BS_LIST *list, const void *data, int id); | 67 | int 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 | */ |
75 | int bs_list_remove(BS_LIST *list, const void *data, int id); | 75 | int 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 | */ |
939 | static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint16_t max_num) | 945 | static 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 | */ |
1638 | int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port) | 1649 | int 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 | */ |
1932 | static int crypto_id_ip_port(const Net_Crypto *c, IP_Port ip_port) | 1949 | static 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 | |||
1987 | static void send_crypto_packets(Net_Crypto *c) | 2011 | static 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 | */ |
2330 | void save_keys(const Net_Crypto *c, uint8_t *keys) | 2365 | void 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 | */ |
2339 | void load_keys(Net_Crypto *c, const uint8_t *keys) | 2374 | void 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 | |||
85 | typedef struct { | 88 | typedef 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 | */ |
230 | int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port); | 236 | int 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 | */ |
379 | void save_keys(const Net_Crypto *c, uint8_t *keys); | 385 | void 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 | */ |
384 | void load_keys(Net_Crypto *c, const uint8_t *keys); | 390 | void 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 | */ |
149 | int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_Path *path) | 149 | int 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 | |||
56 | typedef struct { | 58 | typedef 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 | ||
241 | static 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 | |||
266 | bool tox_bootstrap(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error) | 242 | bool 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 | ||
322 | TOX_CONNECTION tox_self_get_connection_status(const Tox *tox) | 356 | TOX_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 | ||
1206 | uint16_t tox_self_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error) | 1240 | uint16_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); |