Rebased on master and removed alpha channel (again)

This commit is contained in:
mannol 2015-06-05 22:14:37 +02:00
commit d694839d60
25 changed files with 373 additions and 335 deletions

View File

@ -2,6 +2,9 @@
- [Installation](#installation) - [Installation](#installation)
- [Unix like](#unix) - [Unix like](#unix)
- [Quick install](#quick-install)
- [Build manually](#build-manually)
- [Compile toxcore](#compile-toxcore)
- [OS X](#osx) - [OS X](#osx)
- [Homebrew](#homebrew) - [Homebrew](#homebrew)
- [Non-Homebrew](#non-homebrew) - [Non-Homebrew](#non-homebrew)
@ -24,16 +27,33 @@
<a name="unix" /> <a name="unix" />
###Most Unix like OSes: ###Most Unix like OSes:
#### Quick install:
On Gentoo:
```
# layman -f && layman -a tox-overlay && emerge net-libs/tox
```
And you're done `:)`</br>
If you happen to run some other distro which isn't made for compiling, there are steps below:
#### Build manually
Build dependencies: Build dependencies:
Note: package fetching commands may vary by OS. Note: package fetching commands may vary by OS.
On Ubuntu: On Ubuntu `< 15.04` / Debian `< 8`:
```bash ```bash
sudo apt-get install build-essential libtool autotools-dev automake checkinstall check git yasm sudo apt-get install build-essential libtool autotools-dev automake checkinstall check git yasm
``` ```
On Ubuntu `>= 15.04` / Debian `>= 8`:
```bash
sudo apt-get install build-essential libtool autotools-dev automake checkinstall check git yasm libsodium13 libsodium-dev
```
On Fedora: On Fedora:
```bash ```bash
@ -55,7 +75,7 @@ Note, if you install from ports select NaCl for performance, and sodium if you w
**For A/V support, also install the dependences listed in the [libtoxav] (#libtoxav) section.** **For A/V support, also install the dependences listed in the [libtoxav] (#libtoxav) section.**
You should get and install [libsodium](https://github.com/jedisct1/libsodium): You should get and install [libsodium](https://github.com/jedisct1/libsodium). If you have installed `libsodium` from repo, ommit this step, and jump directly to [compiling toxcore](#compile-toxcore):
```bash ```bash
git clone git://github.com/jedisct1/libsodium.git git clone git://github.com/jedisct1/libsodium.git
cd libsodium cd libsodium
@ -88,7 +108,9 @@ echo '/usr/local/lib/' | sudo tee -a /etc/ld.so.conf.d/locallib.conf
sudo ldconfig sudo ldconfig
``` ```
Then clone this repo and generate makefile: ##### Compile toxcore
Then clone this repo, generate makefile, and install `toxcore` system-wide:
```bash ```bash
git clone git://github.com/irungentoo/toxcore.git git clone git://github.com/irungentoo/toxcore.git
cd toxcore cd toxcore

View File

@ -22,9 +22,9 @@ EXTRA_DIST = \
$(top_srcdir)/docs/updates/Crypto.md \ $(top_srcdir)/docs/updates/Crypto.md \
$(top_srcdir)/docs/updates/Spam-Prevention.md \ $(top_srcdir)/docs/updates/Spam-Prevention.md \
$(top_srcdir)/docs/updates/Symmetric-NAT-Transversal.md \ $(top_srcdir)/docs/updates/Symmetric-NAT-Transversal.md \
$(top_srcdir)/tools/README \ $(top_srcdir)/other/astyle/README \
$(top_srcdir)/tools/astylerc \ $(top_srcdir)/other/astyle/astylerc \
$(top_srcdir)/tools/pre-commit $(top_srcdir)/other/astyle/pre-commit
if BUILD_AV if BUILD_AV

View File

@ -55,8 +55,8 @@ END_TEST
START_TEST(test_save_friend) START_TEST(test_save_friend)
{ {
Tox *tox1 = tox_new(0, 0, 0, 0); Tox *tox1 = tox_new(0, 0);
Tox *tox2 = tox_new(0, 0, 0, 0); Tox *tox2 = tox_new(0, 0);
ck_assert_msg(tox1 || tox2, "Failed to create 2 tox instances"); ck_assert_msg(tox1 || tox2, "Failed to create 2 tox instances");
uint32_t to_compare = 974536; uint32_t to_compare = 974536;
tox_callback_friend_request(tox2, accept_friend_request, &to_compare); tox_callback_friend_request(tox2, accept_friend_request, &to_compare);
@ -75,15 +75,23 @@ START_TEST(test_save_friend)
ck_assert_msg(ret, "failed to encrypted save: %u", error1); ck_assert_msg(ret, "failed to encrypted save: %u", error1);
ck_assert_msg(tox_is_data_encrypted(enc_data), "magic number missing"); ck_assert_msg(tox_is_data_encrypted(enc_data), "magic number missing");
struct Tox_Options options;
tox_options_default(&options);
options.savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE;
options.savedata_data = enc_data;
options.savedata_length = size2;
TOX_ERR_NEW err2; TOX_ERR_NEW err2;
Tox *tox3 = tox_new(0, enc_data, size2, &err2); Tox *tox3 = tox_new(&options, &err2);
ck_assert_msg(err2 == TOX_ERR_NEW_LOAD_ENCRYPTED, "wrong error! %u. should fail with %u", err2, ck_assert_msg(err2 == TOX_ERR_NEW_LOAD_ENCRYPTED, "wrong error! %u. should fail with %u", err2,
TOX_ERR_NEW_LOAD_ENCRYPTED); TOX_ERR_NEW_LOAD_ENCRYPTED);
uint8_t dec_data[size]; uint8_t dec_data[size];
TOX_ERR_DECRYPTION err3; TOX_ERR_DECRYPTION err3;
ret = tox_pass_decrypt(enc_data, size2, "correcthorsebatterystaple", 25, dec_data, &err3); ret = tox_pass_decrypt(enc_data, size2, "correcthorsebatterystaple", 25, dec_data, &err3);
ck_assert_msg(ret, "failed to decrypt save: %u", err3); ck_assert_msg(ret, "failed to decrypt save: %u", err3);
tox3 = tox_new(0, dec_data, size, &err2); options.savedata_data = dec_data;
options.savedata_length = size;
tox3 = tox_new(&options, &err2);
ck_assert_msg(err2 == TOX_ERR_NEW_OK, "failed to load from decrypted data: %u", err2); ck_assert_msg(err2 == TOX_ERR_NEW_OK, "failed to load from decrypted data: %u", err2);
uint8_t address2[TOX_PUBLIC_KEY_SIZE]; uint8_t address2[TOX_PUBLIC_KEY_SIZE];
ret = tox_friend_get_public_key(tox3, 0, address2, 0); ret = tox_friend_get_public_key(tox3, 0, address2, 0);
@ -111,7 +119,9 @@ START_TEST(test_save_friend)
// and now with the code in use (I only bothered with manually to debug this, and it seems a waste // and now with the code in use (I only bothered with manually to debug this, and it seems a waste
// to remove the manual check now that it's there) // to remove the manual check now that it's there)
Tox *tox4 = tox_new(0, out1, size, &err2); options.savedata_data = out1;
options.savedata_length = size;
Tox *tox4 = tox_new(&options, &err2);
ck_assert_msg(err2 == TOX_ERR_NEW_OK, "failed to new the third"); ck_assert_msg(err2 == TOX_ERR_NEW_OK, "failed to new the third");
uint8_t address5[TOX_PUBLIC_KEY_SIZE]; uint8_t address5[TOX_PUBLIC_KEY_SIZE];
ret = tox_friend_get_public_key(tox4, 0, address5, 0); ret = tox_friend_get_public_key(tox4, 0, address5, 0);
@ -154,6 +164,10 @@ START_TEST(test_keys)
ck_assert_msg(ret, "generic failure 5: %u", decerr); ck_assert_msg(ret, "generic failure 5: %u", decerr);
ck_assert_msg(memcmp(out2, string, 44) == 0, "decryption 2 failed"); ck_assert_msg(memcmp(out2, string, 44) == 0, "decryption 2 failed");
ret = tox_pass_decrypt(encrypted2, 44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH, NULL, 0, out2, &decerr);
ck_assert_msg(!ret, "Decrypt succeeded with wrong pass");
ck_assert_msg(decerr != TOX_ERR_DECRYPTION_FAILED, "Bad error code %u", decerr);
// test that pass_decrypt can decrypt things from pass_key_encrypt // test that pass_decrypt can decrypt things from pass_key_encrypt
ret = tox_pass_decrypt(encrypted, 44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH, "123qweasdzxc", 12, out1, &decerr); ret = tox_pass_decrypt(encrypted, 44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH, "123qweasdzxc", 12, out1, &decerr);
ck_assert_msg(ret, "generic failure 6: %u", decerr); ck_assert_msg(ret, "generic failure 6: %u", decerr);

View File

@ -286,8 +286,8 @@ void tox_connection_status(Tox *tox, TOX_CONNECTION connection_status, void *use
START_TEST(test_one) START_TEST(test_one)
{ {
Tox *tox1 = tox_new(0, 0, 0, 0); Tox *tox1 = tox_new(0, 0);
Tox *tox2 = tox_new(0, 0, 0, 0); Tox *tox2 = tox_new(0, 0);
{ {
TOX_ERR_GET_PORT error; TOX_ERR_GET_PORT error;
@ -340,7 +340,12 @@ START_TEST(test_one)
tox_kill(tox2); tox_kill(tox2);
TOX_ERR_NEW err_n; TOX_ERR_NEW err_n;
tox2 = tox_new(0, data, save_size, &err_n); struct Tox_Options options;
tox_options_default(&options);
options.savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE;
options.savedata_data = data;
options.savedata_length = save_size;
tox2 = tox_new(&options, &err_n);
ck_assert_msg(err_n == TOX_ERR_NEW_OK, "Load failed"); ck_assert_msg(err_n == TOX_ERR_NEW_OK, "Load failed");
ck_assert_msg(tox_self_get_name_size(tox2) == sizeof name, "Wrong name size."); ck_assert_msg(tox_self_get_name_size(tox2) == sizeof name, "Wrong name size.");
@ -352,6 +357,23 @@ START_TEST(test_one)
tox_self_get_name(tox2, new_name); tox_self_get_name(tox2, new_name);
ck_assert_msg(memcmp(name, new_name, TOX_MAX_NAME_LENGTH) == 0, "Wrong name"); ck_assert_msg(memcmp(name, new_name, TOX_MAX_NAME_LENGTH) == 0, "Wrong name");
uint8_t sk[TOX_SECRET_KEY_SIZE];
tox_self_get_secret_key(tox2, sk);
tox_kill(tox2);
tox_options_default(&options);
options.savedata_type = TOX_SAVEDATA_TYPE_SECRET_KEY;
options.savedata_data = sk;
options.savedata_length = sizeof(sk);
tox2 = tox_new(&options, &err_n);
ck_assert_msg(err_n == TOX_ERR_NEW_OK, "Load failed");
uint8_t address3[TOX_ADDRESS_SIZE];
tox_self_get_address(tox2, address3);
ck_assert_msg(memcmp(address3, address, TOX_PUBLIC_KEY_SIZE) == 0, "Wrong public key.");
uint8_t pk[TOX_PUBLIC_KEY_SIZE];
tox_self_get_public_key(tox2, pk);
ck_assert_msg(memcmp(pk, address, TOX_PUBLIC_KEY_SIZE) == 0, "Wrong public key.");
tox_kill(tox1); tox_kill(tox1);
tox_kill(tox2); tox_kill(tox2);
} }
@ -361,11 +383,11 @@ START_TEST(test_few_clients)
{ {
long long unsigned int con_time, cur_time = time(NULL); long long unsigned int con_time, cur_time = time(NULL);
TOX_ERR_NEW t_n_error; TOX_ERR_NEW t_n_error;
Tox *tox1 = tox_new(0, 0, 0, &t_n_error); Tox *tox1 = tox_new(0, &t_n_error);
ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "wrong error"); ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "wrong error");
Tox *tox2 = tox_new(0, 0, 0, &t_n_error); Tox *tox2 = tox_new(0, &t_n_error);
ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "wrong error"); ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "wrong error");
Tox *tox3 = tox_new(0, 0, 0, &t_n_error); Tox *tox3 = tox_new(0, &t_n_error);
ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "wrong error"); ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "wrong error");
ck_assert_msg(tox1 || tox2 || tox3, "Failed to create 3 tox instances"); ck_assert_msg(tox1 || tox2 || tox3, "Failed to create 3 tox instances");
@ -745,7 +767,7 @@ START_TEST(test_many_clients)
uint32_t to_comp = 974536; uint32_t to_comp = 974536;
for (i = 0; i < NUM_TOXES; ++i) { for (i = 0; i < NUM_TOXES; ++i) {
toxes[i] = tox_new(0, 0, 0, 0); toxes[i] = tox_new(0, 0);
ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i); ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i);
tox_callback_friend_request(toxes[i], accept_friend_request, &to_comp); tox_callback_friend_request(toxes[i], accept_friend_request, &to_comp);
} }
@ -832,7 +854,7 @@ START_TEST(test_many_clients_tcp)
opts.udp_enabled = 0; opts.udp_enabled = 0;
} }
toxes[i] = tox_new(&opts, 0, 0, 0); toxes[i] = tox_new(&opts, 0);
ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i); ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i);
tox_callback_friend_request(toxes[i], accept_friend_request, &to_comp); tox_callback_friend_request(toxes[i], accept_friend_request, &to_comp);
uint8_t dpk[TOX_PUBLIC_KEY_SIZE]; uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
@ -926,7 +948,7 @@ START_TEST(test_many_clients_tcp_b)
opts.udp_enabled = 0; opts.udp_enabled = 0;
} }
toxes[i] = tox_new(&opts, 0, 0, 0); toxes[i] = tox_new(&opts, 0);
ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i); ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i);
tox_callback_friend_request(toxes[i], accept_friend_request, &to_comp); tox_callback_friend_request(toxes[i], accept_friend_request, &to_comp);
uint8_t dpk[TOX_PUBLIC_KEY_SIZE]; uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
@ -1062,7 +1084,7 @@ START_TEST(test_many_group)
uint32_t to_comp = 234212; uint32_t to_comp = 234212;
for (i = 0; i < NUM_GROUP_TOX; ++i) { for (i = 0; i < NUM_GROUP_TOX; ++i) {
toxes[i] = tox_new(0, 0, 0, 0); toxes[i] = tox_new(0, 0);
ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i); ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i);
tox_callback_friend_request(toxes[i], &g_accept_friend_request, &to_comp); tox_callback_friend_request(toxes[i], &g_accept_friend_request, &to_comp);
tox_callback_group_invite(toxes[i], &print_group_invite_callback, &to_comp); tox_callback_group_invite(toxes[i], &print_group_invite_callback, &to_comp);
@ -1189,7 +1211,7 @@ Suite *tox_suite(void)
DEFTESTCASE(one); DEFTESTCASE(one);
DEFTESTCASE_SLOW(few_clients, 50); DEFTESTCASE_SLOW(few_clients, 50);
DEFTESTCASE_SLOW(many_clients, 150); DEFTESTCASE_SLOW(many_clients, 80);
DEFTESTCASE_SLOW(many_clients_tcp, 20); DEFTESTCASE_SLOW(many_clients_tcp, 20);
DEFTESTCASE_SLOW(many_clients_tcp_b, 20); DEFTESTCASE_SLOW(many_clients_tcp_b, 20);
DEFTESTCASE_SLOW(many_group, 100); DEFTESTCASE_SLOW(many_group, 100);

View File

@ -131,13 +131,13 @@ START_TEST(test_AV_flows)
{ {
TOX_ERR_NEW error; TOX_ERR_NEW error;
bootstrap = tox_new(NULL, NULL, 0, &error); bootstrap = tox_new(NULL, &error);
ck_assert(error == TOX_ERR_NEW_OK); ck_assert(error == TOX_ERR_NEW_OK);
Alice = tox_new(NULL, NULL, 0, &error); Alice = tox_new(NULL, &error);
ck_assert(error == TOX_ERR_NEW_OK); ck_assert(error == TOX_ERR_NEW_OK);
Bob = tox_new(NULL, NULL, 0, &error); Bob = tox_new(NULL, &error);
ck_assert(error == TOX_ERR_NEW_OK); ck_assert(error == TOX_ERR_NEW_OK);
} }

View File

@ -56,9 +56,7 @@ void t_toxav_call_cb(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool
} }
void t_toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_data) void t_toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_data)
{ {
(void) av; printf("Handling CALL STATE callback: %d %p\n", state, av);
printf("Handling CALL STATE callback: %d\n", state);
((CallControl*)user_data)[friend_number].state = state; ((CallControl*)user_data)[friend_number].state = state;
} }
void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number, void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number,
@ -188,7 +186,7 @@ void* call_thread(void* pd)
toxav_call_control(AliceAV, friend_number, TOXAV_CALL_CONTROL_CANCEL, &rc); toxav_call_control(AliceAV, friend_number, TOXAV_CALL_CONTROL_CANCEL, &rc);
if (rc != TOXAV_ERR_CALL_CONTROL_OK) { if (rc != TOXAV_ERR_CALL_CONTROL_OK) {
printf("toxav_call_control failed: %d\n", rc); printf("toxav_call_control failed: %d %p %p\n", rc, AliceAV, BobAV);
ck_assert(0); ck_assert(0);
} }
} }
@ -210,19 +208,19 @@ START_TEST(test_AV_three_calls)
{ {
TOX_ERR_NEW error; TOX_ERR_NEW error;
bootstrap = tox_new(NULL, NULL, 0, &error); bootstrap = tox_new(NULL, &error);
ck_assert(error == TOX_ERR_NEW_OK); ck_assert(error == TOX_ERR_NEW_OK);
Alice = tox_new(NULL, NULL, 0, &error); Alice = tox_new(NULL, &error);
ck_assert(error == TOX_ERR_NEW_OK); ck_assert(error == TOX_ERR_NEW_OK);
Bobs[0] = tox_new(NULL, NULL, 0, &error); Bobs[0] = tox_new(NULL, &error);
ck_assert(error == TOX_ERR_NEW_OK); ck_assert(error == TOX_ERR_NEW_OK);
Bobs[1] = tox_new(NULL, NULL, 0, &error); Bobs[1] = tox_new(NULL, &error);
ck_assert(error == TOX_ERR_NEW_OK); ck_assert(error == TOX_ERR_NEW_OK);
Bobs[2] = tox_new(NULL, NULL, 0, &error); Bobs[2] = tox_new(NULL, &error);
ck_assert(error == TOX_ERR_NEW_OK); ck_assert(error == TOX_ERR_NEW_OK);
} }

View File

@ -340,6 +340,24 @@ enum class PROXY_TYPE {
SOCKS5, SOCKS5,
} }
/**
* Type of savedata to create the Tox instance from.
*/
enum class SAVEDATA_TYPE {
/**
* No savedata.
*/
NONE,
/**
* Savedata is one that was obtained from ${savedata.get}
*/
TOX_SAVE,
/**
* Savedata is a secret key of length ${SECRET_KEY_SIZE}
*/
SECRET_KEY,
}
static class options { static class options {
/** /**
@ -416,6 +434,23 @@ static class options {
* The port to use for the TCP server. If 0, the tcp server is disabled. * The port to use for the TCP server. If 0, the tcp server is disabled.
*/ */
uint16_t tcp_port; uint16_t tcp_port;
namespace savedata {
/**
* The type of savedata to load from.
*/
SAVEDATA_TYPE type;
/**
* The savedata.
*/
const uint8_t[length] data;
/**
* The length of the savedata.
*/
size_t length;
}
} }
@ -474,21 +509,17 @@ static class options {
* This function will bring the instance into a valid state. Running the event * This function will bring the instance into a valid state. Running the event
* loop with a new instance will operate correctly. * loop with a new instance will operate correctly.
* *
* If the data parameter is not NULL, this function will load the Tox instance
* from a byte array previously filled by ${savedata.get}.
*
* If loading failed or succeeded only partially, the new or partially loaded * If loading failed or succeeded only partially, the new or partially loaded
* instance is returned and an error code is set. * instance is returned and an error code is set.
* *
* @param options An options object as described above. If this parameter is * @param options An options object as described above. If this parameter is
* NULL, the default options are used. * NULL, the default options are used.
* @param data A byte array containing data previously stored by ${savedata.get}.
* @param length The length of the byte array data. If this parameter is 0, the
* data parameter is ignored.
* *
* @see $iterate for the event loop. * @see $iterate for the event loop.
*
* @return A new Tox instance pointer on success or NULL on failure.
*/ */
static this new(const options_t *options, const uint8_t[length] data) { static this new(const options_t *options) {
NULL, NULL,
/** /**
* The function was unable to allocate enough memory to store the internal * The function was unable to allocate enough memory to store the internal
@ -580,13 +611,8 @@ uint8_t[size] savedata {
* Sends a "get nodes" request to the given bootstrap node with IP, port, and * Sends a "get nodes" request to the given bootstrap node with IP, port, and
* public key to setup connections. * public key to setup connections.
* *
* This function will attempt to connect to the node using UDP and TCP at the * This function will attempt to connect to the node using UDP. You must use
* same time. * this function even if ${options.this.udp_enabled} was set to false.
*
* Tox will use the node as a TCP relay in case ${options.this.udp_enabled} was
* false, and also to connect to friends that are in TCP-only mode. Tox will
* also use the TCP connection when NAT hole punching is slow, and later switch
* to UDP if hole punching succeeds.
* *
* @param address The hostname or IP address (IPv4 or IPv6) of the node. * @param address The hostname or IP address (IPv4 or IPv6) of the node.
* @param port The port on the host on which the bootstrap Tox instance is * @param port The port on the host on which the bootstrap Tox instance is
@ -1481,7 +1507,7 @@ namespace file {
*/ */
DATA, DATA,
/** /**
* Avatar filename. This consists of $hash(image). * Avatar file_id. This consists of $hash(image).
* Avatar data. This consists of the image data. * Avatar data. This consists of the image data.
* *
* Avatars can be sent at any time the client wishes. Generally, a client will * Avatars can be sent at any time the client wishes. Generally, a client will
@ -1625,6 +1651,7 @@ namespace file {
error for get { error for get {
NULL,
/** /**
* The friend_number passed did not designate a valid friend. * The friend_number passed did not designate a valid friend.
*/ */

View File

@ -562,10 +562,9 @@ namespace video {
* @param y Y (Luminance) plane data. * @param y Y (Luminance) plane data.
* @param u U (Chroma) plane data. * @param u U (Chroma) plane data.
* @param v V (Chroma) plane data. * @param v V (Chroma) plane data.
* @param a A (Alpha) plane data.
*/ */
bool send_frame(uint32_t friend_number, uint16_t width, uint16_t height, bool send_frame(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) with error for send_frame; const uint8_t *y, const uint8_t *u, const uint8_t *v) with error for send_frame;
} }
/******************************************************************************* /*******************************************************************************
* *
@ -603,19 +602,17 @@ namespace video {
* Y = MAX(width, abs(ystride)) * height, * Y = MAX(width, abs(ystride)) * height,
* U = MAX(width/2, abs(ustride)) * (height/2) and * U = MAX(width/2, abs(ustride)) * (height/2) and
* V = MAX(width/2, abs(vstride)) * (height/2). * V = MAX(width/2, abs(vstride)) * (height/2).
* A = MAX(width, abs(astride)) * height.
* @param ystride * @param ystride
* @param ustride * @param ustride
* @param vstride * @param vstride Strides data. Strides represent padding for each plane
* @param astride Strides data. Strides represent padding for each plane
* that may or may not be present. You must handle strides in * that may or may not be present. You must handle strides in
* your image processing code. Strides are negative if the * your image processing code. Strides are negative if the
* image is bottom-up hence why you MUST abs() it when * image is bottom-up hence why you MUST abs() it when
* calculating plane buffer size. * calculating plane buffer size.
*/ */
typedef void(uint32_t friend_number, uint16_t width, uint16_t height, typedef void(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, const uint8_t *y, const uint8_t *u, const uint8_t *v,
int32_t ystride, int32_t ustride, int32_t vstride, int32_t astride); int32_t ystride, int32_t ustride, int32_t vstride);
} }
} }

View File

@ -1,6 +1,17 @@
##Instructions #Instructions
This instruction primarily tested on Linux but, may be, will work on other POSIX-compliant systems. - [For `systemd` users](#systemd)
- [Troubleshooting](#systemd-troubleshooting)
<br>
- [For `init.d` users](#initd)
- [Troubleshooting](#initd-troubleshooting)
These instructions are primarily tested on Debian Linux, Wheezy for init.d and Jessie for systemd, but they should work on other POSIX-compliant systems too.
<a name="systemd" />
##For `systemd` users:
For security reasons we run the daemon under its own user. For security reasons we run the daemon under its own user.
@ -9,21 +20,91 @@ Create a new user by executing the following:
sudo useradd --home-dir /var/lib/tox-bootstrapd --create-home --system --shell /sbin/nologin --comment "Account to run Tox's DHT bootstrap daemon" --user-group tox-bootstrapd sudo useradd --home-dir /var/lib/tox-bootstrapd --create-home --system --shell /sbin/nologin --comment "Account to run Tox's DHT bootstrap daemon" --user-group tox-bootstrapd
``` ```
Copy `tox-bootstrapd.conf` file to where `CFGFILE` variable from `tox-bootstrapd.sh` tells (for `init.d` users) or `ExecStart=` from `tox-bootstrap.service` ( for `systemd` users). By default it's `/etc/tox-bootstrapd.conf`. Restrict access to home directory:
```sh
sudo chmod 700 /var/lib/tox-bootstrapd
```
Go over everything in `tox-bootstrapd.conf`. Make sure `pid_file_path` matches `PIDFILE` from `tox-bootstrapd.sh` (`init.d`) or `PIDFile=` from `tox-bootstrap.service` AND file in `ExecStartPre`(`systemd`). Copy `tox-bootstrapd.conf` file to where `ExecStart=` from `tox-bootstrapd.service` points to. By default it's `/etc/tox-bootstrapd.conf`.
```sh
sudo cp tox-bootstrapd.conf /etc/tox-bootstrapd.conf
```
Go over everything in the copied `tox-bootstrapd.conf` file. Set options you want and add actual working nodes to the `bootstrap_nodes` list, instead of the example ones, if you want your node to connect to the Tox network. Make sure `pid_file_path` matches `PIDFile=` from `tox-bootstrapd.service`.
Copy `tox-bootstrapd.service` to `/etc/systemd/system/`:
```sh
sudo cp tox-bootstrapd.service /etc/systemd/system/
```
You must uncomment the next line in tox-bootstrapd.service, if you want to use port number < 1024
#CapabilityBoundingSet=CAP_NET_BIND_SERVICE
and, possibly, install `libcap2-bin` or `libcap2` package, depending of your distribution.
Reload systemd units definitions, enable service for automatic start (if needed), start it and verify it's running:
```sh
sudo systemctl daemon-reload
sudo systemctl enable tox-bootstrapd.service
sudo systemctl start tox-bootstrapd.service
sudo systemctl status tox-bootstrapd.service
```
Get your public key and check that the daemon initialized correctly:
```sh
sudo grep "tox-bootstrapd" /var/log/syslog
```
<a name="systemd-troubleshooting" />
###Troubleshooting:
- Check daemon's status:
```sh
sudo systemctl status tox-bootstrapd.service
```
- Check the log for errors:
```sh
sudo grep "tox-bootstrapd" /var/log/syslog
# or
sudo journalctl --pager-end
# or
sudo journalctl -f _SYSTEMD_UNIT=tox-bootstrapd.service
```
- Make sure tox-bootstrapd user has write permission for keys and pid files.
- Make sure tox-bootstrapd has read permission for the config file.
- Make sure tox-bootstrapd location matches its path in tox-bootstrapd.service file.
<a name="initd" />
##For `init.d` users
For security reasons we run the daemon under its own user.
Create a new user by executing the following:
```sh
sudo useradd --home-dir /var/lib/tox-bootstrapd --create-home --system --shell /sbin/nologin --comment "Account to run Tox's DHT bootstrap daemon" --user-group tox-bootstrapd
```
Restrict access to home directory: Restrict access to home directory:
```sh ```sh
sudo chmod 700 /var/lib/tox-bootstrapd sudo chmod 700 /var/lib/tox-bootstrapd
``` ```
##For `init.d` users: Copy `tox-bootstrapd.conf` file to where `CFGFILE` variable from `tox-bootstrapd.sh` points to. By default it's `/etc/tox-bootstrapd.conf`.
```sh
sudo cp tox-bootstrapd.conf /etc/tox-bootstrapd.conf
```
Look at the variable declarations in the beginning of `tox-bootstrapd.sh` init script to see if you need to change anything for it to work for you. The default values must be fine for most users and we assume that you use those next. Go over everything in the copied `tox-bootstrapd.conf` file. Set options you want and add actual working nodes to the `bootstrap_nodes` list, instead of the example ones, if you want your node to connect to the Tox network. Make sure `pid_file_path` matches `PIDFILE` from `tox-bootstrapd.sh`.
Copy `tox-bootstrapd.sh` init file to `/etc/init.d/tox-bootstrapd` (note the disappearance of ".sh" ending). Look at the variable declarations in the beginning of `tox-bootstrapd.sh` init script to see if you need to change anything for it to work on your system. The default values must be fine for most users and we assume that you use those next.
Copy `tox-bootstrapd.sh` init script to `/etc/init.d/tox-bootstrapd` (note the disappearance of ".sh" ending):
```sh ```sh
sudo cp tox-bootstrapd.sh /etc/init.d/tox-bootstrapd sudo cp tox-bootstrapd.sh /etc/init.d/tox-bootstrapd
``` ```
@ -33,18 +114,10 @@ Set permissions for the init system to run the script:
sudo chmod 755 /etc/init.d/tox-bootstrapd sudo chmod 755 /etc/init.d/tox-bootstrapd
``` ```
Make the init system aware of the script: Make the init system aware of the script, start the daemon and verify it's running:
```sh ```sh
sudo update-rc.d tox-bootstrapd defaults sudo update-rc.d tox-bootstrapd defaults
```
Start the daemon:
```sh
sudo service tox-bootstrapd start sudo service tox-bootstrapd start
```
Verify it's running:
```sh
sudo service tox-bootstrapd status sudo service tox-bootstrapd status
``` ```
@ -53,56 +126,23 @@ Get your public key and check that the daemon initialized correctly:
sudo grep "tox-bootstrapd" /var/log/syslog sudo grep "tox-bootstrapd" /var/log/syslog
``` ```
##For `systemd` users: <a name="initd-troubleshooting" />
Copy tox-bootstrap.service to /etc/systemd/system/:
```sh
sudo cp tox-bootstrap.service /etc/systemd/system/
```
Make sure, that path to `chown` and `mkdir` is correct in `tox-bootstrap.service` (they may be different in some distributions, by default `/bin/chown` and `/bin/mkdir`)
You must uncomment the next line in tox-bootstrap.service, if you want to use port number <1024
#CapabilityBoundingSet=CAP_NET_BIND_SERVICE
and, possibly, install `libcap2-bin` or `libcap2` package, depending of your distribution.
Reload systemd units definitions, enable service for automatic start (if needed), and start it:
```sh
sudo systemctl daemon-reload
sudo systemctl enable tox-bootstrap.service
sudo systemctl start tox-bootstrap.service
```
###Troubleshooting: ###Troubleshooting:
- Check daemon's status: - Check daemon's status:
```sh ```sh
#init.d
sudo service tox-bootstrapd status sudo service tox-bootstrapd status
#systemd
sudo systemctl status tox-bootstrap.service
``` ```
- Check the log for errors: - Check the log for errors:
```sh ```sh
#init.d
sudo grep "tox-bootstrapd" /var/log/syslog sudo grep "tox-bootstrapd" /var/log/syslog
#systemd
sudo journalctl -f _SYSTEMD_UNIT=tox-bootstrap.service
``` ```
`init.d`:
- Check that variables in the beginning of `/etc/init.d/tox-bootstrapd` are valid. - Check that variables in the beginning of `/etc/init.d/tox-bootstrapd` are valid.
- Make sure tox-bootstrapd user has write permission for keys and pid files.
Common:
- Make sure tox-bootstrapd user has write permission for keys and pid files (in systemd pid file insured by unit definition).
- Make sure tox-bootstrapd has read permission for the config file. - Make sure tox-bootstrapd has read permission for the config file.
- Make sure tox-bootstrapd location matches its path in init scripts, if you specified non-default `--prefix`, when building. - Make sure tox-bootstrapd location matches its path in the `/etc/init.d/tox-bootstrapd` init script.

View File

@ -4,16 +4,14 @@ After=network.target
[Service] [Service]
Type=forking Type=forking
PermissionsStartOnly=true RuntimeDirectory=tox-bootstrapd
ExecStartPre=-/bin/mkdir /var/run/tox-bootstrapd -p RuntimeDirectoryMode=750
ExecStartPre=/bin/chown tox-bootstrapd:tox-bootstrapd -R /var/run/tox-bootstrapd PIDFile=/var/run/tox-bootstrapd/tox-bootstrapd.pid
WorkingDirectory=/var/lib/tox-bootstrapd WorkingDirectory=/var/lib/tox-bootstrapd
ExecStart=/usr/local/bin/tox-bootstrapd /etc/tox-bootstrapd.conf ExecStart=/usr/local/bin/tox-bootstrapd /etc/tox-bootstrapd.conf
User=tox-bootstrapd User=tox-bootstrapd
Group=tox-bootstrapd Group=tox-bootstrapd
PIDFile=/var/run/tox-bootstrapd/tox-bootstrapd.pid
#CapabilityBoundingSet=CAP_NET_BIND_SERVICE #CapabilityBoundingSet=CAP_NET_BIND_SERVICE
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target

View File

@ -222,7 +222,7 @@ Tox *init_tox(int argc, char *argv[])
exit(0); exit(0);
} }
Tox *tox = tox_new(0, 0, 0, 0); Tox *tox = tox_new(0, 0);
if (!tox) if (!tox)
exit(1); exit(1);

View File

@ -942,7 +942,17 @@ static Tox *load_data()
return 0; return 0;
} }
Tox *m = tox_new(0, data, size, NULL); struct Tox_Options options;
tox_options_default(&options);
options.savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE;
options.savedata_data = data;
options.savedata_length = size;
Tox *m = tox_new(&options, NULL);
if (fclose(data_file) < 0) { if (fclose(data_file) < 0) {
perror("[!] fclose failed"); perror("[!] fclose failed");
@ -953,7 +963,7 @@ static Tox *load_data()
return m; return m;
} }
return tox_new(0, 0, 0, NULL); return tox_new(NULL, NULL);
} }
static int save_data(Tox *m) static int save_data(Tox *m)

View File

@ -95,7 +95,7 @@ int main(int argc, char *argv[])
printf("error setting flags\n"); printf("error setting flags\n");
} }
Tox *tox = tox_new(0, 0, 0, 0); Tox *tox = tox_new(0, 0);
tox_callback_friend_connection_status(tox, print_online, NULL); tox_callback_friend_connection_status(tox, print_online, NULL);
tox_callback_friend_message(tox, print_message, master); tox_callback_friend_message(tox, print_message, master);

View File

@ -243,7 +243,7 @@ int main(int argc, char *argv[])
exit(0); exit(0);
} }
Tox *tox = tox_new(0, 0, 0, 0); Tox *tox = tox_new(0, 0);
tox_callback_file_recv_chunk(tox, write_file, NULL); tox_callback_file_recv_chunk(tox, write_file, NULL);
tox_callback_file_recv_control(tox, file_print_control, NULL); tox_callback_file_recv_control(tox, file_print_control, NULL);
tox_callback_file_recv(tox, file_request_accept, NULL); tox_callback_file_recv(tox, file_request_accept, NULL);

View File

@ -807,7 +807,7 @@ END:
return rc == TOXAV_ERR_SEND_FRAME_OK; 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) 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, TOXAV_ERR_SEND_FRAME* error)
{ {
TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK; TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK;
ToxAVCall* call; ToxAVCall* call;
@ -852,10 +852,6 @@ bool toxav_video_send_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_U], u, (width/2) * (height/2));
memcpy(img.planes[VPX_PLANE_V], v, (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, int vrc = vpx_codec_encode(call->video.second->encoder, &img,
call->video.second->frame_counter, 1, 0, MAX_ENCODE_TIME_US); call->video.second->frame_counter, 1, 0, MAX_ENCODE_TIME_US);

View File

@ -82,35 +82,27 @@ typedef struct Tox Tox;
#define TOXAV_DEFINED #define TOXAV_DEFINED
typedef struct ToxAV ToxAV; typedef struct ToxAV ToxAV;
#endif /* TOXAV_DEFINED */ #endif /* TOXAV_DEFINED */
/******************************************************************************* /*******************************************************************************
* *
* :: API version * :: API version
* *
******************************************************************************/ ******************************************************************************/
/** /**
* The major version number. Incremented when the API or ABI changes in an * The major version number. Incremented when the API or ABI changes in an
* incompatible way. * incompatible way.
*/ */
#define TOXAV_VERSION_MAJOR 0u #define TOXAV_VERSION_MAJOR 0u
/** /**
* The minor version number. Incremented when functionality is added without * The minor version number. Incremented when functionality is added without
* breaking the API or ABI. Set to 0 when the major version number is * breaking the API or ABI. Set to 0 when the major version number is
* incremented. * incremented.
*/ */
#define TOXAV_VERSION_MINOR 0u #define TOXAV_VERSION_MINOR 0u
/** /**
* The patch or revision number. Incremented when bugfixes are applied without * The patch or revision number. Incremented when bugfixes are applied without
* changing any functionality or API or ABI. * changing any functionality or API or ABI.
*/ */
#define TOXAV_VERSION_PATCH 0u #define TOXAV_VERSION_PATCH 0u
/** /**
* A macro to check at preprocessing time whether the client code is compatible * A macro to check at preprocessing time whether the client code is compatible
* with the installed version of ToxAV. * with the installed version of ToxAV.
@ -120,84 +112,65 @@ typedef struct ToxAV ToxAV;
(TOXAV_VERSION_MINOR > MINOR || \ (TOXAV_VERSION_MINOR > MINOR || \
(TOXAV_VERSION_MINOR == MINOR && \ (TOXAV_VERSION_MINOR == MINOR && \
TOXAV_VERSION_PATCH >= PATCH))) TOXAV_VERSION_PATCH >= PATCH)))
/** /**
* A macro to make compilation fail if the client code is not compatible with * A macro to make compilation fail if the client code is not compatible with
* the installed version of ToxAV. * the installed version of ToxAV.
*/ */
#define TOXAV_VERSION_REQUIRE(MAJOR, MINOR, PATCH) \ #define TOXAV_VERSION_REQUIRE(MAJOR, MINOR, PATCH) \
typedef char toxav_required_version[TOXAV_IS_COMPATIBLE(MAJOR, MINOR, PATCH) ? 1 : -1] typedef char toxav_required_version[TOXAV_IS_COMPATIBLE(MAJOR, MINOR, PATCH) ? 1 : -1]
/** /**
* A convenience macro to call toxav_version_is_compatible with the currently * A convenience macro to call toxav_version_is_compatible with the currently
* compiling API version. * compiling API version.
*/ */
#define TOXAV_VERSION_IS_ABI_COMPATIBLE() \ #define TOXAV_VERSION_IS_ABI_COMPATIBLE() \
toxav_version_is_compatible(TOXAV_VERSION_MAJOR, TOXAV_VERSION_MINOR, TOXAV_VERSION_PATCH) toxav_version_is_compatible(TOXAV_VERSION_MAJOR, TOXAV_VERSION_MINOR, TOXAV_VERSION_PATCH)
/** /**
* Return the major version number of the library. Can be used to display the * Return the major version number of the library. Can be used to display the
* ToxAV library version or to check whether the client is compatible with the * ToxAV library version or to check whether the client is compatible with the
* dynamically linked version of ToxAV. * dynamically linked version of ToxAV.
*/ */
uint32_t toxav_version_major(void); uint32_t toxav_version_major(void);
/** /**
* Return the minor version number of the library. * Return the minor version number of the library.
*/ */
uint32_t toxav_version_minor(void); uint32_t toxav_version_minor(void);
/** /**
* Return the patch number of the library. * Return the patch number of the library.
*/ */
uint32_t toxav_version_patch(void); uint32_t toxav_version_patch(void);
/** /**
* Return whether the compiled library version is compatible with the passed * Return whether the compiled library version is compatible with the passed
* version numbers. * version numbers.
*/ */
bool toxav_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch); bool toxav_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch);
/******************************************************************************* /*******************************************************************************
* *
* :: Creation and destruction * :: Creation and destruction
* *
******************************************************************************/ ******************************************************************************/
typedef enum TOXAV_ERR_NEW { typedef enum TOXAV_ERR_NEW {
/** /**
* The function returned successfully. * The function returned successfully.
*/ */
TOXAV_ERR_NEW_OK, TOXAV_ERR_NEW_OK,
/** /**
* One of the arguments to the function was NULL when it was not expected. * One of the arguments to the function was NULL when it was not expected.
*/ */
TOXAV_ERR_NEW_NULL, TOXAV_ERR_NEW_NULL,
/** /**
* Memory allocation failure while trying to allocate structures required for * Memory allocation failure while trying to allocate structures required for
* the A/V session. * the A/V session.
*/ */
TOXAV_ERR_NEW_MALLOC, TOXAV_ERR_NEW_MALLOC,
/** /**
* Attempted to create a second session for the same Tox instance. * Attempted to create a second session for the same Tox instance.
*/ */
TOXAV_ERR_NEW_MULTIPLE, TOXAV_ERR_NEW_MULTIPLE,
} TOXAV_ERR_NEW; } TOXAV_ERR_NEW;
/** /**
* Start new A/V session. There can only be only one session per Tox instance. * Start new A/V session. There can only be only one session per Tox instance.
*/ */
ToxAV *toxav_new(Tox *tox, TOXAV_ERR_NEW *error); ToxAV *toxav_new(Tox *tox, TOXAV_ERR_NEW *error);
/** /**
* Releases all resources associated with the A/V session. * Releases all resources associated with the A/V session.
* *
@ -206,80 +179,59 @@ ToxAV *toxav_new(Tox *tox, TOXAV_ERR_NEW *error);
* called and the av pointer becomes invalid. * called and the av pointer becomes invalid.
*/ */
void toxav_kill(ToxAV *toxAV); void toxav_kill(ToxAV *toxAV);
/** /**
* Returns the Tox instance the A/V object was created for. * Returns the Tox instance the A/V object was created for.
*/ */
Tox *toxav_get_tox(const ToxAV *toxAV); Tox *toxav_get_tox(const ToxAV *toxAV);
/******************************************************************************* /*******************************************************************************
* *
* :: A/V event loop * :: A/V event loop
* *
******************************************************************************/ ******************************************************************************/
/** /**
* Returns the interval in milliseconds when the next toxav_iterate call should * Returns the interval in milliseconds when the next toxav_iterate call should
* be. If no call is active at the moment, this function returns 200. * be. If no call is active at the moment, this function returns 200.
*/ */
uint32_t toxav_iteration_interval(const ToxAV *toxAV); uint32_t toxav_iteration_interval(const ToxAV *toxAV);
/** /**
* Main loop for the session. This function needs to be called in intervals of * Main loop for the session. This function needs to be called in intervals of
* toxav_iteration_interval() milliseconds. It is best called in the separate * toxav_iteration_interval() milliseconds. It is best called in the separate
* thread from tox_iterate. * thread from tox_iterate.
*/ */
void toxav_iterate(ToxAV *toxAV); void toxav_iterate(ToxAV *toxAV);
/******************************************************************************* /*******************************************************************************
* *
* :: Call setup * :: Call setup
* *
******************************************************************************/ ******************************************************************************/
typedef enum TOXAV_ERR_CALL { typedef enum TOXAV_ERR_CALL {
/** /**
* The function returned successfully. * The function returned successfully.
*/ */
TOXAV_ERR_CALL_OK, TOXAV_ERR_CALL_OK,
/** /**
* A resource allocation error occurred while trying to create the structures * A resource allocation error occurred while trying to create the structures
* required for the call. * required for the call.
*/ */
TOXAV_ERR_CALL_MALLOC, TOXAV_ERR_CALL_MALLOC,
/** /**
* The friend number did not designate a valid friend. * The friend number did not designate a valid friend.
*/ */
TOXAV_ERR_CALL_FRIEND_NOT_FOUND, TOXAV_ERR_CALL_FRIEND_NOT_FOUND,
/** /**
* The friend was valid, but not currently connected. * The friend was valid, but not currently connected.
*/ */
TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED, TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED,
/** /**
* Attempted to call a friend while already in an audio or video call with * Attempted to call a friend while already in an audio or video call with
* them. * them.
*/ */
TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL, TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL,
/** /**
* Audio or video bit rate is invalid. * Audio or video bit rate is invalid.
*/ */
TOXAV_ERR_CALL_INVALID_BIT_RATE, TOXAV_ERR_CALL_INVALID_BIT_RATE,
} TOXAV_ERR_CALL; } TOXAV_ERR_CALL;
/** /**
* Call a friend. This will start ringing the friend. * Call a friend. This will start ringing the friend.
* *
@ -294,7 +246,6 @@ typedef enum TOXAV_ERR_CALL {
* video sending. * video sending.
*/ */
bool toxav_call(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL *error); bool toxav_call(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL *error);
/** /**
* The function type for the call callback. * The function type for the call callback.
* *
@ -303,47 +254,36 @@ bool toxav_call(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, u
* @param video_enabled True if friend is sending video. * @param video_enabled True if friend is sending video.
*/ */
typedef void toxav_call_cb(ToxAV *toxAV, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data); typedef void toxav_call_cb(ToxAV *toxAV, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data);
/** /**
* Set the callback for the `call` event. Pass NULL to unset. * Set the callback for the `call` event. Pass NULL to unset.
* *
*/ */
void toxav_callback_call(ToxAV *toxAV, toxav_call_cb *callback, void *user_data); void toxav_callback_call(ToxAV *toxAV, toxav_call_cb *callback, void *user_data);
typedef enum TOXAV_ERR_ANSWER { typedef enum TOXAV_ERR_ANSWER {
/** /**
* The function returned successfully. * The function returned successfully.
*/ */
TOXAV_ERR_ANSWER_OK, TOXAV_ERR_ANSWER_OK,
/** /**
* Failed to initialize codecs for call session. Note that codec initiation * Failed to initialize codecs for call session. Note that codec initiation
* will fail if there is no receive callback registered for either audio or * will fail if there is no receive callback registered for either audio or
* video. * video.
*/ */
TOXAV_ERR_ANSWER_CODEC_INITIALIZATION, TOXAV_ERR_ANSWER_CODEC_INITIALIZATION,
/** /**
* The friend number did not designate a valid friend. * The friend number did not designate a valid friend.
*/ */
TOXAV_ERR_ANSWER_FRIEND_NOT_FOUND, TOXAV_ERR_ANSWER_FRIEND_NOT_FOUND,
/** /**
* The friend was valid, but they are not currently trying to initiate a call. * The friend was valid, but they are not currently trying to initiate a call.
* This is also returned if this client is already in a call with the friend. * This is also returned if this client is already in a call with the friend.
*/ */
TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING, TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING,
/** /**
* Audio or video bit rate is invalid. * Audio or video bit rate is invalid.
*/ */
TOXAV_ERR_ANSWER_INVALID_BIT_RATE, TOXAV_ERR_ANSWER_INVALID_BIT_RATE,
} TOXAV_ERR_ANSWER; } TOXAV_ERR_ANSWER;
/** /**
* Accept an incoming call. * Accept an incoming call.
* *
@ -357,18 +297,12 @@ typedef enum TOXAV_ERR_ANSWER {
* video sending. * video sending.
*/ */
bool toxav_answer(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER *error); bool toxav_answer(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER *error);
/******************************************************************************* /*******************************************************************************
* *
* :: Call state graph * :: Call state graph
* *
******************************************************************************/ ******************************************************************************/
enum TOXAV_CALL_STATE { enum TOXAV_CALL_STATE {
/** /**
* Set by the AV core if an error occurred on the remote end or if friend * Set by the AV core if an error occurred on the remote end or if friend
* timed out. This is the final state after which no more state * timed out. This is the final state after which no more state
@ -376,34 +310,28 @@ enum TOXAV_CALL_STATE {
* in combination with other call states. * in combination with other call states.
*/ */
TOXAV_CALL_STATE_ERROR = 1, TOXAV_CALL_STATE_ERROR = 1,
/** /**
* The call has finished. This is the final state after which no more state * The call has finished. This is the final state after which no more state
* transitions can occur for the call. This call state will never be * transitions can occur for the call. This call state will never be
* triggered in combination with other call states. * triggered in combination with other call states.
*/ */
TOXAV_CALL_STATE_FINISHED = 2, TOXAV_CALL_STATE_FINISHED = 2,
/** /**
* The flag that marks that friend is sending audio. * The flag that marks that friend is sending audio.
*/ */
TOXAV_CALL_STATE_SENDING_A = 4, TOXAV_CALL_STATE_SENDING_A = 4,
/** /**
* The flag that marks that friend is sending video. * The flag that marks that friend is sending video.
*/ */
TOXAV_CALL_STATE_SENDING_V = 8, TOXAV_CALL_STATE_SENDING_V = 8,
/** /**
* The flag that marks that friend is receiving audio. * The flag that marks that friend is receiving audio.
*/ */
TOXAV_CALL_STATE_RECEIVING_A = 16, TOXAV_CALL_STATE_RECEIVING_A = 16,
/** /**
* The flag that marks that friend is receiving video. * The flag that marks that friend is receiving video.
*/ */
TOXAV_CALL_STATE_RECEIVING_V = 32, TOXAV_CALL_STATE_RECEIVING_V = 32,
}; };
@ -415,96 +343,72 @@ enum TOXAV_CALL_STATE {
* the previous state. The state is set to 0 when the call is paused. * the previous state. The state is set to 0 when the call is paused.
*/ */
typedef void toxav_call_state_cb(ToxAV *toxAV, uint32_t friend_number, uint32_t state, void *user_data); typedef void toxav_call_state_cb(ToxAV *toxAV, uint32_t friend_number, uint32_t state, void *user_data);
/** /**
* Set the callback for the `call_state` event. Pass NULL to unset. * Set the callback for the `call_state` event. Pass NULL to unset.
* *
*/ */
void toxav_callback_call_state(ToxAV *toxAV, toxav_call_state_cb *callback, void *user_data); void toxav_callback_call_state(ToxAV *toxAV, toxav_call_state_cb *callback, void *user_data);
/******************************************************************************* /*******************************************************************************
* *
* :: Call control * :: Call control
* *
******************************************************************************/ ******************************************************************************/
typedef enum TOXAV_CALL_CONTROL { typedef enum TOXAV_CALL_CONTROL {
/** /**
* Resume a previously paused call. Only valid if the pause was caused by this * Resume a previously paused call. Only valid if the pause was caused by this
* client, if not, this control is ignored. Not valid before the call is accepted. * client, if not, this control is ignored. Not valid before the call is accepted.
*/ */
TOXAV_CALL_CONTROL_RESUME, TOXAV_CALL_CONTROL_RESUME,
/** /**
* Put a call on hold. Not valid before the call is accepted. * Put a call on hold. Not valid before the call is accepted.
*/ */
TOXAV_CALL_CONTROL_PAUSE, TOXAV_CALL_CONTROL_PAUSE,
/** /**
* Reject a call if it was not answered, yet. Cancel a call after it was * Reject a call if it was not answered, yet. Cancel a call after it was
* answered. * answered.
*/ */
TOXAV_CALL_CONTROL_CANCEL, TOXAV_CALL_CONTROL_CANCEL,
/** /**
* Request that the friend stops sending audio. Regardless of the friend's * Request that the friend stops sending audio. Regardless of the friend's
* compliance, this will cause the audio_receive_frame event to stop being * compliance, this will cause the audio_receive_frame event to stop being
* triggered on receiving an audio frame from the friend. * triggered on receiving an audio frame from the friend.
*/ */
TOXAV_CALL_CONTROL_MUTE_AUDIO, TOXAV_CALL_CONTROL_MUTE_AUDIO,
/** /**
* Calling this control will notify client to start sending audio again. * Calling this control will notify client to start sending audio again.
*/ */
TOXAV_CALL_CONTROL_UNMUTE_AUDIO, TOXAV_CALL_CONTROL_UNMUTE_AUDIO,
/** /**
* Request that the friend stops sending video. Regardless of the friend's * Request that the friend stops sending video. Regardless of the friend's
* compliance, this will cause the video_receive_frame event to stop being * compliance, this will cause the video_receive_frame event to stop being
* triggered on receiving an video frame from the friend. * triggered on receiving an video frame from the friend.
*/ */
TOXAV_CALL_CONTROL_HIDE_VIDEO, TOXAV_CALL_CONTROL_HIDE_VIDEO,
/** /**
* Calling this control will notify client to start sending video again. * Calling this control will notify client to start sending video again.
*/ */
TOXAV_CALL_CONTROL_SHOW_VIDEO, TOXAV_CALL_CONTROL_SHOW_VIDEO,
} TOXAV_CALL_CONTROL; } TOXAV_CALL_CONTROL;
typedef enum TOXAV_ERR_CALL_CONTROL { typedef enum TOXAV_ERR_CALL_CONTROL {
/** /**
* The function returned successfully. * The function returned successfully.
*/ */
TOXAV_ERR_CALL_CONTROL_OK, TOXAV_ERR_CALL_CONTROL_OK,
/** /**
* The friend_number passed did not designate a valid friend. * The friend_number passed did not designate a valid friend.
*/ */
TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_FOUND, TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_FOUND,
/** /**
* This client is currently not in a call with the friend. Before the call is * This client is currently not in a call with the friend. Before the call is
* answered, only CANCEL is a valid control. * answered, only CANCEL is a valid control.
*/ */
TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL, TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL,
/** /**
* Happens if user tried to pause an already paused call or if trying to * Happens if user tried to pause an already paused call or if trying to
* resume a call that is not paused. * resume a call that is not paused.
*/ */
TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION, TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION,
} TOXAV_ERR_CALL_CONTROL; } TOXAV_ERR_CALL_CONTROL;
/** /**
* Sends a call control command to a friend. * Sends a call control command to a friend.
* *
@ -515,41 +419,29 @@ typedef enum TOXAV_ERR_CALL_CONTROL {
* @return true on success. * @return true on success.
*/ */
bool toxav_call_control(ToxAV *toxAV, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL *error); bool toxav_call_control(ToxAV *toxAV, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL *error);
/******************************************************************************* /*******************************************************************************
* *
* :: Controlling bit rates * :: Controlling bit rates
* *
******************************************************************************/ ******************************************************************************/
typedef enum TOXAV_ERR_SET_BIT_RATE { typedef enum TOXAV_ERR_SET_BIT_RATE {
/** /**
* The function returned successfully. * The function returned successfully.
*/ */
TOXAV_ERR_SET_BIT_RATE_OK, TOXAV_ERR_SET_BIT_RATE_OK,
/** /**
* The bit rate passed was not one of the supported values. * The bit rate passed was not one of the supported values.
*/ */
TOXAV_ERR_SET_BIT_RATE_INVALID, TOXAV_ERR_SET_BIT_RATE_INVALID,
/** /**
* The friend_number passed did not designate a valid friend. * The friend_number passed did not designate a valid friend.
*/ */
TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_FOUND, TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_FOUND,
/** /**
* This client is currently not in a call with the friend. * This client is currently not in a call with the friend.
*/ */
TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_IN_CALL, TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_IN_CALL,
} TOXAV_ERR_SET_BIT_RATE; } TOXAV_ERR_SET_BIT_RATE;
/** /**
* The function type for the audio_bit_rate_status callback. * The function type for the audio_bit_rate_status callback.
* *
@ -564,14 +456,11 @@ typedef enum TOXAV_ERR_SET_BIT_RATE {
* @param bit_rate The bit rate in Kb/sec. * @param bit_rate The bit rate in Kb/sec.
*/ */
typedef void toxav_audio_bit_rate_status_cb(ToxAV *toxAV, uint32_t friend_number, bool stable, uint32_t bit_rate, void *user_data); typedef void toxav_audio_bit_rate_status_cb(ToxAV *toxAV, uint32_t friend_number, bool stable, uint32_t bit_rate, void *user_data);
/** /**
* Set the callback for the `audio_bit_rate_status` event. Pass NULL to unset. * Set the callback for the `audio_bit_rate_status` event. Pass NULL to unset.
* *
*/ */
void toxav_callback_audio_bit_rate_status(ToxAV *toxAV, toxav_audio_bit_rate_status_cb *callback, void *user_data); void toxav_callback_audio_bit_rate_status(ToxAV *toxAV, toxav_audio_bit_rate_status_cb *callback, void *user_data);
/** /**
* Set the audio bit rate to be used in subsequent audio frames. If the passed * Set the audio bit rate to be used in subsequent audio frames. If the passed
* bit rate is the same as the current bit rate this function will return true * bit rate is the same as the current bit rate this function will return true
@ -588,7 +477,6 @@ void toxav_callback_audio_bit_rate_status(ToxAV *toxAV, toxav_audio_bit_rate_sta
* *
*/ */
bool toxav_audio_bit_rate_set(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_SET_BIT_RATE *error); bool toxav_audio_bit_rate_set(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_SET_BIT_RATE *error);
/** /**
* The function type for the video_bit_rate_status callback. * The function type for the video_bit_rate_status callback.
* *
@ -603,14 +491,11 @@ bool toxav_audio_bit_rate_set(ToxAV *toxAV, uint32_t friend_number, uint32_t aud
* @param bit_rate The bit rate in Kb/sec. * @param bit_rate The bit rate in Kb/sec.
*/ */
typedef void toxav_video_bit_rate_status_cb(ToxAV *toxAV, uint32_t friend_number, bool stable, uint32_t bit_rate, void *user_data); typedef void toxav_video_bit_rate_status_cb(ToxAV *toxAV, uint32_t friend_number, bool stable, uint32_t bit_rate, void *user_data);
/** /**
* Set the callback for the `video_bit_rate_status` event. Pass NULL to unset. * Set the callback for the `video_bit_rate_status` event. Pass NULL to unset.
* *
*/ */
void toxav_callback_video_bit_rate_status(ToxAV *toxAV, toxav_video_bit_rate_status_cb *callback, void *user_data); void toxav_callback_video_bit_rate_status(ToxAV *toxAV, toxav_video_bit_rate_status_cb *callback, void *user_data);
/** /**
* Set the video bit rate to be used in subsequent video frames. If the passed * Set the video bit rate to be used in subsequent video frames. If the passed
* bit rate is the same as the current bit rate this function will return true * bit rate is the same as the current bit rate this function will return true
@ -627,53 +512,39 @@ void toxav_callback_video_bit_rate_status(ToxAV *toxAV, toxav_video_bit_rate_sta
* *
*/ */
bool toxav_video_bit_rate_set(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_SET_BIT_RATE *error); bool toxav_video_bit_rate_set(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_SET_BIT_RATE *error);
/******************************************************************************* /*******************************************************************************
* *
* :: A/V sending * :: A/V sending
* *
******************************************************************************/ ******************************************************************************/
typedef enum TOXAV_ERR_SEND_FRAME { typedef enum TOXAV_ERR_SEND_FRAME {
/** /**
* The function returned successfully. * The function returned successfully.
*/ */
TOXAV_ERR_SEND_FRAME_OK, TOXAV_ERR_SEND_FRAME_OK,
/** /**
* In case of video, one of Y, U, or V was NULL. In case of audio, the samples * In case of video, one of Y, U, or V was NULL. In case of audio, the samples
* data pointer was NULL. * data pointer was NULL.
*/ */
TOXAV_ERR_SEND_FRAME_NULL, TOXAV_ERR_SEND_FRAME_NULL,
/** /**
* The friend_number passed did not designate a valid friend. * The friend_number passed did not designate a valid friend.
*/ */
TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND, TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND,
/** /**
* This client is currently not in a call with the friend. * This client is currently not in a call with the friend.
*/ */
TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL, TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL,
/** /**
* One of the frame parameters was invalid. E.g. the resolution may be too * One of the frame parameters was invalid. E.g. the resolution may be too
* small or too large, or the audio sampling rate may be unsupported. * small or too large, or the audio sampling rate may be unsupported.
*/ */
TOXAV_ERR_SEND_FRAME_INVALID, TOXAV_ERR_SEND_FRAME_INVALID,
/** /**
* Failed to push frame through rtp interface. * Failed to push frame through rtp interface.
*/ */
TOXAV_ERR_SEND_FRAME_RTP_FAILED, TOXAV_ERR_SEND_FRAME_RTP_FAILED,
} TOXAV_ERR_SEND_FRAME; } TOXAV_ERR_SEND_FRAME;
/** /**
* Send an audio frame to a friend. * Send an audio frame to a friend.
* *
@ -695,7 +566,6 @@ typedef enum TOXAV_ERR_SEND_FRAME {
* rates are 8000, 12000, 16000, 24000, or 48000. * rates are 8000, 12000, 16000, 24000, or 48000.
*/ */
bool toxav_audio_send_frame(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, TOXAV_ERR_SEND_FRAME *error); bool toxav_audio_send_frame(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, TOXAV_ERR_SEND_FRAME *error);
/** /**
* Send a video frame to a friend. * Send a video frame to a friend.
* *
@ -710,19 +580,13 @@ bool toxav_audio_send_frame(ToxAV *toxAV, uint32_t friend_number, const int16_t
* @param y Y (Luminance) plane data. * @param y Y (Luminance) plane data.
* @param u U (Chroma) plane data. * @param u U (Chroma) plane data.
* @param v V (Chroma) plane data. * @param v V (Chroma) plane data.
* @param a A (Alpha) plane data.
*/ */
bool toxav_video_send_frame(ToxAV *toxAV, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v, const uint8_t *a, TOXAV_ERR_SEND_FRAME *error); bool toxav_video_send_frame(ToxAV *toxAV, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v, TOXAV_ERR_SEND_FRAME *error);
/******************************************************************************* /*******************************************************************************
* *
* :: A/V receiving * :: A/V receiving
* *
******************************************************************************/ ******************************************************************************/
/** /**
* The function type for the audio_receive_frame callback. * The function type for the audio_receive_frame callback.
* *
@ -734,14 +598,11 @@ bool toxav_video_send_frame(ToxAV *toxAV, uint32_t friend_number, uint16_t width
* *
*/ */
typedef void toxav_audio_receive_frame_cb(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, void *user_data); typedef void toxav_audio_receive_frame_cb(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, void *user_data);
/** /**
* Set the callback for the `audio_receive_frame` event. Pass NULL to unset. * Set the callback for the `audio_receive_frame` event. Pass NULL to unset.
* *
*/ */
void toxav_callback_audio_receive_frame(ToxAV *toxAV, toxav_audio_receive_frame_cb *callback, void *user_data); void toxav_callback_audio_receive_frame(ToxAV *toxAV, toxav_audio_receive_frame_cb *callback, void *user_data);
/** /**
* The function type for the video_receive_frame callback. * The function type for the video_receive_frame callback.
* *
@ -755,23 +616,18 @@ void toxav_callback_audio_receive_frame(ToxAV *toxAV, toxav_audio_receive_frame_
* Y = MAX(width, abs(ystride)) * height, * Y = MAX(width, abs(ystride)) * height,
* U = MAX(width/2, abs(ustride)) * (height/2) and * U = MAX(width/2, abs(ustride)) * (height/2) and
* V = MAX(width/2, abs(vstride)) * (height/2). * V = MAX(width/2, abs(vstride)) * (height/2).
* A = MAX(width, abs(astride)) * height.
* @param ystride * @param ystride
* @param ustride * @param ustride
* @param vstride * @param vstride Strides data. Strides represent padding for each plane
* @param astride Strides data. Strides represent padding for each plane
* that may or may not be present. You must handle strides in * that may or may not be present. You must handle strides in
* your image processing code. Strides are negative if the * your image processing code. Strides are negative if the
* image is bottom-up hence why you MUST abs() it when * image is bottom-up hence why you MUST abs() it when
* calculating plane buffer size. * calculating plane buffer size.
*/ */
typedef void toxav_video_receive_frame_cb(ToxAV *toxAV, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v, const uint8_t *a, int32_t ystride, int32_t ustride, int32_t vstride, int32_t astride, void *user_data); typedef void toxav_video_receive_frame_cb(ToxAV *toxAV, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v, int32_t ystride, int32_t ustride, int32_t vstride, void *user_data);
/** /**
* Set the callback for the `video_receive_frame` event. Pass NULL to unset. * Set the callback for the `video_receive_frame` event. Pass NULL to unset.
* *
*/ */
void toxav_callback_video_receive_frame(ToxAV *toxAV, toxav_video_receive_frame_cb *callback, void *user_data); void toxav_callback_video_receive_frame(ToxAV *toxAV, toxav_video_receive_frame_cb *callback, void *user_data);
#endif #endif

View File

@ -141,9 +141,8 @@ void vc_do(VCSession* vc)
for (; dest; dest = vpx_codec_get_frame(vc->decoder, &iter)) { for (; dest; dest = vpx_codec_get_frame(vc->decoder, &iter)) {
if (vc->vcb.first) if (vc->vcb.first)
vc->vcb.first(vc->av, vc->friend_number, dest->d_w, dest->d_h, 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[0], (const uint8_t*)dest->planes[1], (const uint8_t*)dest->planes[2],
(const uint8_t*)dest->planes[2], (const uint8_t*)dest->planes[3], dest->stride[0], dest->stride[1], dest->stride[2], vc->vcb.second);
dest->stride[0], dest->stride[1], dest->stride[2], dest->stride[3], vc->vcb.second);
vpx_img_free(dest); vpx_img_free(dest);
} }

View File

@ -384,12 +384,12 @@ int m_delfriend(Messenger *m, int32_t friendnumber)
clear_receipts(m, friendnumber); clear_receipts(m, friendnumber);
remove_request_received(&(m->fr), m->friendlist[friendnumber].real_pk); 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); friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, 0, 0, 0, 0, 0);
kill_friend_connection(m->fr_c, m->friendlist[friendnumber].friendcon_id);
if (friend_con_connected(m->fr_c, m->friendlist[friendnumber].friendcon_id) == FRIENDCONN_STATUS_CONNECTED) { if (friend_con_connected(m->fr_c, m->friendlist[friendnumber].friendcon_id) == FRIENDCONN_STATUS_CONNECTED) {
send_offline_packet(m, m->friendlist[friendnumber].friendcon_id); send_offline_packet(m, m->friendlist[friendnumber].friendcon_id);
} }
kill_friend_connection(m->fr_c, m->friendlist[friendnumber].friendcon_id);
memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend)); memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend));
uint32_t i; uint32_t i;
@ -864,6 +864,11 @@ static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, ui
if (was_online) { if (was_online) {
break_files(m, friendnumber); break_files(m, friendnumber);
clear_receipts(m, friendnumber); clear_receipts(m, friendnumber);
} else {
m->friendlist[friendnumber].name_sent = 0;
m->friendlist[friendnumber].userstatus_sent = 0;
m->friendlist[friendnumber].statusmessage_sent = 0;
m->friendlist[friendnumber].user_istyping_sent = 0;
} }
m->friendlist[friendnumber].status = status; m->friendlist[friendnumber].status = status;
@ -1891,10 +1896,6 @@ static int handle_status(void *object, int i, uint8_t status)
if (status) { /* Went online. */ if (status) { /* Went online. */
send_online_packet(m, i); send_online_packet(m, i);
m->friendlist[i].name_sent = 0;
m->friendlist[i].userstatus_sent = 0;
m->friendlist[i].statusmessage_sent = 0;
m->friendlist[i].user_istyping_sent = 0;
} else { /* Went offline. */ } else { /* Went offline. */
if (m->friendlist[i].status == FRIEND_ONLINE) { if (m->friendlist[i].status == FRIEND_ONLINE) {
set_friend_status(m, i, FRIEND_CONFIRMED); set_friend_status(m, i, FRIEND_CONFIRMED);

View File

@ -510,10 +510,9 @@ static uint8_t candidates_create_new(const Assoc *assoc, hash_t hash, const uint
static void client_id_self_update(Assoc *assoc) static void client_id_self_update(Assoc *assoc)
{ {
if (assoc->self_hash || !assoc->self_client_id) if (assoc->self_hash)
return; return;
if (!assoc->self_hash) {
size_t i, sum = 0; size_t i, sum = 0;
for (i = 0; i < crypto_box_PUBLICKEYBYTES; i++) for (i = 0; i < crypto_box_PUBLICKEYBYTES; i++)
@ -523,7 +522,6 @@ static void client_id_self_update(Assoc *assoc)
return; return;
assoc->self_hash = id_hash(assoc, assoc->self_client_id); assoc->self_hash = id_hash(assoc, assoc->self_client_id);
}
LOGGER_DEBUG("id is now set, purging cache of self-references"); LOGGER_DEBUG("id is now set, purging cache of self-references");
@ -532,7 +530,7 @@ static void client_id_self_update(Assoc *assoc)
*/ */
bucket_t b_id = candidates_id_bucket(assoc, assoc->self_client_id); bucket_t b_id = candidates_id_bucket(assoc, assoc->self_client_id);
candidates_bucket *cnd_bckt = &assoc->candidates[b_id]; candidates_bucket *cnd_bckt = &assoc->candidates[b_id];
size_t i, pos = assoc->self_hash % assoc->candidates_bucket_size; size_t pos = assoc->self_hash % assoc->candidates_bucket_size;
for (i = 0; i < HASH_COLLIDE_COUNT; pos = hash_collide(assoc, pos), i++) { for (i = 0; i < HASH_COLLIDE_COUNT; pos = hash_collide(assoc, pos), i++) {
Client_entry *entry = &cnd_bckt->list[pos]; Client_entry *entry = &cnd_bckt->list[pos];

View File

@ -1149,7 +1149,7 @@ int group_new_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_n
* return 0 on success * return 0 on success
* return -1 on failure * return -1 on failure
*/ */
int group_kill_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_num) static int group_kill_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_num)
{ {
uint8_t packet[GROUP_MESSAGE_KILL_PEER_LENGTH]; uint8_t packet[GROUP_MESSAGE_KILL_PEER_LENGTH];

View File

@ -2006,7 +2006,7 @@ static int udp_handle_packet(void *object, IP_Port source, const uint8_t *packet
#define PACKET_RESEND_MULTIPLIER 2 #define PACKET_RESEND_MULTIPLIER 2
/* Timeout for increasing speed after congestion event (in ms). */ /* Timeout for increasing speed after congestion event (in ms). */
#define CONGESTION_EVENT_TIMEOUT 4000 #define CONGESTION_EVENT_TIMEOUT 2000
static void send_crypto_packets(Net_Crypto *c) static void send_crypto_packets(Net_Crypto *c)
{ {
@ -2086,7 +2086,7 @@ static void send_crypto_packets(Net_Crypto *c)
PACKET_COUNTER_AVERAGE_INTERVAL)); PACKET_COUNTER_AVERAGE_INTERVAL));
if (conn->last_congestion_event + CONGESTION_EVENT_TIMEOUT < temp_time) { if (conn->last_congestion_event + CONGESTION_EVENT_TIMEOUT < temp_time) {
conn->packet_send_rate = min_speed * 1.2; conn->packet_send_rate = min_speed * 1.25;
} else { } else {
conn->packet_send_rate = min_speed; conn->packet_send_rate = min_speed;
} }

View File

@ -121,33 +121,46 @@ void tox_options_free(struct Tox_Options *options)
free(options); free(options);
} }
Tox *tox_new(const struct Tox_Options *options, const uint8_t *data, size_t length, TOX_ERR_NEW *error) Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error)
{ {
if (!logger_get_global()) if (!logger_get_global())
logger_set_global(logger_new(LOGGER_OUTPUT_FILE, LOGGER_LEVEL, "toxcore")); logger_set_global(logger_new(LOGGER_OUTPUT_FILE, LOGGER_LEVEL, "toxcore"));
if (data == NULL && length != 0) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_NULL);
return NULL;
}
if (data && length) {
if (length < TOX_ENC_SAVE_MAGIC_LENGTH) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
return NULL;
}
if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_ENCRYPTED);
return NULL;
}
}
Messenger_Options m_options = {0}; Messenger_Options m_options = {0};
_Bool load_savedata_sk = 0, load_savedata_tox = 0;
if (options == NULL) { if (options == NULL) {
m_options.ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; m_options.ipv6enabled = TOX_ENABLE_IPV6_DEFAULT;
} else { } else {
if (options->savedata_type != TOX_SAVEDATA_TYPE_NONE) {
if (options->savedata_data == NULL || options->savedata_length == 0) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
return NULL;
}
}
if (options->savedata_type == TOX_SAVEDATA_TYPE_SECRET_KEY) {
if (options->savedata_length != TOX_SECRET_KEY_SIZE) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
return NULL;
}
load_savedata_sk = 1;
} else if (options->savedata_type == TOX_SAVEDATA_TYPE_TOX_SAVE) {
if (options->savedata_length < TOX_ENC_SAVE_MAGIC_LENGTH) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
return NULL;
}
if (memcmp(options->savedata_data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_ENCRYPTED);
return NULL;
}
load_savedata_tox = 1;
}
m_options.ipv6enabled = options->ipv6_enabled; m_options.ipv6enabled = options->ipv6_enabled;
m_options.udp_disabled = !options->udp_enabled; m_options.udp_disabled = !options->udp_enabled;
m_options.port_range[0] = options->start_port; m_options.port_range[0] = options->start_port;
@ -201,6 +214,8 @@ Tox *tox_new(const struct Tox_Options *options, const uint8_t *data, size_t leng
if (m_error == MESSENGER_ERROR_PORT) { if (m_error == MESSENGER_ERROR_PORT) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PORT_ALLOC); SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PORT_ALLOC);
} else if (m_error == MESSENGER_ERROR_TCP_SERVER) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PORT_ALLOC);
} else { } else {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC); SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
} }
@ -208,8 +223,11 @@ Tox *tox_new(const struct Tox_Options *options, const uint8_t *data, size_t leng
return NULL; return NULL;
} }
if (data && length && messenger_load(m, data, length) == -1) { if (load_savedata_tox && messenger_load(m, options->savedata_data, options->savedata_length) == -1) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT); SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
} else if (load_savedata_sk) {
load_secret_key(m->net_crypto, options->savedata_data);
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK);
} else { } else {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK); SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK);
} }
@ -993,6 +1011,11 @@ void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *function
bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t *file_id, bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t *file_id,
TOX_ERR_FILE_GET *error) TOX_ERR_FILE_GET *error)
{ {
if (!file_id) {
SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_NULL);
return 0;
}
const Messenger *m = tox; const Messenger *m = tox;
int ret = file_get_id(m, friend_number, file_number, file_id); int ret = file_get_id(m, friend_number, file_number, file_id);

View File

@ -351,6 +351,29 @@ typedef enum TOX_PROXY_TYPE {
} TOX_PROXY_TYPE; } TOX_PROXY_TYPE;
/**
* Type of savedata to create the Tox instance from.
*/
typedef enum TOX_SAVEDATA_TYPE {
/**
* No savedata.
*/
TOX_SAVEDATA_TYPE_NONE,
/**
* Savedata is one that was obtained from tox_get_savedata
*/
TOX_SAVEDATA_TYPE_TOX_SAVE,
/**
* Savedata is a secret key of length TOX_SECRET_KEY_SIZE
*/
TOX_SAVEDATA_TYPE_SECRET_KEY,
} TOX_SAVEDATA_TYPE;
/** /**
* This struct contains all the startup options for Tox. You can either allocate * This struct contains all the startup options for Tox. You can either allocate
* this object yourself, and pass it to tox_options_default, or call * this object yourself, and pass it to tox_options_default, or call
@ -432,6 +455,24 @@ struct Tox_Options {
*/ */
uint16_t tcp_port; uint16_t tcp_port;
/**
* The type of savedata to load from.
*/
TOX_SAVEDATA_TYPE savedata_type;
/**
* The savedata.
*/
const uint8_t *savedata_data;
/**
* The length of the savedata.
*/
size_t savedata_length;
}; };
@ -561,21 +602,17 @@ typedef enum TOX_ERR_NEW {
* This function will bring the instance into a valid state. Running the event * This function will bring the instance into a valid state. Running the event
* loop with a new instance will operate correctly. * loop with a new instance will operate correctly.
* *
* If the data parameter is not NULL, this function will load the Tox instance
* from a byte array previously filled by tox_get_savedata.
*
* If loading failed or succeeded only partially, the new or partially loaded * If loading failed or succeeded only partially, the new or partially loaded
* instance is returned and an error code is set. * instance is returned and an error code is set.
* *
* @param options An options object as described above. If this parameter is * @param options An options object as described above. If this parameter is
* NULL, the default options are used. * NULL, the default options are used.
* @param data A byte array containing data previously stored by tox_get_savedata.
* @param length The length of the byte array data. If this parameter is 0, the
* data parameter is ignored.
* *
* @see tox_iterate for the event loop. * @see tox_iterate for the event loop.
*
* @return A new Tox instance pointer on success or NULL on failure.
*/ */
Tox *tox_new(const struct Tox_Options *options, const uint8_t *data, size_t length, TOX_ERR_NEW *error); Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error);
/** /**
* Releases all resources associated with the Tox instance and disconnects from * Releases all resources associated with the Tox instance and disconnects from
@ -642,13 +679,8 @@ typedef enum TOX_ERR_BOOTSTRAP {
* Sends a "get nodes" request to the given bootstrap node with IP, port, and * Sends a "get nodes" request to the given bootstrap node with IP, port, and
* public key to setup connections. * public key to setup connections.
* *
* This function will attempt to connect to the node using UDP and TCP at the * This function will attempt to connect to the node using UDP. You must use
* same time. * this function even if Tox_Options.udp_enabled was set to false.
*
* Tox will use the node as a TCP relay in case Tox_Options.udp_enabled was
* false, and also to connect to friends that are in TCP-only mode. Tox will
* also use the TCP connection when NAT hole punching is slow, and later switch
* to UDP if hole punching succeeds.
* *
* @param address The hostname or IP address (IPv4 or IPv6) of the node. * @param address The hostname or IP address (IPv4 or IPv6) of the node.
* @param port The port on the host on which the bootstrap Tox instance is * @param port The port on the host on which the bootstrap Tox instance is
@ -1559,7 +1591,7 @@ enum TOX_FILE_KIND {
TOX_FILE_KIND_DATA, TOX_FILE_KIND_DATA,
/** /**
* Avatar filename. This consists of tox_hash(image). * Avatar file_id. This consists of tox_hash(image).
* Avatar data. This consists of the image data. * Avatar data. This consists of the image data.
* *
* Avatars can be sent at any time the client wishes. Generally, a client will * Avatars can be sent at any time the client wishes. Generally, a client will
@ -1748,6 +1780,11 @@ typedef enum TOX_ERR_FILE_GET {
*/ */
TOX_ERR_FILE_GET_OK, TOX_ERR_FILE_GET_OK,
/**
* One of the arguments to the function was NULL when it was not expected.
*/
TOX_ERR_FILE_GET_NULL,
/** /**
* The friend_number passed did not designate a valid friend. * The friend_number passed did not designate a valid friend.
*/ */

View File

@ -82,7 +82,7 @@ bool tox_get_salt(const uint8_t *data, uint8_t *salt)
* *
* returns true on success * returns true on success
*/ */
bool tox_derive_key_from_pass(uint8_t *passphrase, size_t pplength, TOX_PASS_KEY *out_key, bool tox_derive_key_from_pass(const uint8_t *passphrase, size_t pplength, TOX_PASS_KEY *out_key,
TOX_ERR_KEY_DERIVATION *error) TOX_ERR_KEY_DERIVATION *error)
{ {
uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
@ -93,10 +93,10 @@ bool tox_derive_key_from_pass(uint8_t *passphrase, size_t pplength, TOX_PASS_KEY
/* Same as above, except with use the given salt for deterministic key derivation. /* Same as above, except with use the given salt for deterministic key derivation.
* The salt must be TOX_PASS_SALT_LENGTH bytes in length. * The salt must be TOX_PASS_SALT_LENGTH bytes in length.
*/ */
bool tox_derive_key_with_salt(uint8_t *passphrase, size_t pplength, uint8_t *salt, TOX_PASS_KEY *out_key, bool tox_derive_key_with_salt(const uint8_t *passphrase, size_t pplength, const uint8_t *salt, TOX_PASS_KEY *out_key,
TOX_ERR_KEY_DERIVATION *error) TOX_ERR_KEY_DERIVATION *error)
{ {
if (pplength == 0 || !passphrase || !salt || !out_key) { if (!salt || !out_key || (!passphrase && pplength != 0)) {
SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_NULL); SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_NULL);
return 0; return 0;
} }
@ -180,7 +180,7 @@ bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const TOX_PASS_K
* *
* returns true on success * returns true on success
*/ */
bool tox_pass_encrypt(const uint8_t *data, size_t data_len, uint8_t *passphrase, size_t pplength, uint8_t *out, bool tox_pass_encrypt(const uint8_t *data, size_t data_len, const uint8_t *passphrase, size_t pplength, uint8_t *out,
TOX_ERR_ENCRYPTION *error) TOX_ERR_ENCRYPTION *error)
{ {
TOX_PASS_KEY key; TOX_PASS_KEY key;
@ -252,10 +252,10 @@ bool tox_pass_key_decrypt(const uint8_t *data, size_t length, const TOX_PASS_KEY
* *
* returns true on success * returns true on success
*/ */
bool tox_pass_decrypt(const uint8_t *data, size_t length, uint8_t *passphrase, size_t pplength, uint8_t *out, bool tox_pass_decrypt(const uint8_t *data, size_t length, const uint8_t *passphrase, size_t pplength, uint8_t *out,
TOX_ERR_DECRYPTION *error) TOX_ERR_DECRYPTION *error)
{ {
if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH || pplength == 0) { if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) {
SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH); SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH);
return 0; return 0;
} }

View File

@ -143,7 +143,7 @@ typedef enum TOX_ERR_DECRYPTION {
* *
* returns true on success * returns true on success
*/ */
bool tox_pass_encrypt(const uint8_t *data, size_t data_len, uint8_t *passphrase, size_t pplength, uint8_t *out, bool tox_pass_encrypt(const uint8_t *data, size_t data_len, const uint8_t *passphrase, size_t pplength, uint8_t *out,
TOX_ERR_ENCRYPTION *error); TOX_ERR_ENCRYPTION *error);
@ -155,7 +155,7 @@ bool tox_pass_encrypt(const uint8_t *data, size_t data_len, uint8_t *passphrase,
* *
* returns true on success * returns true on success
*/ */
bool tox_pass_decrypt(const uint8_t *data, size_t length, uint8_t *passphrase, size_t pplength, uint8_t *out, bool tox_pass_decrypt(const uint8_t *data, size_t length, const uint8_t *passphrase, size_t pplength, uint8_t *out,
TOX_ERR_DECRYPTION *error); TOX_ERR_DECRYPTION *error);
@ -183,13 +183,13 @@ typedef struct {
* *
* returns true on success * returns true on success
*/ */
bool tox_derive_key_from_pass(uint8_t *passphrase, size_t pplength, TOX_PASS_KEY *out_key, bool tox_derive_key_from_pass(const uint8_t *passphrase, size_t pplength, TOX_PASS_KEY *out_key,
TOX_ERR_KEY_DERIVATION *error); TOX_ERR_KEY_DERIVATION *error);
/* Same as above, except use the given salt for deterministic key derivation. /* Same as above, except use the given salt for deterministic key derivation.
* The salt must be TOX_PASS_SALT_LENGTH bytes in length. * The salt must be TOX_PASS_SALT_LENGTH bytes in length.
*/ */
bool tox_derive_key_with_salt(uint8_t *passphrase, size_t pplength, uint8_t *salt, TOX_PASS_KEY *out_key, bool tox_derive_key_with_salt(const uint8_t *passphrase, size_t pplength, const uint8_t *salt, TOX_PASS_KEY *out_key,
TOX_ERR_KEY_DERIVATION *error); TOX_ERR_KEY_DERIVATION *error);
/* This retrieves the salt used to encrypt the given data, which can then be passed to /* This retrieves the salt used to encrypt the given data, which can then be passed to