Updated with master

This commit is contained in:
mannol 2015-05-22 23:22:31 +02:00
commit 3100042a2b
40 changed files with 1354 additions and 741 deletions

View File

@ -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;
}

View File

@ -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");
}

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -622,4 +622,4 @@ namespace video {
}
%{
#endif
%}
%}

View File

@ -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) {

View File

@ -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)) {

View File

@ -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, &copy_groupmessage, 0);
tox_callback_group_action(tox, &copy_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);

View File

@ -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);

View File

@ -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.
*/

View File

@ -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 )

View File

@ -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;

View File

@ -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);
}
/*******************************************************************************
*

File diff suppressed because it is too large Load Diff

View File

@ -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);
}

View File

@ -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.
*/

View File

@ -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)

View File

@ -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;

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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;

View File

@ -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 {

View File

@ -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

View File

@ -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. */
}
}

View File

@ -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;

View File

@ -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);

View File

@ -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
*

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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.
*

View File

@ -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

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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"

View File

@ -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;
};

View File

@ -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);