mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Updated with master
This commit is contained in:
commit
3100042a2b
|
@ -332,6 +332,7 @@ START_TEST(test_one)
|
|||
tox_self_set_name(tox1, name, sizeof(name), 0);
|
||||
ck_assert_msg(tox_self_get_name_size(tox1) == sizeof(name), "Can't set name of TOX_MAX_NAME_LENGTH");
|
||||
|
||||
tox_self_get_address(tox1, address);
|
||||
size_t save_size = tox_get_savedata_size(tox1);
|
||||
uint8_t data[save_size];
|
||||
tox_get_savedata(tox1, data);
|
||||
|
@ -344,6 +345,9 @@ START_TEST(test_one)
|
|||
|
||||
ck_assert_msg(tox_self_get_name_size(tox2) == sizeof name, "Wrong name size.");
|
||||
|
||||
uint8_t address2[TOX_ADDRESS_SIZE];
|
||||
tox_self_get_address(tox2, address2);
|
||||
ck_assert_msg(memcmp(address2, address, TOX_ADDRESS_SIZE) == 0, "Wrong address.");
|
||||
uint8_t new_name[TOX_MAX_NAME_LENGTH] = { 0 };
|
||||
tox_self_get_name(tox2, new_name);
|
||||
ck_assert_msg(memcmp(name, new_name, TOX_MAX_NAME_LENGTH) == 0, "Wrong name");
|
||||
|
@ -809,6 +813,196 @@ loop_top:
|
|||
}
|
||||
END_TEST
|
||||
|
||||
#define TCP_RELAY_PORT 33448
|
||||
|
||||
START_TEST(test_many_clients_tcp)
|
||||
{
|
||||
long long unsigned int cur_time = time(NULL);
|
||||
Tox *toxes[NUM_TOXES];
|
||||
uint32_t i, j;
|
||||
uint32_t to_comp = 974536;
|
||||
|
||||
for (i = 0; i < NUM_TOXES; ++i) {
|
||||
struct Tox_Options opts;
|
||||
tox_options_default(&opts);
|
||||
|
||||
if (i == 0) {
|
||||
opts.tcp_port = TCP_RELAY_PORT;
|
||||
} else {
|
||||
opts.udp_enabled = 0;
|
||||
}
|
||||
|
||||
toxes[i] = tox_new(&opts, 0, 0, 0);
|
||||
ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i);
|
||||
tox_callback_friend_request(toxes[i], accept_friend_request, &to_comp);
|
||||
uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
|
||||
tox_self_get_dht_id(toxes[0], dpk);
|
||||
ck_assert_msg(tox_add_tcp_relay(toxes[i], "::1", TCP_RELAY_PORT, dpk, 0), "add relay error");
|
||||
ck_assert_msg(tox_bootstrap(toxes[i], "::1", 33445, dpk, 0), "Bootstrap error");
|
||||
}
|
||||
|
||||
{
|
||||
TOX_ERR_GET_PORT error;
|
||||
ck_assert_msg(tox_self_get_udp_port(toxes[0], &error) == 33445, "First Tox instance did not bind to udp port 33445.\n");
|
||||
ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
|
||||
ck_assert_msg(tox_self_get_tcp_port(toxes[0], &error) == TCP_RELAY_PORT,
|
||||
"First Tox instance did not bind to tcp port %u.\n", TCP_RELAY_PORT);
|
||||
ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
|
||||
}
|
||||
|
||||
struct {
|
||||
uint16_t tox1;
|
||||
uint16_t tox2;
|
||||
} pairs[NUM_FRIENDS];
|
||||
|
||||
uint8_t address[TOX_ADDRESS_SIZE];
|
||||
|
||||
for (i = 0; i < NUM_FRIENDS; ++i) {
|
||||
loop_top:
|
||||
pairs[i].tox1 = rand() % NUM_TOXES;
|
||||
pairs[i].tox2 = (pairs[i].tox1 + rand() % (NUM_TOXES - 1) + 1) % NUM_TOXES;
|
||||
|
||||
for (j = 0; j < i; ++j) {
|
||||
if (pairs[j].tox2 == pairs[i].tox1 && pairs[j].tox1 == pairs[i].tox2)
|
||||
goto loop_top;
|
||||
}
|
||||
|
||||
tox_self_get_address(toxes[pairs[i].tox1], address);
|
||||
|
||||
TOX_ERR_FRIEND_ADD test;
|
||||
uint32_t num = tox_friend_add(toxes[pairs[i].tox2], address, (uint8_t *)"Gentoo", 7, &test);
|
||||
|
||||
if (test == TOX_ERR_FRIEND_ADD_ALREADY_SENT) {
|
||||
goto loop_top;
|
||||
}
|
||||
|
||||
ck_assert_msg(num != UINT32_MAX && test == TOX_ERR_FRIEND_ADD_OK, "Failed to add friend error code: %i", test);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
uint16_t counter = 0;
|
||||
|
||||
for (i = 0; i < NUM_TOXES; ++i) {
|
||||
for (j = 0; j < tox_self_get_friend_list_size(toxes[i]); ++j)
|
||||
if (tox_friend_get_connection_status(toxes[i], j, 0) == TOX_CONNECTION_TCP)
|
||||
++counter;
|
||||
}
|
||||
|
||||
if (counter == NUM_FRIENDS * 2) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_TOXES; ++i) {
|
||||
tox_iterate(toxes[i]);
|
||||
}
|
||||
|
||||
c_sleep(50);
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_TOXES; ++i) {
|
||||
tox_kill(toxes[i]);
|
||||
}
|
||||
|
||||
printf("test_many_clients_tcp succeeded, took %llu seconds\n", time(NULL) - cur_time);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
#define NUM_TCP_RELAYS 3
|
||||
|
||||
START_TEST(test_many_clients_tcp_b)
|
||||
{
|
||||
long long unsigned int cur_time = time(NULL);
|
||||
Tox *toxes[NUM_TOXES];
|
||||
uint32_t i, j;
|
||||
uint32_t to_comp = 974536;
|
||||
|
||||
for (i = 0; i < NUM_TOXES; ++i) {
|
||||
struct Tox_Options opts;
|
||||
tox_options_default(&opts);
|
||||
|
||||
if (i < NUM_TCP_RELAYS) {
|
||||
opts.tcp_port = TCP_RELAY_PORT + i;
|
||||
} else {
|
||||
opts.udp_enabled = 0;
|
||||
}
|
||||
|
||||
toxes[i] = tox_new(&opts, 0, 0, 0);
|
||||
ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i);
|
||||
tox_callback_friend_request(toxes[i], accept_friend_request, &to_comp);
|
||||
uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
|
||||
tox_self_get_dht_id(toxes[(i % NUM_TCP_RELAYS)], dpk);
|
||||
ck_assert_msg(tox_add_tcp_relay(toxes[i], "::1", TCP_RELAY_PORT + (i % NUM_TCP_RELAYS), dpk, 0), "add relay error");
|
||||
tox_self_get_dht_id(toxes[0], dpk);
|
||||
ck_assert_msg(tox_bootstrap(toxes[i], "::1", 33445, dpk, 0), "Bootstrap error");
|
||||
}
|
||||
|
||||
{
|
||||
TOX_ERR_GET_PORT error;
|
||||
ck_assert_msg(tox_self_get_udp_port(toxes[0], &error) == 33445, "First Tox instance did not bind to udp port 33445.\n");
|
||||
ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
|
||||
ck_assert_msg(tox_self_get_tcp_port(toxes[0], &error) == TCP_RELAY_PORT,
|
||||
"First Tox instance did not bind to tcp port %u.\n", TCP_RELAY_PORT);
|
||||
ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
|
||||
}
|
||||
|
||||
struct {
|
||||
uint16_t tox1;
|
||||
uint16_t tox2;
|
||||
} pairs[NUM_FRIENDS];
|
||||
|
||||
uint8_t address[TOX_ADDRESS_SIZE];
|
||||
|
||||
for (i = 0; i < NUM_FRIENDS; ++i) {
|
||||
loop_top:
|
||||
pairs[i].tox1 = rand() % NUM_TOXES;
|
||||
pairs[i].tox2 = (pairs[i].tox1 + rand() % (NUM_TOXES - 1) + 1) % NUM_TOXES;
|
||||
|
||||
for (j = 0; j < i; ++j) {
|
||||
if (pairs[j].tox2 == pairs[i].tox1 && pairs[j].tox1 == pairs[i].tox2)
|
||||
goto loop_top;
|
||||
}
|
||||
|
||||
tox_self_get_address(toxes[pairs[i].tox1], address);
|
||||
|
||||
TOX_ERR_FRIEND_ADD test;
|
||||
uint32_t num = tox_friend_add(toxes[pairs[i].tox2], address, (uint8_t *)"Gentoo", 7, &test);
|
||||
|
||||
if (test == TOX_ERR_FRIEND_ADD_ALREADY_SENT) {
|
||||
goto loop_top;
|
||||
}
|
||||
|
||||
ck_assert_msg(num != UINT32_MAX && test == TOX_ERR_FRIEND_ADD_OK, "Failed to add friend error code: %i", test);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
uint16_t counter = 0;
|
||||
|
||||
for (i = 0; i < NUM_TOXES; ++i) {
|
||||
for (j = 0; j < tox_self_get_friend_list_size(toxes[i]); ++j)
|
||||
if (tox_friend_get_connection_status(toxes[i], j, 0) == TOX_CONNECTION_TCP)
|
||||
++counter;
|
||||
}
|
||||
|
||||
if (counter == NUM_FRIENDS * 2) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_TOXES; ++i) {
|
||||
tox_iterate(toxes[i]);
|
||||
}
|
||||
|
||||
c_sleep(50);
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_TOXES; ++i) {
|
||||
tox_kill(toxes[i]);
|
||||
}
|
||||
|
||||
printf("test_many_clients_tcp_b succeeded, took %llu seconds\n", time(NULL) - cur_time);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
#define NUM_GROUP_TOX 32
|
||||
|
||||
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)
|
|||
DEFTESTCASE(one);
|
||||
DEFTESTCASE_SLOW(few_clients, 50);
|
||||
DEFTESTCASE_SLOW(many_clients, 150);
|
||||
DEFTESTCASE_SLOW(many_clients_tcp, 20);
|
||||
DEFTESTCASE_SLOW(many_clients_tcp_b, 20);
|
||||
DEFTESTCASE_SLOW(many_group, 100);
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -66,8 +66,8 @@ void t_toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, vo
|
|||
}
|
||||
void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number,
|
||||
uint16_t width, uint16_t height,
|
||||
uint8_t const *y, uint8_t const *u, uint8_t const *v,
|
||||
int32_t ystride, int32_t ustride, int32_t vstride,
|
||||
uint8_t const *y, uint8_t const *u, uint8_t const *v, uint8_t const *a,
|
||||
int32_t ystride, int32_t ustride, int32_t vstride, int32_t astride,
|
||||
void *user_data)
|
||||
{
|
||||
(void) av;
|
||||
|
@ -185,13 +185,13 @@ START_TEST(test_AV_flows)
|
|||
|
||||
toxav_callback_call(AliceAV, t_toxav_call_cb, &AliceCC);
|
||||
toxav_callback_call_state(AliceAV, t_toxav_call_state_cb, &AliceCC);
|
||||
toxav_callback_receive_video_frame(AliceAV, t_toxav_receive_video_frame_cb, &AliceCC);
|
||||
toxav_callback_receive_audio_frame(AliceAV, t_toxav_receive_audio_frame_cb, &AliceCC);
|
||||
toxav_callback_video_receive_frame(AliceAV, t_toxav_receive_video_frame_cb, &AliceCC);
|
||||
toxav_callback_audio_receive_frame(AliceAV, t_toxav_receive_audio_frame_cb, &AliceCC);
|
||||
|
||||
toxav_callback_call(BobAV, t_toxav_call_cb, &BobCC);
|
||||
toxav_callback_call_state(BobAV, t_toxav_call_state_cb, &BobCC);
|
||||
toxav_callback_receive_video_frame(BobAV, t_toxav_receive_video_frame_cb, &BobCC);
|
||||
toxav_callback_receive_audio_frame(BobAV, t_toxav_receive_audio_frame_cb, &BobCC);
|
||||
toxav_callback_video_receive_frame(BobAV, t_toxav_receive_video_frame_cb, &BobCC);
|
||||
toxav_callback_audio_receive_frame(BobAV, t_toxav_receive_audio_frame_cb, &BobCC);
|
||||
|
||||
printf("Created 2 instances of ToxAV\n");
|
||||
printf("All set after %llu seconds!\n", time(NULL) - cur_time);
|
||||
|
@ -214,7 +214,7 @@ START_TEST(test_AV_flows)
|
|||
long long unsigned int start_time = time(NULL); \
|
||||
\
|
||||
\
|
||||
while (BobCC.state != TOXAV_CALL_STATE_END) { \
|
||||
while (BobCC.state != TOXAV_CALL_STATE_FINISHED) { \
|
||||
\
|
||||
if (BobCC.incoming) { \
|
||||
TOXAV_ERR_ANSWER rc; \
|
||||
|
@ -228,7 +228,7 @@ START_TEST(test_AV_flows)
|
|||
} else { \
|
||||
/* TODO rtp */ \
|
||||
\
|
||||
if (time(NULL) - start_time == 5) { \
|
||||
if (time(NULL) - start_time >= 1) { \
|
||||
\
|
||||
TOXAV_ERR_CALL_CONTROL rc; \
|
||||
toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc); \
|
||||
|
@ -358,8 +358,10 @@ START_TEST(test_AV_flows)
|
|||
/* At first try all stuff while in invalid state */
|
||||
ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_PAUSE, NULL));
|
||||
ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_RESUME, NULL));
|
||||
ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL));
|
||||
ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_HIDE_VIDEO, NULL));
|
||||
ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_MUTE_AUDIO, NULL));
|
||||
ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_UNMUTE_AUDIO, NULL));
|
||||
ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_HIDE_VIDEO, NULL));
|
||||
ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_SHOW_VIDEO, NULL));
|
||||
|
||||
{
|
||||
TOXAV_ERR_ANSWER rc;
|
||||
|
@ -377,32 +379,32 @@ START_TEST(test_AV_flows)
|
|||
printf("Pause and Resume\n");
|
||||
ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_PAUSE, NULL));
|
||||
iterate_tox(bootstrap, Alice, Bob);
|
||||
ck_assert(BobCC.state == TOXAV_CALL_STATE_PAUSED);
|
||||
ck_assert(BobCC.state == 0);
|
||||
ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_RESUME, NULL));
|
||||
iterate_tox(bootstrap, Alice, Bob);
|
||||
ck_assert(BobCC.state & (TOXAV_CALL_STATE_SENDING_A | TOXAV_CALL_STATE_SENDING_V));
|
||||
|
||||
/* Mute/Unmute single */
|
||||
printf("Mute/Unmute single\n");
|
||||
ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL));
|
||||
ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_MUTE_AUDIO, NULL));
|
||||
iterate_tox(bootstrap, Alice, Bob);
|
||||
ck_assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_A);
|
||||
ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL));
|
||||
ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_UNMUTE_AUDIO, NULL));
|
||||
iterate_tox(bootstrap, Alice, Bob);
|
||||
ck_assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_A);
|
||||
|
||||
/* Mute/Unmute both */
|
||||
printf("Mute/Unmute both\n");
|
||||
ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL));
|
||||
ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_MUTE_AUDIO, NULL));
|
||||
iterate_tox(bootstrap, Alice, Bob);
|
||||
ck_assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_A);
|
||||
ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_HIDE_VIDEO, NULL));
|
||||
ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_HIDE_VIDEO, NULL));
|
||||
iterate_tox(bootstrap, Alice, Bob);
|
||||
ck_assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_V);
|
||||
ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL));
|
||||
ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_UNMUTE_AUDIO, NULL));
|
||||
iterate_tox(bootstrap, Alice, Bob);
|
||||
ck_assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_A);
|
||||
ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_HIDE_VIDEO, NULL));
|
||||
ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_SHOW_VIDEO, NULL));
|
||||
iterate_tox(bootstrap, Alice, Bob);
|
||||
ck_assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_V);
|
||||
|
||||
|
@ -417,7 +419,7 @@ START_TEST(test_AV_flows)
|
|||
}
|
||||
|
||||
iterate_tox(bootstrap, Alice, Bob);
|
||||
ck_assert(BobCC.state == TOXAV_CALL_STATE_END);
|
||||
ck_assert(BobCC.state == TOXAV_CALL_STATE_FINISHED);
|
||||
|
||||
printf("Success!\n");
|
||||
}
|
||||
|
|
|
@ -63,8 +63,8 @@ void t_toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, vo
|
|||
}
|
||||
void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number,
|
||||
uint16_t width, uint16_t height,
|
||||
uint8_t const *y, uint8_t const *u, uint8_t const *v,
|
||||
int32_t ystride, int32_t ustride, int32_t vstride,
|
||||
uint8_t const *y, uint8_t const *u, uint8_t const *v, uint8_t const *a,
|
||||
int32_t ystride, int32_t ustride, int32_t vstride, int32_t stride,
|
||||
void *user_data)
|
||||
{
|
||||
(void) av;
|
||||
|
@ -115,8 +115,8 @@ ToxAV* setup_av_instance(Tox* tox, CallControl *CC)
|
|||
|
||||
toxav_callback_call(av, t_toxav_call_cb, CC);
|
||||
toxav_callback_call_state(av, t_toxav_call_state_cb, CC);
|
||||
toxav_callback_receive_video_frame(av, t_toxav_receive_video_frame_cb, CC);
|
||||
toxav_callback_receive_audio_frame(av, t_toxav_receive_audio_frame_cb, CC);
|
||||
toxav_callback_video_receive_frame(av, t_toxav_receive_video_frame_cb, CC);
|
||||
toxav_callback_audio_receive_frame(av, t_toxav_receive_audio_frame_cb, CC);
|
||||
|
||||
return av;
|
||||
}
|
||||
|
@ -161,22 +161,24 @@ void* call_thread(void* pd)
|
|||
uint8_t video_y[800*600];
|
||||
uint8_t video_u[800*600 / 2];
|
||||
uint8_t video_v[800*600 / 2];
|
||||
uint8_t video_a[800*600];
|
||||
|
||||
memset(PCM, 0, sizeof(PCM));
|
||||
memset(video_y, 0, sizeof(video_y));
|
||||
memset(video_u, 0, sizeof(video_u));
|
||||
memset(video_v, 0, sizeof(video_v));
|
||||
memset(video_a, 0, sizeof(video_a));
|
||||
|
||||
time_t start_time = time(NULL);
|
||||
while(time(NULL) - start_time < 4) {
|
||||
toxav_iterate(AliceAV);
|
||||
toxav_iterate(BobAV);
|
||||
|
||||
toxav_send_audio_frame(AliceAV, friend_number, PCM, 960, 1, 48000, NULL);
|
||||
toxav_send_audio_frame(BobAV, 0, PCM, 960, 1, 48000, NULL);
|
||||
toxav_audio_send_frame(AliceAV, friend_number, PCM, 960, 1, 48000, NULL);
|
||||
toxav_audio_send_frame(BobAV, 0, PCM, 960, 1, 48000, NULL);
|
||||
|
||||
toxav_send_video_frame(AliceAV, friend_number, 800, 600, video_y, video_u, video_v, NULL);
|
||||
toxav_send_video_frame(BobAV, 0, 800, 600, video_y, video_u, video_v, NULL);
|
||||
toxav_video_send_frame(AliceAV, friend_number, 800, 600, video_y, video_u, video_v, video_a, NULL);
|
||||
toxav_video_send_frame(BobAV, 0, 800, 600, video_y, video_u, video_v, video_a, NULL);
|
||||
|
||||
c_sleep(10);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ with: https://github.com/iphydf/apidsl
|
|||
You can also use the following command if you can't install it:
|
||||
|
||||
```
|
||||
cat tox.in.h | curl -X POST --data-binary @- https://criticism.herokuapp.com/apidsl > tox.h
|
||||
curl -X POST --data-binary @- https://criticism.herokuapp.com/apidsl < tox.in.h > tox.h
|
||||
```
|
||||
|
||||
Note that the output must be passed through astyle with the config in
|
||||
|
|
|
@ -411,6 +411,11 @@ static class options {
|
|||
* The end port of the inclusive port range to attempt to use.
|
||||
*/
|
||||
uint16_t end_port;
|
||||
|
||||
/**
|
||||
* The port to use for the TCP server. If 0, the tcp server is disabled.
|
||||
*/
|
||||
uint16_t tcp_port;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -622,4 +622,4 @@ namespace video {
|
|||
}
|
||||
%{
|
||||
#endif
|
||||
%}
|
||||
%}
|
||||
|
|
|
@ -105,6 +105,9 @@ int manage_keys(DHT *dht, char *keys_file_path)
|
|||
|
||||
keys_file = fopen(keys_file_path, "w");
|
||||
|
||||
if (!keys_file)
|
||||
return 0;
|
||||
|
||||
const size_t write_size = fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file);
|
||||
|
||||
if (write_size != KEYS_SIZE) {
|
||||
|
|
|
@ -134,10 +134,15 @@ void t_toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, vo
|
|||
}
|
||||
void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number,
|
||||
uint16_t width, uint16_t height,
|
||||
uint8_t const *y, uint8_t const *u, uint8_t const *v,
|
||||
int32_t ystride, int32_t ustride, int32_t vstride,
|
||||
uint8_t const *y, uint8_t const *u, uint8_t const *v, uint8_t const *a,
|
||||
int32_t ystride, int32_t ustride, int32_t vstride, int32_t astride,
|
||||
void *user_data)
|
||||
{
|
||||
ystride = abs(ystride);
|
||||
ustride = abs(ustride);
|
||||
vstride = abs(vstride);
|
||||
astride = abs(astride);
|
||||
|
||||
uint16_t *img_data = malloc(height * width * 6);
|
||||
|
||||
unsigned long int i, j;
|
||||
|
@ -278,18 +283,18 @@ void initialize_tox(Tox** bootstrap, ToxAV** AliceAV, CallControl* AliceCC, ToxA
|
|||
/* Alice */
|
||||
toxav_callback_call(*AliceAV, t_toxav_call_cb, AliceCC);
|
||||
toxav_callback_call_state(*AliceAV, t_toxav_call_state_cb, AliceCC);
|
||||
toxav_callback_receive_video_frame(*AliceAV, t_toxav_receive_video_frame_cb, AliceCC);
|
||||
toxav_callback_receive_audio_frame(*AliceAV, t_toxav_receive_audio_frame_cb, AliceCC);
|
||||
toxav_callback_audio_bit_rate_status(*AliceAV, t_toxav_audio_bit_rate_status_cb, AliceCC);
|
||||
toxav_callback_video_receive_frame(*AliceAV, t_toxav_receive_video_frame_cb, AliceCC);
|
||||
toxav_callback_audio_receive_frame(*AliceAV, t_toxav_receive_audio_frame_cb, AliceCC);
|
||||
toxav_callback_video_bit_rate_status(*AliceAV, t_toxav_video_bit_rate_status_cb, AliceCC);
|
||||
toxav_callback_audio_bit_rate_status(*AliceAV, t_toxav_audio_bit_rate_status_cb, AliceCC);
|
||||
|
||||
/* Bob */
|
||||
toxav_callback_call(*BobAV, t_toxav_call_cb, BobCC);
|
||||
toxav_callback_call_state(*BobAV, t_toxav_call_state_cb, BobCC);
|
||||
toxav_callback_receive_video_frame(*BobAV, t_toxav_receive_video_frame_cb, BobCC);
|
||||
toxav_callback_receive_audio_frame(*BobAV, t_toxav_receive_audio_frame_cb, BobCC);
|
||||
toxav_callback_audio_bit_rate_status(*BobAV, t_toxav_audio_bit_rate_status_cb, BobCC);
|
||||
toxav_callback_video_receive_frame(*BobAV, t_toxav_receive_video_frame_cb, BobCC);
|
||||
toxav_callback_audio_receive_frame(*BobAV, t_toxav_receive_audio_frame_cb, BobCC);
|
||||
toxav_callback_video_bit_rate_status(*BobAV, t_toxav_video_bit_rate_status_cb, BobCC);
|
||||
toxav_callback_audio_bit_rate_status(*BobAV, t_toxav_audio_bit_rate_status_cb, BobCC);
|
||||
|
||||
|
||||
printf("Created 2 instances of ToxAV\n");
|
||||
|
@ -364,7 +369,7 @@ int send_opencv_img(ToxAV* av, uint32_t friend_number, const IplImage* img)
|
|||
}
|
||||
|
||||
|
||||
int rc = toxav_send_video_frame(av, friend_number, img->width, img->height, planes[0], planes[1], planes[2], NULL);
|
||||
int rc = toxav_video_send_frame(av, friend_number, img->width, img->height, planes[0], planes[1], planes[2], NULL, NULL);
|
||||
free(planes[0]);
|
||||
free(planes[1]);
|
||||
free(planes[2]);
|
||||
|
@ -586,7 +591,7 @@ int main (int argc, char** argv)
|
|||
err = Pa_StartStream(adout);
|
||||
assert(err == paNoError);
|
||||
|
||||
toxav_set_audio_bit_rate(AliceAV, 0, 64, false, NULL);
|
||||
toxav_audio_bit_rate_set(AliceAV, 0, 64, false, NULL);
|
||||
|
||||
/* Start write thread */
|
||||
pthread_t t;
|
||||
|
@ -599,7 +604,7 @@ int main (int argc, char** argv)
|
|||
int64_t count = sf_read_short(af_handle, PCM, frame_size);
|
||||
if (count > 0) {
|
||||
TOXAV_ERR_SEND_FRAME rc;
|
||||
if (toxav_send_audio_frame(AliceAV, 0, PCM, count/af_info.channels, af_info.channels, af_info.samplerate, &rc) == false) {
|
||||
if (toxav_audio_send_frame(AliceAV, 0, PCM, count/af_info.channels, af_info.channels, af_info.samplerate, &rc) == false) {
|
||||
printf("Error sending frame of size %ld: %d\n", count, rc);
|
||||
}
|
||||
}
|
||||
|
@ -691,7 +696,7 @@ int main (int argc, char** argv)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
toxav_set_video_bit_rate(AliceAV, 0, 5000, false, NULL);
|
||||
toxav_video_bit_rate_set(AliceAV, 0, 5000, false, NULL);
|
||||
|
||||
time_t start_time = time(NULL);
|
||||
while(start_time + 90 > time(NULL)) {
|
||||
|
|
|
@ -163,9 +163,15 @@ void send_irc_group(Tox *tox, uint8_t *msg, uint16_t len)
|
|||
uint8_t req[len];
|
||||
unsigned int i;
|
||||
|
||||
unsigned int spaces = 0;
|
||||
|
||||
for (i = 0; i < (len - 1); ++i) {
|
||||
if (msg[i + 1] == ':') {
|
||||
break;
|
||||
if (msg[i + 1] == ' ') {
|
||||
++spaces;
|
||||
} else {
|
||||
if (spaces >= 3 && msg[i + 1] == ':') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
req[i] = msg[i + 1];
|
||||
|
@ -227,11 +233,6 @@ Tox *init_tox(int argc, char *argv[])
|
|||
tox_callback_group_message(tox, ©_groupmessage, 0);
|
||||
tox_callback_group_action(tox, ©_groupmessage, 0);
|
||||
|
||||
uint16_t port = atoi(argv[argvoffset + 2]);
|
||||
unsigned char *binary_string = hex_string_to_bin(argv[argvoffset + 3]);
|
||||
tox_bootstrap(tox, argv[argvoffset + 1], port, binary_string, 0);
|
||||
free(binary_string);
|
||||
|
||||
char temp_id[128];
|
||||
printf("\nEnter the address of irc_syncbots master (38 bytes HEX format):\n");
|
||||
|
||||
|
@ -239,6 +240,11 @@ Tox *init_tox(int argc, char *argv[])
|
|||
exit (1);
|
||||
}
|
||||
|
||||
uint16_t port = atoi(argv[argvoffset + 2]);
|
||||
unsigned char *binary_string = hex_string_to_bin(argv[argvoffset + 3]);
|
||||
tox_bootstrap(tox, argv[argvoffset + 1], port, binary_string, 0);
|
||||
free(binary_string);
|
||||
|
||||
uint8_t *bin_id = hex_string_to_bin(temp_id);
|
||||
uint32_t num = tox_friend_add(tox, bin_id, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo") - 1, 0);
|
||||
free(bin_id);
|
||||
|
|
|
@ -38,7 +38,7 @@ bool reconfigure_audio_decoder(ACSession* ac, int32_t sampling_rate, int8_t chan
|
|||
|
||||
|
||||
|
||||
ACSession* ac_new(ToxAV* av, uint32_t friend_number, toxav_receive_audio_frame_cb *cb, void *cb_data)
|
||||
ACSession* ac_new(ToxAV* av, uint32_t friend_number, toxav_audio_receive_frame_cb *cb, void *cb_data)
|
||||
{
|
||||
ACSession *ac = calloc(sizeof(ACSession), 1);
|
||||
|
||||
|
|
|
@ -61,13 +61,13 @@ typedef struct ACSession_s {
|
|||
|
||||
ToxAV* av;
|
||||
uint32_t friend_number;
|
||||
PAIR(toxav_receive_audio_frame_cb *, void *) acb; /* Audio frame receive callback */
|
||||
PAIR(toxav_audio_receive_frame_cb *, void *) acb; /* Audio frame receive callback */
|
||||
} ACSession;
|
||||
|
||||
/*
|
||||
* Create new Audio Codec session.
|
||||
*/
|
||||
ACSession* ac_new(ToxAV* av, uint32_t friend_number, toxav_receive_audio_frame_cb *cb, void *cb_data);
|
||||
ACSession* ac_new(ToxAV* av, uint32_t friend_number, toxav_audio_receive_frame_cb *cb, void *cb_data);
|
||||
/*
|
||||
* Kill the Audio Codec session.
|
||||
*/
|
||||
|
|
|
@ -683,7 +683,7 @@ void handle_push ( MSICall *call, const MSIMessage *msg )
|
|||
|
||||
/* Only act if capabilities changed */
|
||||
if ( call->peer_capabilities != msg->capabilities.value) {
|
||||
LOGGER_INFO("Friend is changing capabilities");
|
||||
LOGGER_INFO("Friend is changing capabilities to: %u", msg->capabilities.value);
|
||||
|
||||
call->peer_capabilities = msg->capabilities.value;
|
||||
if ( invoke_callback(call, msi_OnCapabilities) == -1 )
|
||||
|
|
|
@ -50,10 +50,10 @@ typedef enum {
|
|||
* Supported capabilities
|
||||
*/
|
||||
typedef enum {
|
||||
msi_CapSAudio = 1, /* sending audio */
|
||||
msi_CapSVideo = 2, /* sending video */
|
||||
msi_CapRAudio = 4, /* receiving audio */
|
||||
msi_CapRVideo = 8, /* receiving video */
|
||||
msi_CapSAudio = 4, /* sending audio */
|
||||
msi_CapSVideo = 8, /* sending video */
|
||||
msi_CapRAudio = 16, /* receiving audio */
|
||||
msi_CapRVideo = 32, /* receiving video */
|
||||
} MSICapabilities;
|
||||
|
||||
|
||||
|
|
444
toxav/toxav.c
444
toxav/toxav.c
|
@ -91,8 +91,8 @@ struct ToxAV {
|
|||
|
||||
PAIR(toxav_call_cb *, void*) ccb; /* Call callback */
|
||||
PAIR(toxav_call_state_cb *, void *) scb; /* Call state callback */
|
||||
PAIR(toxav_receive_audio_frame_cb *, void *) acb; /* Audio frame receive callback */
|
||||
PAIR(toxav_receive_video_frame_cb *, void *) vcb; /* Video frame receive callback */
|
||||
PAIR(toxav_audio_receive_frame_cb *, void *) acb; /* Audio frame receive callback */
|
||||
PAIR(toxav_video_receive_frame_cb *, void *) vcb; /* Video frame receive callback */
|
||||
PAIR(toxav_audio_bit_rate_status_cb *, void *) abcb; /* Audio bit rate control callback */
|
||||
PAIR(toxav_video_bit_rate_status_cb *, void *) vbcb; /* Video bit rate control callback */
|
||||
|
||||
|
@ -122,6 +122,27 @@ void call_kill_transmission(ToxAVCall* call);
|
|||
void ba_set(ToxAvBitrateAdapter* ba, uint32_t bit_rate);
|
||||
bool ba_shoud_send_dummy(ToxAvBitrateAdapter* ba);
|
||||
|
||||
uint32_t toxav_version_major(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
uint32_t toxav_version_minor(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
uint32_t toxav_version_patch(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
bool toxav_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch)
|
||||
{
|
||||
(void)major;
|
||||
(void)minor;
|
||||
(void)patch;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
ToxAV* toxav_new(Tox* tox, TOXAV_ERR_NEW* error)
|
||||
{
|
||||
TOXAV_ERR_NEW rc = TOXAV_ERR_NEW_OK;
|
||||
|
@ -204,7 +225,7 @@ void toxav_kill(ToxAV* av)
|
|||
free(av);
|
||||
}
|
||||
|
||||
Tox* toxav_get_tox(ToxAV* av)
|
||||
Tox* toxav_get_tox(const ToxAV* av)
|
||||
{
|
||||
return (Tox*) av->m;
|
||||
}
|
||||
|
@ -430,20 +451,14 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
|
|||
goto END;
|
||||
}
|
||||
|
||||
|
||||
ToxAVCall* call = call_get(av, friend_number);
|
||||
if (call == NULL) {
|
||||
if (call == NULL || (!call->active && control != TOXAV_CALL_CONTROL_CANCEL)) {
|
||||
rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL;
|
||||
goto END;
|
||||
}
|
||||
|
||||
switch (control) {
|
||||
case TOXAV_CALL_CONTROL_RESUME: {
|
||||
if (!call->active) {
|
||||
rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL;
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Only act if paused and had media transfer active before */
|
||||
if (call->msi_call->self_capabilities == 0 &&
|
||||
call->previous_self_capabilities ) {
|
||||
|
@ -459,17 +474,12 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
|
|||
rtp_start_receiving(call->audio.first);
|
||||
rtp_start_receiving(call->video.first);
|
||||
} else {
|
||||
rc = TOXAV_ERR_CALL_CONTROL_NOT_PAUSED;
|
||||
rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION;
|
||||
goto END;
|
||||
}
|
||||
} break;
|
||||
|
||||
case TOXAV_CALL_CONTROL_PAUSE: {
|
||||
if (!call->active) {
|
||||
rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL;
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Only act if not already paused */
|
||||
if (call->msi_call->self_capabilities) {
|
||||
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
|
|||
rtp_stop_receiving(call->audio.first);
|
||||
rtp_stop_receiving(call->video.first);
|
||||
} else {
|
||||
rc = TOXAV_ERR_CALL_CONTROL_ALREADY_PAUSED;
|
||||
rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION;
|
||||
goto END;
|
||||
}
|
||||
} break;
|
||||
|
@ -498,12 +508,7 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
|
|||
call_remove(call);
|
||||
} break;
|
||||
|
||||
case TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO: {
|
||||
if (!call->active) {
|
||||
rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL;
|
||||
goto END;
|
||||
}
|
||||
|
||||
case TOXAV_CALL_CONTROL_MUTE_AUDIO: {
|
||||
if (call->msi_call->self_capabilities & msi_CapRAudio) {
|
||||
if (msi_change_capabilities(call->msi_call, call->
|
||||
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
|
|||
|
||||
rtp_stop_receiving(call->audio.first);
|
||||
} else {
|
||||
/* This call was already muted so notify the friend that he can
|
||||
* start sending audio again
|
||||
*/
|
||||
rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION;
|
||||
goto END;
|
||||
}
|
||||
} break;
|
||||
|
||||
case TOXAV_CALL_CONTROL_UNMUTE_AUDIO: {
|
||||
if (call->msi_call->self_capabilities ^ msi_CapRAudio) {
|
||||
if (msi_change_capabilities(call->msi_call, call->
|
||||
msi_call->self_capabilities | msi_CapRAudio) == -1) {
|
||||
/* 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
|
|||
}
|
||||
|
||||
rtp_start_receiving(call->audio.first);
|
||||
} else {
|
||||
rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION;
|
||||
goto END;
|
||||
}
|
||||
} break;
|
||||
|
||||
case TOXAV_CALL_CONTROL_TOGGLE_HIDE_VIDEO: {
|
||||
if (!call->active) {
|
||||
rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL;
|
||||
goto END;
|
||||
}
|
||||
|
||||
case TOXAV_CALL_CONTROL_HIDE_VIDEO: {
|
||||
if (call->msi_call->self_capabilities & msi_CapRVideo) {
|
||||
if (msi_change_capabilities(call->msi_call, call->
|
||||
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
|
|||
|
||||
rtp_stop_receiving(call->video.first);
|
||||
} else {
|
||||
/* This call was already muted so notify the friend that he can
|
||||
* start sending video again
|
||||
*/
|
||||
rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION;
|
||||
goto END;
|
||||
}
|
||||
} break;
|
||||
|
||||
case TOXAV_CALL_CONTROL_SHOW_VIDEO: {
|
||||
if (call->msi_call->self_capabilities ^ msi_CapRVideo) {
|
||||
if (msi_change_capabilities(call->msi_call, call->
|
||||
msi_call->self_capabilities | msi_CapRVideo) == -1) {
|
||||
/* 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
|
|||
goto END;
|
||||
}
|
||||
|
||||
rtp_start_receiving(call->video.first);
|
||||
rtp_start_receiving(call->audio.first);
|
||||
} else {
|
||||
rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION;
|
||||
goto END;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
@ -572,65 +586,6 @@ END:
|
|||
return rc == TOXAV_ERR_CALL_CONTROL_OK;
|
||||
}
|
||||
|
||||
void toxav_callback_video_bit_rate_status(ToxAV* av, toxav_video_bit_rate_status_cb* function, void* user_data)
|
||||
{
|
||||
pthread_mutex_lock(av->mutex);
|
||||
av->vbcb.first = function;
|
||||
av->vbcb.second = user_data;
|
||||
pthread_mutex_unlock(av->mutex);
|
||||
}
|
||||
|
||||
bool toxav_set_video_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t video_bit_rate, bool force, TOXAV_ERR_BIT_RATE* error)
|
||||
{
|
||||
TOXAV_ERR_BIT_RATE rc = TOXAV_ERR_BIT_RATE_OK;
|
||||
ToxAVCall* call;
|
||||
|
||||
if (m_friend_exists(av->m, friend_number) == 0) {
|
||||
rc = TOXAV_ERR_BIT_RATE_FRIEND_NOT_FOUND;
|
||||
goto END;
|
||||
}
|
||||
|
||||
if (video_bit_rate_invalid(video_bit_rate)) {
|
||||
rc = TOXAV_ERR_BIT_RATE_INVALID;
|
||||
goto END;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(av->mutex);
|
||||
call = call_get(av, friend_number);
|
||||
if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) {
|
||||
pthread_mutex_unlock(av->mutex);
|
||||
rc = TOXAV_ERR_BIT_RATE_FRIEND_NOT_IN_CALL;
|
||||
goto END;
|
||||
}
|
||||
|
||||
if (call->video_bit_rate == video_bit_rate || (call->vba.active && call->vba.bit_rate == video_bit_rate)) {
|
||||
pthread_mutex_unlock(av->mutex);
|
||||
goto END;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(call->mutex);
|
||||
|
||||
if (video_bit_rate > call->video_bit_rate && !force)
|
||||
ba_set(&call->vba, video_bit_rate);
|
||||
else {
|
||||
/* Cancel any previous non forceful bitrate change request */
|
||||
memset(&call->vba, 0, sizeof(call->vba));
|
||||
call->video_bit_rate = video_bit_rate;
|
||||
|
||||
if (!force && av->vbcb.first)
|
||||
av->vbcb.first (av, call->friend_number, true, video_bit_rate, av->vbcb.second);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(call->mutex);
|
||||
pthread_mutex_unlock(av->mutex);
|
||||
|
||||
END:
|
||||
if (error)
|
||||
*error = rc;
|
||||
|
||||
return rc == TOXAV_ERR_BIT_RATE_OK;
|
||||
}
|
||||
|
||||
void toxav_callback_audio_bit_rate_status(ToxAV* av, toxav_audio_bit_rate_status_cb* function, void* user_data)
|
||||
{
|
||||
pthread_mutex_lock(av->mutex);
|
||||
|
@ -639,18 +594,18 @@ void toxav_callback_audio_bit_rate_status(ToxAV* av, toxav_audio_bit_rate_status
|
|||
pthread_mutex_unlock(av->mutex);
|
||||
}
|
||||
|
||||
bool toxav_set_audio_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_BIT_RATE* error)
|
||||
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)
|
||||
{
|
||||
TOXAV_ERR_BIT_RATE rc = TOXAV_ERR_BIT_RATE_OK;
|
||||
TOXAV_ERR_SET_BIT_RATE rc = TOXAV_ERR_SET_BIT_RATE_OK;
|
||||
ToxAVCall* call;
|
||||
|
||||
if (m_friend_exists(av->m, friend_number) == 0) {
|
||||
rc = TOXAV_ERR_BIT_RATE_FRIEND_NOT_FOUND;
|
||||
rc = TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_FOUND;
|
||||
goto END;
|
||||
}
|
||||
|
||||
if (audio_bit_rate_invalid(audio_bit_rate)) {
|
||||
rc = TOXAV_ERR_BIT_RATE_INVALID;
|
||||
rc = TOXAV_ERR_SET_BIT_RATE_INVALID;
|
||||
goto END;
|
||||
}
|
||||
|
||||
|
@ -658,7 +613,7 @@ bool toxav_set_audio_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t audio_
|
|||
call = call_get(av, friend_number);
|
||||
if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) {
|
||||
pthread_mutex_unlock(av->mutex);
|
||||
rc = TOXAV_ERR_BIT_RATE_FRIEND_NOT_IN_CALL;
|
||||
rc = TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_IN_CALL;
|
||||
goto END;
|
||||
}
|
||||
|
||||
|
@ -688,10 +643,171 @@ END:
|
|||
if (error)
|
||||
*error = rc;
|
||||
|
||||
return rc == TOXAV_ERR_BIT_RATE_OK;
|
||||
return rc == TOXAV_ERR_SET_BIT_RATE_OK;
|
||||
}
|
||||
|
||||
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)
|
||||
void toxav_callback_video_bit_rate_status(ToxAV* av, toxav_video_bit_rate_status_cb* function, void* user_data)
|
||||
{
|
||||
pthread_mutex_lock(av->mutex);
|
||||
av->vbcb.first = function;
|
||||
av->vbcb.second = user_data;
|
||||
pthread_mutex_unlock(av->mutex);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
TOXAV_ERR_SET_BIT_RATE rc = TOXAV_ERR_SET_BIT_RATE_OK;
|
||||
ToxAVCall* call;
|
||||
|
||||
if (m_friend_exists(av->m, friend_number) == 0) {
|
||||
rc = TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_FOUND;
|
||||
goto END;
|
||||
}
|
||||
|
||||
if (video_bit_rate_invalid(video_bit_rate)) {
|
||||
rc = TOXAV_ERR_SET_BIT_RATE_INVALID;
|
||||
goto END;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(av->mutex);
|
||||
call = call_get(av, friend_number);
|
||||
if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) {
|
||||
pthread_mutex_unlock(av->mutex);
|
||||
rc = TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_IN_CALL;
|
||||
goto END;
|
||||
}
|
||||
|
||||
if (call->video_bit_rate == video_bit_rate || (call->vba.active && call->vba.bit_rate == video_bit_rate)) {
|
||||
pthread_mutex_unlock(av->mutex);
|
||||
goto END;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(call->mutex);
|
||||
|
||||
if (video_bit_rate > call->video_bit_rate && !force)
|
||||
ba_set(&call->vba, video_bit_rate);
|
||||
else {
|
||||
/* Cancel any previous non forceful bitrate change request */
|
||||
memset(&call->vba, 0, sizeof(call->vba));
|
||||
call->video_bit_rate = video_bit_rate;
|
||||
|
||||
if (!force && av->vbcb.first)
|
||||
av->vbcb.first (av, call->friend_number, true, video_bit_rate, av->vbcb.second);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(call->mutex);
|
||||
pthread_mutex_unlock(av->mutex);
|
||||
|
||||
END:
|
||||
if (error)
|
||||
*error = rc;
|
||||
|
||||
return rc == TOXAV_ERR_SET_BIT_RATE_OK;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK;
|
||||
ToxAVCall* call;
|
||||
|
||||
if (m_friend_exists(av->m, friend_number) == 0) {
|
||||
rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND;
|
||||
goto END;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(av->mutex);
|
||||
call = call_get(av, friend_number);
|
||||
if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) {
|
||||
pthread_mutex_unlock(av->mutex);
|
||||
rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL;
|
||||
goto END;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(call->mutex_audio);
|
||||
pthread_mutex_unlock(av->mutex);
|
||||
|
||||
if ( pcm == NULL ) {
|
||||
pthread_mutex_unlock(call->mutex_audio);
|
||||
rc = TOXAV_ERR_SEND_FRAME_NULL;
|
||||
goto END;
|
||||
}
|
||||
|
||||
if ( channels > 2 ) {
|
||||
pthread_mutex_unlock(call->mutex_audio);
|
||||
rc = TOXAV_ERR_SEND_FRAME_INVALID;
|
||||
goto END;
|
||||
}
|
||||
|
||||
{ /* Encode and send */
|
||||
if (ac_reconfigure_encoder(call->audio.second, call->audio_bit_rate * 1000, sampling_rate, channels) != 0) {
|
||||
pthread_mutex_unlock(call->mutex_audio);
|
||||
rc = TOXAV_ERR_SEND_FRAME_INVALID;
|
||||
goto END;
|
||||
}
|
||||
|
||||
uint8_t dest[sample_count + sizeof(sampling_rate)]; /* This is more than enough always */
|
||||
|
||||
sampling_rate = htonl(sampling_rate);
|
||||
memcpy(dest, &sampling_rate, sizeof(sampling_rate));
|
||||
int vrc = opus_encode(call->audio.second->encoder, pcm, sample_count,
|
||||
dest + sizeof(sampling_rate), sizeof(dest) - sizeof(sampling_rate));
|
||||
|
||||
if (vrc < 0) {
|
||||
LOGGER_WARNING("Failed to encode frame %s", opus_strerror(vrc));
|
||||
pthread_mutex_unlock(call->mutex_audio);
|
||||
rc = TOXAV_ERR_SEND_FRAME_INVALID;
|
||||
goto END;
|
||||
}
|
||||
|
||||
if (rtp_send_data(call->audio.first, dest, vrc + sizeof(sampling_rate), false) != 0) {
|
||||
LOGGER_WARNING("Failed to send audio packet");
|
||||
rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED;
|
||||
}
|
||||
|
||||
|
||||
/* For bit rate measurement; send dummy packet */
|
||||
if (ba_shoud_send_dummy(&call->aba)) {
|
||||
sampling_rate = ntohl(sampling_rate);
|
||||
if (ac_reconfigure_test_encoder(call->audio.second, call->audio_bit_rate * 1000, sampling_rate, channels) != 0) {
|
||||
/* FIXME should the bit rate changing fail here? */
|
||||
pthread_mutex_unlock(call->mutex_audio);
|
||||
rc = TOXAV_ERR_SEND_FRAME_INVALID;
|
||||
goto END;
|
||||
}
|
||||
|
||||
sampling_rate = htonl(sampling_rate);
|
||||
memcpy(dest, &sampling_rate, sizeof(sampling_rate));
|
||||
vrc = opus_encode(call->audio.second->test_encoder, pcm, sample_count,
|
||||
dest + sizeof(sampling_rate), sizeof(dest) - sizeof(sampling_rate));
|
||||
|
||||
if (vrc < 0) {
|
||||
LOGGER_WARNING("Failed to encode frame %s", opus_strerror(vrc));
|
||||
pthread_mutex_unlock(call->mutex_audio);
|
||||
rc = TOXAV_ERR_SEND_FRAME_INVALID;
|
||||
goto END;
|
||||
}
|
||||
|
||||
if (rtp_send_data(call->audio.first, dest, vrc + sizeof(sampling_rate), true) != 0) {
|
||||
LOGGER_WARNING("Failed to send audio packet");
|
||||
rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED;
|
||||
}
|
||||
|
||||
if (call->aba.end_time == (uint64_t) ~0)
|
||||
call->aba.end_time = current_time_monotonic() + BITRATE_CHANGE_TESTING_TIME_MS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pthread_mutex_unlock(call->mutex_audio);
|
||||
|
||||
END:
|
||||
if (error)
|
||||
*error = rc;
|
||||
|
||||
return rc == TOXAV_ERR_SEND_FRAME_OK;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK;
|
||||
ToxAVCall* call;
|
||||
|
@ -736,6 +852,10 @@ bool toxav_send_video_frame(ToxAV* av, uint32_t friend_number, uint16_t width, u
|
|||
memcpy(img.planes[VPX_PLANE_U], u, (width/2) * (height/2));
|
||||
memcpy(img.planes[VPX_PLANE_V], v, (width/2) * (height/2));
|
||||
|
||||
/* TODO LOL */
|
||||
if (a && img.planes[VPX_PLANE_ALPHA])
|
||||
memcpy(img.planes[VPX_PLANE_ALPHA], a, width * height);
|
||||
|
||||
int vrc = vpx_codec_encode(call->video.second->encoder, &img,
|
||||
call->video.second->frame_counter, 1, 0, MAX_ENCODE_TIME_US);
|
||||
|
||||
|
@ -856,117 +976,7 @@ END:
|
|||
return rc == TOXAV_ERR_SEND_FRAME_OK;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK;
|
||||
ToxAVCall* call;
|
||||
|
||||
if (m_friend_exists(av->m, friend_number) == 0) {
|
||||
rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND;
|
||||
goto END;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(av->mutex);
|
||||
call = call_get(av, friend_number);
|
||||
if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) {
|
||||
pthread_mutex_unlock(av->mutex);
|
||||
rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL;
|
||||
goto END;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(call->mutex_audio);
|
||||
pthread_mutex_unlock(av->mutex);
|
||||
|
||||
if ( pcm == NULL ) {
|
||||
pthread_mutex_unlock(call->mutex_audio);
|
||||
rc = TOXAV_ERR_SEND_FRAME_NULL;
|
||||
goto END;
|
||||
}
|
||||
|
||||
if ( channels > 2 ) {
|
||||
pthread_mutex_unlock(call->mutex_audio);
|
||||
rc = TOXAV_ERR_SEND_FRAME_INVALID;
|
||||
goto END;
|
||||
}
|
||||
|
||||
{ /* Encode and send */
|
||||
if (ac_reconfigure_encoder(call->audio.second, call->audio_bit_rate * 1000, sampling_rate, channels) != 0) {
|
||||
pthread_mutex_unlock(call->mutex_audio);
|
||||
rc = TOXAV_ERR_SEND_FRAME_INVALID;
|
||||
goto END;
|
||||
}
|
||||
|
||||
uint8_t dest[sample_count + sizeof(sampling_rate)]; /* This is more than enough always */
|
||||
|
||||
sampling_rate = htonl(sampling_rate);
|
||||
memcpy(dest, &sampling_rate, sizeof(sampling_rate));
|
||||
int vrc = opus_encode(call->audio.second->encoder, pcm, sample_count,
|
||||
dest + sizeof(sampling_rate), sizeof(dest) - sizeof(sampling_rate));
|
||||
|
||||
if (vrc < 0) {
|
||||
LOGGER_WARNING("Failed to encode frame %s", opus_strerror(vrc));
|
||||
pthread_mutex_unlock(call->mutex_audio);
|
||||
rc = TOXAV_ERR_SEND_FRAME_INVALID;
|
||||
goto END;
|
||||
}
|
||||
|
||||
if (rtp_send_data(call->audio.first, dest, vrc + sizeof(sampling_rate), false) != 0) {
|
||||
LOGGER_WARNING("Failed to send audio packet");
|
||||
rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED;
|
||||
}
|
||||
|
||||
|
||||
/* For bit rate measurement; send dummy packet */
|
||||
if (ba_shoud_send_dummy(&call->aba)) {
|
||||
sampling_rate = ntohl(sampling_rate);
|
||||
if (ac_reconfigure_test_encoder(call->audio.second, call->audio_bit_rate * 1000, sampling_rate, channels) != 0) {
|
||||
/* FIXME should the bit rate changing fail here? */
|
||||
pthread_mutex_unlock(call->mutex_audio);
|
||||
rc = TOXAV_ERR_SEND_FRAME_INVALID;
|
||||
goto END;
|
||||
}
|
||||
|
||||
sampling_rate = htonl(sampling_rate);
|
||||
memcpy(dest, &sampling_rate, sizeof(sampling_rate));
|
||||
vrc = opus_encode(call->audio.second->test_encoder, pcm, sample_count,
|
||||
dest + sizeof(sampling_rate), sizeof(dest) - sizeof(sampling_rate));
|
||||
|
||||
if (vrc < 0) {
|
||||
LOGGER_WARNING("Failed to encode frame %s", opus_strerror(vrc));
|
||||
pthread_mutex_unlock(call->mutex_audio);
|
||||
rc = TOXAV_ERR_SEND_FRAME_INVALID;
|
||||
goto END;
|
||||
}
|
||||
|
||||
if (rtp_send_data(call->audio.first, dest, vrc + sizeof(sampling_rate), true) != 0) {
|
||||
LOGGER_WARNING("Failed to send audio packet");
|
||||
rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED;
|
||||
}
|
||||
|
||||
if (call->aba.end_time == (uint64_t) ~0)
|
||||
call->aba.end_time = current_time_monotonic() + BITRATE_CHANGE_TESTING_TIME_MS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pthread_mutex_unlock(call->mutex_audio);
|
||||
|
||||
END:
|
||||
if (error)
|
||||
*error = rc;
|
||||
|
||||
return rc == TOXAV_ERR_SEND_FRAME_OK;
|
||||
}
|
||||
|
||||
void toxav_callback_receive_video_frame(ToxAV* av, toxav_receive_video_frame_cb* function, void* user_data)
|
||||
{
|
||||
pthread_mutex_lock(av->mutex);
|
||||
av->vcb.first = function;
|
||||
av->vcb.second = user_data;
|
||||
pthread_mutex_unlock(av->mutex);
|
||||
}
|
||||
|
||||
void toxav_callback_receive_audio_frame(ToxAV* av, toxav_receive_audio_frame_cb* function, void* user_data)
|
||||
void toxav_callback_audio_receive_frame(ToxAV* av, toxav_audio_receive_frame_cb* function, void* user_data)
|
||||
{
|
||||
pthread_mutex_lock(av->mutex);
|
||||
av->acb.first = function;
|
||||
|
@ -974,6 +984,14 @@ void toxav_callback_receive_audio_frame(ToxAV* av, toxav_receive_audio_frame_cb*
|
|||
pthread_mutex_unlock(av->mutex);
|
||||
}
|
||||
|
||||
void toxav_callback_video_receive_frame(ToxAV* av, toxav_video_receive_frame_cb* function, void* user_data)
|
||||
{
|
||||
pthread_mutex_lock(av->mutex);
|
||||
av->vcb.first = function;
|
||||
av->vcb.second = user_data;
|
||||
pthread_mutex_unlock(av->mutex);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
|
|
826
toxav/toxav.h
826
toxav/toxav.h
File diff suppressed because it is too large
Load Diff
|
@ -42,7 +42,7 @@ typedef struct { uint16_t size; uint8_t data[]; } Payload;
|
|||
bool create_video_encoder (vpx_codec_ctx_t* dest, int32_t bit_rate);
|
||||
|
||||
|
||||
VCSession* vc_new(ToxAV* av, uint32_t friend_number, toxav_receive_video_frame_cb* cb, void* cb_data, uint32_t mvfpsz)
|
||||
VCSession* vc_new(ToxAV* av, uint32_t friend_number, toxav_video_receive_frame_cb* cb, void* cb_data, uint32_t mvfpsz)
|
||||
{
|
||||
VCSession *vc = calloc(sizeof(VCSession), 1);
|
||||
|
||||
|
@ -141,8 +141,9 @@ void vc_do(VCSession* vc)
|
|||
for (; dest; dest = vpx_codec_get_frame(vc->decoder, &iter)) {
|
||||
if (vc->vcb.first)
|
||||
vc->vcb.first(vc->av, vc->friend_number, dest->d_w, dest->d_h,
|
||||
(const uint8_t*)dest->planes[0], (const uint8_t*)dest->planes[1], (const uint8_t*)dest->planes[2],
|
||||
dest->stride[0], dest->stride[1], dest->stride[2], vc->vcb.second);
|
||||
(const uint8_t*)dest->planes[0], (const uint8_t*)dest->planes[1],
|
||||
(const uint8_t*)dest->planes[2], (const uint8_t*)dest->planes[3],
|
||||
dest->stride[0], dest->stride[1], dest->stride[2], dest->stride[3], vc->vcb.second);
|
||||
|
||||
vpx_img_free(dest);
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ typedef struct VCSession_s {
|
|||
ToxAV *av;
|
||||
uint32_t friend_number;
|
||||
|
||||
PAIR(toxav_receive_video_frame_cb *, void *) vcb; /* Video frame receive callback */
|
||||
PAIR(toxav_video_receive_frame_cb *, void *) vcb; /* Video frame receive callback */
|
||||
|
||||
pthread_mutex_t queue_mutex[1];
|
||||
} VCSession;
|
||||
|
@ -79,7 +79,7 @@ typedef struct VCSession_s {
|
|||
/*
|
||||
* Create new Video Codec session.
|
||||
*/
|
||||
VCSession* vc_new(ToxAV* av, uint32_t friend_number, toxav_receive_video_frame_cb *cb, void *cb_data, uint32_t mvfpsz);
|
||||
VCSession* vc_new(ToxAV* av, uint32_t friend_number, toxav_video_receive_frame_cb *cb, void *cb_data, uint32_t mvfpsz);
|
||||
/*
|
||||
* Kill the Video Codec session.
|
||||
*/
|
||||
|
|
|
@ -145,7 +145,7 @@ void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t
|
|||
*/
|
||||
void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *client_id)
|
||||
{
|
||||
return get_shared_key(&dht->shared_keys_recv, shared_key, dht->self_secret_key, client_id);
|
||||
get_shared_key(&dht->shared_keys_recv, shared_key, dht->self_secret_key, client_id);
|
||||
}
|
||||
|
||||
/* 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
|
|||
*/
|
||||
void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *client_id)
|
||||
{
|
||||
return get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, client_id);
|
||||
get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, client_id);
|
||||
}
|
||||
|
||||
void to_net_family(IP *ip)
|
||||
|
|
|
@ -227,17 +227,42 @@ static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast)
|
|||
return ip;
|
||||
}
|
||||
|
||||
/* return 0 if ip is a LAN ip.
|
||||
* return -1 if it is not.
|
||||
*/
|
||||
int LAN_ip(IP ip)
|
||||
/* Is IP a local ip or not. */
|
||||
_Bool Local_ip(IP ip)
|
||||
{
|
||||
if (ip.family == AF_INET) {
|
||||
IP4 ip4 = ip.ip4;
|
||||
|
||||
/* Loopback. */
|
||||
if (ip4.uint8[0] == 127)
|
||||
return 0;
|
||||
return 1;
|
||||
} else {
|
||||
/* embedded IPv4-in-IPv6 */
|
||||
if (IPV6_IPV4_IN_V6(ip.ip6)) {
|
||||
IP ip4;
|
||||
ip4.family = AF_INET;
|
||||
ip4.ip4.uint32 = ip.ip6.uint32[3];
|
||||
return Local_ip(ip4);
|
||||
}
|
||||
|
||||
/* localhost in IPv6 (::1) */
|
||||
if (ip.ip6.uint64[0] == 0 && ip.ip6.uint32[2] == 0 && ip.ip6.uint32[3] == htonl(1))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return 0 if ip is a LAN ip.
|
||||
* return -1 if it is not.
|
||||
*/
|
||||
int LAN_ip(IP ip)
|
||||
{
|
||||
if (Local_ip(ip))
|
||||
return 0;
|
||||
|
||||
if (ip.family == AF_INET) {
|
||||
IP4 ip4 = ip.ip4;
|
||||
|
||||
/* 10.0.0.0 to 10.255.255.255 range. */
|
||||
if (ip4.uint8[0] == 10)
|
||||
|
@ -276,10 +301,6 @@ int LAN_ip(IP ip)
|
|||
ip4.ip4.uint32 = ip.ip6.uint32[3];
|
||||
return LAN_ip(ip4);
|
||||
}
|
||||
|
||||
/* localhost in IPv6 (::1) */
|
||||
if (ip.ip6.uint64[0] == 0 && ip.ip6.uint32[2] == 0 && ip.ip6.uint32[3] == htonl(1))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
|
|
@ -40,6 +40,9 @@ void LANdiscovery_init(DHT *dht);
|
|||
/* Clear packet handlers. */
|
||||
void LANdiscovery_kill(DHT *dht);
|
||||
|
||||
/* Is IP a local ip or not. */
|
||||
_Bool Local_ip(IP ip);
|
||||
|
||||
/* checks if a given IP isn't routable
|
||||
*
|
||||
* return 0 if ip is a LAN ip.
|
||||
|
|
|
@ -52,24 +52,6 @@ static uint8_t friend_not_valid(const Messenger *m, int32_t friendnumber)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int add_online_friend(Messenger *m, int32_t friendnumber)
|
||||
{
|
||||
if (friend_not_valid(m, friendnumber))
|
||||
return -1;
|
||||
|
||||
++m->numonline_friends;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int remove_online_friend(Messenger *m, int32_t friendnumber)
|
||||
{
|
||||
if (friend_not_valid(m, friendnumber))
|
||||
return -1;
|
||||
|
||||
--m->numonline_friends;
|
||||
return 0;
|
||||
}
|
||||
/* Set the size of the friend list to numfriends.
|
||||
*
|
||||
* return -1 if realloc fails.
|
||||
|
@ -399,9 +381,6 @@ int m_delfriend(Messenger *m, int32_t friendnumber)
|
|||
if (friend_not_valid(m, friendnumber))
|
||||
return -1;
|
||||
|
||||
if (m->friendlist[friendnumber].status == FRIEND_ONLINE)
|
||||
remove_online_friend(m, friendnumber);
|
||||
|
||||
clear_receipts(m, friendnumber);
|
||||
remove_request_received(&(m->fr), m->friendlist[friendnumber].real_pk);
|
||||
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
|
|||
if (is_online != was_online) {
|
||||
if (was_online) {
|
||||
break_files(m, friendnumber);
|
||||
remove_online_friend(m, friendnumber);
|
||||
clear_receipts(m, friendnumber);
|
||||
} else {
|
||||
add_online_friend(m, friendnumber);
|
||||
}
|
||||
|
||||
m->friendlist[friendnumber].status = status;
|
||||
|
@ -1831,6 +1807,27 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (options->tcp_server_port) {
|
||||
m->tcp_server = new_TCP_server(options->ipv6enabled, 1, &options->tcp_server_port, m->dht->self_public_key,
|
||||
m->dht->self_secret_key, m->onion);
|
||||
|
||||
if (m->tcp_server == NULL) {
|
||||
kill_friend_connections(m->fr_c);
|
||||
kill_onion(m->onion);
|
||||
kill_onion_announce(m->onion_a);
|
||||
kill_onion_client(m->onion_c);
|
||||
kill_DHT(m->dht);
|
||||
kill_net_crypto(m->net_crypto);
|
||||
kill_networking(m->net);
|
||||
free(m);
|
||||
|
||||
if (error)
|
||||
*error = MESSENGER_ERROR_TCP_SERVER;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
m->options = *options;
|
||||
friendreq_init(&(m->fr), m->fr_c);
|
||||
set_nospam(&(m->fr), random_int());
|
||||
|
@ -1850,6 +1847,10 @@ void kill_messenger(Messenger *m)
|
|||
|
||||
uint32_t i;
|
||||
|
||||
if (m->tcp_server) {
|
||||
kill_TCP_server(m->tcp_server);
|
||||
}
|
||||
|
||||
kill_friend_connections(m->fr_c);
|
||||
kill_onion(m->onion);
|
||||
kill_onion_announce(m->onion_a);
|
||||
|
@ -2285,6 +2286,15 @@ void do_messenger(Messenger *m)
|
|||
for (i = 0; i < NUM_SAVED_TCP_RELAYS; ++i) {
|
||||
add_tcp_relay(m->net_crypto, m->loaded_relays[i].ip_port, m->loaded_relays[i].public_key);
|
||||
}
|
||||
|
||||
if (m->tcp_server) {
|
||||
/* Add self tcp server. */
|
||||
IP_Port local_ip_port;
|
||||
local_ip_port.port = m->options.tcp_server_port;
|
||||
local_ip_port.ip.family = AF_INET;
|
||||
local_ip_port.ip.ip4.uint32 = INADDR_LOOPBACK;
|
||||
add_tcp_relay(m->net_crypto, local_ip_port, m->tcp_server->public_key);
|
||||
}
|
||||
}
|
||||
|
||||
unix_time_update();
|
||||
|
@ -2294,6 +2304,10 @@ void do_messenger(Messenger *m)
|
|||
do_DHT(m->dht);
|
||||
}
|
||||
|
||||
if (m->tcp_server) {
|
||||
do_TCP_server(m->tcp_server);
|
||||
}
|
||||
|
||||
do_net_crypto(m->net_crypto);
|
||||
do_onion_client(m->onion_c);
|
||||
do_friend_connections(m->fr_c);
|
||||
|
@ -2622,13 +2636,11 @@ static int messenger_load_state_callback(void *outer, const uint8_t *data, uint3
|
|||
case MESSENGER_STATE_TYPE_NOSPAMKEYS:
|
||||
if (length == crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t)) {
|
||||
set_nospam(&(m->fr), *(uint32_t *)data);
|
||||
load_keys(m->net_crypto, &data[sizeof(uint32_t)]);
|
||||
#ifdef ENABLE_ASSOC_DHT
|
||||
load_secret_key(m->net_crypto, (&data[sizeof(uint32_t)]) + crypto_box_PUBLICKEYBYTES);
|
||||
|
||||
if (m->dht->assoc)
|
||||
Assoc_self_client_id_changed(m->dht->assoc, m->net_crypto->self_public_key);
|
||||
|
||||
#endif
|
||||
if (memcmp((&data[sizeof(uint32_t)]), m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES) != 0) {
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
return -1; /* critical */
|
||||
|
||||
|
@ -2738,12 +2750,6 @@ uint32_t count_friendlist(const Messenger *m)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Return the number of online friends in the instance m. */
|
||||
uint32_t get_num_online_friends(const Messenger *m)
|
||||
{
|
||||
return m->numonline_friends;
|
||||
}
|
||||
|
||||
/* Copy a list of valid friend IDs into the array out_list.
|
||||
* If out_list is NULL, returns 0.
|
||||
* Otherwise, returns the number of elements copied.
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#define MESSENGER_H
|
||||
|
||||
#include "friend_requests.h"
|
||||
#include "LAN_discovery.h"
|
||||
#include "friend_connection.h"
|
||||
|
||||
#define MAX_NAME_LENGTH 128
|
||||
|
@ -71,6 +70,7 @@ typedef struct {
|
|||
uint8_t udp_disabled;
|
||||
TCP_Proxy_Info proxy_info;
|
||||
uint16_t port_range[2];
|
||||
uint16_t tcp_server_port;
|
||||
} Messenger_Options;
|
||||
|
||||
|
||||
|
@ -220,6 +220,7 @@ struct Messenger {
|
|||
|
||||
Friend_Connections *fr_c;
|
||||
|
||||
TCP_Server *tcp_server;
|
||||
Friend_Requests fr;
|
||||
uint8_t name[MAX_NAME_LENGTH];
|
||||
uint16_t name_length;
|
||||
|
@ -232,8 +233,6 @@ struct Messenger {
|
|||
Friend *friendlist;
|
||||
uint32_t numfriends;
|
||||
|
||||
uint32_t numonline_friends;
|
||||
|
||||
#define NUM_SAVED_TCP_RELAYS 8
|
||||
uint8_t has_added_relays; // If the first connection has occurred in do_messenger
|
||||
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
|
|||
enum {
|
||||
MESSENGER_ERROR_NONE,
|
||||
MESSENGER_ERROR_PORT,
|
||||
MESSENGER_ERROR_TCP_SERVER,
|
||||
MESSENGER_ERROR_OTHER
|
||||
};
|
||||
|
||||
|
@ -772,9 +772,6 @@ int messenger_load(Messenger *m, const uint8_t *data, uint32_t length);
|
|||
* for copy_friendlist. */
|
||||
uint32_t count_friendlist(const Messenger *m);
|
||||
|
||||
/* Return the number of online friends in the instance m. */
|
||||
uint32_t get_num_online_friends(const Messenger *m);
|
||||
|
||||
/* Copy a list of valid friend IDs into the array out_list.
|
||||
* If out_list is NULL, returns 0.
|
||||
* Otherwise, returns the number of elements copied.
|
||||
|
|
|
@ -249,7 +249,6 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c
|
|||
for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
|
||||
uint32_t tcp_con_num = con_to->connections[i].tcp_connection;
|
||||
uint8_t status = con_to->connections[i].status;
|
||||
uint8_t connection_id = con_to->connections[i].connection_id;
|
||||
|
||||
if (tcp_con_num && status == TCP_CONNECTIONS_STATUS_REGISTERED) {
|
||||
tcp_con_num -= 1;
|
||||
|
|
|
@ -85,7 +85,7 @@ typedef struct TCP_Priority_List TCP_Priority_List;
|
|||
struct TCP_Priority_List {
|
||||
TCP_Priority_List *next;
|
||||
uint16_t size, sent;
|
||||
uint8_t data[0];
|
||||
uint8_t data[];
|
||||
};
|
||||
|
||||
typedef struct TCP_Secure_Connection {
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <crypto_hash_sha512.h>
|
||||
#include <crypto_verify_16.h>
|
||||
#include <crypto_verify_32.h>
|
||||
#include <crypto_scalarmult_curve25519.h>
|
||||
#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
|
||||
#endif
|
||||
|
||||
|
|
|
@ -158,6 +158,15 @@ int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, IP_Port ip_
|
|||
if (!friend_con)
|
||||
return -1;
|
||||
|
||||
/* Local ip and same pk means that they are hosting a TCP relay. */
|
||||
if (Local_ip(ip_port.ip) && memcmp(friend_con->dht_temp_pk, public_key, crypto_box_PUBLICKEYBYTES) == 0) {
|
||||
if (friend_con->dht_ip_port.ip.family != 0) {
|
||||
ip_port.ip = friend_con->dht_ip_port.ip;
|
||||
} else {
|
||||
friend_con->hosting_tcp_relay = 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int i;
|
||||
|
||||
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)
|
|||
friend_new_connection(fr_c, number);
|
||||
}
|
||||
|
||||
set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port);
|
||||
set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, 1);
|
||||
friend_con->dht_ip_port = ip_port;
|
||||
friend_con->dht_ip_port_lastrecv = unix_time();
|
||||
|
||||
if (friend_con->hosting_tcp_relay) {
|
||||
friend_add_tcp_relay(fr_c, number, ip_port, friend_con->dht_temp_pk);
|
||||
friend_con->hosting_tcp_relay = 0;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
|||
|
||||
friend_con->status = FRIENDCONN_STATUS_CONNECTING;
|
||||
friend_con->crypt_connection_id = -1;
|
||||
friend_con->hosting_tcp_relay = 0;
|
||||
}
|
||||
|
||||
if (call_cb) {
|
||||
|
@ -458,7 +473,7 @@ static int handle_new_connections(void *object, New_Connection *n_c)
|
|||
friend_con->crypt_connection_id = id;
|
||||
|
||||
if (n_c->source.ip.family != AF_INET && n_c->source.ip.family != AF_INET6) {
|
||||
set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port);
|
||||
set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0);
|
||||
} else {
|
||||
friend_con->dht_ip_port = n_c->source;
|
||||
friend_con->dht_ip_port_lastrecv = unix_time();
|
||||
|
@ -796,7 +811,7 @@ void do_friend_connections(Friend_Connections *fr_c)
|
|||
|
||||
if (friend_con->dht_lock) {
|
||||
if (friend_new_connection(fr_c, i) == 0) {
|
||||
set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port);
|
||||
set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0);
|
||||
connect_to_saved_tcp_relays(fr_c, i, (MAX_FRIEND_TCP_CONNECTIONS / 2)); /* Only fill it half up. */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,6 +96,8 @@ typedef struct {
|
|||
|
||||
Node_format tcp_relays[FRIEND_MAX_STORED_TCP_RELAYS];
|
||||
uint16_t tcp_relay_counter;
|
||||
|
||||
_Bool hosting_tcp_relay;
|
||||
} Friend_Conn;
|
||||
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
* < 0 : no match, returns index (return value is INDEX(index)) where
|
||||
* the data should be inserted
|
||||
*/
|
||||
static int find(const BS_LIST *list, const void *data)
|
||||
static int find(const BS_LIST *list, const uint8_t *data)
|
||||
{
|
||||
//should work well, but could be improved
|
||||
if (list->n == 0) {
|
||||
|
@ -162,7 +162,7 @@ void bs_list_free(BS_LIST *list)
|
|||
free(list->ids);
|
||||
}
|
||||
|
||||
int bs_list_find(const BS_LIST *list, const void *data)
|
||||
int bs_list_find(const BS_LIST *list, const uint8_t *data)
|
||||
{
|
||||
int r = find(list, data);
|
||||
|
||||
|
@ -174,7 +174,7 @@ int bs_list_find(const BS_LIST *list, const void *data)
|
|||
return list->ids[r];
|
||||
}
|
||||
|
||||
int bs_list_add(BS_LIST *list, const void *data, int id)
|
||||
int bs_list_add(BS_LIST *list, const uint8_t *data, int id)
|
||||
{
|
||||
//find where the new element should be inserted
|
||||
//see: return value of find()
|
||||
|
@ -214,7 +214,7 @@ int bs_list_add(BS_LIST *list, const void *data, int id)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int bs_list_remove(BS_LIST *list, const void *data, int id)
|
||||
int bs_list_remove(BS_LIST *list, const uint8_t *data, int id)
|
||||
{
|
||||
int i = find(list, data);
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ typedef struct {
|
|||
uint32_t n; //number of elements
|
||||
uint32_t capacity; //number of elements memory is allocated for
|
||||
uint32_t element_size; //size of the elements
|
||||
void *data; //array of elements
|
||||
uint8_t *data; //array of elements
|
||||
int *ids; //array of element ids
|
||||
} BS_LIST;
|
||||
|
||||
|
@ -56,7 +56,7 @@ void bs_list_free(BS_LIST *list);
|
|||
* >= 0 : id associated with data
|
||||
* -1 : failure
|
||||
*/
|
||||
int bs_list_find(const BS_LIST *list, const void *data);
|
||||
int bs_list_find(const BS_LIST *list, const uint8_t *data);
|
||||
|
||||
/* Add an element with associated id to the list
|
||||
*
|
||||
|
@ -64,7 +64,7 @@ int bs_list_find(const BS_LIST *list, const void *data);
|
|||
* 1 : success
|
||||
* 0 : failure (data already in list)
|
||||
*/
|
||||
int bs_list_add(BS_LIST *list, const void *data, int id);
|
||||
int bs_list_add(BS_LIST *list, const uint8_t *data, int id);
|
||||
|
||||
/* Remove element from the list
|
||||
*
|
||||
|
@ -72,7 +72,7 @@ int bs_list_add(BS_LIST *list, const void *data, int id);
|
|||
* 1 : success
|
||||
* 0 : failure (element not found or id does not match)
|
||||
*/
|
||||
int bs_list_remove(BS_LIST *list, const void *data, int id);
|
||||
int bs_list_remove(BS_LIST *list, const uint8_t *data, int id);
|
||||
|
||||
/* Removes the memory overhead
|
||||
*
|
||||
|
|
|
@ -676,6 +676,8 @@ static int handle_request_packet(Packets_Array *send_array, const uint8_t *data,
|
|||
uint32_t i, n = 1;
|
||||
uint32_t requested = 0;
|
||||
|
||||
uint64_t temp_time = current_time_monotonic();
|
||||
|
||||
for (i = send_array->buffer_start; i != send_array->buffer_end; ++i) {
|
||||
if (length == 0)
|
||||
break;
|
||||
|
@ -684,7 +686,11 @@ static int handle_request_packet(Packets_Array *send_array, const uint8_t *data,
|
|||
|
||||
if (n == data[0]) {
|
||||
if (send_array->buffer[num]) {
|
||||
send_array->buffer[num]->sent = 0;
|
||||
uint64_t sent_time = send_array->buffer[num]->sent_time;
|
||||
|
||||
if ((sent_time + DEFAULT_PING_CONNECTION) < temp_time) {
|
||||
send_array->buffer[num]->sent_time = 0;
|
||||
}
|
||||
}
|
||||
|
||||
++data;
|
||||
|
@ -788,12 +794,12 @@ static int reset_max_speed_reached(Net_Crypto *c, int crypt_connection_id)
|
|||
uint8_t send_failed = 0;
|
||||
|
||||
if (ret == 1) {
|
||||
if (!dt->sent) {
|
||||
if (!dt->sent_time) {
|
||||
if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, dt->data,
|
||||
dt->length) != 0) {
|
||||
send_failed = 1;
|
||||
} else {
|
||||
dt->sent = 1;
|
||||
dt->sent_time = current_time_monotonic();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -831,7 +837,7 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, cons
|
|||
}
|
||||
|
||||
Packet_Data dt;
|
||||
dt.sent = 0;
|
||||
dt.sent_time = 0;
|
||||
dt.length = length;
|
||||
memcpy(dt.data, data, length);
|
||||
pthread_mutex_lock(&conn->mutex);
|
||||
|
@ -849,7 +855,7 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, cons
|
|||
Packet_Data *dt1 = NULL;
|
||||
|
||||
if (get_data_pointer(&conn->send_array, &dt1, packet_num) == 1)
|
||||
dt1->sent = 1;
|
||||
dt1->sent_time = current_time_monotonic();
|
||||
} else {
|
||||
conn->maximum_speed_reached = 1;
|
||||
LOGGER_ERROR("send_data_packet failed\n");
|
||||
|
@ -936,7 +942,7 @@ static int send_request_packet(Net_Crypto *c, int crypt_connection_id)
|
|||
* return -1 on failure.
|
||||
* return number of packets sent on success.
|
||||
*/
|
||||
static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint16_t max_num)
|
||||
static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32_t max_num)
|
||||
{
|
||||
if (max_num == 0)
|
||||
return -1;
|
||||
|
@ -946,6 +952,7 @@ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint16
|
|||
if (conn == 0)
|
||||
return -1;
|
||||
|
||||
uint64_t temp_time = current_time_monotonic();
|
||||
uint32_t i, num_sent = 0, array_size = num_packets_array(&conn->send_array);
|
||||
|
||||
for (i = 0; i < array_size; ++i) {
|
||||
|
@ -959,13 +966,13 @@ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint16
|
|||
continue;
|
||||
}
|
||||
|
||||
if (dt->sent) {
|
||||
if (dt->sent_time) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, dt->data,
|
||||
dt->length) == 0) {
|
||||
dt->sent = 1;
|
||||
dt->sent_time = temp_time;
|
||||
++num_sent;
|
||||
}
|
||||
|
||||
|
@ -1439,10 +1446,10 @@ static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id,
|
|||
|
||||
if (source.ip.family == AF_INET || source.ip.family == AF_INET6) {
|
||||
if (!ipport_equal(&source, &conn->ip_port)) {
|
||||
if (!bs_list_add(&c->ip_port_list, &source, crypt_connection_id))
|
||||
if (!bs_list_add(&c->ip_port_list, (uint8_t *)&source, crypt_connection_id))
|
||||
return -1;
|
||||
|
||||
bs_list_remove(&c->ip_port_list, &conn->ip_port, crypt_connection_id);
|
||||
bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_port, crypt_connection_id);
|
||||
conn->ip_port = source;
|
||||
}
|
||||
|
||||
|
@ -1547,12 +1554,13 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c)
|
|||
return -1;
|
||||
|
||||
pthread_mutex_lock(&c->tcp_mutex);
|
||||
conn->connection_number_tcp = new_tcp_connection_to(c->tcp_c, n_c->dht_public_key, crypt_connection_id);
|
||||
int connection_number_tcp = new_tcp_connection_to(c->tcp_c, n_c->dht_public_key, crypt_connection_id);
|
||||
pthread_mutex_unlock(&c->tcp_mutex);
|
||||
|
||||
if (conn->connection_number_tcp == -1)
|
||||
if (connection_number_tcp == -1)
|
||||
return -1;
|
||||
|
||||
conn->connection_number_tcp = connection_number_tcp;
|
||||
memcpy(conn->public_key, n_c->public_key, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(conn->recv_nonce, n_c->recv_nonce, crypto_box_NONCEBYTES);
|
||||
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
|
|||
return -1;
|
||||
|
||||
pthread_mutex_lock(&c->tcp_mutex);
|
||||
conn->connection_number_tcp = new_tcp_connection_to(c->tcp_c, dht_public_key, crypt_connection_id);
|
||||
int connection_number_tcp = new_tcp_connection_to(c->tcp_c, dht_public_key, crypt_connection_id);
|
||||
pthread_mutex_unlock(&c->tcp_mutex);
|
||||
|
||||
if (conn->connection_number_tcp == -1)
|
||||
if (connection_number_tcp == -1)
|
||||
return -1;
|
||||
|
||||
conn->connection_number_tcp = connection_number_tcp;
|
||||
memcpy(conn->public_key, real_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
random_nonce(conn->sent_nonce);
|
||||
crypto_box_keypair(conn->sessionpublic_key, conn->sessionsecret_key);
|
||||
|
@ -1631,11 +1640,13 @@ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const u
|
|||
}
|
||||
|
||||
/* Set the direct ip of the crypto connection.
|
||||
*
|
||||
* Connected is 0 if we are not sure we are connected to that person, 1 if we are sure.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port)
|
||||
int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, _Bool connected)
|
||||
{
|
||||
Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
|
||||
|
||||
|
@ -1656,10 +1667,16 @@ int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (bs_list_add(&c->ip_port_list, &ip_port, crypt_connection_id)) {
|
||||
bs_list_remove(&c->ip_port_list, &conn->ip_port, crypt_connection_id);
|
||||
if (bs_list_add(&c->ip_port_list, (uint8_t *)&ip_port, crypt_connection_id)) {
|
||||
bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_port, crypt_connection_id);
|
||||
conn->ip_port = ip_port;
|
||||
conn->direct_lastrecv_time = 0;
|
||||
|
||||
if (connected) {
|
||||
conn->direct_lastrecv_time = unix_time();
|
||||
} else {
|
||||
conn->direct_lastrecv_time = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -1931,7 +1948,7 @@ int nc_dht_pk_callback(Net_Crypto *c, int crypt_connection_id, void (*function)(
|
|||
*/
|
||||
static int crypto_id_ip_port(const Net_Crypto *c, IP_Port ip_port)
|
||||
{
|
||||
return bs_list_find(&c->ip_port_list, &ip_port);
|
||||
return bs_list_find(&c->ip_port_list, (uint8_t *)&ip_port);
|
||||
}
|
||||
|
||||
#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
|
|||
/* Ratio of recv queue size / recv packet rate (in seconds) times
|
||||
* the number of ms between request packets to send at that ratio
|
||||
*/
|
||||
#define REQUEST_PACKETS_COMPARE_CONSTANT (0.5 * 100.0)
|
||||
#define REQUEST_PACKETS_COMPARE_CONSTANT (0.125 * 100.0)
|
||||
|
||||
/* Multiplier for maximum allowed resends. */
|
||||
#define PACKET_RESEND_MULTIPLIER 2
|
||||
|
||||
/* Timeout for increasing speed after congestion event (in ms). */
|
||||
#define CONGESTION_EVENT_TIMEOUT 4000
|
||||
|
||||
static void send_crypto_packets(Net_Crypto *c)
|
||||
{
|
||||
uint32_t i;
|
||||
|
@ -2061,7 +2085,11 @@ static void send_crypto_packets(Net_Crypto *c)
|
|||
double min_speed = 1000.0 * (((double)(total_sent)) / ((double)(CONGESTION_QUEUE_ARRAY_SIZE) *
|
||||
PACKET_COUNTER_AVERAGE_INTERVAL));
|
||||
|
||||
conn->packet_send_rate = min_speed * 1.2;
|
||||
if (conn->last_congestion_event + CONGESTION_EVENT_TIMEOUT < temp_time) {
|
||||
conn->packet_send_rate = min_speed * 1.2;
|
||||
} else {
|
||||
conn->packet_send_rate = min_speed;
|
||||
}
|
||||
|
||||
if (conn->packet_send_rate < CRYPTO_PACKET_MIN_RATE) {
|
||||
conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE;
|
||||
|
@ -2084,10 +2112,15 @@ static void send_crypto_packets(Net_Crypto *c)
|
|||
conn->last_packets_left_set = temp_time;
|
||||
}
|
||||
|
||||
int ret = send_requested_packets(c, i, conn->packets_left);
|
||||
int ret = send_requested_packets(c, i, conn->packets_left * PACKET_RESEND_MULTIPLIER);
|
||||
|
||||
if (ret != -1) {
|
||||
conn->packets_left -= ret;
|
||||
if (ret < conn->packets_left) {
|
||||
conn->packets_left -= ret;
|
||||
} else {
|
||||
conn->last_congestion_event = temp_time;
|
||||
conn->packets_left = 0;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
|||
kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp);
|
||||
pthread_mutex_unlock(&c->tcp_mutex);
|
||||
|
||||
bs_list_remove(&c->ip_port_list, &conn->ip_port, crypt_connection_id);
|
||||
bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_port, crypt_connection_id);
|
||||
clear_temp_packet(c, crypt_connection_id);
|
||||
clear_buffer(&conn->send_array);
|
||||
clear_buffer(&conn->recv_array);
|
||||
|
@ -2326,6 +2359,8 @@ void new_keys(Net_Crypto *c)
|
|||
|
||||
/* Save the public and private keys to the keys array.
|
||||
* Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES.
|
||||
*
|
||||
* TODO: Save only secret key.
|
||||
*/
|
||||
void save_keys(const Net_Crypto *c, uint8_t *keys)
|
||||
{
|
||||
|
@ -2333,13 +2368,13 @@ void save_keys(const Net_Crypto *c, uint8_t *keys)
|
|||
memcpy(keys + crypto_box_PUBLICKEYBYTES, c->self_secret_key, crypto_box_SECRETKEYBYTES);
|
||||
}
|
||||
|
||||
/* Load the public and private keys from the keys array.
|
||||
* Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES.
|
||||
/* Load the secret key.
|
||||
* Length must be crypto_box_SECRETKEYBYTES.
|
||||
*/
|
||||
void load_keys(Net_Crypto *c, const uint8_t *keys)
|
||||
void load_secret_key(Net_Crypto *c, const uint8_t *sk)
|
||||
{
|
||||
memcpy(c->self_public_key, keys, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(c->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES);
|
||||
memcpy(c->self_secret_key, sk, crypto_box_SECRETKEYBYTES);
|
||||
crypto_scalarmult_curve25519_base(c->self_public_key, c->self_secret_key);
|
||||
}
|
||||
|
||||
/* Run this to (re)initialize net_crypto.
|
||||
|
|
|
@ -82,8 +82,11 @@
|
|||
at the dT defined in net_crypto.c */
|
||||
#define CONGESTION_QUEUE_ARRAY_SIZE 24
|
||||
|
||||
/* Connection ping in ms. TODO: calculate it per connection. */
|
||||
#define DEFAULT_PING_CONNECTION 50
|
||||
|
||||
typedef struct {
|
||||
_Bool sent;
|
||||
uint64_t sent_time;
|
||||
uint16_t length;
|
||||
uint8_t data[MAX_CRYPTO_DATA_SIZE];
|
||||
} Packet_Data;
|
||||
|
@ -146,6 +149,7 @@ typedef struct {
|
|||
uint32_t last_sendqueue_size[CONGESTION_QUEUE_ARRAY_SIZE], last_sendqueue_counter;
|
||||
long signed int last_num_packets_sent[CONGESTION_QUEUE_ARRAY_SIZE];
|
||||
uint32_t packets_sent;
|
||||
uint64_t last_congestion_event;
|
||||
|
||||
/* TCP_connection connection_number */
|
||||
unsigned int connection_number_tcp;
|
||||
|
@ -223,11 +227,13 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c);
|
|||
int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const uint8_t *dht_public_key);
|
||||
|
||||
/* Set the direct ip of the crypto connection.
|
||||
*
|
||||
* Connected is 0 if we are not sure we are connected to that person, 1 if we are sure.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port);
|
||||
int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, _Bool connected);
|
||||
|
||||
/* Set function to be called when connection with crypt_connection_id goes connects/disconnects.
|
||||
*
|
||||
|
@ -378,10 +384,10 @@ void new_keys(Net_Crypto *c);
|
|||
*/
|
||||
void save_keys(const Net_Crypto *c, uint8_t *keys);
|
||||
|
||||
/* Load the public and private keys from the keys array.
|
||||
* Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES.
|
||||
/* Load the secret key.
|
||||
* Length must be crypto_box_SECRETKEYBYTES.
|
||||
*/
|
||||
void load_keys(Net_Crypto *c, const uint8_t *keys);
|
||||
void load_secret_key(Net_Crypto *c, const uint8_t *sk);
|
||||
|
||||
/* Create new instance of Net_Crypto.
|
||||
* Sets all the global connection variables to their default values.
|
||||
|
|
|
@ -813,7 +813,7 @@ void ipport_copy(IP_Port *target, const IP_Port *source)
|
|||
return;
|
||||
|
||||
memcpy(target, source, sizeof(IP_Port));
|
||||
};
|
||||
}
|
||||
|
||||
/* ip_ntoa
|
||||
* converts ip into a string
|
||||
|
|
|
@ -104,7 +104,7 @@ static int ipport_unpack(IP_Port *target, const uint8_t *data, unsigned int data
|
|||
|
||||
/* Create a new onion path.
|
||||
*
|
||||
* Create a new onion path out of nodes (nodes is a list of 3 nodes)
|
||||
* Create a new onion path out of nodes (nodes is a list of ONION_PATH_LENGTH nodes)
|
||||
*
|
||||
* new_path must be an empty memory location of atleast Onion_Path size.
|
||||
*
|
||||
|
@ -148,7 +148,7 @@ int create_onion_path(const DHT *dht, Onion_Path *new_path, const Node_format *n
|
|||
*/
|
||||
int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_Path *path)
|
||||
{
|
||||
if (num_nodes < 3)
|
||||
if (num_nodes < ONION_PATH_LENGTH)
|
||||
return -1;
|
||||
|
||||
nodes[0].ip_port = path->ip_port1;
|
||||
|
|
|
@ -53,6 +53,8 @@ typedef struct {
|
|||
#define ONION_MAX_DATA_SIZE (ONION_MAX_PACKET_SIZE - (ONION_SEND_1 + 1))
|
||||
#define ONION_RESPONSE_MAX_DATA_SIZE (ONION_MAX_PACKET_SIZE - (1 + ONION_RETURN_3))
|
||||
|
||||
#define ONION_PATH_LENGTH 3
|
||||
|
||||
typedef struct {
|
||||
uint8_t shared_key1[crypto_box_BEFORENMBYTES];
|
||||
uint8_t shared_key2[crypto_box_BEFORENMBYTES];
|
||||
|
@ -76,7 +78,7 @@ typedef struct {
|
|||
|
||||
/* Create a new onion path.
|
||||
*
|
||||
* Create a new onion path out of nodes (nodes is a list of 3 nodes)
|
||||
* Create a new onion path out of nodes (nodes is a list of ONION_PATH_LENGTH nodes)
|
||||
*
|
||||
* new_path must be an empty memory location of atleast Onion_Path size.
|
||||
*
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
#include "onion.h"
|
||||
|
||||
#define ONION_ANNOUNCE_MAX_ENTRIES 64
|
||||
#define ONION_ANNOUNCE_MAX_ENTRIES 96
|
||||
#define ONION_ANNOUNCE_TIMEOUT 300
|
||||
#define ONION_PING_ID_SIZE crypto_hash_sha256_BYTES
|
||||
|
||||
|
|
|
@ -190,7 +190,7 @@ static int is_path_used(const Onion_Client_Paths *onion_paths, const Node_format
|
|||
continue;
|
||||
}
|
||||
|
||||
if (ipport_equal(&onion_paths->paths[i].ip_port1, &nodes[2].ip_port)) {
|
||||
if (ipport_equal(&onion_paths->paths[i].ip_port1, &nodes[ONION_PATH_LENGTH - 1].ip_port)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -215,9 +215,9 @@ static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_pa
|
|||
if ((onion_paths->last_path_success[pathnum] + ONION_PATH_TIMEOUT < onion_paths->last_path_used[pathnum]
|
||||
&& onion_paths->last_path_used_times[pathnum] >= ONION_PATH_MAX_NO_RESPONSE_USES)
|
||||
|| is_timeout(onion_paths->path_creation_time[pathnum], ONION_PATH_MAX_LIFETIME)) {
|
||||
Node_format nodes[3];
|
||||
Node_format nodes[ONION_PATH_LENGTH];
|
||||
|
||||
if (random_nodes_path_onion(onion_c, nodes, 3) != 3)
|
||||
if (random_nodes_path_onion(onion_c, nodes, ONION_PATH_LENGTH) != ONION_PATH_LENGTH)
|
||||
return -1;
|
||||
|
||||
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
|
|||
onion_paths->last_path_success[path_num % NUMBER_ONION_PATHS] = unix_time();
|
||||
onion_paths->last_path_used_times[path_num % NUMBER_ONION_PATHS] = 0;
|
||||
|
||||
unsigned int path_len = 3;
|
||||
Node_format nodes[path_len];
|
||||
Node_format nodes[ONION_PATH_LENGTH];
|
||||
|
||||
if (onion_path_to_nodes(nodes, path_len, &onion_paths->paths[path_num % NUMBER_ONION_PATHS]) == 0) {
|
||||
if (onion_path_to_nodes(nodes, ONION_PATH_LENGTH, &onion_paths->paths[path_num % NUMBER_ONION_PATHS]) == 0) {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < path_len; ++i) {
|
||||
for (i = 0; i < ONION_PATH_LENGTH; ++i) {
|
||||
onion_add_path_node(onion_c, nodes[i].ip_port, nodes[i].public_key);
|
||||
}
|
||||
}
|
||||
|
@ -1205,7 +1204,7 @@ static void populate_path_nodes_tcp(Onion_Client *onion_c)
|
|||
unsigned int i;
|
||||
|
||||
for (i = 0; i < num_nodes; ++i) {
|
||||
onion_add_path_node(onion_c, nodes_list[i].ip_port, nodes_list[i].public_key);
|
||||
onion_add_bs_path_node(onion_c, nodes_list[i].ip_port, nodes_list[i].public_key);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -304,16 +304,18 @@ void do_to_ping(PING *ping)
|
|||
if (!ip_isset(&ping->to_ping[0].ip_port.ip))
|
||||
return;
|
||||
|
||||
ping->last_to_ping = unix_time();
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < MAX_TO_PING; ++i) {
|
||||
if (!ip_isset(&ping->to_ping[i].ip_port.ip))
|
||||
return;
|
||||
break;
|
||||
|
||||
send_ping_request(ping, ping->to_ping[i].ip_port, ping->to_ping[i].public_key);
|
||||
ip_reset(&ping->to_ping[i].ip_port.ip);
|
||||
}
|
||||
|
||||
if (i != 0)
|
||||
ping->last_to_ping = unix_time();
|
||||
}
|
||||
|
||||
|
||||
|
|
134
toxcore/tox.c
134
toxcore/tox.c
|
@ -152,6 +152,7 @@ Tox *tox_new(const struct Tox_Options *options, const uint8_t *data, size_t leng
|
|||
m_options.udp_disabled = !options->udp_enabled;
|
||||
m_options.port_range[0] = options->start_port;
|
||||
m_options.port_range[1] = options->end_port;
|
||||
m_options.tcp_server_port = options->tcp_port;
|
||||
|
||||
switch (options->proxy_type) {
|
||||
case TOX_PROXY_TYPE_HTTP:
|
||||
|
@ -238,31 +239,6 @@ void tox_get_savedata(const Tox *tox, uint8_t *data)
|
|||
}
|
||||
}
|
||||
|
||||
static int address_to_ip(Messenger *m, const char *address, IP_Port *ip_port, IP_Port *ip_port_v4)
|
||||
{
|
||||
if (!addr_parse_ip(address, &ip_port->ip)) {
|
||||
if (m->options.udp_disabled) { /* Disable DNS when udp is disabled. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
IP *ip_extra = NULL;
|
||||
ip_init(&ip_port->ip, m->options.ipv6enabled);
|
||||
|
||||
if (m->options.ipv6enabled && ip_port_v4) {
|
||||
/* setup for getting BOTH: an IPv6 AND an IPv4 address */
|
||||
ip_port->ip.family = AF_UNSPEC;
|
||||
ip_reset(&ip_port_v4->ip);
|
||||
ip_extra = &ip_port_v4->ip;
|
||||
}
|
||||
|
||||
if (!addr_resolve(address, &ip_port->ip, ip_extra)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool tox_bootstrap(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error)
|
||||
{
|
||||
if (!address || !public_key) {
|
||||
|
@ -270,23 +246,53 @@ bool tox_bootstrap(Tox *tox, const char *address, uint16_t port, const uint8_t *
|
|||
return 0;
|
||||
}
|
||||
|
||||
Messenger *m = tox;
|
||||
bool ret = tox_add_tcp_relay(tox, address, port, public_key, error);
|
||||
|
||||
if (!ret) {
|
||||
if (port == 0) {
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_PORT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (m->options.udp_disabled) {
|
||||
return ret;
|
||||
} else { /* DHT only works on UDP. */
|
||||
if (DHT_bootstrap_from_address(m->dht, address, m->options.ipv6enabled, htons(port), public_key) == 0) {
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
|
||||
return 0;
|
||||
struct addrinfo *root, *info;
|
||||
|
||||
if (getaddrinfo(address, NULL, NULL, &root) != 0) {
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
info = root;
|
||||
|
||||
unsigned int count = 0;
|
||||
|
||||
do {
|
||||
IP_Port ip_port;
|
||||
ip_port.port = htons(port);
|
||||
ip_port.ip.family = info->ai_family;
|
||||
|
||||
if (info->ai_socktype && info->ai_socktype != SOCK_DGRAM) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (info->ai_family == AF_INET) {
|
||||
ip_port.ip.ip4.in_addr = ((struct sockaddr_in *)info->ai_addr)->sin_addr;
|
||||
} else if (info->ai_family == AF_INET6) {
|
||||
ip_port.ip.ip6.in6_addr = ((struct sockaddr_in6 *)info->ai_addr)->sin6_addr;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
Messenger *m = tox;
|
||||
onion_add_bs_path_node(m->onion_c, ip_port, public_key);
|
||||
DHT_bootstrap(m->dht, ip_port, public_key);
|
||||
++count;
|
||||
} while ((info = info->ai_next));
|
||||
|
||||
freeaddrinfo(root);
|
||||
|
||||
if (count) {
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK);
|
||||
return 1;
|
||||
} else {
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -298,25 +304,53 @@ bool tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8
|
|||
return 0;
|
||||
}
|
||||
|
||||
Messenger *m = tox;
|
||||
IP_Port ip_port, ip_port_v4;
|
||||
|
||||
if (port == 0) {
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_PORT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (address_to_ip(m, address, &ip_port, &ip_port_v4) == -1) {
|
||||
struct addrinfo *root, *info;
|
||||
|
||||
if (getaddrinfo(address, NULL, NULL, &root) != 0) {
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ip_port.port = htons(port);
|
||||
add_tcp_relay(m->net_crypto, ip_port, public_key);
|
||||
onion_add_bs_path_node(m->onion_c, ip_port, public_key); //TODO: move this
|
||||
info = root;
|
||||
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK);
|
||||
return 1;
|
||||
unsigned int count = 0;
|
||||
|
||||
do {
|
||||
IP_Port ip_port;
|
||||
ip_port.port = htons(port);
|
||||
ip_port.ip.family = info->ai_family;
|
||||
|
||||
if (info->ai_socktype && info->ai_socktype != SOCK_STREAM) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (info->ai_family == AF_INET) {
|
||||
ip_port.ip.ip4.in_addr = ((struct sockaddr_in *)info->ai_addr)->sin_addr;
|
||||
} else if (info->ai_family == AF_INET6) {
|
||||
ip_port.ip.ip6.in6_addr = ((struct sockaddr_in6 *)info->ai_addr)->sin6_addr;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
Messenger *m = tox;
|
||||
add_tcp_relay(m->net_crypto, ip_port, public_key);
|
||||
++count;
|
||||
} while ((info = info->ai_next));
|
||||
|
||||
freeaddrinfo(root);
|
||||
|
||||
if (count) {
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK);
|
||||
return 1;
|
||||
} else {
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
|||
|
||||
uint16_t tox_self_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error)
|
||||
{
|
||||
/* TCP server not yet implemented in clients. */
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND);
|
||||
return 0;
|
||||
const Messenger *m = tox;
|
||||
|
||||
if (m->tcp_server) {
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK);
|
||||
return m->options.tcp_server_port;
|
||||
} else {
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#include "tox_old_code.h"
|
||||
|
|
|
@ -426,6 +426,12 @@ struct Tox_Options {
|
|||
*/
|
||||
uint16_t end_port;
|
||||
|
||||
|
||||
/**
|
||||
* The port to use for the TCP server. If 0, the tcp server is disabled.
|
||||
*/
|
||||
uint16_t tcp_port;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -160,25 +160,14 @@ static int decode(uint8_t *dest, uint8_t *src)
|
|||
while (*p) {
|
||||
uint8_t ch = *p++;
|
||||
|
||||
switch (ch) {
|
||||
case 'A' ... 'Z': {
|
||||
ch = ch - 'A';
|
||||
break;
|
||||
}
|
||||
|
||||
case 'a' ... 'z': {
|
||||
ch = ch - 'a';
|
||||
break;
|
||||
}
|
||||
|
||||
case '0' ... '5': {
|
||||
ch = ch - '0' + 26;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
return - 1;
|
||||
}
|
||||
if ('A' <= ch && ch <= 'Z') {
|
||||
ch = ch - 'A';
|
||||
} else if ('a' <= ch && ch <= 'z') {
|
||||
ch = ch - 'a';
|
||||
} else if ('0' <= ch && ch <= '5') {
|
||||
ch = ch - '0' + 26;
|
||||
} else {
|
||||
return - 1;
|
||||
}
|
||||
|
||||
*op |= (ch << bits);
|
||||
|
|
Loading…
Reference in New Issue
Block a user